xdepthmaker: avoid using the same depth price for the new maker order

This commit is contained in:
c9s 2024-09-25 15:52:52 +08:00
parent 6a5ab424c9
commit e11db4a2d1
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
4 changed files with 30 additions and 14 deletions

View File

@ -255,10 +255,9 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange,
if cancelAll { if cancelAll {
orders = b.Orders() orders = b.Orders()
} else { } else {
// partial cancel // for partial cancel
orders = filterCanceledOrders(orders) orders = filterCanceledOrders(orders)
} }
} else { } else {
log.Warnf("[ActiveOrderBook] using open orders API to verify the active orders...") log.Warnf("[ActiveOrderBook] using open orders API to verify the active orders...")

View File

@ -883,6 +883,9 @@ func (s *Strategy) generateMakerOrders(
continue continue
} }
accumulatedDepth := fixedpoint.Zero
lastMakerPrice := fixedpoint.Zero
layerLoop: layerLoop:
for i := 1; i <= maxLayer; i++ { for i := 1; i <= maxLayer; i++ {
// simple break, we need to check the market minNotional and minQuantity later // simple break, we need to check the market minNotional and minQuantity later
@ -899,8 +902,9 @@ func (s *Strategy) generateMakerOrders(
// requiredDepth is the required depth in quote currency // requiredDepth is the required depth in quote currency
requiredDepth := fixedpoint.NewFromFloat(requiredDepthFloat) requiredDepth := fixedpoint.NewFromFloat(requiredDepthFloat)
accumulatedDepth = accumulatedDepth.Add(requiredDepth)
index := sideBook.IndexByQuoteVolumeDepth(requiredDepth) index := sideBook.IndexByQuoteVolumeDepth(accumulatedDepth)
pvs := types.PriceVolumeSlice{} pvs := types.PriceVolumeSlice{}
if index == -1 { if index == -1 {
@ -913,9 +917,7 @@ func (s *Strategy) generateMakerOrders(
continue continue
} }
log.Infof("side: %s required depth: %f, pvs: %+v", side, requiredDepth.Float64(), pvs) depthPrice := pvs.AverageDepthPriceByQuote(accumulatedDepth, 0)
depthPrice := pvs.AverageDepthPriceByQuote(fixedpoint.Zero, 0)
switch side { switch side {
case types.SideTypeBuy: case types.SideTypeBuy:
@ -935,9 +937,19 @@ func (s *Strategy) generateMakerOrders(
depthPrice = s.makerMarket.TruncatePrice(depthPrice) depthPrice = s.makerMarket.TruncatePrice(depthPrice)
if lastMakerPrice.Sign() > 0 && depthPrice.Compare(lastMakerPrice) == 0 {
switch side {
case types.SideTypeBuy:
depthPrice = depthPrice.Sub(s.makerMarket.TickSize)
case types.SideTypeSell:
depthPrice = depthPrice.Add(s.makerMarket.TickSize)
}
}
quantity := requiredDepth.Div(depthPrice) quantity := requiredDepth.Div(depthPrice)
quantity = s.makerMarket.TruncateQuantity(quantity) quantity = s.makerMarket.TruncateQuantity(quantity)
log.Infof("side: %s required depth: %f price: %f quantity: %f", side, requiredDepth.Float64(), depthPrice.Float64(), quantity.Float64())
s.logger.Infof("%d) %s required depth: %f %s@%s", i, side, accumulatedDepth.Float64(), quantity.String(), depthPrice.String())
switch side { switch side {
case types.SideTypeBuy: case types.SideTypeBuy:
@ -986,6 +998,8 @@ func (s *Strategy) generateMakerOrders(
Price: depthPrice, Price: depthPrice,
Quantity: quantity, Quantity: quantity,
}) })
lastMakerPrice = depthPrice
} }
} }
@ -1052,7 +1066,7 @@ func (s *Strategy) updateQuote(ctx context.Context, maxLayer int) {
balances, err := s.MakerOrderExecutor.Session().Exchange.QueryAccountBalances(ctx) balances, err := s.MakerOrderExecutor.Session().Exchange.QueryAccountBalances(ctx)
if err != nil { if err != nil {
log.WithError(err).Errorf("balance query error") s.logger.WithError(err).Errorf("balance query error")
return return
} }
@ -1068,22 +1082,22 @@ func (s *Strategy) updateQuote(ctx context.Context, maxLayer int) {
return return
} }
log.Infof("quote balance: %s, base balance: %s", quoteBalance, baseBalance) s.logger.Infof("quote balance: %s, base balance: %s", quoteBalance, baseBalance)
submitOrders, err := s.generateMakerOrders(s.sourceBook, maxLayer, baseBalance.Available, quoteBalance.Available) submitOrders, err := s.generateMakerOrders(s.sourceBook, maxLayer, baseBalance.Available, quoteBalance.Available)
if err != nil { if err != nil {
log.WithError(err).Errorf("generate order error") s.logger.WithError(err).Errorf("generate order error")
return return
} }
if len(submitOrders) == 0 { if len(submitOrders) == 0 {
log.Warnf("no orders are generated") s.logger.Warnf("no orders are generated")
return return
} }
_, err = s.MakerOrderExecutor.SubmitOrders(ctx, submitOrders...) _, err = s.MakerOrderExecutor.SubmitOrders(ctx, submitOrders...)
if err != nil { if err != nil {
log.WithError(err).Errorf("order error: %s", err.Error()) s.logger.WithError(err).Errorf("order error: %s", err.Error())
return return
} }
} }

