Formatting stock data fetched from Yahoo

master
Michael Dvorkin 12 years ago
parent dd91d958d4
commit b498decc9c
  1. 112
      lib/format.go
  2. 2
      lib/profile.go
  3. 4
      lib/screen.go
  4. 110
      lib/yahoo_finance.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<right>{{.Now}}</right>
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 "<red>" + str + "</red>"
} 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)
}

@ -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"
}

@ -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))
}
//

@ -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 "</green><green>"
} else {
return "" // "</red><red>"
}
}
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

Loading…
Cancel
Save