forked from sklinkert/alphavantage
-
Notifications
You must be signed in to change notification settings - Fork 0
/
indicator_stoch.go
93 lines (83 loc) · 2.87 KB
/
indicator_stoch.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
package alphavantage
import (
"encoding/json"
"fmt"
"sort"
"time"
)
// IndicatorStoch represents the overall struct for stochastics indicator
// Example https://www.alphavantage.co/query?function=STOCH&symbol=MSFT&interval=daily&apikey=demo
type IndicatorStoch struct {
Metadata IndicatorStochMetadata `json:"Meta Data"`
TechnicalAnalysis map[string]TechnicalStochAnalysis `json:"Technical Analysis: STOCH"`
}
// IndicatorStochMetadata is the metadata subset of IndicatorStoch
type IndicatorStochMetadata struct {
Symbol string `json:"1: Symbol"`
Indicator string `json:"2: Indicator"`
LastRefreshed string `json:"3: Last Refreshed"`
Interval string `json:"4: Interval"`
FastKPeriod int `json:"5.1: FastK Period"`
SlowKPeriod int `json:"5.2: SlowK Period"`
SlowKMAType int `json:"5.3: SlowK MA Type"`
SlowDPeriod int `json:"5.4: SlowD Period"`
SlowDMAType int `json:"5.5: SlowD MA Type"`
TimeZone string `json:"6: Time Zone"`
}
// TechnicalStochAnalysis is the stoch indicator subset of IndicatorStoch
type TechnicalStochAnalysis struct {
SlowK float64 `json:",string"`
SlowD float64 `json:",string"`
}
func toIndicatorStoch(buf []byte) (*IndicatorStoch, error) {
indicatorStoch := &IndicatorStoch{}
if err := json.Unmarshal(buf, indicatorStoch); err != nil {
return nil, err
}
return indicatorStoch, nil
}
// IndicatorStoch fetches the "STOCH" indicators for given symbol from API.
// The order of dates in TechnicalAnalysis is random because it's a map.
func (c *Client) IndicatorStoch(symbol string, interval Interval) (*IndicatorStoch, error) {
const functionName = "STOCH"
url := fmt.Sprintf("%s/query?function=%s&symbol=%s&interval=%s&apikey=%s",
baseURL, functionName, symbol, interval, c.apiKey)
body, err := c.makeHTTPRequest(url)
if err != nil {
return nil, err
}
indicator, err := toIndicatorStoch(body)
if err != nil {
return nil, fmt.Errorf("failed to parse response: %w", err)
}
return indicator, nil
}
// Latest returns the most recent TechnicalStochAnalysis for given stoch.
func (stoch *IndicatorStoch) Latest() (date string, latest *TechnicalStochAnalysis) {
if len(stoch.TechnicalAnalysis) == 0 {
return "", nil
}
dates := make([]string, len(stoch.TechnicalAnalysis))
for date := range stoch.TechnicalAnalysis {
dates = append(dates, date)
}
sort.Strings(dates)
date = dates[len(dates)-1]
latestVal, _ := stoch.TechnicalAnalysis[date]
latest = &latestVal
return
}
// Today returns TechnicalStochAnalysis for today.
func (stoch *IndicatorStoch) Today() *TechnicalStochAnalysis {
today := time.Now()
return stoch.ByDate(today)
}
// ByDate returns TechnicalStochAnalysis for the given date.
func (stoch *IndicatorStoch) ByDate(date time.Time) *TechnicalStochAnalysis {
day := date.Format(DateFormat)
item, exists := stoch.TechnicalAnalysis[day]
if !exists {
return nil
}
return &item
}