-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmain.go
More file actions
105 lines (89 loc) · 2.54 KB
/
Copy pathmain.go
File metadata and controls
105 lines (89 loc) · 2.54 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
package main
import (
"fmt"
"net/http"
"os"
"strconv"
"time"
"github.com/cjhall1283/algo/config"
"github.com/cjhall1283/algo/robinhood"
)
func main() {
// Get config
conf, err := config.Parse("./example_config.yaml")
if err != nil {
fmt.Println(err)
os.Exit(1)
}
client := &http.Client{
Timeout: 5 * time.Second,
}
incomingQuotes := make(chan robinhood.Quote)
outgoingDecisions := make(chan map[string]int)
for _, symbol := range conf.Symbols {
fmt.Println(robinhood.GetInstrumentID(symbol, client))
}
go liveProducer(conf, client, incomingQuotes)
go algo(incomingQuotes, outgoingDecisions)
go broker(outgoingDecisions)
select {}
}
func liveProducer(conf config.Config, client *http.Client, c chan robinhood.Quote) {
for {
// Collect quotes
quotes, err := robinhood.GetLiveQuotes(conf.Symbols, client)
if err != nil {
fmt.Println(err)
}
// Insert collected data into the chan
for _, quote := range quotes.QuotesArray {
c <- quote
}
// Sleep so we don't overwhelm the API
time.Sleep(time.Duration(conf.LiveFrequency) * time.Second)
}
}
func histProducer(conf config.Config, client *http.Client, c chan robinhood.Quote) {
// Collect quotes
hist, err := robinhood.GetHistoricalQuotes(conf.Symbols, conf.HistFrequency, conf.HistRange, client)
if err != nil {
fmt.Println(err)
}
for _, res := range hist.Results {
for _, histQuote := range res.Timeseries {
quote := robinhood.Quote{Symbol: res.Symbol, LastTradePrice: histQuote.OpenPrice}
c <- quote
}
}
}
func algo(incomingQuotes chan robinhood.Quote, outgoingDecisions chan map[string]int) {
rollingAverages := make(map[string]float64)
for {
select {
case quote := <-incomingQuotes:
val, _ := strconv.ParseFloat(quote.LastTradePrice, 64)
if _, exists := rollingAverages[quote.Symbol]; !exists {
rollingAverages[quote.Symbol] = val
} else {
if val > (rollingAverages[quote.Symbol]*1.002) {
outgoingDecisions <- map[string]int{quote.Symbol: 5}
}
if val < (rollingAverages[quote.Symbol]*0.998) {
outgoingDecisions <- map[string]int{quote.Symbol: -5}
}
fmt.Println(fmt.Sprintf("[[%s]] Live: %f Rolling: %f Live/Rolling: %f", quote.Symbol, val, rollingAverages[quote.Symbol], val/rollingAverages[quote.Symbol]))
rollingAverages[quote.Symbol] = (rollingAverages[quote.Symbol]*0.9 + val*0.1)
}
}
}
}
func broker(outgoingDecisions chan map[string]int) {
for {
select {
case decision := <-outgoingDecisions:
for k := range decision {
fmt.Println(fmt.Sprintf("%s:%d", k, decision[k]))
}
}
}
}