2021-05-28 12:51:10 +00:00
|
|
|
package okexapi
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
|
|
|
"fmt"
|
|
|
|
"net/url"
|
|
|
|
"strconv"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Candle struct {
|
|
|
|
InstrumentID string
|
|
|
|
Interval string
|
|
|
|
Time time.Time
|
|
|
|
Open fixedpoint.Value
|
|
|
|
High fixedpoint.Value
|
|
|
|
Low fixedpoint.Value
|
|
|
|
Close fixedpoint.Value
|
|
|
|
Volume fixedpoint.Value
|
|
|
|
VolumeInCurrency fixedpoint.Value
|
|
|
|
}
|
|
|
|
|
|
|
|
type CandlesticksRequest struct {
|
|
|
|
client *RestClient
|
|
|
|
|
2022-05-03 03:14:53 +00:00
|
|
|
instId string `param:"instId"`
|
2021-05-28 12:51:10 +00:00
|
|
|
|
2022-05-03 03:14:53 +00:00
|
|
|
limit *int `param:"limit"`
|
2021-05-28 12:51:10 +00:00
|
|
|
|
2022-05-03 03:14:53 +00:00
|
|
|
bar *string `param:"bar"`
|
2021-05-28 12:51:10 +00:00
|
|
|
|
2022-05-03 03:14:53 +00:00
|
|
|
after *int64 `param:"after,seconds"`
|
2021-05-28 12:51:10 +00:00
|
|
|
|
2022-05-03 03:14:53 +00:00
|
|
|
before *int64 `param:"before,seconds"`
|
2021-05-28 12:51:10 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (r *CandlesticksRequest) After(after int64) *CandlesticksRequest {
|
|
|
|
r.after = &after
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *CandlesticksRequest) Before(before int64) *CandlesticksRequest {
|
|
|
|
r.before = &before
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *CandlesticksRequest) Bar(bar string) *CandlesticksRequest {
|
|
|
|
r.bar = &bar
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *CandlesticksRequest) Limit(limit int) *CandlesticksRequest {
|
|
|
|
r.limit = &limit
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *CandlesticksRequest) InstrumentID(instId string) *CandlesticksRequest {
|
|
|
|
r.instId = instId
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *CandlesticksRequest) Do(ctx context.Context) ([]Candle, error) {
|
|
|
|
// SPOT, SWAP, FUTURES, OPTION
|
|
|
|
var params = url.Values{}
|
|
|
|
params.Add("instId", r.instId)
|
|
|
|
|
|
|
|
if r.bar != nil {
|
|
|
|
params.Add("bar", *r.bar)
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.before != nil {
|
|
|
|
params.Add("before", strconv.FormatInt(*r.before, 10))
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.after != nil {
|
|
|
|
params.Add("after", strconv.FormatInt(*r.after, 10))
|
|
|
|
}
|
|
|
|
|
|
|
|
if r.limit != nil {
|
|
|
|
params.Add("limit", strconv.Itoa(*r.limit))
|
|
|
|
}
|
|
|
|
|
|
|
|
req, err := r.client.newRequest("GET", "/api/v5/market/candles", params, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
resp, err := r.client.sendRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
type candleEntry [7]string
|
|
|
|
var candlesResponse struct {
|
|
|
|
Code string `json:"code"`
|
|
|
|
Message string `json:"msg"`
|
|
|
|
Data []candleEntry `json:"data"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := resp.DecodeJSON(&candlesResponse); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var candles []Candle
|
|
|
|
for _, entry := range candlesResponse.Data {
|
|
|
|
timestamp, err := strconv.ParseInt(entry[0], 10, 64)
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
open, err := fixedpoint.NewFromString(entry[1])
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
high, err := fixedpoint.NewFromString(entry[2])
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
low, err := fixedpoint.NewFromString(entry[3])
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
cls, err := fixedpoint.NewFromString(entry[4])
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
vol, err := fixedpoint.NewFromString(entry[5])
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
volCcy, err := fixedpoint.NewFromString(entry[6])
|
|
|
|
if err != nil {
|
|
|
|
return candles, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var interval = "1m"
|
|
|
|
if r.bar != nil {
|
|
|
|
interval = *r.bar
|
|
|
|
}
|
|
|
|
|
|
|
|
candles = append(candles, Candle{
|
|
|
|
InstrumentID: r.instId,
|
|
|
|
Interval: interval,
|
|
|
|
Time: time.Unix(0, timestamp*int64(time.Millisecond)),
|
|
|
|
Open: open,
|
|
|
|
High: high,
|
|
|
|
Low: low,
|
|
|
|
Close: cls,
|
|
|
|
Volume: vol,
|
|
|
|
VolumeInCurrency: volCcy,
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
|
|
|
return candles, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type MarketTickersRequest struct {
|
|
|
|
client *RestClient
|
|
|
|
|
|
|
|
instType string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MarketTickersRequest) InstrumentType(instType string) *MarketTickersRequest {
|
|
|
|
r.instType = instType
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MarketTickersRequest) Do(ctx context.Context) ([]MarketTicker, error) {
|
|
|
|
// SPOT, SWAP, FUTURES, OPTION
|
|
|
|
var params = url.Values{}
|
|
|
|
params.Add("instType", string(r.instType))
|
|
|
|
|
|
|
|
req, err := r.client.newRequest("GET", "/api/v5/market/tickers", params, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := r.client.sendRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var tickerResponse struct {
|
|
|
|
Code string `json:"code"`
|
|
|
|
Message string `json:"msg"`
|
|
|
|
Data []MarketTicker `json:"data"`
|
|
|
|
}
|
|
|
|
|
|
|
|
if err := response.DecodeJSON(&tickerResponse); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
return tickerResponse.Data, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type MarketTickerRequest struct {
|
|
|
|
client *RestClient
|
|
|
|
|
|
|
|
instId string
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MarketTickerRequest) InstrumentID(instId string) *MarketTickerRequest {
|
|
|
|
r.instId = instId
|
|
|
|
return r
|
|
|
|
}
|
|
|
|
|
|
|
|
func (r *MarketTickerRequest) Do(ctx context.Context) (*MarketTicker, error) {
|
|
|
|
// SPOT, SWAP, FUTURES, OPTION
|
|
|
|
var params = url.Values{}
|
|
|
|
params.Add("instId", r.instId)
|
|
|
|
|
|
|
|
req, err := r.client.newRequest("GET", "/api/v5/market/ticker", params, nil)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
response, err := r.client.sendRequest(req)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
var tickerResponse struct {
|
|
|
|
Code string `json:"code"`
|
|
|
|
Message string `json:"msg"`
|
|
|
|
Data []MarketTicker `json:"data"`
|
|
|
|
}
|
|
|
|
if err := response.DecodeJSON(&tickerResponse); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(tickerResponse.Data) == 0 {
|
|
|
|
return nil, fmt.Errorf("ticker of %s not found", r.instId)
|
|
|
|
}
|
|
|
|
|
|
|
|
return &tickerResponse.Data[0], nil
|
|
|
|
}
|
|
|
|
|
|
|
|
type MarketDataService struct {
|
|
|
|
client *RestClient
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MarketDataService) NewMarketTickerRequest(instId string) *MarketTickerRequest {
|
|
|
|
return &MarketTickerRequest{
|
|
|
|
client: c.client,
|
|
|
|
instId: instId,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MarketDataService) NewMarketTickersRequest(instType string) *MarketTickersRequest {
|
|
|
|
return &MarketTickersRequest{
|
|
|
|
client: c.client,
|
|
|
|
instType: instType,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func (c *MarketDataService) NewCandlesticksRequest(instId string) *CandlesticksRequest {
|
|
|
|
return &CandlesticksRequest{
|
|
|
|
client: c.client,
|
|
|
|
instId: instId,
|
|
|
|
}
|
|
|
|
}
|