From fa2c0be6a3696ec949f48ccca86f62d5488a4a48 Mon Sep 17 00:00:00 2001 From: c9s Date: Sun, 17 Nov 2024 17:30:48 +0800 Subject: [PATCH] xdepthmaker: improve and fix order generator --- pkg/strategy/xdepthmaker/strategy.go | 28 +++++++++++++---------- pkg/strategy/xdepthmaker/strategy_test.go | 2 +- pkg/types/price_volume_slice.go | 2 ++ 3 files changed, 19 insertions(+), 13 deletions(-) diff --git a/pkg/strategy/xdepthmaker/strategy.go b/pkg/strategy/xdepthmaker/strategy.go index 8b48e4483..6cd827cc0 100644 --- a/pkg/strategy/xdepthmaker/strategy.go +++ b/pkg/strategy/xdepthmaker/strategy.go @@ -1037,11 +1037,17 @@ func (s *Strategy) generateMakerOrders( } if lastMakerPrice.Sign() > 0 && depthPrice.Compare(lastMakerPrice) == 0 { - switch side { - case types.SideTypeBuy: - depthPrice = depthPrice.Sub(s.makerMarket.TickSize.Mul(s.Pips)) - case types.SideTypeSell: - depthPrice = depthPrice.Add(s.makerMarket.TickSize.Mul(s.Pips)) + tickSize := s.makerMarket.TickSize + if tickSize.IsZero() { + s.logger.Warnf("maker market tick size is zero") + } else if tickSize.Sign() > 0 { + tickSize = s.makerMarket.TickSize.Mul(s.Pips) + switch side { + case types.SideTypeBuy: + depthPrice = depthPrice.Sub(tickSize) + case types.SideTypeSell: + depthPrice = depthPrice.Add(tickSize) + } } } @@ -1056,15 +1062,15 @@ func (s *Strategy) generateMakerOrders( accumulatedBidQuantity = accumulatedBidQuantity.Add(quantity) quoteQuantity := fixedpoint.Mul(quantity, depthPrice) - quoteQuantity = quoteQuantity.Round(s.makerMarket.PricePrecision, fixedpoint.Up) + quoteQuantity = quoteQuantity.Round(s.makerMarket.PricePrecision, fixedpoint.Down) if !availableSideBalance.Eq(fixedpoint.PosInf) && availableSideBalance.Compare(quoteQuantity) <= 0 { quoteQuantity = availableSideBalance quantity = quoteQuantity.Div(depthPrice).Round(s.makerMarket.PricePrecision, fixedpoint.Down) } - if quantity.Compare(s.makerMarket.MinQuantity) <= 0 || quoteQuantity.Compare(s.makerMarket.MinNotional) <= 0 { - break layerLoop + if s.makerMarket.IsDustQuantity(quantity, depthPrice) { + continue layerLoop } availableSideBalance = availableSideBalance.Sub(quoteQuantity) @@ -1073,19 +1079,17 @@ func (s *Strategy) generateMakerOrders( case types.SideTypeSell: quantity = quantity.Sub(accumulatedAskQuantity) - quoteQuantity := quantity.Mul(depthPrice) // balance check if !availableSideBalance.Eq(fixedpoint.PosInf) && availableSideBalance.Compare(quantity) <= 0 { break layerLoop } - if quantity.Compare(s.makerMarket.MinQuantity) <= 0 || quoteQuantity.Compare(s.makerMarket.MinNotional) <= 0 { - break layerLoop + if s.makerMarket.IsDustQuantity(quantity, depthPrice) { + continue layerLoop } availableSideBalance = availableSideBalance.Sub(quantity) - accumulatedAskQuantity = accumulatedAskQuantity.Add(quantity) } diff --git a/pkg/strategy/xdepthmaker/strategy_test.go b/pkg/strategy/xdepthmaker/strategy_test.go index d81adcf2a..6eb247a2b 100644 --- a/pkg/strategy/xdepthmaker/strategy_test.go +++ b/pkg/strategy/xdepthmaker/strategy_test.go @@ -71,7 +71,7 @@ func TestStrategy_generateMakerOrders(t *testing.T) { {Side: types.SideTypeBuy, Price: Number("24866.66"), Quantity: Number("0.281715")}, // =~ $7005.3111219, accumulated amount =~ $1000.00 + $7005.3111219 = $8005.3111219 {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.34"), Quantity: Number("0.2772")}, {Side: types.SideTypeSell, Price: Number("25300"), Quantity: Number("0.275845")}, }, orders) } diff --git a/pkg/types/price_volume_slice.go b/pkg/types/price_volume_slice.go index 08255747e..092c652a5 100644 --- a/pkg/types/price_volume_slice.go +++ b/pkg/types/price_volume_slice.go @@ -254,6 +254,8 @@ func ParsePriceVolumeSliceJSON(b []byte) (slice PriceVolumeSlice, err error) { return slice, nil } +// AverageDepthPriceByQuote calculates the average price by the required quote depth +// maxLevel is the maximum level to calculate the average price func (slice PriceVolumeSlice) AverageDepthPriceByQuote(requiredDepthInQuote fixedpoint.Value, maxLevel int) fixedpoint.Value { if len(slice) == 0 { return fixedpoint.Zero