pkg/exchange: update query open orders to latest

This commit is contained in:
edwin 2024-10-15 12:00:39 +08:00
parent 5a4c38caa2
commit b41cd348bc
4 changed files with 45 additions and 19 deletions

View File

@ -78,7 +78,7 @@ type Order struct {
PlaceType string `json:"placeType"` PlaceType string `json:"placeType"`
} }
//go:generate GetRequest -url "/v5/order/realtime" -type GetOpenOrdersRequest -responseDataType .OrdersResponse //go:generate GetRequest -url "/v5/order/realtime" -type GetOpenOrdersRequest -responseDataType .OrdersResponse -rateLimiter 1+45/1s
type GetOpenOrdersRequest struct { type GetOpenOrdersRequest struct {
client requestgen.AuthenticatedAPIClient client requestgen.AuthenticatedAPIClient

View File

@ -1,4 +1,4 @@
// Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Result -url /v5/order/realtime -type GetOpenOrdersRequest -responseDataType .OrdersResponse"; DO NOT EDIT. // Code generated by "requestgen -method GET -responseType .APIResponse -responseDataField Result -url /v5/order/realtime -type GetOpenOrdersRequest -responseDataType .OrdersResponse -rateLimiter 1+45/1s"; DO NOT EDIT.
package bybitapi package bybitapi
@ -6,11 +6,14 @@ import (
"context" "context"
"encoding/json" "encoding/json"
"fmt" "fmt"
"golang.org/x/time/rate"
"net/url" "net/url"
"reflect" "reflect"
"regexp" "regexp"
) )
var GetOpenOrdersRequestLimiter = rate.NewLimiter(45.00000045, 1)
func (g *GetOpenOrdersRequest) Category(category Category) *GetOpenOrdersRequest { func (g *GetOpenOrdersRequest) Category(category Category) *GetOpenOrdersRequest {
g.category = category g.category = category
return g return g
@ -265,6 +268,9 @@ func (g *GetOpenOrdersRequest) 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 *GetOpenOrdersRequest) Do(ctx context.Context) (*OrdersResponse, error) { func (g *GetOpenOrdersRequest) Do(ctx context.Context) (*OrdersResponse, error) {
if err := GetOpenOrdersRequestLimiter.Wait(ctx); err != nil {
return nil, err
}
// no body params // no body params
var params interface{} var params interface{}
@ -288,15 +294,29 @@ func (g *GetOpenOrdersRequest) Do(ctx context.Context) (*OrdersResponse, error)
} }
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
} }

View File

@ -76,9 +76,9 @@ func toGlobalOrder(order bybitapi.Order) (*types.Order, error) {
return nil, fmt.Errorf("unexpected order id: %s, err: %w", order.OrderId, err) return nil, fmt.Errorf("unexpected order id: %s, err: %w", order.OrderId, err)
} }
qty, err := processMarketBuyQuantity(order) price := order.Price
if err != nil { if orderType == types.OrderTypeMarket {
return nil, err price = order.AvgPrice
} }
return &types.Order{ return &types.Order{
@ -87,9 +87,11 @@ func toGlobalOrder(order bybitapi.Order) (*types.Order, error) {
Symbol: order.Symbol, Symbol: order.Symbol,
Side: side, Side: side,
Type: orderType, Type: orderType,
Quantity: qty, // We specified the quantity for the market buy order as the base coin when we submitted the order,
Price: order.Price, // so we can just use the Qty field.
TimeInForce: timeInForce, Quantity: order.Qty,
Price: price,
TimeInForce: timeInForce,
}, },
Exchange: types.ExchangeBybit, Exchange: types.ExchangeBybit,
OrderID: orderIdNum, OrderID: orderIdNum,

View File

@ -33,9 +33,7 @@ var (
// sharedRateLimiter indicates that the API belongs to the public API. // sharedRateLimiter indicates that the API belongs to the public API.
// The default order limiter apply 5 requests per second and a 5 initial bucket // The default order limiter apply 5 requests per second and a 5 initial bucket
// this includes QueryMarkets, QueryTicker, QueryAccountBalances, GetFeeRates // this includes QueryMarkets, QueryTicker, QueryAccountBalances, GetFeeRates
sharedRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5) sharedRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
queryOrderTradeRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
closedOrderQueryLimiter = rate.NewLimiter(rate.Every(time.Second), 1)
log = logrus.WithFields(logrus.Fields{ log = logrus.WithFields(logrus.Fields{
"exchange": "bybit", "exchange": "bybit",
@ -164,18 +162,24 @@ func (e *Exchange) QueryTickers(ctx context.Context, symbols ...string) (map[str
return tickers, nil return tickers, nil
} }
// QueryOpenOrders queries open orders by symbol.
//
// Primarily query unfilled or partially filled orders in real-time, but also supports querying recent 500 closed status
// (Cancelled, Filled) orders. Please see the usage of request param openOnly.
// UTA2.0 can query filled, canceled, and rejected orders to the most recent 500 orders for spot, linear, inverse and
// option categories
//
// The records are sorted by the createdTime from newest to oldest.
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) { func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
cursor := "" cursor := ""
// OpenOnlyOrder: UTA2.0, UTA1.0, classic account query open status orders (e.g., New, PartiallyFilled) only
req := e.client.NewGetOpenOrderRequest().Symbol(symbol).OpenOnly(bybitapi.OpenOnlyOrder).Limit(defaultQueryLimit)
for { for {
req := e.client.NewGetOpenOrderRequest().Symbol(symbol)
if len(cursor) != 0 { if len(cursor) != 0 {
// the default limit is 20. // the default limit is 20.
req = req.Cursor(cursor) req = req.Cursor(cursor)
} }
if err = queryOrderTradeRateLimiter.Wait(ctx); err != nil {
return nil, fmt.Errorf("place order rate limiter wait error: %w", err)
}
res, err := req.Do(ctx) res, err := req.Do(ctx)
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to query open orders, err: %w", err) return nil, fmt.Errorf("failed to query open orders, err: %w", err)