Created
April 20, 2015 02:56
-
-
Save zhengwy888/63404185ba39fae9d254 to your computer and use it in GitHub Desktop.
To use run: > go run <script_name> <stock symbol> and it will display Price and Volume graph from the past year in your terminal
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// +build ignore | |
// Author: Weiyi Zheng, 2015 | |
/* learning termui and go language | |
To use run: > go run <script_name> <stock symbol> | |
and it will display Price and Volume info from last year in your terminal | |
things are lacking: | |
- two graphs can't be scaled to the same width | |
- no control over axis label | |
- be cautious running any termui stuff in chromebook's Secure Shell, it will freeze | |
Things I learned when coding this: | |
- With a typed language, it is easier to access elements inside a struct with accessor function, not Pluck (in Go's case, it's Reflect) | |
- Strict variable checking and module checking sometimes is a little annoying. By commenting out one line that consumes a variable, you will have to comment out the definition (if there is no other place that use this variable), and comments out the imports | |
- "go fmt" is nice to have, but don't run it too often as it slows you down | |
- I still don't know how to create an array using variable as size. From pointer perspective it makes sense. Just use append | |
- NewList is such a strange syntax. You have no way telling whether you are calling a plain function or creating a object by simply looking at the function name. | |
- what happened on January 2nd, 2006 at 3pm? why formatting a time requires me to remember this specific date? I rather remember one more person's birthday. | |
- var variable Int doesn't seemed to be needed in most use case. := is better. Though it increases the amount of documentation look up | |
- if you return an err object, you are forcing the caller to write some err handling code. Doesn't this lead to error handling everywhere? | |
*/ | |
package main | |
import ui "github.com/gizak/termui" | |
import "github.com/doneland/yquotes" | |
import "time" | |
import "reflect" | |
import "os" | |
import "fmt" | |
// from reflect package, two reasons not to use | |
// 1, unpresented key will croak | |
// 2. look up is slow comparing to use static name | |
// to check the interface, checkout documentation at | |
// https://github.com/doneland/yquotes/blob/master/yquotes.go | |
func Pluck(prices []yquotes.PriceH, key string) []float64 { | |
ps := []float64{} | |
for _, price := range prices { | |
reflected := reflect.ValueOf(price) | |
ps = append(ps, reflect.Indirect(reflected).FieldByName(key).Float()) | |
} | |
return ps | |
} | |
func FsToInts(data []float64) []int { | |
ps := []int{} | |
for _, v := range data { | |
ps = append(ps, int(v)) | |
} | |
return ps | |
} | |
func main() { | |
err := ui.Init() | |
sticker := os.Args[1] | |
if sticker == "" { | |
fmt.Printf("Please add your sticker symbol as the first argument") | |
os.Exit(1) | |
} | |
if err != nil { | |
panic(err) | |
} | |
defer ui.Close() | |
ui.UseTheme("helloworld") | |
//from,_ := time.Parse("2006-01-02", "2015-01-01") | |
//to := time.Now() | |
//prices, err := yquotes.GetDailyHistory("AAPL", from, to) | |
prices, err := yquotes.HistoryForYears(sticker, 1, yquotes.Daily) | |
if err != nil { | |
panic(err) | |
} | |
// reverse, how to use a function? | |
for i, j := 0, len(prices)-1; i < j; i, j = i+1, j-1 { | |
prices[i], prices[j] = prices[j], prices[i] | |
} | |
stock, err := yquotes.NewStock(sticker, true) | |
if err != nil { | |
panic(err) | |
} | |
// title and stock symbol | |
titlePar := ui.NewPar(fmt.Sprintf("Stock Price for %s - 1Y Daily (q to quit)", stock.Name)) | |
titlePar.Height = 1 | |
titlePar.Y = 1 | |
titlePar.HasBorder = false | |
// price | |
quoteC := ui.NewLineChart() | |
quoteC.Border.Label = "Daily Adjusted Close" | |
quoteC.Data = Pluck(prices, "AdjClose") | |
quoteC.Height = 11 | |
quoteC.AxesColor = ui.ColorWhite | |
quoteC.LineColor = ui.ColorYellow | |
// Price information | |
lastPrice := stock.Price // Price struct | |
strs := []string{ | |
fmt.Sprintf("Bid: %.2f", lastPrice.Bid), | |
fmt.Sprintf("Ask: %.2f", lastPrice.Ask), | |
fmt.Sprintf("Open: %.2f", lastPrice.Open), | |
fmt.Sprintf("Last: %.2f", lastPrice.Last), | |
} | |
lastInfo := ui.NewList() | |
lastInfo.Items = strs | |
lastInfo.ItemFgColor = ui.ColorYellow | |
lastInfo.Border.Label = "Info" | |
lastInfo.Height = 11 | |
// volume | |
/* | |
spark := ui.NewSparkline() | |
spark.Height = 8 | |
//spdata := sinpsint | |
spark.Data = FsToInts(Pluck(prices, "Volume")) | |
spark.TitleColor = ui.ColorWhite | |
spark.Title = "Volume" | |
sparklines := ui.NewSparklines(spark) | |
sparklines.Height = 8 | |
sparklines.Border.Label = "Volume" | |
*/ | |
volumeC := ui.NewLineChart() | |
volumeC.Height = 6 | |
//volumeC.Mode = "dot" | |
volumeC.Data = Pluck(prices, "Volume") | |
volumeC.AxesColor = ui.ColorWhite | |
volumeC.LineColor = ui.ColorWhite | |
volumeC.Border.Label = "Volume" | |
par := ui.NewPar("Author is too lazy to leave anything here") | |
par.Height = 5 | |
par.Border.Label = "Preserved Space" | |
// build layout | |
ui.Body.AddRows( | |
ui.NewRow( | |
ui.NewCol(10, 2, titlePar), | |
), | |
ui.NewRow( | |
ui.NewCol(10, 0, quoteC), | |
ui.NewCol(2, 0, lastInfo)), | |
ui.NewRow( | |
ui.NewCol(10, 0, volumeC), | |
ui.NewCol(2, 0, par)), | |
) | |
// calculate layout | |
ui.Body.Align() | |
draw := func(t int) { | |
//volumnSpark.Lines[0].Data = spdata[t:] | |
//quoteC.Data = sinps[2*t:] | |
ui.Render(ui.Body) | |
} | |
evt := ui.EventCh() | |
i := 0 | |
for { | |
select { | |
case e := <-evt: | |
if e.Type == ui.EventKey && e.Ch == 'q' { | |
return | |
} | |
default: | |
ui.Body.Width = ui.TermWidth() | |
ui.Body.Align() | |
draw(i) | |
i++ | |
if i == 102 { | |
return | |
} | |
time.Sleep(time.Second / 2) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment