Skip to content

Commit

Permalink
Multiple portfolios
Browse files Browse the repository at this point in the history
  • Loading branch information
howeyc committed Nov 5, 2017
1 parent fc80487 commit e105ae8
Show file tree
Hide file tree
Showing 14 changed files with 187 additions and 106 deletions.
118 changes: 59 additions & 59 deletions cmd/lweb/bindata.go

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions cmd/lweb/handler_accounts.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ func accountsHandler(w http.ResponseWriter, r *http.Request) {

var pData pageData
pData.Reports = reportConfigData.Reports
pData.Portfolios = portfolioConfigData.Portfolios
pData.Accounts = balances
pData.Transactions = trans

Expand Down
1 change: 1 addition & 0 deletions cmd/lweb/handler_ledger.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ func ledgerHandler(w http.ResponseWriter, r *http.Request) {

var pData pageData
pData.Reports = reportConfigData.Reports
pData.Portfolios = portfolioConfigData.Portfolios
pData.Transactions = trans

err = t.Execute(w, pData)
Expand Down
67 changes: 57 additions & 10 deletions cmd/lweb/handler_portfolio.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"net/http"
"sort"

"github.com/go-martini/martini"
"github.com/howeyc/ledger"
)

Expand All @@ -31,7 +32,37 @@ func stockQuote(symbol string) (quote iexQuote, err error) {
return quote, nil
}

func portfolioHandler(w http.ResponseWriter, r *http.Request) {
type gdaxQuote struct {
Volume string `json:"volume"`
PreviousClose float64 `json:"open,string"`
Last float64 `json:"last,string"`
}

// https://docs.gdax.com/
func cryptoQuote(symbol string) (quote gdaxQuote, err error) {
resp, herr := http.Get("https://api.gdax.com/products/" + symbol + "/stats")
if herr != nil {
return quote, herr
}
defer resp.Body.Close()
dec := json.NewDecoder(resp.Body)
dec.Decode(&quote)
if quote.Volume == "" {
return quote, errors.New("Unable to find data for symbol " + symbol)
}
return quote, nil
}

func portfolioHandler(w http.ResponseWriter, r *http.Request, params martini.Params) {
portfolioName := params["portfolioName"]

var portfolio portfolioStruct
for _, port := range portfolioConfigData.Portfolios {
if port.Name == portfolioName {
portfolio = port
}
}

t, err := parseAssets("templates/template.portfolio.html", "templates/template.nav.html")
if err != nil {
http.Error(w, err.Error(), 500)
Expand All @@ -45,15 +76,22 @@ func portfolioHandler(w http.ResponseWriter, r *http.Request) {
}
balances := ledger.GetBalances(trans, []string{})

var pData pageData
type portPageData struct {
pageData
PortfolioName string
}

var pData portPageData
pData.Reports = reportConfigData.Reports
pData.Portfolios = portfolioConfigData.Portfolios
pData.Transactions = trans
pData.PortfolioName = portfolioName

sectionTotals := make(map[string]stockInfo)
siChan := make(chan stockInfo)

for _, stock := range stockConfigData.Stocks {
go func(name, account, symbol, section string, shares float64) {
for _, stock := range portfolio.Stocks {
go func(name, account, symbol, securityType, section string, shares float64) {
si := stockInfo{Name: name,
Section: section,
Ticker: symbol,
Expand All @@ -67,10 +105,19 @@ func portfolioHandler(w http.ResponseWriter, r *http.Request) {
sprice := cprice
sclose := cprice

quote, qerr := stockQuote(symbol)
if qerr == nil {
sprice = quote.Last
sclose = quote.PreviousClose
switch securityType {
case "Stock":
quote, qerr := stockQuote(symbol)
if qerr == nil {
sprice = quote.Last
sclose = quote.PreviousClose
}
case "Crypto":
quote, qerr := cryptoQuote(symbol)
if qerr == nil {
sprice = quote.Last
sclose = quote.PreviousClose
}
}

si.Price = sprice
Expand All @@ -82,9 +129,9 @@ func portfolioHandler(w http.ResponseWriter, r *http.Request) {
si.PriceChangePctOverall = (si.PriceChangeOverall / cprice) * 100.0
si.GainLossDay = si.Shares * si.PriceChangeDay
siChan <- si
}(stock.Name, stock.Account, stock.Ticker, stock.Section, stock.Shares)
}(stock.Name, stock.Account, stock.Ticker, stock.SecurityType, stock.Section, stock.Shares)
}
for range stockConfigData.Stocks {
for range portfolio.Stocks {
pData.Stocks = append(pData.Stocks, <-siChan)
}

Expand Down
1 change: 1 addition & 0 deletions cmd/lweb/handler_report.go
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ func reportHandler(w http.ResponseWriter, r *http.Request, params martini.Params

var pData piePageData
pData.Reports = reportConfigData.Reports
pData.Portfolios = portfolioConfigData.Portfolios
pData.Transactions = vtrans
pData.ChartAccounts = values
pData.RangeStart = rStart
Expand Down
27 changes: 17 additions & 10 deletions cmd/lweb/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -87,11 +87,12 @@ type reportConfigStruct struct {
var reportConfigData reportConfigStruct

type stockConfig struct {
Name string
Section string
Ticker string
Account string
Shares float64
Name string
SecurityType string `toml:"security_type"`
Section string
Ticker string
Account string
Shares float64
}

type stockInfo struct {
Expand All @@ -112,17 +113,23 @@ type stockInfo struct {
GainLossOverall float64
}

type stockConfigStruct struct {
type portfolioStruct struct {
Name string
Stocks []stockConfig `toml:"stock"`
}

var stockConfigData stockConfigStruct
type portfolioConfigStruct struct {
Portfolios []portfolioStruct `toml:"portfolio"`
}

var portfolioConfigData portfolioConfigStruct

type pageData struct {
Reports []reportConfig
Transactions []*ledger.Transaction
Accounts []*ledger.Account
Stocks []stockInfo
Portfolios []portfolioStruct
}

func main() {
Expand Down Expand Up @@ -152,9 +159,9 @@ func main() {
}()

if len(stockConfigFileName) > 0 {
var sLoadData stockConfigStruct
var sLoadData portfolioConfigStruct
toml.DecodeFile(stockConfigFileName, &sLoadData)
stockConfigData = sLoadData
portfolioConfigData = sLoadData
}

// initialize cache
Expand All @@ -166,7 +173,7 @@ func main() {

m.Get("/ledger", ledgerHandler)
m.Get("/accounts", accountsHandler)
m.Get("/portfolio", portfolioHandler)
m.Get("/portfolio/:portfolioName", portfolioHandler)
m.Get("/account/:accountName", accountHandler)
m.Get("/report/:reportName", reportHandler)
m.Get("/", func(w http.ResponseWriter, r *http.Request) {
Expand Down
53 changes: 35 additions & 18 deletions cmd/lweb/portfolio-sample.toml
Original file line number Diff line number Diff line change
@@ -1,20 +1,37 @@
[[stock]]
name = "Vanguard"
section = "Fund"
ticker = "VASGX"
account = "Assets:Investments:TD Ameritrade:Invested:Fund:VASGX"
shares = 3000
[[porfolio]]
name = "Stocks"

[[stock]]
name = "S&P 500"
section = "ETF"
ticker = "IVV"
account = "Assets:Investments:TD Ameritrade:Invested:ETF:IVV"
shares = 3000
[[portfolio.stock]]
name = "Vanguard"
security_type = "Fund"
section = "Fund"
ticker = "VASGX"
account = "Assets:Investments:TD Ameritrade:Invested:Fund:VASGX"
shares = 3000

[[stock]]
name = "S&P 500 High Div"
section = "ETF"
ticker = "SPHD"
account = "Assets:Investments:TD Ameritrade:Invested:ETF:SPHD"
shares = 3000
[[portfolio.stock]]
name = "S&P 500"
security_type = "Stock"
section = "ETF"
ticker = "IVV"
account = "Assets:Investments:TD Ameritrade:Invested:ETF:IVV"
shares = 3000

[[portfolio.stock]]
name = "S&P 500 High Div"
security_type = "Stock"
section = "ETF"
ticker = "SPHD"
account = "Assets:Investments:TD Ameritrade:Invested:ETF:SPHD"
shares = 3000

[[portfolio]]
name = "Crypto Holdings"

[[portfolio.stock]]
name = "Litecoin"
security_type = "Crypto"
section = "LTC"
ticker = "LTC-USD"
account = "Assets:Investments:Crypto:LTC"
shares = 10
2 changes: 1 addition & 1 deletion cmd/lweb/templates/template.account.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

<body>

{{template "nav" .Reports}}
{{template "nav" .}}

<div class="container">
<div class="content-header">
Expand Down
2 changes: 1 addition & 1 deletion cmd/lweb/templates/template.accounts.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

<body>

{{template "nav" .Reports}}
{{template "nav" .}}

<div class="container">
<div class="content-header">
Expand Down
2 changes: 1 addition & 1 deletion cmd/lweb/templates/template.barlinechart.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

<body>

{{template "nav" .Reports}}
{{template "nav" .}}

<div class="container">
<div class="content-header">
Expand Down
2 changes: 1 addition & 1 deletion cmd/lweb/templates/template.ledger.html
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@

<body>

{{template "nav" .Reports}}
{{template "nav" .}}

<div class="container">
<div class="content-header">
Expand Down
11 changes: 9 additions & 2 deletions cmd/lweb/templates/template.nav.html
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,19 @@
<li class="dropdown">
<a href="#" class="dropdown toggle" data-toggle="dropdown">Reports <span class="caret"></span></a>
<ul class="dropdown-menu">
{{range .}}
{{range .Reports}}
<li><a href="/report/{{.Name}}">{{.Name}}</a></li>
{{end}}
</ul>
</li>
<li><a href="/portfolio">Portfolio</a></li>
<li class="dropdown">
<a href="#" class="dropdown toggle" data-toggle="dropdown">Portfolios <span class="caret"></span></a>
<ul class="dropdown-menu">
{{range .Portfolios}}
<li><a href="/portfolio/{{.Name}}">{{.Name}}</a></li>
{{end}}
</ul>
</li>
</ul>
</div><!--/.nav-collapse -->
</div>
Expand Down
2 changes: 1 addition & 1 deletion cmd/lweb/templates/template.piechart.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@

<body>

{{template "nav" .Reports}}
{{template "nav" .}}

<div class="container">
<div class="content-header">
Expand Down
4 changes: 2 additions & 2 deletions cmd/lweb/templates/template.portfolio.html
Original file line number Diff line number Diff line change
Expand Up @@ -43,13 +43,13 @@

<body>

{{template "nav" .Reports}}
{{template "nav" .}}

<div class="container">
<div class="content-header">
<div class="row">
<div class="col-xs-8">
<h1>Portfolio<span id="info" class="visible-xs-inline"> - Overall</span></h1>
<h1>Portfolio {{.PortfolioName}}<span id="info" class="visible-xs-inline"> - Overall</span></h1>
</div>
<div class="col-xs-4"><a class="btn btn-default visible-xs-block" href="#" onclick="toggleInfo();">Toggle</a></div>
</div>
Expand Down

0 comments on commit e105ae8

Please sign in to comment.