-
Notifications
You must be signed in to change notification settings - Fork 0
/
indices.go
161 lines (137 loc) · 3.77 KB
/
indices.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
156
157
158
159
160
161
package moexiss
import (
"bufio"
"bytes"
"context"
"github.com/buger/jsonparser"
"path"
)
//Indices struct represents a list of the indices that include the security
type Indices struct {
IndexId string // "SECID"
IndexName string // "SHORTNAME"
From string // "FROM"
Till string // "TILL"
}
//IndicesResponse struct represents a response with the list of the indices
type IndicesResponse struct {
SecurityId string
Indices []Indices
}
const (
indicesPartsUrl = "indices.json"
indicesKeyId = "SECID"
indicesKeyName = "SHORTNAME"
indicesKeyFrom = "FROM"
indicesKeyTill = "TILL"
indicesKeyIndices = "indices"
)
// IndicesService gets a list of the indices that include the security
// from the MoEx ISS API.
//
// MoEx ISS API docs: https://iss.moex.com/iss/reference/160
type IndicesService service
// GetIndices provides a list of the indices that include the security of MoEx ISS
func (i *IndicesService) GetIndices(ctx context.Context, security string, opt *IndicesRequestOptions) (*IndicesResponse, error) {
url, err := i.getUrl(security, opt)
if err != nil {
return nil, err
}
req, err := i.client.NewRequest("GET", url, nil)
if err != nil {
return nil, err
}
var b bytes.Buffer
w := bufio.NewWriter(&b)
_, err = i.client.Do(ctx, req, w)
if err != nil {
return nil, err
}
ir := IndicesResponse{}
err = parseIndicesResponse(b.Bytes(), &ir)
if err != nil {
return nil, err
}
ir.SecurityId = security
return &ir, nil
}
// getUrl provides an url for a request of indices with parameters from IndicesRequestOptions
// opt *IndicesRequestOptions can be nil, it is safe
// 'security' parameter must not be empty otherwise getUrl returns ErrBadSecurityParameter
func (i *IndicesService) getUrl(security string, opt *IndicesRequestOptions) (string, error) {
if !isOkSecurityParam(security) {
return "", ErrBadSecurityParameter
}
url, _ := i.client.BaseURL.Parse("securities")
url.Path = path.Join(url.Path, security, indicesPartsUrl)
gotURL := addIndicesRequestOptions(url, opt)
return gotURL.String(), nil
}
func parseIndicesResponse(byteData []byte, indicesResponse *IndicesResponse) error {
var err error
if indicesResponse == nil {
err = ErrNilPointer
return err
}
var errInCb error
_, err = jsonparser.ArrayEach(byteData, func(indicesBytes []byte, _ jsonparser.ValueType, offset int, errCb error) {
var data []byte
var dataType jsonparser.ValueType
data, dataType, _, errInCb = jsonparser.Get(indicesBytes, indicesKeyIndices)
if errInCb == nil && data != nil && dataType == jsonparser.Array {
errInCb = parseIndices(data, &indicesResponse.Indices)
if errInCb != nil {
return
}
}
})
if err == nil && errInCb != nil {
err = errInCb
}
return err
}
func parseIndices(data []byte, i *[]Indices) (err error) {
var errInCb error
_, err = jsonparser.ArrayEach(data, func(indicesItemData []byte, dataType jsonparser.ValueType, offset int, errCb error) {
if errInCb != nil {
return
}
if dataType != jsonparser.Object {
errInCb = ErrUnexpectedDataType
return
}
indices := Indices{}
errInCb = parseIndicesItem(indicesItemData, &indices)
if errInCb != nil {
return
}
*i = append(*i, indices)
})
if err == nil && errInCb != nil {
err = errInCb
}
return
}
func parseIndicesItem(data []byte, i *Indices) (err error) {
id, err := parseStringWithDefaultValueByKey(data, indicesKeyId, "")
if err != nil {
return
}
name, err := parseStringWithDefaultValueByKey(data, indicesKeyName, "")
if err != nil {
return
}
from, err := parseStringWithDefaultValueByKey(data, indicesKeyFrom, "")
if err != nil {
return
}
till, err := parseStringWithDefaultValueByKey(data, indicesKeyTill, "")
if err != nil {
return
}
i.IndexId = id
i.IndexName = name
i.From = from
i.Till = till
return
}