mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 06:53:52 +00:00
Merge pull request #1446 from c9s/feature/xdepthmaker
IMPROVE: [bitget] add more debug logs
This commit is contained in:
commit
b2895a0434
|
@ -38,13 +38,17 @@ type GetUnfilledOrdersRequest struct {
|
||||||
client requestgen.AuthenticatedAPIClient
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
symbol *string `param:"symbol,query"`
|
symbol *string `param:"symbol,query"`
|
||||||
// Limit number default 100 max 100
|
|
||||||
|
// limit number default 100 max 100
|
||||||
limit *string `param:"limit,query"`
|
limit *string `param:"limit,query"`
|
||||||
|
|
||||||
// idLessThan requests the content on the page before this ID (older data), the value input should be the orderId of the corresponding interface.
|
// idLessThan requests the content on the page before this ID (older data), the value input should be the orderId of the corresponding interface.
|
||||||
idLessThan *string `param:"idLessThan,query"`
|
idLessThan *string `param:"idLessThan,query"`
|
||||||
startTime *time.Time `param:"startTime,milliseconds,query"`
|
|
||||||
endTime *time.Time `param:"endTime,milliseconds,query"`
|
startTime *time.Time `param:"startTime,milliseconds,query"`
|
||||||
orderId *string `param:"orderId,query"`
|
endTime *time.Time `param:"endTime,milliseconds,query"`
|
||||||
|
|
||||||
|
orderId *string `param:"orderId,query"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Client) NewGetUnfilledOrdersRequest() *GetUnfilledOrdersRequest {
|
func (c *Client) NewGetUnfilledOrdersRequest() *GetUnfilledOrdersRequest {
|
||||||
|
|
|
@ -191,7 +191,7 @@ func unfilledOrderToGlobalOrder(order v2.UnfilledOrder) (*types.Order, error) {
|
||||||
// The market order will be executed immediately, so this check is used to handle corner cases.
|
// The market order will be executed immediately, so this check is used to handle corner cases.
|
||||||
if orderType == types.OrderTypeMarket {
|
if orderType == types.OrderTypeMarket {
|
||||||
qty = order.BaseVolume
|
qty = order.BaseVolume
|
||||||
log.Warnf("!!! The price(%f) and quantity(%f) are not verified for market orders, because we only receive limit orders in the test environment !!!", price.Float64(), qty.Float64())
|
log.Warnf("!!! The price(%f) and quantity(%f) are not verified for market orders, because we only receive limit orders in the test environment !!!", price.Float64(), qty.Float64())
|
||||||
}
|
}
|
||||||
|
|
||||||
return &types.Order{
|
return &types.Order{
|
||||||
|
@ -202,6 +202,7 @@ func unfilledOrderToGlobalOrder(order v2.UnfilledOrder) (*types.Order, error) {
|
||||||
Type: orderType,
|
Type: orderType,
|
||||||
Quantity: qty,
|
Quantity: qty,
|
||||||
Price: price,
|
Price: price,
|
||||||
|
|
||||||
// Bitget does not include the "time-in-force" field in its API response for spot trading, so we set GTC.
|
// Bitget does not include the "time-in-force" field in its API response for spot trading, so we set GTC.
|
||||||
TimeInForce: types.TimeInForceGTC,
|
TimeInForce: types.TimeInForceGTC,
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi"
|
"github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi"
|
||||||
v2 "github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi/v2"
|
v2 "github.com/c9s/bbgo/pkg/exchange/bitget/bitgetapi/v2"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
"github.com/c9s/bbgo/pkg/util"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
|
@ -34,26 +35,45 @@ var log = logrus.WithFields(logrus.Fields{
|
||||||
var (
|
var (
|
||||||
// queryMarketRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-symbols
|
// queryMarketRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-symbols
|
||||||
queryMarketRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
queryMarketRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
||||||
|
|
||||||
// queryAccountRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-account-assets
|
// queryAccountRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-account-assets
|
||||||
queryAccountRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
queryAccountRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
||||||
|
|
||||||
// queryTickerRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-single-ticker
|
// queryTickerRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-single-ticker
|
||||||
queryTickerRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
queryTickerRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
||||||
|
|
||||||
// queryTickersRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-all-tickers
|
// queryTickersRateLimiter has its own rate limit. https://bitgetlimited.github.io/apidoc/en/spot/#get-all-tickers
|
||||||
queryTickersRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
queryTickersRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
||||||
|
|
||||||
// queryOpenOrdersRateLimiter has its own rate limit. https://www.bitget.com/zh-CN/api-doc/spot/trade/Get-Unfilled-Orders
|
// queryOpenOrdersRateLimiter has its own rate limit. https://www.bitget.com/zh-CN/api-doc/spot/trade/Get-Unfilled-Orders
|
||||||
queryOpenOrdersRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
queryOpenOrdersRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
||||||
|
|
||||||
// closedQueryOrdersRateLimiter has its own rate limit. https://www.bitget.com/api-doc/spot/trade/Get-History-Orders
|
// closedQueryOrdersRateLimiter has its own rate limit. https://www.bitget.com/api-doc/spot/trade/Get-History-Orders
|
||||||
closedQueryOrdersRateLimiter = rate.NewLimiter(rate.Every(time.Second/15), 5)
|
closedQueryOrdersRateLimiter = rate.NewLimiter(rate.Every(time.Second/15), 5)
|
||||||
// submitOrdersRateLimiter has its own rate limit. https://www.bitget.com/zh-CN/api-doc/spot/trade/Place-Order
|
|
||||||
submitOrdersRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
// submitOrderRateLimiter has its own rate limit. https://www.bitget.com/zh-CN/api-doc/spot/trade/Place-Order
|
||||||
|
submitOrderRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
||||||
|
|
||||||
// queryTradeRateLimiter has its own rate limit. https://www.bitget.com/zh-CN/api-doc/spot/trade/Get-Fills
|
// queryTradeRateLimiter has its own rate limit. https://www.bitget.com/zh-CN/api-doc/spot/trade/Get-Fills
|
||||||
queryTradeRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
queryTradeRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
||||||
|
|
||||||
// cancelOrderRateLimiter has its own rate limit. https://www.bitget.com/api-doc/spot/trade/Cancel-Order
|
// cancelOrderRateLimiter has its own rate limit. https://www.bitget.com/api-doc/spot/trade/Cancel-Order
|
||||||
cancelOrderRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
cancelOrderRateLimiter = rate.NewLimiter(rate.Every(time.Second/5), 5)
|
||||||
|
|
||||||
// kLineRateLimiter has its own rate limit. https://www.bitget.com/api-doc/spot/market/Get-Candle-Data
|
// kLineRateLimiter has its own rate limit. https://www.bitget.com/api-doc/spot/market/Get-Candle-Data
|
||||||
kLineOrderRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
kLineRateLimiter = rate.NewLimiter(rate.Every(time.Second/10), 5)
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var debugf func(msg string, args ...interface{})
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
if v, ok := util.GetEnvVarBool("DEBUG_BITGET"); ok && v {
|
||||||
|
debugf = log.Infof
|
||||||
|
} else {
|
||||||
|
debugf = func(msg string, args ...interface{}) {}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Exchange struct {
|
type Exchange struct {
|
||||||
key, secret, passphrase string
|
key, secret, passphrase string
|
||||||
|
|
||||||
|
@ -199,7 +219,7 @@ func (e *Exchange) QueryKLines(
|
||||||
req.EndTime(*options.EndTime)
|
req.EndTime(*options.EndTime)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := kLineOrderRateLimiter.Wait(ctx); err != nil {
|
if err := kLineRateLimiter.Wait(ctx); err != nil {
|
||||||
return nil, fmt.Errorf("query klines rate limiter wait error: %w", err)
|
return nil, fmt.Errorf("query klines rate limiter wait error: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -322,26 +342,34 @@ func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (cr
|
||||||
req.ClientOrderId(order.ClientOrderID)
|
req.ClientOrderId(order.ClientOrderID)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := submitOrdersRateLimiter.Wait(ctx); err != nil {
|
if err := submitOrderRateLimiter.Wait(ctx); err != nil {
|
||||||
return nil, fmt.Errorf("place order rate limiter wait error: %w", err)
|
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 place order, order: %#v, err: %w", order, err)
|
return nil, fmt.Errorf("failed to place order, order: %#v, err: %w", order, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
debugf("order created: %+v", res)
|
||||||
|
|
||||||
if len(res.OrderId) == 0 || (len(order.ClientOrderID) != 0 && res.ClientOrderId != order.ClientOrderID) {
|
if len(res.OrderId) == 0 || (len(order.ClientOrderID) != 0 && res.ClientOrderId != order.ClientOrderID) {
|
||||||
return nil, fmt.Errorf("unexpected order id, resp: %#v, order: %#v", res, order)
|
return nil, fmt.Errorf("unexpected order id, resp: %#v, order: %#v", res, order)
|
||||||
}
|
}
|
||||||
|
|
||||||
orderId := res.OrderId
|
orderId := res.OrderId
|
||||||
|
|
||||||
|
debugf("fetching unfilled order info for order #%s", orderId)
|
||||||
ordersResp, err := e.v2client.NewGetUnfilledOrdersRequest().OrderId(orderId).Do(ctx)
|
ordersResp, err := e.v2client.NewGetUnfilledOrdersRequest().OrderId(orderId).Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to query open order by order id: %s, err: %w", orderId, err)
|
return nil, fmt.Errorf("failed to query open order by order id: %s, err: %w", orderId, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
switch len(ordersResp) {
|
debugf("unfilled order response: %+v", ordersResp)
|
||||||
case 0:
|
|
||||||
|
if len(ordersResp) == 1 {
|
||||||
|
return unfilledOrderToGlobalOrder(ordersResp[0])
|
||||||
|
} else if len(ordersResp) == 0 {
|
||||||
// The market order will be executed immediately, so we cannot retrieve it through the NewGetUnfilledOrdersRequest API.
|
// The market order will be executed immediately, so we cannot retrieve it through the NewGetUnfilledOrdersRequest API.
|
||||||
// Try to get the order from the NewGetHistoryOrdersRequest API.
|
// Try to get the order from the NewGetHistoryOrdersRequest API.
|
||||||
ordersResp, err := e.v2client.NewGetHistoryOrdersRequest().OrderId(orderId).Do(ctx)
|
ordersResp, err := e.v2client.NewGetHistoryOrdersRequest().OrderId(orderId).Do(ctx)
|
||||||
|
@ -354,13 +382,9 @@ func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (cr
|
||||||
}
|
}
|
||||||
|
|
||||||
return toGlobalOrder(ordersResp[0])
|
return toGlobalOrder(ordersResp[0])
|
||||||
|
|
||||||
case 1:
|
|
||||||
return unfilledOrderToGlobalOrder(ordersResp[0])
|
|
||||||
|
|
||||||
default:
|
|
||||||
return nil, fmt.Errorf("unexpected order length, order id: %s", orderId)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return nil, fmt.Errorf("unexpected order length, order id: %s", orderId)
|
||||||
}
|
}
|
||||||
|
|
||||||
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) {
|
||||||
|
|
|
@ -647,14 +647,10 @@ func (s *Strategy) generateMakerOrders(
|
||||||
// copy the pricing book because during the generation the book data could change
|
// copy the pricing book because during the generation the book data could change
|
||||||
dupPricingBook := pricingBook.Copy()
|
dupPricingBook := pricingBook.Copy()
|
||||||
|
|
||||||
log.Infof("dupPricingBook: \n\tbids: %+v \n\tasks: %+v",
|
log.Infof("pricingBook: \n\tbids: %+v \n\tasks: %+v",
|
||||||
dupPricingBook.SideBook(types.SideTypeBuy),
|
dupPricingBook.SideBook(types.SideTypeBuy),
|
||||||
dupPricingBook.SideBook(types.SideTypeSell))
|
dupPricingBook.SideBook(types.SideTypeSell))
|
||||||
|
|
||||||
log.Infof("pricingBook: \n\tbids: %+v \n\tasks: %+v",
|
|
||||||
pricingBook.SideBook(types.SideTypeBuy),
|
|
||||||
pricingBook.SideBook(types.SideTypeSell))
|
|
||||||
|
|
||||||
if maxLayer == 0 || maxLayer > s.NumLayers {
|
if maxLayer == 0 || maxLayer > s.NumLayers {
|
||||||
maxLayer = s.NumLayers
|
maxLayer = s.NumLayers
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user