View File

@ -6,6 +6,7 @@ import (
"testing" "testing"
"time" "time"
"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert" "github.com/stretchr/testify/assert"
"github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/bbgo"
@ -42,6 +43,7 @@ func TestStrategy_generateMakerOrders(t *testing.T) {
CrossExchangeMarketMakingStrategy: &CrossExchangeMarketMakingStrategy{ CrossExchangeMarketMakingStrategy: &CrossExchangeMarketMakingStrategy{
makerMarket: newTestBTCUSDTMarket(), makerMarket: newTestBTCUSDTMarket(),
}, },
logger: logrus.New(),
} }
pricingBook := types.NewStreamBook("BTCUSDT", types.ExchangeBinance) pricingBook := types.NewStreamBook("BTCUSDT", types.ExchangeBinance)
@ -70,6 +72,6 @@ func TestStrategy_generateMakerOrders(t *testing.T) {
{Side: types.SideTypeBuy, Price: Number("24800"), Quantity: Number("0.283123")}, // =~ $7021.4504, accumulated amount =~ $1000.00 + $7005.3111219 + $7021.4504 = $8005.3111219 + $7021.4504 =~ $15026.7615219 {Side: types.SideTypeBuy, Price: Number("24800"), Quantity: Number("0.283123")}, // =~ $7021.4504, accumulated amount =~ $1000.00 + $7005.3111219 + $7021.4504 = $8005.3111219 + $7021.4504 =~ $15026.7615219
{Side: types.SideTypeSell, Price: Number("25100"), Quantity: Number("0.03984")}, {Side: types.SideTypeSell, Price: Number("25100"), Quantity: Number("0.03984")},
{Side: types.SideTypeSell, Price: Number("25233.33"), Quantity: Number("0.2772")}, {Side: types.SideTypeSell, Price: Number("25233.33"), Quantity: Number("0.2772")},
{Side: types.SideTypeSell, Price: Number("25233.33"), Quantity: Number("0.277411")}, {Side: types.SideTypeSell, Price: Number("25300"), Quantity: Number("0.275845")},
}, orders) }, orders)
} }

View File

@ -168,7 +168,7 @@ func trimTrailingZero(a float64) string {
// String is for console output // String is for console output
func (trade Trade) String() string { func (trade Trade) String() string {
return fmt.Sprintf("TRADE %s %s %4s %-4s @ %-6s | AMOUNT %s | FEE %s %s | OrderID %d | TID %d | %s", return fmt.Sprintf("TRADE %s %s %4s %-4s @ %-6s | AMOUNT %s | FEE %s %s | OrderID %d | TID %d | %s | %s",
trade.Exchange.String(), trade.Exchange.String(),
trade.Symbol, trade.Symbol,
trade.Side, trade.Side,
@ -180,6 +180,7 @@ func (trade Trade) String() string {
trade.OrderID, trade.OrderID,
trade.ID, trade.ID,
trade.Time.Time().Format(time.StampMilli), trade.Time.Time().Format(time.StampMilli),
trade.Liquidity(),
) )
} }