mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
kucoin: implement QueryKLines and fix interval conversion
This commit is contained in:
parent
e3181202db
commit
1da0c8e755
|
@ -72,6 +72,9 @@ func toLocalInterval(i types.Interval) string {
|
|||
case types.Interval1m:
|
||||
return "1min"
|
||||
|
||||
case types.Interval5m:
|
||||
return "5min"
|
||||
|
||||
case types.Interval15m:
|
||||
return "15min"
|
||||
|
||||
|
@ -87,9 +90,18 @@ func toLocalInterval(i types.Interval) string {
|
|||
case types.Interval4h:
|
||||
return "4hour"
|
||||
|
||||
case types.Interval6h:
|
||||
return "6hour"
|
||||
|
||||
case types.Interval12h:
|
||||
return "12hour"
|
||||
|
||||
case types.Interval1d:
|
||||
return "1day"
|
||||
|
||||
}
|
||||
|
||||
return "1h"
|
||||
return "1hour"
|
||||
}
|
||||
|
||||
// convertSubscriptions global subscription to local websocket command
|
||||
|
|
|
@ -27,6 +27,7 @@ type Exchange struct {
|
|||
client *kucoinapi.RestClient
|
||||
}
|
||||
|
||||
|
||||
func New(key, secret, passphrase string) *Exchange {
|
||||
client := kucoinapi.NewClient()
|
||||
|
||||
|
@ -125,8 +126,64 @@ func (e *Exchange) QueryTickers(ctx context.Context, symbols ...string) (map[str
|
|||
return tickers, nil
|
||||
}
|
||||
|
||||
|
||||
var supportedIntervals = map[types.Interval]int{
|
||||
types.Interval1m: 60,
|
||||
types.Interval5m: 60 * 5,
|
||||
types.Interval5m: 60 * 15,
|
||||
types.Interval30m: 60 * 30,
|
||||
types.Interval1h: 60 * 60,
|
||||
types.Interval2h: 60 * 60 * 2,
|
||||
types.Interval4h: 60 * 60 * 4,
|
||||
types.Interval6h: 60 * 60 * 6,
|
||||
// types.Interval8h: 60 * 60 * 8,
|
||||
types.Interval12h: 60 * 60 * 12,
|
||||
}
|
||||
|
||||
func (e *Exchange) SupportedInterval() map[types.Interval]int {
|
||||
return supportedIntervals
|
||||
}
|
||||
|
||||
func (e *Exchange) IsSupportedInterval(interval types.Interval) bool {
|
||||
_, ok := supportedIntervals[interval]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (e *Exchange) QueryKLines(ctx context.Context, symbol string, interval types.Interval, options types.KLineQueryOptions) ([]types.KLine, error) {
|
||||
panic("implement me")
|
||||
req := e.client.MarketDataService.NewGetKLinesRequest()
|
||||
req.Symbol(toLocalSymbol(symbol))
|
||||
req.Interval(toLocalInterval(interval))
|
||||
if options.StartTime != nil {
|
||||
req.StartAt(*options.StartTime)
|
||||
} else if options.EndTime != nil {
|
||||
req.StartAt(*options.EndTime)
|
||||
}
|
||||
|
||||
ks, err := req.Do(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var klines []types.KLine
|
||||
for _, k := range ks {
|
||||
gi := toGlobalInterval(k.Interval)
|
||||
klines = append(klines, types.KLine{
|
||||
Exchange: types.ExchangeKucoin,
|
||||
Symbol: toGlobalSymbol(k.Symbol),
|
||||
StartTime: types.Time(k.StartTime),
|
||||
EndTime: types.Time(k.StartTime.Add(gi.Duration() - time.Millisecond)),
|
||||
Interval: gi,
|
||||
Open: k.Open.Float64(),
|
||||
Close: k.Close.Float64(),
|
||||
High: k.High.Float64(),
|
||||
Low: k.Low.Float64(),
|
||||
Volume: k.Volume.Float64(),
|
||||
QuoteVolume: k.QuoteVolume.Float64(),
|
||||
Closed: true,
|
||||
})
|
||||
}
|
||||
|
||||
return klines, nil
|
||||
}
|
||||
|
||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
||||
|
|
100
pkg/exchange/kucoin/kucoinapi/get_k_lines_request_accessors.go
Normal file
100
pkg/exchange/kucoin/kucoinapi/get_k_lines_request_accessors.go
Normal file
|
@ -0,0 +1,100 @@
|
|||
// Code generated by "requestgen -type GetKLinesRequest"; DO NOT EDIT.
|
||||
|
||||
package kucoinapi
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
)
|
||||
|
||||
func (g *GetKLinesRequest) Symbol(symbol string) *GetKLinesRequest {
|
||||
g.symbol = symbol
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) Interval(interval string) *GetKLinesRequest {
|
||||
g.interval = interval
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) StartAt(startAt time.Time) *GetKLinesRequest {
|
||||
g.startAt = &startAt
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) EndAt(endAt time.Time) *GetKLinesRequest {
|
||||
g.endAt = &endAt
|
||||
return g
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) GetParameters() (map[string]interface{}, error) {
|
||||
var params = map[string]interface{}{}
|
||||
|
||||
// check symbol field -> json key symbol
|
||||
symbol := g.symbol
|
||||
|
||||
// assign parameter of symbol
|
||||
params["symbol"] = symbol
|
||||
|
||||
// check interval field -> json key interval
|
||||
interval := g.interval
|
||||
|
||||
switch interval {
|
||||
case "1min", "3min", "5min", "15min", "30min", "1hour", "2hour", "4hour", "6hour", "8hour", "12hour", "1day", "1week":
|
||||
params["interval"] = interval
|
||||
|
||||
default:
|
||||
return params, fmt.Errorf("interval value %v is invalid", interval)
|
||||
|
||||
}
|
||||
|
||||
// assign parameter of interval
|
||||
params["interval"] = interval
|
||||
|
||||
// check startAt field -> json key startAt
|
||||
if g.startAt != nil {
|
||||
startAt := *g.startAt
|
||||
|
||||
// assign parameter of startAt
|
||||
// convert time.Time to seconds time stamp
|
||||
params["startAt"] = strconv.FormatInt(startAt.Unix(), 10)
|
||||
}
|
||||
|
||||
// check endAt field -> json key endAt
|
||||
if g.endAt != nil {
|
||||
endAt := *g.endAt
|
||||
|
||||
// assign parameter of endAt
|
||||
// convert time.Time to seconds time stamp
|
||||
params["endAt"] = strconv.FormatInt(endAt.Unix(), 10)
|
||||
}
|
||||
|
||||
return params, nil
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) GetParametersQuery() (url.Values, error) {
|
||||
query := url.Values{}
|
||||
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return query, err
|
||||
}
|
||||
|
||||
for k, v := range params {
|
||||
query.Add(k, fmt.Sprintf("%v", v))
|
||||
}
|
||||
|
||||
return query, nil
|
||||
}
|
||||
|
||||
func (g *GetKLinesRequest) GetParametersJSON() ([]byte, error) {
|
||||
params, err := g.GetParameters()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return json.Marshal(params)
|
||||
}
|
|
@ -1,20 +1,29 @@
|
|||
package kucoinapi
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/valyala/fastjson"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
)
|
||||
|
||||
type MarketDataService struct {
|
||||
client *RestClient
|
||||
}
|
||||
|
||||
func (s *MarketDataService) NewGetKLinesRequest() *GetKLinesRequest {
|
||||
return &GetKLinesRequest{client: s.client}
|
||||
}
|
||||
|
||||
type Symbol struct {
|
||||
Symbol string `json:"symbol"`
|
||||
Name string `json:"name"`
|
||||
|
@ -268,8 +277,6 @@ func (s *MarketDataService) GetOrderBook(symbol string, depth int) (*OrderBook,
|
|||
return nil, err
|
||||
}
|
||||
|
||||
fmt.Println(string(response.Body))
|
||||
|
||||
var apiResponse struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"msg"`
|
||||
|
@ -282,3 +289,119 @@ func (s *MarketDataService) GetOrderBook(symbol string, depth int) (*OrderBook,
|
|||
|
||||
return apiResponse.Data, nil
|
||||
}
|
||||
|
||||
//go:generate requestgen -type GetKLinesRequest
|
||||
type GetKLinesRequest struct {
|
||||
client *RestClient
|
||||
|
||||
symbol string `param:"symbol"`
|
||||
|
||||
interval string `param:"interval" validValues:"1min,3min,5min,15min,30min,1hour,2hour,4hour,6hour,8hour,12hour,1day,1week"`
|
||||
|
||||
startAt *time.Time `param:"startAt,seconds"`
|
||||
|
||||
endAt *time.Time `param:"endAt,seconds"`
|
||||
}
|
||||
|
||||
type KLine struct {
|
||||
Symbol string
|
||||
Interval string
|
||||
StartTime time.Time
|
||||
Open fixedpoint.Value
|
||||
High fixedpoint.Value
|
||||
Low fixedpoint.Value
|
||||
Close fixedpoint.Value
|
||||
Volume, QuoteVolume fixedpoint.Value
|
||||
}
|
||||
|
||||
func (r *GetKLinesRequest) Do(ctx context.Context) ([]KLine, error) {
|
||||
params, err := r.GetParametersQuery()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
req, err := r.client.NewRequest("GET", "/api/v1/market/candles", params, nil)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
response, err := r.client.SendRequest(req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var apiResponse struct {
|
||||
Code string `json:"code"`
|
||||
Message string `json:"msg"`
|
||||
Data json.RawMessage `json:"data"`
|
||||
}
|
||||
|
||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if apiResponse.Data == nil {
|
||||
return nil, errors.New("api error: [" + apiResponse.Code + "] " + apiResponse.Message)
|
||||
}
|
||||
|
||||
return parseKLines(apiResponse.Data, r.symbol, r.interval)
|
||||
}
|
||||
|
||||
func parseKLines(b []byte, symbol, interval string) (klines []KLine, err error) {
|
||||
s, err := fastjson.ParseBytes(b)
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
for _, v := range s.GetArray() {
|
||||
arr := v.GetArray()
|
||||
ts, err := strconv.ParseInt(string(arr[0].GetStringBytes()), 10, 64)
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
o, err := fixedpoint.NewFromString(string(arr[1].GetStringBytes()))
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
c, err := fixedpoint.NewFromString(string(arr[2].GetStringBytes()))
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
h, err := fixedpoint.NewFromString(string(arr[3].GetStringBytes()))
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
l, err := fixedpoint.NewFromString(string(arr[4].GetStringBytes()))
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
vv, err := fixedpoint.NewFromString(string(arr[5].GetStringBytes()))
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
qv, err := fixedpoint.NewFromString(string(arr[6].GetStringBytes()))
|
||||
if err != nil {
|
||||
return klines, err
|
||||
}
|
||||
|
||||
klines = append(klines, KLine{
|
||||
Symbol: symbol,
|
||||
Interval: interval,
|
||||
StartTime: time.Unix(ts, 0),
|
||||
Open: o,
|
||||
High: h,
|
||||
Low: l,
|
||||
Close: c,
|
||||
Volume: vv,
|
||||
QuoteVolume: qv,
|
||||
})
|
||||
}
|
||||
|
||||
return klines, err
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user