Refactored quotes

master
Michael Dvorkin 12 years ago
parent fd46f19683
commit cef05232a6
  1. 21
      lib/format.go
  2. 18
      lib/line_editor.go
  3. 2
      lib/profile.go
  4. 7
      lib/screen.go
  5. 97
      lib/yahoo_quotes.go
  6. 13
      mop.go

@ -52,15 +52,15 @@ func FormatMarket(m *Market) string {
}
//-----------------------------------------------------------------------------
func FormatQuotes(quotes Quotes) string {
func FormatQuotes(q *Quotes) string {
vars := struct {
Now string
Header string
Stocks Quotes
Stocks []Stock
}{
time.Now().Format(`3:04:05pm PST`),
header(),
prettify(quotes),
prettify(q.stocks),
}
markup := `<right><white>{{.Now}}</white></right>
@ -85,6 +85,7 @@ func FormatQuotes(quotes Quotes) string {
return buffer.String()
}
//-----------------------------------------------------------------------------
func header() string {
str := fmt.Sprintf(`<u>%-7s `, `Ticker`)
str += fmt.Sprintf(`%9s `, `Last`)
@ -105,9 +106,10 @@ func header() string {
return str
}
func prettify(quotes Quotes) Quotes {
pretty := make(Quotes, len(quotes))
for i, q := range quotes {
//-----------------------------------------------------------------------------
func prettify(stocks []Stock) []Stock {
pretty := make([]Stock, len(stocks))
for i, q := range stocks {
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)
@ -127,6 +129,7 @@ func prettify(quotes Quotes) Quotes {
return pretty
}
//-----------------------------------------------------------------------------
func nullify(str string) string {
if len(str) == 3 && str[0:3] == `N/A` {
return `-`
@ -135,6 +138,7 @@ func nullify(str string) string {
}
}
//-----------------------------------------------------------------------------
func last_of_pair(str string) string {
if len(str) >= 6 && str[0:6] != `N/A - ` {
return str
@ -143,6 +147,7 @@ func last_of_pair(str string) string {
}
}
//-----------------------------------------------------------------------------
func with_currency(str string) string {
if str == `N/A` || str == `0.00` {
return `-`
@ -156,6 +161,7 @@ func with_currency(str string) string {
}
}
//-----------------------------------------------------------------------------
func with_percent(str string) string {
if str == `N/A` {
return `-`
@ -164,6 +170,7 @@ func with_percent(str string) string {
}
}
//-----------------------------------------------------------------------------
func colorize(str string) string {
if str == `N/A` {
return `-`
@ -174,6 +181,7 @@ func colorize(str string) string {
}
}
//-----------------------------------------------------------------------------
func ticker(str string, change string) string {
if change[0:1] == `-` {
return `<red>` + str + `</red>`
@ -182,6 +190,7 @@ func ticker(str string, change string) string {
}
}
//-----------------------------------------------------------------------------
func pad(str string, width int) string {
re := regexp.MustCompile(`(\.\d+)[MB]?$`)
match := re.FindStringSubmatch(str)

@ -14,13 +14,13 @@ type LineEditor struct {
cursor int
input string
screen *Screen
profile *Profile
quotes *Quotes
}
//-----------------------------------------------------------------------------
func (self *LineEditor) Initialize(screen *Screen, profile *Profile) *LineEditor {
func (self *LineEditor) Initialize(screen *Screen, quotes *Quotes) *LineEditor {
self.screen = screen
self.profile = profile
self.quotes = quotes
return self
}
@ -147,17 +147,17 @@ func (self *LineEditor) execute() {
case '+':
tickers := self.tokenize()
if len(tickers) > 0 {
self.profile.AddTickers(tickers)
self.screen.DrawQuotes(self.profile.Quotes())
self.quotes.profile.AddTickers(tickers)
self.screen.DrawQuotes(self.quotes)
}
case '-':
tickers := self.tokenize()
if len(tickers) > 0 {
before := len(self.profile.Tickers)
self.profile.RemoveTickers(tickers)
after := len(self.profile.Tickers)
before := len(self.quotes.profile.Tickers)
self.quotes.profile.RemoveTickers(tickers)
after := len(self.quotes.profile.Tickers)
if after < before {
self.screen.DrawQuotes(self.profile.Quotes())
self.screen.DrawQuotes(self.quotes)
for i := before; i > after; i-- {
self.screen.ClearLine(0, i + 4)
}

@ -47,7 +47,7 @@ func (self *Profile) Save() error {
}
//-----------------------------------------------------------------------------
func (self *Profile) Quotes() string {
func (self *Profile) ListOfTickers() string {
return strings.Join(self.Tickers, `+`)
}

@ -60,13 +60,12 @@ func (self *Screen) Close() {
//-----------------------------------------------------------------------------
func (self *Screen) DrawMarket(market *Market) {
self.draw(FormatMarket(market))
self.draw(FormatMarket(market.Fetch()))
}
//-----------------------------------------------------------------------------
func (self *Screen) DrawQuotes(stocks string) {
quotes := GetQuotes(stocks)
self.draw(FormatQuotes(quotes))
func (self *Screen) DrawQuotes(quotes *Quotes) {
self.draw(FormatQuotes(quotes.Fetch()))
}
//-----------------------------------------------------------------------------

@ -10,10 +10,10 @@ import (
`strings`
)
// See http://www.gummy-stuff.org/Yahoo-data.htm
// See http://www.gummy-stuff.org/Yahoo-stocks.htm
// Also http://query.yahooapis.com/v1/public/yql
// ?q=select%20*%20from%20yahoo.finance.quotes%20where%20symbol%20in(%22ALU%22,%22AAPL%22)
// &env=http%3A%2F%2Fdatatables.org%2Falltables.env
// &env=http%3A%2F%2Fstockstables.org%2Falltables.env
// &format=json'
//
// Current, Change, Open, High, Low, 52-W High, 52-W Low, Volume, AvgVolume, P/E, Yield, Market Cap.
@ -36,7 +36,7 @@ import (
const yahoo_quotes_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,l1c6k2oghjkva2r2rdyj3j1`
type Quote struct {
type Stock struct {
Ticker string
LastTrade string
Change string
@ -55,12 +55,26 @@ type Quote struct {
MarketCap string
MarketCapX string
}
type Quotes []Quote
func GetQuotes(tickers string) Quotes {
type Quotes struct {
market *Market
profile *Profile
stocks []Stock
}
//-----------------------------------------------------------------------------
func (self *Quotes) Initialize(market *Market, profile *Profile) *Quotes {
self.market = market
self.profile = profile
return self
}
//-----------------------------------------------------------------------------
func (self *Quotes) Fetch() *Quotes {
// Format the URL and send the request.
url := fmt.Sprintf(yahoo_quotes_url, tickers)
url := fmt.Sprintf(yahoo_quotes_url, self.profile.ListOfTickers())
response, err := http.Get(url)
if err != nil {
panic(err)
@ -73,51 +87,48 @@ func GetQuotes(tickers string) Quotes {
panic(err)
}
return parse(sanitize(body))
}
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)
return self.parse(self.sanitize(body))
}
func parse(body []byte) Quotes {
//-----------------------------------------------------------------------------
func (self *Quotes) parse(body []byte) *Quotes {
lines := bytes.Split(body, []byte{'\n'})
quotes := make(Quotes, len(lines))
self.stocks = make([]Stock, len(lines))
for i, line := range lines {
// fmt.Printf("\n\n{%d} -> [%s]\n\n", i, string(line))
parse_line(line, &quotes[i])
columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
self.stocks[i].Ticker = string(columns[0])
self.stocks[i].LastTrade = string(columns[1])
self.stocks[i].Change = string(columns[2])
self.stocks[i].ChangePercent = string(columns[3])
self.stocks[i].Open = string(columns[4])
self.stocks[i].Low = string(columns[5])
self.stocks[i].High = string(columns[6])
self.stocks[i].Low52 = string(columns[7])
self.stocks[i].High52 = string(columns[8])
self.stocks[i].Volume = string(columns[9])
self.stocks[i].AvgVolume = string(columns[10])
self.stocks[i].PeRatio = string(columns[11])
self.stocks[i].PeRatioX = string(columns[12])
self.stocks[i].Dividend = string(columns[13])
self.stocks[i].Yield = string(columns[14])
self.stocks[i].MarketCap = string(columns[15])
self.stocks[i].MarketCapX = string(columns[16])
}
return quotes
return self
}
func parse_line(line []byte, quote *Quote) {
columns := bytes.Split(bytes.TrimSpace(line), []byte{','})
//-----------------------------------------------------------------------------
func (self *Quotes) sanitize(body []byte) []byte {
return bytes.Replace(bytes.TrimSpace(body), []byte{'"'}, []byte{}, -1)
}
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 (stock *Stock) Color() string {
if strings.Index(stock.Change, "-") == -1 {
return `</green><green>`
} else {
return `` // `</red><red>`
}
}

@ -23,9 +23,10 @@ func mainLoop(screen *mop.Screen, profile *mop.Profile) {
}()
market := new(mop.Market).Initialize().Fetch()
quotes := new(mop.Quotes).Initialize(market, profile)
screen.Clear()
screen.DrawMarket(market)
screen.DrawQuotes(profile.Quotes())
screen.DrawQuotes(quotes)
loop:
for {
@ -37,7 +38,7 @@ loop:
if event.Key == termbox.KeyEsc {
break loop
} else if event.Ch == '+' || event.Ch == '-' {
line_editor = new(mop.LineEditor).Initialize(screen, profile)
line_editor = new(mop.LineEditor).Initialize(screen, quotes)
line_editor.Prompt(event.Ch)
}
} else {
@ -48,18 +49,18 @@ loop:
}
case termbox.EventResize:
screen.Resize().Clear()
screen.DrawMarket(market.Fetch())
screen.DrawQuotes(profile.Quotes())
screen.DrawMarket(market)
screen.DrawQuotes(quotes)
}
case <-timestamp_queue.C:
screen.DrawTime()
case <-quotes_queue.C:
screen.DrawQuotes(profile.Quotes())
screen.DrawQuotes(quotes)
case <-market_queue.C:
screen.DrawMarket(market.Fetch())
screen.DrawMarket(market)
}
}
}

Loading…
Cancel
Save