Column sorting

master
Michael Dvorkin 11 years ago
parent 4d4ed17228
commit e0b8453680
  1. 122
      lib/layout.go
  2. 91
      lib/sorter.go
  3. 7
      lib/yahoo_market.go
  4. 70
      lib/yahoo_quotes.go

@ -8,6 +8,7 @@ import (
`regexp`
`strings`
`text/template`
`sort`
`time`
)
@ -24,23 +25,23 @@ type Layout struct {
//-----------------------------------------------------------------------------
func (self *Layout) Initialize() *Layout {
self.columns = make([]Column, TotalColumns)
self.columns[0] = Column{ -7, `Ticker`}
self.columns[1] = Column{ 10, `Last`}
self.columns[2] = Column{ 10, `Change`}
self.columns[3] = Column{ 10, `%Change`}
self.columns[4] = Column{ 10, `Open`}
self.columns[5] = Column{ 10, `Low`}
self.columns[6] = Column{ 10, `High`}
self.columns[7] = Column{ 10, `52w Low`}
self.columns[8] = Column{ 10, `52w High`}
self.columns[9] = Column{ 11, `Volume`}
self.columns[10] = Column{ 11, `AvgVolume`}
self.columns[11] = Column{ 10, `P/E`}
self.columns[12] = Column{ 10, `Dividend`}
self.columns[13] = Column{ 10, `Yield`}
self.columns[14] = Column{ 11, `MktCap`}
self.columns = []Column{
{ -7, `Ticker`},
{ 10, `Last`},
{ 10, `Change`},
{ 10, `%Change`},
{ 10, `Open`},
{ 10, `Low`},
{ 10, `High`},
{ 10, `52w Low`},
{ 10, `52w High`},
{ 11, `Volume`},
{ 11, `AvgVolume`},
{ 10, `P/E`},
{ 10, `Dividend`},
{ 10, `Yield`},
{ 11, `MktCap`},
}
return self
}
@ -68,7 +69,7 @@ func (self *Layout) Market(m *Market) string {
markup += "\n"
markup += `{{.Advances.name}}: {{.Advances.nyse}} ({{.Advances.nysep}}) on NYSE and {{.Advances.nasdaq}} ({{.Advances.nasdaqp}}) on Nasdaq. `
markup += `{{.Declines.name}}: {{.Declines.nyse}} ({{.Declines.nysep}}) on NYSE and {{.Declines.nasdaq}} ({{.Declines.nasdaqp}}) on Nasdaq`
if !m.Open {
if m.IsClosed {
markup += `<right>U.S. markets closed</right>`
}
markup += "\n"
@ -105,7 +106,7 @@ func (self *Layout) Quotes(quotes *Quotes) string {
{{.Header}}
{{range.Stocks}}{{.Color}}{{.Ticker}}{{.LastTrade}}{{.Change}}{{.ChangePercent}}{{.Open}}{{.Low}}{{.High}}{{.Low52}}{{.High52}}{{.Volume}}{{.AvgVolume}}{{.PeRatio}}{{.Dividend}}{{.Yield}}{{.MarketCap}}
{{range.Stocks}}{{.Color}}{{.Ticker}}{{.LastTrade}}{{.Change}}{{.ChangePct}}{{.Open}}{{.Low}}{{.High}}{{.Low52}}{{.High52}}{{.Volume}}{{.AvgVolume}}{{.PeRatio}}{{.Dividend}}{{.Yield}}{{.MarketCap}}
{{end}}`
//markup += fmt.Sprintf("[%v]", quotes.profile.Grouped)
template, err := template.New(`quotes`).Parse(markup)
@ -140,24 +141,71 @@ func (self *Layout) Header(profile *Profile) string {
//-----------------------------------------------------------------------------
func (self *Layout) prettify(quotes *Quotes) []Stock {
var sorts []sort.Interface
pretty := make([]Stock, len(quotes.stocks))
for i, q := range group(quotes) {
pretty[i].Ticker = pad(q.Ticker, self.columns[0].width)
pretty[i].LastTrade = pad(with_currency(q.LastTrade), self.columns[1].width)
pretty[i].Change = pad(with_currency(q.Change), self.columns[2].width)
pretty[i].ChangePercent = pad(last_of_pair(q.ChangePercent), self.columns[3].width)
pretty[i].Open = pad(with_currency(q.Open), self.columns[4].width)
pretty[i].Low = pad(with_currency(q.Low), self.columns[5].width)
pretty[i].High = pad(with_currency(q.High), self.columns[6].width)
pretty[i].Low52 = pad(with_currency(q.Low52), self.columns[7].width)
pretty[i].High52 = pad(with_currency(q.High52), self.columns[8].width)
pretty[i].Volume = pad(q.Volume, self.columns[9].width)
pretty[i].AvgVolume = pad(q.AvgVolume, self.columns[10].width)
pretty[i].PeRatio = pad(nullify(q.PeRatioX), self.columns[11].width)
pretty[i].Dividend = pad(with_currency(q.Dividend), self.columns[12].width)
pretty[i].Yield = pad(with_percent(q.Yield), self.columns[13].width)
pretty[i].MarketCap = pad(with_currency(q.MarketCapX), self.columns[14].width)
//for i, q := range group(quotes) {
for i, q := range quotes.stocks {
pretty[i].Ticker = pad(q.Ticker, self.columns[0].width)
pretty[i].LastTrade = pad(with_currency(q.LastTrade), self.columns[1].width)
pretty[i].Change = pad(with_currency(q.Change), self.columns[2].width)
pretty[i].ChangePct = pad(last_of_pair(q.ChangePct), self.columns[3].width)
pretty[i].Open = pad(with_currency(q.Open), self.columns[4].width)
pretty[i].Low = pad(with_currency(q.Low), self.columns[5].width)
pretty[i].High = pad(with_currency(q.High), self.columns[6].width)
pretty[i].Low52 = pad(with_currency(q.Low52), self.columns[7].width)
pretty[i].High52 = pad(with_currency(q.High52), self.columns[8].width)
pretty[i].Volume = pad(q.Volume, self.columns[9].width)
pretty[i].AvgVolume = pad(q.AvgVolume, self.columns[10].width)
pretty[i].PeRatio = pad(nullify(q.PeRatioX), self.columns[11].width)
pretty[i].Dividend = pad(with_currency(q.Dividend), self.columns[12].width)
pretty[i].Yield = pad(with_percent(q.Yield), self.columns[13].width)
pretty[i].MarketCap = pad(with_currency(q.MarketCapX), self.columns[14].width)
}
if quotes.profile.Ascending {
sorts = []sort.Interface{
ByTickerAsc { pretty },
ByLastTradeAsc { pretty },
ByChangeAsc { pretty },
ByChangePctAsc { pretty },
ByOpenAsc { pretty },
ByLowAsc { pretty },
ByHighAsc { pretty },
ByLow52Asc { pretty },
ByHigh52Asc { pretty },
ByVolumeAsc { pretty },
ByAvgVolumeAsc { pretty },
ByPeRatioAsc { pretty },
//ByPeRatioXAsc { pretty },
ByDividendAsc { pretty },
ByYieldAsc { pretty },
ByMarketCapAsc { pretty },
//ByMarketCapXAsc { pretty },
}
} else {
sorts = []sort.Interface{
ByTickerDesc { pretty },
ByLastTradeDesc { pretty },
ByChangeDesc { pretty },
ByChangePctDesc { pretty },
ByOpenDesc { pretty },
ByLowDesc { pretty },
ByHighDesc { pretty },
ByLow52Desc { pretty },
ByHigh52Desc { pretty },
ByVolumeDesc { pretty },
ByAvgVolumeDesc { pretty },
ByPeRatioDesc { pretty },
//ByPeRatioXDesc { pretty },
ByDividendDesc { pretty },
ByYieldDesc { pretty },
ByMarketCapDesc { pretty },
//ByMarketCapXDesc { pretty },
}
}
sort.Sort(sorts[quotes.profile.SortColumn])
return pretty
}
@ -188,9 +236,9 @@ func group(quotes *Quotes) []Stock {
func arrow_for(column int, profile *Profile) string {
if column == profile.SortColumn {
if profile.Ascending {
return string('\U00002193')
} else {
return string('\U00002191')
} else {
return string('\U00002193')
}
}
return ``

@ -0,0 +1,91 @@
// Copyright (c) 2013 by Michael Dvorkin. All Rights Reserved.
//=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
package mop
import (
`strings`
`strconv`
)
type Sortable []Stock
func (list Sortable) Len() int { return len(list) }
func (list Sortable) Swap(i, j int) { list[i], list[j] = list[j], list[i] }
type ByTickerAsc struct { Sortable }
type ByLastTradeAsc struct { Sortable }
type ByChangeAsc struct { Sortable }
type ByChangePctAsc struct { Sortable }
type ByOpenAsc struct { Sortable }
type ByLowAsc struct { Sortable }
type ByHighAsc struct { Sortable }
type ByLow52Asc struct { Sortable }
type ByHigh52Asc struct { Sortable }
type ByVolumeAsc struct { Sortable }
type ByAvgVolumeAsc struct { Sortable }
type ByPeRatioAsc struct { Sortable }
type ByPeRatioXAsc struct { Sortable }
type ByDividendAsc struct { Sortable }
type ByYieldAsc struct { Sortable }
type ByMarketCapAsc struct { Sortable }
type ByMarketCapXAsc struct { Sortable }
type ByTickerDesc struct { Sortable }
type ByLastTradeDesc struct { Sortable }
type ByChangeDesc struct { Sortable }
type ByChangePctDesc struct { Sortable }
type ByOpenDesc struct { Sortable }
type ByLowDesc struct { Sortable }
type ByHighDesc struct { Sortable }
type ByLow52Desc struct { Sortable }
type ByHigh52Desc struct { Sortable }
type ByVolumeDesc struct { Sortable }
type ByAvgVolumeDesc struct { Sortable }
type ByPeRatioDesc struct { Sortable }
type ByPeRatioXDesc struct { Sortable }
type ByDividendDesc struct { Sortable }
type ByYieldDesc struct { Sortable }
type ByMarketCapDesc struct { Sortable }
type ByMarketCapXDesc struct { Sortable }
func (list ByTickerAsc) Less(i, j int) bool { return list.Sortable[i].Ticker < list.Sortable[j].Ticker }
func (list ByLastTradeAsc) Less(i, j int) bool { return list.Sortable[i].LastTrade < list.Sortable[j].LastTrade }
func (list ByChangeAsc) Less(i, j int) bool { return z(list.Sortable[i].Change) < z(list.Sortable[j].Change) }
func (list ByChangePctAsc) Less(i, j int) bool { return z(list.Sortable[i].ChangePct) < z(list.Sortable[j].ChangePct) }
func (list ByOpenAsc) Less(i, j int) bool { return list.Sortable[i].Open < list.Sortable[j].Open }
func (list ByLowAsc) Less(i, j int) bool { return list.Sortable[i].Low < list.Sortable[j].Low }
func (list ByHighAsc) Less(i, j int) bool { return list.Sortable[i].High < list.Sortable[j].High }
func (list ByLow52Asc) Less(i, j int) bool { return list.Sortable[i].Low52 < list.Sortable[j].Low52 }
func (list ByHigh52Asc) Less(i, j int) bool { return list.Sortable[i].High52 < list.Sortable[j].High52 }
func (list ByVolumeAsc) Less(i, j int) bool { return list.Sortable[i].Volume < list.Sortable[j].Volume }
func (list ByAvgVolumeAsc) Less(i, j int) bool { return list.Sortable[i].AvgVolume < list.Sortable[j].AvgVolume }
func (list ByPeRatioAsc) Less(i, j int) bool { return list.Sortable[i].PeRatio < list.Sortable[j].PeRatio }
func (list ByPeRatioXAsc) Less(i, j int) bool { return list.Sortable[i].PeRatioX < list.Sortable[j].PeRatioX }
func (list ByDividendAsc) Less(i, j int) bool { return list.Sortable[i].Dividend < list.Sortable[j].Dividend }
func (list ByYieldAsc) Less(i, j int) bool { return list.Sortable[i].Yield < list.Sortable[j].Yield }
func (list ByMarketCapAsc) Less(i, j int) bool { return list.Sortable[i].MarketCap < list.Sortable[j].MarketCap }
func (list ByMarketCapXAsc) Less(i, j int) bool { return list.Sortable[i].MarketCapX < list.Sortable[j].MarketCapX }
func (list ByTickerDesc) Less(i, j int) bool { return list.Sortable[j].Ticker < list.Sortable[i].Ticker }
func (list ByLastTradeDesc) Less(i, j int) bool { return list.Sortable[j].LastTrade < list.Sortable[i].LastTrade }
func (list ByChangeDesc) Less(i, j int) bool { return z(list.Sortable[j].Change) < z(list.Sortable[i].Change) }
func (list ByChangePctDesc) Less(i, j int) bool { return z(list.Sortable[j].ChangePct) < z(list.Sortable[i].ChangePct) }
func (list ByOpenDesc) Less(i, j int) bool { return list.Sortable[j].Open < list.Sortable[i].Open }
func (list ByLowDesc) Less(i, j int) bool { return list.Sortable[j].Low < list.Sortable[i].Low }
func (list ByHighDesc) Less(i, j int) bool { return list.Sortable[j].High < list.Sortable[i].High }
func (list ByLow52Desc) Less(i, j int) bool { return list.Sortable[j].Low52 < list.Sortable[i].Low52 }
func (list ByHigh52Desc) Less(i, j int) bool { return list.Sortable[j].High52 < list.Sortable[i].High52 }
func (list ByVolumeDesc) Less(i, j int) bool { return list.Sortable[j].Volume < list.Sortable[i].Volume }
func (list ByAvgVolumeDesc) Less(i, j int) bool { return list.Sortable[j].AvgVolume < list.Sortable[i].AvgVolume }
func (list ByPeRatioDesc) Less(i, j int) bool { return list.Sortable[j].PeRatio < list.Sortable[i].PeRatio }
func (list ByPeRatioXDesc) Less(i, j int) bool { return list.Sortable[j].PeRatioX < list.Sortable[i].PeRatioX }
func (list ByDividendDesc) Less(i, j int) bool { return list.Sortable[j].Dividend < list.Sortable[i].Dividend }
func (list ByYieldDesc) Less(i, j int) bool { return list.Sortable[j].Yield < list.Sortable[i].Yield }
func (list ByMarketCapDesc) Less(i, j int) bool { return list.Sortable[j].MarketCap < list.Sortable[i].MarketCap }
func (list ByMarketCapXDesc) Less(i, j int) bool { return list.Sortable[j].MarketCapX < list.Sortable[i].MarketCapX }
func z(str string) float32 {
float := strings.Replace(strings.Trim(str, ` %`), `$`, ``, 1)
value,_ := strconv.ParseFloat(float, 32)
return float32(value)
}

@ -11,7 +11,7 @@ import (
)
type Market struct {
Open bool
IsClosed bool
Dow map[string]string
Nasdaq map[string]string
Sp500 map[string]string
@ -24,7 +24,7 @@ type Market struct {
//-----------------------------------------------------------------------------
func (self *Market) Initialize() *Market {
self.Open = true
self.IsClosed = false
self.Dow = make(map[string]string)
self.Nasdaq = make(map[string]string)
self.Sp500 = make(map[string]string)
@ -65,7 +65,8 @@ func (self *Market) Format() string {
func (self *Market) check_if_market_open(body []byte) []byte {
start := bytes.Index(body, []byte(`id="yfs_market_time"`))
finish := start + bytes.Index(body[start:], []byte(`</span>`))
self.Open = !bytes.Contains(body[start:finish], []byte(`closed`))
snippet := body[start:finish]
self.IsClosed = bytes.Contains(snippet, []byte(`closed`)) || bytes.Contains(snippet, []byte(`open in`))
return body[finish:]
}

@ -37,23 +37,23 @@ import (
const yahoo_quotes_url = `http://download.finance.yahoo.com/d/quotes.csv?s=%s&f=,l1c6k2oghjkva2r2rdyj3j1`
type Stock struct {
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
Ticker string
LastTrade string
Change string
ChangePct 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 struct {
@ -72,7 +72,7 @@ func (self *Quotes) Initialize(market *Market, profile *Profile) *Quotes {
//-----------------------------------------------------------------------------
func (self *Quotes) Fetch() *Quotes {
if self.market.Open || self.stocks == nil {
if !self.market.IsClosed || self.stocks == nil {
// Format the URL and send the request.
url := fmt.Sprintf(yahoo_quotes_url, self.profile.ListOfTickers())
response, err := http.Get(url)
@ -121,23 +121,23 @@ func (self *Quotes) parse(body []byte) *Quotes {
for i, line := range lines {
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])
self.stocks[i].Ticker = string(columns[0])
self.stocks[i].LastTrade = string(columns[1])
self.stocks[i].Change = string(columns[2])
self.stocks[i].ChangePct = 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 self

Loading…
Cancel
Save