mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-15 03:23:52 +00:00
Merge pull request #1775 from c9s/edwin/bybit/query-closed-order
FEATURE: [bybit] update query closed order to latest
This commit is contained in:
commit
0ca566e1e8
|
@ -9,7 +9,7 @@ import (
|
||||||
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Result
|
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Result
|
||||||
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Result
|
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Result
|
||||||
|
|
||||||
//go:generate GetRequest -url "/v5/order/history" -type GetOrderHistoriesRequest -responseDataType .OrdersResponse
|
//go:generate GetRequest -url "/v5/order/history" -type GetOrderHistoriesRequest -responseDataType .OrdersResponse -rateLimiter 5+45/1s
|
||||||
type GetOrderHistoriesRequest struct {
|
type GetOrderHistoriesRequest struct {
|
||||||
client requestgen.AuthenticatedAPIClient
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Result -url /v5/order/history -type GetOrderHistoriesRequest -responseDataType .OrdersResponse"; DO NOT EDIT.
|
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Result -url /v5/order/history -type GetOrderHistoriesRequest -responseDataType .OrdersResponse -rateLimiter 5+45/1s"; DO NOT EDIT.
|
||||||
|
|
||||||
package bybitapi
|
package bybitapi
|
||||||
|
|
||||||
|
@ -6,6 +6,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -13,6 +14,8 @@ import (
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var GetOrderHistoriesRequestLimiter = rate.NewLimiter(45.00000045, 5)
|
||||||
|
|
||||||
func (g *GetOrderHistoriesRequest) Category(category Category) *GetOrderHistoriesRequest {
|
func (g *GetOrderHistoriesRequest) Category(category Category) *GetOrderHistoriesRequest {
|
||||||
g.category = category
|
g.category = category
|
||||||
return g
|
return g
|
||||||
|
@ -269,6 +272,9 @@ func (g *GetOrderHistoriesRequest) GetPath() string {
|
||||||
|
|
||||||
// Do generates the request object and send the request object to the API endpoint
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (g *GetOrderHistoriesRequest) Do(ctx context.Context) (*OrdersResponse, error) {
|
func (g *GetOrderHistoriesRequest) Do(ctx context.Context) (*OrdersResponse, error) {
|
||||||
|
if err := GetOrderHistoriesRequestLimiter.Wait(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
// no body params
|
// no body params
|
||||||
var params interface{}
|
var params interface{}
|
||||||
|
@ -292,15 +298,29 @@ func (g *GetOrderHistoriesRequest) Do(ctx context.Context) (*OrdersResponse, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse APIResponse
|
var apiResponse APIResponse
|
||||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
|
||||||
return nil, err
|
type responseUnmarshaler interface {
|
||||||
|
Unmarshal(data []byte) error
|
||||||
|
}
|
||||||
|
|
||||||
|
if unmarshaler, ok := interface{}(&apiResponse).(responseUnmarshaler); ok {
|
||||||
|
if err := unmarshaler.Unmarshal(response.Body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The line below checks the content type, however, some API server might not send the correct content type header,
|
||||||
|
// Hence, this is commented for backward compatibility
|
||||||
|
// response.IsJSON()
|
||||||
|
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseValidator interface {
|
type responseValidator interface {
|
||||||
Validate() error
|
Validate() error
|
||||||
}
|
}
|
||||||
validator, ok := interface{}(apiResponse).(responseValidator)
|
|
||||||
if ok {
|
if validator, ok := interface{}(&apiResponse).(responseValidator); ok {
|
||||||
if err := validator.Validate(); err != nil {
|
if err := validator.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -23,6 +23,8 @@ const (
|
||||||
defaultKLineLimit = 1000
|
defaultKLineLimit = 1000
|
||||||
|
|
||||||
queryTradeDurationLimit = 7 * 24 * time.Hour
|
queryTradeDurationLimit = 7 * 24 * time.Hour
|
||||||
|
|
||||||
|
maxHistoricalDataQueryPeriod = 2 * 365 * 24 * time.Hour
|
||||||
)
|
)
|
||||||
|
|
||||||
// https://bybit-exchange.github.io/docs/zh-TW/v5/rate-limit
|
// https://bybit-exchange.github.io/docs/zh-TW/v5/rate-limit
|
||||||
|
@ -376,38 +378,68 @@ func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (err
|
||||||
return errs
|
return errs
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// QueryClosedOrders queries closed orders by symbol, since, until, and lastOrderID.
|
||||||
|
// startTime and endTime are not passed, return 7 days by default
|
||||||
|
// Only startTime is passed, return range between startTime and startTime+7 days
|
||||||
|
// Only endTime is passed, return range between endTime-7 days and endTime
|
||||||
|
// If both are passed, the rule is endTime - startTime <= 7 days
|
||||||
|
//
|
||||||
|
// ** since and until are inclusive. **
|
||||||
|
// ** sort by creation time in descending order. **
|
||||||
func (e *Exchange) QueryClosedOrders(
|
func (e *Exchange) QueryClosedOrders(
|
||||||
ctx context.Context, symbol string, since, util time.Time, lastOrderID uint64,
|
ctx context.Context, symbol string, since, until time.Time, _ uint64,
|
||||||
) (orders []types.Order, err error) {
|
) (orders []types.Order, err error) {
|
||||||
if !since.IsZero() || !util.IsZero() {
|
|
||||||
log.Warn("!!!BYBIT EXCHANGE API NOTICE!!! the since/until conditions will not be effected on SPOT account, bybit exchange does not support time-range-based query currently")
|
now := time.Now()
|
||||||
|
|
||||||
|
if time.Since(since) > maxHistoricalDataQueryPeriod {
|
||||||
|
newSince := now.Add(-maxHistoricalDataQueryPeriod)
|
||||||
|
log.Warnf("!!!BYBIT EXCHANGE API NOTICE!!! The closed order API cannot query data beyond 2 years from the current date, update %s -> %s", since, newSince)
|
||||||
|
since = newSince
|
||||||
|
}
|
||||||
|
if until.Before(since) {
|
||||||
|
newUntil := since.Add(queryTradeDurationLimit)
|
||||||
|
log.Warnf("!!!BYBIT EXCHANGE API NOTICE!!! The 'until' comes before 'since', add 7 days to until (%s -> %s).", until, newUntil)
|
||||||
|
until = newUntil
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := closedOrderQueryLimiter.Wait(ctx); err != nil {
|
// if the time range exceeds the server boundary, get the last 7 days of data
|
||||||
return nil, fmt.Errorf("query closed order rate limiter wait error: %w", err)
|
if until.Sub(since) > queryTradeDurationLimit {
|
||||||
|
newStartTime := until.Add(-queryTradeDurationLimit)
|
||||||
|
|
||||||
|
log.Warnf("!!!BYBIT EXCHANGE API NOTICE!!! The time range exceeds the server boundary: %s, start time: %s, end time: %s, updated start time %s -> %s", queryTradeDurationLimit, since.String(), until.String(), since.String(), newStartTime.String())
|
||||||
|
since = newStartTime
|
||||||
}
|
}
|
||||||
res, err := e.client.NewGetOrderHistoriesRequest().
|
req := e.client.NewGetOrderHistoriesRequest().
|
||||||
Symbol(symbol).
|
Symbol(symbol).
|
||||||
Cursor(strconv.FormatUint(lastOrderID, 10)).
|
|
||||||
Limit(defaultQueryLimit).
|
Limit(defaultQueryLimit).
|
||||||
Do(ctx)
|
StartTime(since).
|
||||||
if err != nil {
|
EndTime(until)
|
||||||
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, order := range res.List {
|
cursor := ""
|
||||||
o, err2 := toGlobalOrder(order)
|
for {
|
||||||
if err2 != nil {
|
if len(cursor) != 0 {
|
||||||
err = multierr.Append(err, err2)
|
req = req.Cursor(cursor)
|
||||||
continue
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if o.Status.Closed() {
|
res, err := req.Do(ctx)
|
||||||
orders = append(orders, *o)
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to call get order histories error: %w", err)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
if err != nil {
|
for _, order := range res.List {
|
||||||
return nil, err
|
order, err := toGlobalOrder(order)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("failed to convert order, err: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
orders = append(orders, *order)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(res.NextPageCursor) == 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
cursor = res.NextPageCursor
|
||||||
}
|
}
|
||||||
|
|
||||||
return types.SortOrdersAscending(orders), nil
|
return types.SortOrdersAscending(orders), nil
|
||||||
|
|
Loading…
Reference in New Issue
Block a user