mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
ftx: query kline using rest api
This commit is contained in:
parent
82abd5489b
commit
28c9ac95ac
|
@ -129,3 +129,19 @@ func toGlobalTrade(f fill) (types.Trade, error) {
|
|||
IsIsolated: false,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func toGlobalKLine(symbol string, interval types.Interval, h Candle) (types.KLine, error) {
|
||||
return types.KLine{
|
||||
Exchange: types.ExchangeFTX.String(),
|
||||
Symbol: symbol,
|
||||
StartTime: h.StartTime.Time,
|
||||
EndTime: h.StartTime.Add(interval.Duration()),
|
||||
Interval: interval,
|
||||
Open: h.Open,
|
||||
Close: h.Close,
|
||||
High: h.High,
|
||||
Low: h.Low,
|
||||
Volume: h.Volume,
|
||||
Closed: true,
|
||||
}, nil
|
||||
}
|
||||
|
|
|
@ -142,7 +142,51 @@ func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap,
|
|||
}
|
||||
|
||||
func (e *Exchange) QueryKLines(ctx context.Context, symbol string, interval types.Interval, options types.KLineQueryOptions) ([]types.KLine, error) {
|
||||
panic("implement me")
|
||||
var since, until time.Time
|
||||
if options.StartTime != nil {
|
||||
since = *options.StartTime
|
||||
}
|
||||
if options.EndTime != nil {
|
||||
until = *options.EndTime
|
||||
} else {
|
||||
until = time.Now()
|
||||
}
|
||||
if since.After(until) {
|
||||
return nil, fmt.Errorf("invalid query klines time range, since: %+v, until: %+v", since, until)
|
||||
}
|
||||
if !isIntervalSupportedInKLine(interval) {
|
||||
return nil, fmt.Errorf("interval %s is not supported", interval.String())
|
||||
}
|
||||
resp, err := e.newRest().HistoricalPrices(ctx, symbol, interval, int64(options.Limit), since, until)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !resp.Success {
|
||||
return nil, fmt.Errorf("ftx returns failure")
|
||||
}
|
||||
|
||||
var kline []types.KLine
|
||||
for _, r := range resp.Result {
|
||||
globalKline, err := toGlobalKLine(symbol, interval, r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
kline = append(kline, globalKline)
|
||||
}
|
||||
return kline, nil
|
||||
}
|
||||
|
||||
func isIntervalSupportedInKLine(interval types.Interval) bool {
|
||||
_, ok := map[int]struct{}{
|
||||
15: {},
|
||||
60: {},
|
||||
300: {},
|
||||
900: {},
|
||||
3600: {},
|
||||
14400: {},
|
||||
86400: {},
|
||||
}[interval.Minutes()*60]
|
||||
return ok
|
||||
}
|
||||
|
||||
func (e *Exchange) QueryTrades(ctx context.Context, symbol string, options *types.TradeQueryOptions) ([]types.Trade, error) {
|
||||
|
@ -247,10 +291,6 @@ func (e *Exchange) QueryDepositHistory(ctx context.Context, asset string, since,
|
|||
return
|
||||
}
|
||||
|
||||
func (e *Exchange) QueryWithdrawHistory(ctx context.Context, asset string, since, until time.Time) (allWithdraws []types.Withdraw, err error) {
|
||||
panic("implement me")
|
||||
}
|
||||
|
||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (types.OrderSlice, error) {
|
||||
var createdOrders types.OrderSlice
|
||||
// TODO: currently only support limit and market order
|
||||
|
|
|
@ -620,3 +620,19 @@ func TestExchange_QueryTrades(t *testing.T) {
|
|||
}, trades[0])
|
||||
})
|
||||
}
|
||||
|
||||
func Test_isIntervalSupportedInKLine(t *testing.T) {
|
||||
supportedIntervals := []types.Interval{
|
||||
types.Interval1m,
|
||||
types.Interval5m,
|
||||
types.Interval15m,
|
||||
types.Interval1h,
|
||||
types.Interval4h,
|
||||
types.Interval1d,
|
||||
}
|
||||
for _, i := range supportedIntervals {
|
||||
assert.True(t, isIntervalSupportedInKLine(i))
|
||||
}
|
||||
assert.False(t, isIntervalSupportedInKLine(types.Interval30m))
|
||||
assert.False(t, isIntervalSupportedInKLine(types.Interval3d))
|
||||
}
|
||||
|
|
|
@ -4,6 +4,10 @@ import (
|
|||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type marketRequest struct {
|
||||
|
@ -27,3 +31,41 @@ func (r *marketRequest) Markets(ctx context.Context) (marketsResponse, error) {
|
|||
|
||||
return m, nil
|
||||
}
|
||||
|
||||
/*
|
||||
supported resolutions: window length in seconds. options: 15, 60, 300, 900, 3600, 14400, 86400
|
||||
doc: https://docs.ftx.com/?javascript#get-historical-prices
|
||||
*/
|
||||
func (r *marketRequest) HistoricalPrices(ctx context.Context, market string, interval types.Interval, limit int64, start, end time.Time) (HistoricalPricesResponse, error) {
|
||||
q := map[string]string{
|
||||
"resolution": strconv.FormatInt(int64(interval.Minutes())*60, 10),
|
||||
}
|
||||
|
||||
if limit > 0 {
|
||||
q["limit"] = strconv.FormatInt(limit, 10)
|
||||
}
|
||||
|
||||
if start != (time.Time{}) {
|
||||
q["start_time"] = strconv.FormatInt(start.Unix(), 10)
|
||||
}
|
||||
|
||||
if end != (time.Time{}) {
|
||||
q["end_time"] = strconv.FormatInt(end.Unix(), 10)
|
||||
}
|
||||
|
||||
resp, err := r.
|
||||
Method("GET").
|
||||
Query(q).
|
||||
ReferenceURL(fmt.Sprintf("api/markets/%s/candles", market)).
|
||||
DoAuthenticatedRequest(ctx)
|
||||
|
||||
if err != nil {
|
||||
return HistoricalPricesResponse{}, err
|
||||
}
|
||||
|
||||
var h HistoricalPricesResponse
|
||||
if err := json.Unmarshal(resp.Body, &h); err != nil {
|
||||
return HistoricalPricesResponse{}, fmt.Errorf("failed to unmarshal historical prices response body to json: %w", err)
|
||||
}
|
||||
return h, nil
|
||||
}
|
||||
|
|
|
@ -198,6 +198,35 @@ type market struct {
|
|||
VolumeUsd24h float64 `json:"volumeUsd24h"`
|
||||
}
|
||||
|
||||
/*
|
||||
{
|
||||
"success": true,
|
||||
"result": [
|
||||
{
|
||||
"close": 11055.25,
|
||||
"high": 11089.0,
|
||||
"low": 11043.5,
|
||||
"open": 11059.25,
|
||||
"startTime": "2019-06-24T17:15:00+00:00",
|
||||
"volume": 464193.95725
|
||||
}
|
||||
]
|
||||
}
|
||||
*/
|
||||
type HistoricalPricesResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Result []Candle `json:"result"`
|
||||
}
|
||||
|
||||
type Candle struct {
|
||||
Close float64 `json:"close"`
|
||||
High float64 `json:"high"`
|
||||
Low float64 `json:"low"`
|
||||
Open float64 `json:"open"`
|
||||
StartTime datetime `json:"startTime"`
|
||||
Volume float64 `json:"volume"`
|
||||
}
|
||||
|
||||
type ordersHistoryResponse struct {
|
||||
Success bool `json:"success"`
|
||||
Result []order `json:"result"`
|
||||
|
|
Loading…
Reference in New Issue
Block a user