diff --git a/pkg/bbgo/activeorderbook.go b/pkg/bbgo/activeorderbook.go index f306d5234..5a5559f46 100644 --- a/pkg/bbgo/activeorderbook.go +++ b/pkg/bbgo/activeorderbook.go @@ -255,10 +255,9 @@ func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange, if cancelAll { orders = b.Orders() } else { - // partial cancel + // for partial cancel orders = filterCanceledOrders(orders) } - } else { log.Warnf("[ActiveOrderBook] using open orders API to verify the active orders...") diff --git a/pkg/strategy/xdepthmaker/strategy.go b/pkg/strategy/xdepthmaker/strategy.go index 391e30bf5..74c2477f6 100644 --- a/pkg/strategy/xdepthmaker/strategy.go +++ b/pkg/strategy/xdepthmaker/strategy.go @@ -883,6 +883,9 @@ func (s *Strategy) generateMakerOrders( continue } + accumulatedDepth := fixedpoint.Zero + lastMakerPrice := fixedpoint.Zero + layerLoop: for i := 1; i <= maxLayer; i++ { // 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 := fixedpoint.NewFromFloat(requiredDepthFloat) + accumulatedDepth = accumulatedDepth.Add(requiredDepth) - index := sideBook.IndexByQuoteVolumeDepth(requiredDepth) + index := sideBook.IndexByQuoteVolumeDepth(accumulatedDepth) pvs := types.PriceVolumeSlice{} if index == -1 { @@ -913,9 +917,7 @@ func (s *Strategy) generateMakerOrders( continue } - log.Infof("side: %s required depth: %f, pvs: %+v", side, requiredDepth.Float64(), pvs) - - depthPrice := pvs.AverageDepthPriceByQuote(fixedpoint.Zero, 0) + depthPrice := pvs.AverageDepthPriceByQuote(accumulatedDepth, 0) switch side { case types.SideTypeBuy: @@ -935,9 +937,19 @@ func (s *Strategy) generateMakerOrders( 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 = 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 { case types.SideTypeBuy: @@ -986,6 +998,8 @@ func (s *Strategy) generateMakerOrders( Price: depthPrice, 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) if err != nil { - log.WithError(err).Errorf("balance query error") + s.logger.WithError(err).Errorf("balance query error") return } @@ -1068,22 +1082,22 @@ func (s *Strategy) updateQuote(ctx context.Context, maxLayer int) { 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) if err != nil { - log.WithError(err).Errorf("generate order error") + s.logger.WithError(err).Errorf("generate order error") return } if len(submitOrders) == 0 { - log.Warnf("no orders are generated") + s.logger.Warnf("no orders are generated") return } _, err = s.MakerOrderExecutor.SubmitOrders(ctx, submitOrders...) if err != nil { - log.WithError(err).Errorf("order error: %s", err.Error()) + s.logger.WithError(err).Errorf("order error: %s", err.Error()) return } } diff --git a/pkg/strategy/xdepthmaker/strategy_test.go b/pkg/strategy/xdepthmaker/strategy_test.go index 3ba221425..d81adcf2a 100644 --- a/pkg/strategy/xdepthmaker/strategy_test.go +++ b/pkg/strategy/xdepthmaker/strategy_test.go @@ -6,6 +6,7 @@ import ( "testing" "time" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/c9s/bbgo/pkg/bbgo" @@ -42,6 +43,7 @@ func TestStrategy_generateMakerOrders(t *testing.T) { CrossExchangeMarketMakingStrategy: &CrossExchangeMarketMakingStrategy{ makerMarket: newTestBTCUSDTMarket(), }, + logger: logrus.New(), } 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.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.277411")}, + {Side: types.SideTypeSell, Price: Number("25300"), Quantity: Number("0.275845")}, }, orders) } diff --git a/pkg/types/trade.go b/pkg/types/trade.go index 3e9a6c520..ad5ca6d1f 100644 --- a/pkg/types/trade.go +++ b/pkg/types/trade.go @@ -168,7 +168,7 @@ func trimTrailingZero(a float64) string { // String is for console output 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.Symbol, trade.Side, @@ -180,6 +180,7 @@ func (trade Trade) String() string { trade.OrderID, trade.ID, trade.Time.Time().Format(time.StampMilli), + trade.Liquidity(), ) }