diff --git a/lib/format.go b/lib/format.go index 3e7270e..917c7da 100644 --- a/lib/format.go +++ b/lib/format.go @@ -1,32 +1,33 @@ // Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved. //=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-= -// -// +build ignore - package mop import ( - "bytes" "fmt" + "bytes" + "regexp" + "strings" "text/template" "time" ) //----------------------------------------------------------------------------- -func Format(message []Message) string { +func Format(quotes Quotes) string { vars := struct { Now string - Stocks []Message + Header string + Stocks Quotes }{ time.Now().Format("3:04:05pm PST"), - prettify(message), + header(), + prettify(quotes), } markup := `Hello{{.Now}} -Ticker Last trade Change % Change Dividend Yield -{{range .Stocks}}{{.Color}}{{.Ticker}} {{.LastTrade}} {{.Change}} {{.ChangePercent}} {{.Dividend}} {{.Yield}} +{{.Header}} +{{range .Stocks}}{{.Color}}{{.Ticker}} {{.LastTrade}} {{.Change}} {{.ChangePercent}} {{.Open}} {{.Low}} {{.High}} {{.Low52}} {{.High52}} {{.Volume}} {{.AvgVolume}} {{.PeRatio}} {{.Dividend}} {{.Yield}} {{.MarketCap}} {{end}}...` template, err := template.New("screen").Parse(markup) @@ -43,41 +44,67 @@ Ticker Last trade Change % Change Dividend Yield return buffer.String() } -func color(m Message) string { - return "x" +func header() string { + str := fmt.Sprintf("%-7s ", "Ticker") + str += fmt.Sprintf("%9s ", "Last") + str += fmt.Sprintf("%9s ", "Change") + str += fmt.Sprintf("%9s ", "%Change") + str += fmt.Sprintf("%9s ", "Open") + str += fmt.Sprintf("%9s ", "Low") + str += fmt.Sprintf("%9s ", "High") + str += fmt.Sprintf("%9s ", "52w Low") + str += fmt.Sprintf("%9s ", "52w High") + str += fmt.Sprintf("%10s ", "Volume") + str += fmt.Sprintf("%10s ", "AvgVolume") + str += fmt.Sprintf("%9s ", "P/E") + str += fmt.Sprintf("%9s ", "Dividend") + str += fmt.Sprintf("%9s ", "Yield") + str += fmt.Sprintf("%10s", "MktCap") + + return str } -func prettify(message []Message) []Message { - pretty := make([]Message, len(message)) - for i, m := range message { - pretty[i].Ticker = pad(m.Ticker, -10) - pretty[i].LastTrade = pad(with_currency(m.LastTrade), 10) - pretty[i].CurrentPrice = pad(with_currency(m.CurrentPrice), 10) - pretty[i].Change = pad(with_currency(m.Change), 10) - pretty[i].ChangePercent = pad(with_percent(m.ChangePercent), 10) - // ExLastTrade string `json:"el"` - // ExCurrentPrice string `json:"el_cur"` - // ExLastTradeDateTime string `json:"elt"` - // ExChange string `json:"ec"` - // ExChangePercentage string `json:"ecp"` - pretty[i].Dividend = pad(with_currency(nullify(m.Dividend)), 10) - pretty[i].Yield = pad(with_currency(nullify(m.Yield)), 10) +func prettify(quotes Quotes) Quotes { + pretty := make(Quotes, len(quotes)) + for i, q := range quotes { + pretty[i].Ticker = pad(q.Ticker, -7) + pretty[i].LastTrade = pad(with_currency(q.LastTrade), 9) + pretty[i].Change = pad(with_currency(q.Change), 9) + pretty[i].ChangePercent = pad(last_of_pair(q.ChangePercent), 9) + pretty[i].Open = pad(with_currency(q.Open), 9) + pretty[i].Low = pad(with_currency(q.Low), 9) + pretty[i].High = pad(with_currency(q.High), 9) + pretty[i].Low52 = pad(with_currency(q.Low52), 9) + pretty[i].High52 = pad(with_currency(q.High52), 9) + pretty[i].Volume = pad(q.Volume, 10) + pretty[i].AvgVolume = pad(q.AvgVolume, 10) + pretty[i].PeRatio = pad(nullify(q.PeRatioX), 9) + pretty[i].Dividend = pad(with_currency(q.Dividend), 9) + pretty[i].Yield = pad(with_percent(q.Yield), 9) + pretty[i].MarketCap = pad(with_currency(q.MarketCapX), 10) } - // fmt.Printf("%q", pretty) return pretty } func nullify(str string) string { - if len(str) > 0 { + if len(str) == 3 && str[0:3] == "N/A" { + return "-" + } else { + return str + } +} + +func last_of_pair(str string) string { + if len(str) >= 6 && str[0:6] != "N/A - " { return str - } else { - return "-" - } + } else { + return str[6:] + } } func with_currency(str string) string { - if str == "-" { - return str + if str == "N/A" || str == "0.00" { + return "-" } else { switch str[0:1] { case "+", "-": @@ -89,18 +116,16 @@ func with_currency(str string) string { } func with_percent(str string) string { - if str == "-" { - return str - } else if str[0:1] != "-" { - return "+" + str + "%" + if str == "N/A" { + return "-" } else { return str + "%" } } func colorize(str string) string { - if str == "-" { - return str + if str == "N/A" { + return "-" } else if str[0:1] == "-" { return "" + str + "" } else { @@ -117,5 +142,14 @@ func ticker(str string, change string) string { } func pad(str string, width int) string { + re := regexp.MustCompile(`(\.\d+)[MB]?$`) + match := re.FindStringSubmatch(str) + if len(match) > 0 { + switch len(match[1]) { + case 2: str = strings.Replace(str, match[1], match[1] + "0", 1) + case 4, 5: str = strings.Replace(str, match[1], match[1][0:3], 1) + } + } + return fmt.Sprintf("%*s", width, str) } diff --git a/lib/profile.go b/lib/profile.go index d543f26..56fd3df 100644 --- a/lib/profile.go +++ b/lib/profile.go @@ -4,5 +4,5 @@ package mop //----------------------------------------------------------------------------- func LoadProfile() string { - return "AAPL+ATVI+C+COH+GOOG+HPQ+IBM+MA+TSLA+V+YHOO+ININ+CRM+SAAS" + return "AAPL+ALU+ATVI+C+COH+GOOG+HPQ+IBM+MA+TSLA+V+YHOO+ININ+CRM+SAAS" } diff --git a/lib/screen.go b/lib/screen.go index 0d50ff2..c1e3540 100644 --- a/lib/screen.go +++ b/lib/screen.go @@ -29,14 +29,14 @@ var tags = map[string]termbox.Attribute{ //----------------------------------------------------------------------------- func Draw(stocks string) { - message := Get(stocks) + quotes := Get(stocks) // for _, m := range message { // fmt.Printf("%s, %s, %s\n", m.Ticker, m.LastTrade, m.Change) // } // fmt.Printf("%s\n", Format(message)) - drawScreen(message.Format()) + drawScreen(Format(quotes)) } // diff --git a/lib/yahoo_finance.go b/lib/yahoo_finance.go index 4340fcb..5333210 100644 --- a/lib/yahoo_finance.go +++ b/lib/yahoo_finance.go @@ -6,6 +6,7 @@ import ( "fmt" "time" "bytes" + "strings" "net/http" "io/ioutil" // "strings" @@ -13,7 +14,7 @@ import ( // See http://www.gummy-stuff.org/Yahoo-data.htm // Current, Change, Open, High, Low, 52-W High, 52-W Low, Volume, AvgVolume, P/E, Yield, Market Cap. -// b2: ask rt +// l1: last trade // c6: change rt // k2: change % rt // o: open @@ -25,33 +26,36 @@ import ( // a2: avg volume // r2: p/e rt // r: p/e +// d: dividend/share // y: wield // j3: market cap rt // j1: market cap -const yahoo_finance_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,b2c6k2oghjkva2r2ryj3j1` +const yahoo_finance_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,l1c6k2oghjkva2r2rdyj3j1` -// "AAPL", 602.93, "+2.31", "N/A - +0.55%", 420.95, 417.45, 422.98, 385.10, 705.07, 8604594, 15205700, N/A, 9.99, 2.63, N/A, 395.0B -// "GOOG", 0.00, "+4.12", "N/A - +0.47%", 879.90, 878.50, 889.17, 562.09, 920.60, 1048628, 2353530, N/A, 26.40, N/A, N/A, 294.1B -// "PG", 94.58, "+0.13", "N/A - +0.17%", 78.28, 77.4301, 78.75, 60.86, 82.54, 5347846, 9929320, N/A, 17.58, 2.92, N/A, 215.3B +// "AAPL", 417.42, "-3.38", "N/A - -0.80%", 420.33, 415.35, 423.29, 385.10, 705.07, 9788680, 15181900, N/A, 10.04, 11.00, 2.61, N/A, 391.8B +// "ALU", 1.83, "+0.07", "N/A - +3.98%", 1.77, 1.75, 1.83, 0.91, 2.01, 7957103, 11640700, N/A, N/A, 0.00, N/A, N/A, 4.156B +// "IBM", 194.93, "+1.68", "N/A - +0.87%", 192.83, 192.3501, 195.16, 181.85, 215.90, 2407971, 4376120, N/A, 13.33, 3.50, 1.81, N/A, 216.1B +// "TSLA", 120.09, "+4.85", "N/A - +4.21%", 118.75, 115.70, 120.28, 25.52, 121.89, 6827497, 9464530, N/A, N/A, 0.00, N/A, N/A, 13.877B type Quote struct { - Ticker []byte - Ask []byte - Change []byte - ChangePercent []byte - Open []byte - Low []byte - High []byte - Low52 []byte - High52 []byte - Volume []byte - AvgVolume []byte - PeRatio []byte - PeRatioX []byte - Yield []byte - MarketCap []byte - MarketCapX []byte + Ticker string + LastTrade string + Change string + ChangePercent string + Open string + Low string + High string + Low52 string + High52 string + Volume string + AvgVolume string + PeRatio string + PeRatioX string + Dividend string + Yield string + MarketCap string + MarketCapX string } type Quotes []Quote @@ -74,7 +78,6 @@ func Get(tickers string) Quotes { // Fetch response and get its body. defer response.Body.Close() body, err := ioutil.ReadAll(response.Body) - fmt.Println("\n\n\n\n\n\rFetched quotes: " + time.Now().Format("3:04:05pm PST")) if err != nil { panic(err) } @@ -83,13 +86,19 @@ func Get(tickers string) Quotes { return quotes } +func (q *Quote) Color() string { + if strings.Index(q.Change, "-") == -1 { + return "" + } else { + return "" // "" + } +} + func sanitize(body []byte) []byte { return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1) } -// "AAPL", 602.93, "+2.31", "N/A - +0.55%", 420.95, 417.45, 422.98, 385.10, 705.07, 8604594, 15205700, N/A, 9.99, 2.63, N/A, 395.0B func parse(body []byte) Quotes { - // fmt.Printf("[%s]\n", body) lines := bytes.Split(body, []byte{'\n'}) quotes := make(Quotes, len(lines)) @@ -102,36 +111,35 @@ func parse(body []byte) Quotes { } func parse_line(line []byte, quote *Quote) { - // var quote Quote - columns := bytes.Split(line, []byte{','}) - // fmt.Printf("{%s} -> [%d]", string(line), len(columns)) + columns := bytes.Split(bytes.TrimSpace(line), []byte{','}) - quote.Ticker = columns[0] - quote.Ask = columns[1] - quote.Change = columns[2] - quote.ChangePercent = columns[3] - quote.Open = columns[4] - quote.Low = columns[5] - quote.High = columns[6] - quote.Low52 = columns[7] - quote.High52 = columns[8] - quote.Volume = columns[9] - quote.AvgVolume = columns[10] - quote.PeRatio = columns[11] - quote.PeRatioX = columns[12] - quote.Yield = columns[13] - quote.MarketCap = columns[14] - quote.MarketCapX = columns[15] + quote.Ticker = string(columns[0]) + quote.LastTrade = string(columns[1]) + quote.Change = string(columns[2]) + quote.ChangePercent = string(columns[3]) + quote.Open = string(columns[4]) + quote.Low = string(columns[5]) + quote.High = string(columns[6]) + quote.Low52 = string(columns[7]) + quote.High52 = string(columns[8]) + quote.Volume = string(columns[9]) + quote.AvgVolume = string(columns[10]) + quote.PeRatio = string(columns[11]) + quote.PeRatioX = string(columns[12]) + quote.Dividend = string(columns[13]) + quote.Yield = string(columns[14]) + quote.MarketCap = string(columns[15]) + quote.MarketCapX = string(columns[16]) } -func (quotes Quotes) Format() string { - str := time.Now().Format("3:04:05pm PST\n") - - for _, q := range quotes { - str += fmt.Sprintf("%s - %s - %s - %s\n", q.Ticker, q.Ask, q.Change, q.ChangePercent) - } - return str -} +// func (quotes Quotes) Format() string { +// str := time.Now().Format("3:04:05pm PST\n") +// +// for _, q := range quotes { +// str += fmt.Sprintf("%s - %s - %s - %s\n", q.Ticker, q.Ask, q.Change, q.ChangePercent) +// } +// return str +// } // // http://query.yahooapis.com/v1/public/yql