commit 83f41a06596c334e0516df8912e4cf247f133c24 Author: Greg Pomerantz Date: Thu Nov 14 21:36:06 2024 -0500 initial commit diff --git a/cmd/ohlc/main.go b/cmd/ohlc/main.go new file mode 100644 index 0000000..83e5e18 --- /dev/null +++ b/cmd/ohlc/main.go @@ -0,0 +1,21 @@ +package main + +import ( + "git.wow.st/gmp/ohlc" + "encoding/json" + "fmt" + "os" + "time" +) + +func main() { + if len(os.Args) < 2 { + fmt.Println("Usage: ohlc symbol1 [symbol2...]") + os.Exit(-1) + } + + for _, x := range(os.Args[1:]) { + ohlc.Conv(x) + } +} + diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..9780343 --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.wow.st/gmp/ohlc + +go 1.23.0 diff --git a/main.go b/main.go new file mode 100644 index 0000000..41d93ca --- /dev/null +++ b/main.go @@ -0,0 +1,197 @@ +package ohlc + +import ( + "encoding/json" + "fmt" + "os" + "time" +) + +func Conv(name string) { + text, err := os.ReadFile(name + ".json") + if err != nil { + fmt.Printf("%s: %s\n", name, err) + return + } + + var i interface{} + err = json.Unmarshal(text, &i) + if err != nil { + fmt.Printf("%s: %s\n", name, err) + return + } + + j, ok := i.(map[string]interface{}) + if !ok { fmt.Println(name + ": Bad format"); return } + + j, ok = j["chart"].(map[string]interface{}) + if !ok { fmt.Println(name + ": Bad format (chart)"); return } + + x, ok := j["result"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (result)"); return } + + result, ok := x[0].(map[string]interface{}) + if !ok { fmt.Println(name + ": Bad format (result[0])"); return } + + timestamp, ok := result["timestamp"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (timestamp)"); return } + + indicators, ok := result["indicators"].(map[string]interface{}) + if !ok { fmt.Println(name + ": Bad format (indicators)"); return } + + events, ok := result["events"].(map[string]interface{}) + + dividends, ok := events["dividends"].(map[string]interface{}) + + capgains, ok := events["capitalGains"].(map[string]interface{}) + + splits, ok := events["splits"].(map[string]interface{}) + + x, ok = indicators["quote"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (quote)"); return } + + quote, ok := x[0].(map[string]interface{}) + if !ok { fmt.Println(name + ": Bad format (quote[0])"); return } + + x, ok = indicators["adjclose"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (adjclose)"); return } + + a, ok := x[0].(map[string]interface{}) + if !ok { fmt.Println(name + ": Bad format (adjclose[0])"); return } + + adjclose, ok := a["adjclose"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (adjclose[adjclose])"); return } + + open, ok := quote["open"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (open)"); return } + + high, ok := quote["high"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (high)"); return } + + low, ok := quote["low"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (low)"); return } + + close, ok := quote["close"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (close)"); return } + + volume, ok := quote["volume"].([]interface{}) + if !ok { fmt.Println(name + ": Bad format (volume)"); return } + + out, err := os.Create(name + "-history.csv") + if err != nil { + fmt.Printf("%s: %s\n", name, err) + os.Exit(-1) + } + defer out.Close() + + out.WriteString("Date,Open,High,Low,Close,Adj Close,Volume\n") + for k, v := range timestamp { + unixTime := time.Unix(int64(v.(float64)),0) + if open[k] == nil { + continue + } + out.WriteString(fmt.Sprintf("%s,%f,%f,%f,%f,%f,%d\n", + unixTime.Format("2006-01-02"), + open[k],high[k],low[k],close[k], + adjclose[k],int(volume[k].(float64)))) + } + if dividends != nil { + out, err = os.Create(name + "-div.csv") + if err != nil { + fmt.Printf("%s: %s\n", name, err) + os.Exit(-1) + } + + defer out.Close() + + out.WriteString("Date,Dividends\n") + for _,v := range dividends { + v2, ok := v.(map[string]interface{}) + if !ok { + fmt.Println(name + ": Bad format (dividends)") + return + } + amount, ok := v2["amount"] + if !ok { + fmt.Println(name + ": Bad format (dividend amount)") + return + } + t, ok := v2["date"].(float64) + if !ok { + fmt.Println(name + ": Bad format (dividend date)") + return + } + unixTime := time.Unix(int64(t),0) + out.WriteString(fmt.Sprintf("%s,%f\n", + unixTime.Format("2006-01-02"), + amount.(float64))) + } + } + + if capgains != nil { + out, err = os.Create(name + "-capitalGain.csv") + if err != nil { + fmt.Printf("%s: %s\n", name, err) + os.Exit(-1) + } + + defer out.Close() + + out.WriteString("Date,Capital Gains\n") + for _,v := range capgains { + v2, ok := v.(map[string]interface{}) + if !ok { + fmt.Println(name + ": Bad format (capital gains)") + return + } + amount, ok := v2["amount"] + if !ok { + fmt.Println(name + ": Bad format (capital gains amount)") + return + } + t, ok := v2["date"].(float64) + if !ok { + fmt.Println(name + ": Bad format (capital gains date)") + return + } + unixTime := time.Unix(int64(t),0) + out.WriteString(fmt.Sprintf("%s,%f\n", + unixTime.Format("2006-01-02"), + amount.(float64))) + } + } + + if splits != nil { + out, err = os.Create(name + "-split.csv") + if err != nil { + fmt.Printf("%s: %s\n", name, err) + os.Exit(-1) + } + + defer out.Close() + + out.WriteString("Date,Stock Splits\n") + for _,v := range splits { + v2, ok := v.(map[string]interface{}) + if !ok { + fmt.Println(name + ": Bad format (splits)") + return + } + splitRatio, ok := v2["splitRatio"] + if !ok { + fmt.Println(name + ": Bad format (split ratio)") + return + } + t, ok := v2["date"].(float64) + if !ok { + fmt.Println(name + ": Bad format (split date)") + return + } + unixTime := time.Unix(int64(t),0) + out.WriteString(fmt.Sprintf("%s,%s\n", + unixTime.Format("2006-01-02"), + splitRatio)) + } + } +} +