max: fix max exchange closed order sync

This commit is contained in:
c9s 2022-01-24 23:18:52 +08:00
parent e8fd1486b1
commit 0c0a12781a
3 changed files with 44 additions and 37 deletions

View File

@ -199,8 +199,8 @@ func toGlobalOrder(maxOrder max.Order) (*types.Order, error) {
OrderID: maxOrder.ID,
Status: toGlobalOrderStatus(maxOrder.State, executedVolume, remainingVolume),
ExecutedQuantity: executedVolume.Float64(),
CreationTime: types.Time(maxOrder.CreatedAt),
UpdateTime: types.Time(maxOrder.CreatedAt),
CreationTime: types.Time(maxOrder.CreatedAtMs.Time()),
UpdateTime: types.Time(maxOrder.CreatedAtMs.Time()),
}, nil
}
@ -340,4 +340,3 @@ func convertWebSocketOrderUpdate(u max.OrderUpdate) (*types.Order, error) {
CreationTime: types.Time(time.Unix(0, u.CreatedAtMs*int64(time.Millisecond))),
}, nil
}

View File

@ -19,7 +19,7 @@ import (
"github.com/c9s/bbgo/pkg/util"
)
var closedOrderQueryLimiter = rate.NewLimiter(rate.Every(5*time.Second), 1)
var closedOrderQueryLimiter = rate.NewLimiter(rate.Every(1*time.Second), 1)
var tradeQueryLimiter = rate.NewLimiter(rate.Every(3*time.Second), 1)
var accountQueryLimiter = rate.NewLimiter(rate.Every(3*time.Second), 1)
var marketDataLimiter = rate.NewLimiter(rate.Every(2*time.Second), 10)
@ -179,32 +179,34 @@ func (e *Exchange) QueryClosedOrders(ctx context.Context, symbol string, since,
return nil, err
}
numBatches := 3
limit := 1000 // max limit = 1000
offset := limit * numBatches
limit := 1000 // max limit = 1000, default 100
orderIDs := make(map[uint64]struct{}, limit*2)
for ; offset > 0; offset -= limit {
log.Infof("querying %s closed orders offset %d ~ ", symbol, offset)
log.Warn("max exchange does not support time-range-based query, we will start from the first record")
page := 1
for {
log.Infof("querying %s closed orders from page %d ~ ", symbol, page)
maxOrders, err := e.client.OrderService.Closed(toLocalSymbol(symbol), maxapi.QueryOrderOptions{
Offset: offset,
Limit: limit,
Limit: limit,
Page: page,
})
if err != nil {
return orders, err
}
if len(maxOrders) == 0 {
break
return orders, err
}
log.Infof("%d orders", len(maxOrders))
for _, maxOrder := range maxOrders {
if maxOrder.CreatedAt.Before(since) {
if maxOrder.CreatedAtMs.Time().Before(since) {
log.Debugf("skip orders with creation time before %s, found %s", since, maxOrder.CreatedAtMs.Time())
continue
}
if maxOrder.CreatedAt.After(until) {
if maxOrder.CreatedAtMs.Time().After(until) {
return orders, err
}
@ -214,12 +216,14 @@ func (e *Exchange) QueryClosedOrders(ctx context.Context, symbol string, since,
}
if _, ok := orderIDs[order.OrderID]; ok {
log.Infof("skipping duplicated order: %d", order.OrderID)
log.Debugf("skipping duplicated order: %d", order.OrderID)
}
orderIDs[order.OrderID] = struct{}{}
orders = append(orders, *order)
log.Infof("order %+v", order)
}
page++
}
return orders, err

View File

@ -7,6 +7,8 @@ import (
"time"
"github.com/pkg/errors"
"github.com/c9s/bbgo/pkg/types"
)
var relUrlV2Order *url.URL
@ -43,7 +45,7 @@ const (
type OrderState string
const (
OrderStateDone = OrderState("done")
OrderStateDone = OrderState("done")
OrderStateCancel = OrderState("cancel")
OrderStateWait = OrderState("wait")
@ -68,6 +70,7 @@ type QueryOrderOptions struct {
GroupID int
Offset int
Limit int
Page int
}
// OrderService manages the Order endpoint.
@ -77,32 +80,30 @@ type OrderService struct {
// Order represents one returned order (POST order/GET order/GET orders) on the max platform.
type Order struct {
ID uint64 `json:"id,omitempty"`
Side string `json:"side"`
OrderType OrderType `json:"ord_type"`
Price string `json:"price,omitempty"`
StopPrice string `json:"stop_price,omitempty"`
AveragePrice string `json:"avg_price,omitempty"`
State OrderState `json:"state,omitempty"`
Market string `json:"market,omitempty"`
Volume string `json:"volume"`
RemainingVolume string `json:"remaining_volume,omitempty"`
ExecutedVolume string `json:"executed_volume,omitempty"`
TradesCount int64 `json:"trades_count,omitempty"`
GroupID uint32 `json:"group_id,omitempty"`
ClientOID string `json:"client_oid,omitempty"`
CreatedAt time.Time `json:"-" db:"created_at"`
CreatedAtMs int64 `json:"created_at_in_ms,omitempty"`
InsertedAt time.Time `json:"-" db:"inserted_at"`
ID uint64 `json:"id,omitempty"`
Side string `json:"side"`
OrderType OrderType `json:"ord_type"`
Price string `json:"price,omitempty"`
StopPrice string `json:"stop_price,omitempty"`
AveragePrice string `json:"avg_price,omitempty"`
State OrderState `json:"state,omitempty"`
Market string `json:"market,omitempty"`
Volume string `json:"volume"`
RemainingVolume string `json:"remaining_volume,omitempty"`
ExecutedVolume string `json:"executed_volume,omitempty"`
TradesCount int64 `json:"trades_count,omitempty"`
GroupID uint32 `json:"group_id,omitempty"`
ClientOID string `json:"client_oid,omitempty"`
CreatedAt time.Time `json:"-" db:"created_at"`
CreatedAtMs types.MillisecondTimestamp `json:"created_at_in_ms,omitempty"`
InsertedAt time.Time `json:"-" db:"inserted_at"`
}
// Open returns open orders
func (s *OrderService) Closed(market string, options QueryOrderOptions) ([]Order, error) {
payload := map[string]interface{}{
"market": market,
"state": []OrderState{OrderStateDone, OrderStateCancel, OrderStateFailed},
"order_by": "desc",
"pagination": false,
"market": market,
"state": []OrderState{OrderStateDone},
}
if options.GroupID > 0 {
@ -114,6 +115,9 @@ func (s *OrderService) Closed(market string, options QueryOrderOptions) ([]Order
if options.Limit > 0 {
payload["limit"] = options.Limit
}
if options.Page > 0 {
payload["page"] = options.Page
}
req, err := s.client.newAuthenticatedRequest("GET", "v2/orders", payload, relUrlV2Orders)
if err != nil {