-
Notifications
You must be signed in to change notification settings - Fork 26
/
Copy pathav.go
155 lines (132 loc) · 4.12 KB
/
av.go
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
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
package av
import (
"net/http"
"net/url"
"time"
)
const (
// HostDefault is the default host for Alpha Vantage
HostDefault = "www.alphavantage.co"
)
const (
schemeHttps = "https"
queryApiKey = "apikey"
queryDataType = "datatype"
queryOutputSize = "outputsize"
querySymbol = "symbol"
queryMarket = "market"
queryEndpoint = "function"
queryInterval = "interval"
valueCompact = "compact"
valueJson = "csv"
valueDigitcalCurrencyEndpoint = "DIGITAL_CURRENCY_INTRADAY"
pathQuery = "query"
requestTimeout = time.Second * 30
)
// Connection is an interface that requests data from a server
type Connection interface {
// Request creates an http Response from the given endpoint URL
Request(endpoint *url.URL) (*http.Response, error)
}
type avConnection struct {
client *http.Client
host string
}
// NewConnectionHost creates a new connection at the default Alpha Vantage host
func NewConnection() Connection {
return NewConnectionHost(HostDefault)
}
// NewConnectionHost creates a new connection at the given host
func NewConnectionHost(host string) Connection {
client := &http.Client{
Timeout: requestTimeout,
}
return &avConnection{
client: client,
host: host,
}
}
// Request will make an HTTP GET request for the given endpoint from Alpha Vantage
func (conn *avConnection) Request(endpoint *url.URL) (*http.Response, error) {
endpoint.Scheme = schemeHttps
endpoint.Host = conn.host
targetUrl := endpoint.String()
return conn.client.Get(targetUrl)
}
// Client is a service used to query Alpha Vantage stock data
type Client struct {
conn Connection
apiKey string
}
// NewClientConnection creates a new Client with the default Alpha Vantage connection
func NewClient(apiKey string) *Client {
return NewClientConnection(apiKey, NewConnection())
}
// NewClientConnection creates a Client with a specific connection
func NewClientConnection(apiKey string, connection Connection) *Client {
return &Client{
conn: connection,
apiKey: apiKey,
}
}
// buildRequestPath builds an endpoint URL with the given query parameters
func (c *Client) buildRequestPath(params map[string]string) *url.URL {
// build our URL
endpoint := &url.URL{}
endpoint.Path = pathQuery
// base parameters
query := endpoint.Query()
query.Set(queryApiKey, c.apiKey)
query.Set(queryDataType, valueJson)
query.Set(queryOutputSize, valueCompact)
// additional parameters
for key, value := range params {
query.Set(key, value)
}
endpoint.RawQuery = query.Encode()
return endpoint
}
// StockTimeSeriesIntraday queries a stock symbols statistics throughout the day.
// Data is returned from past to present.
func (c *Client) StockTimeSeriesIntraday(timeInterval TimeInterval, symbol string) ([]*TimeSeriesValue, error) {
endpoint := c.buildRequestPath(map[string]string{
queryEndpoint: timeSeriesIntraday.keyName(),
queryInterval: timeInterval.keyName(),
querySymbol: symbol,
})
response, err := c.conn.Request(endpoint)
if err != nil {
return nil, err
}
defer response.Body.Close()
return parseTimeSeriesData(response.Body)
}
// StockTimeSeries queries a stock symbols statistics for a given time frame.
// Data is returned from past to present.
func (c *Client) StockTimeSeries(timeSeries TimeSeries, symbol string) ([]*TimeSeriesValue, error) {
endpoint := c.buildRequestPath(map[string]string{
queryEndpoint: timeSeries.keyName(),
querySymbol: symbol,
})
response, err := c.conn.Request(endpoint)
if err != nil {
return nil, err
}
defer response.Body.Close()
return parseTimeSeriesData(response.Body)
}
// DigitalCurrency queries statistics of a digital currency in terms of a physical currency throughout the day.
// Data is returned from past to present.
func (c *Client) DigitalCurrency(digital, physical string) ([]*DigitalCurrencySeriesValue, error) {
endpoint := c.buildRequestPath(map[string]string{
queryEndpoint: valueDigitcalCurrencyEndpoint,
querySymbol: digital,
queryMarket: physical,
})
response, err := c.conn.Request(endpoint)
if err != nil {
return nil, err
}
defer response.Body.Close()
return parseDigitalCurrencySeriesData(response.Body)
}