From f160ea856fc2c0a03b3245936424e894137a7983 Mon Sep 17 00:00:00 2001 From: narumi <4680567+narumiruna@users.noreply.github.com> Date: Thu, 21 Dec 2023 16:29:46 +0800 Subject: [PATCH] apply inventory-skew to fixedmaker --- config/fixedmaker.yaml | 11 +++++++-- pkg/strategy/fixedmaker/inventory_skew.go | 13 +++++++++++ pkg/strategy/fixedmaker/strategy.go | 27 ++++++++++++++++++++--- 3 files changed, 46 insertions(+), 5 deletions(-) diff --git a/config/fixedmaker.yaml b/config/fixedmaker.yaml index 63d3ee058..d66a426f7 100644 --- a/config/fixedmaker.yaml +++ b/config/fixedmaker.yaml @@ -16,12 +16,19 @@ exchangeStrategies: - on: max fixedmaker: symbol: USDCUSDT - interval: 5m + interval: 1m halfSpread: 0.05% quantity: 15 orderType: LIMIT_MAKER - dryRun: false + dryRun: true positionHardLimit: 1500 maxPositionQuantity: 1500 circuitBreakLossThreshold: -0.15 + circuitBreakEMA: + interval: 1m + window: 14 + + inventorySkew: + inventoryRangeMultiplier: 1.0 + targetBaseRatio: 0.5 diff --git a/pkg/strategy/fixedmaker/inventory_skew.go b/pkg/strategy/fixedmaker/inventory_skew.go index fbbc03c60..0dafe474a 100644 --- a/pkg/strategy/fixedmaker/inventory_skew.go +++ b/pkg/strategy/fixedmaker/inventory_skew.go @@ -1,6 +1,8 @@ package fixedmaker import ( + "fmt" + "github.com/c9s/bbgo/pkg/fixedpoint" ) @@ -21,6 +23,17 @@ type InventorySkew struct { TargetBaseRatio fixedpoint.Value `json:"targetBaseRatio"` } +func (s *InventorySkew) Validate() error { + if s.InventoryRangeMultiplier.Float64() < 0 { + return fmt.Errorf("inventoryRangeMultiplier should be positive") + } + + if s.TargetBaseRatio.Float64() < 0 { + return fmt.Errorf("targetBaseRatio should be positive") + } + return nil +} + func (s *InventorySkew) CalculateBidAskRatios(quantity fixedpoint.Value, price fixedpoint.Value, baseBalance fixedpoint.Value, quoteBalance fixedpoint.Value) *InventorySkewBidAskRatios { baseValue := baseBalance.Mul(price) totalValue := baseValue.Add(quoteBalance) diff --git a/pkg/strategy/fixedmaker/strategy.go b/pkg/strategy/fixedmaker/strategy.go index af561de09..f08f6c4b4 100644 --- a/pkg/strategy/fixedmaker/strategy.go +++ b/pkg/strategy/fixedmaker/strategy.go @@ -35,6 +35,8 @@ type Strategy struct { OrderType types.OrderType `json:"orderType"` DryRun bool `json:"dryRun"` + InventorySkew InventorySkew `json:"inventorySkew"` + activeOrderBook *bbgo.ActiveOrderBook } @@ -70,6 +72,10 @@ func (s *Strategy) Validate() error { if s.HalfSpread.Float64() <= 0 { return fmt.Errorf("halfSpread should be positive") } + + if err := s.InventorySkew.Validate(); err != nil { + return err + } return nil } @@ -123,7 +129,7 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo. } func (s *Strategy) cancelOrders(ctx context.Context) { - if err := s.Session.Exchange.CancelOrders(ctx, s.activeOrderBook.Orders()...); err != nil { + if err := s.activeOrderBook.GracefulCancel(ctx, s.Session.Exchange); err != nil { log.WithError(err).Errorf("failed to cancel orders") } } @@ -180,6 +186,21 @@ func (s *Strategy) generateOrders(ctx context.Context) ([]types.SubmitOrder, err buyPrice := midPrice.Mul(fixedpoint.One.Sub(s.HalfSpread)).Round(s.Market.PricePrecision, fixedpoint.Down) log.Infof("sell price: %s, buy price: %s", sellPrice.String(), buyPrice.String()) + buyQuantity := s.Quantity + sellQuantity := s.Quantity + if !s.InventorySkew.InventoryRangeMultiplier.IsZero() { + ratios := s.InventorySkew.CalculateBidAskRatios( + s.Quantity, + midPrice, + baseBalance.Total(), + quoteBalance.Total(), + ) + log.Infof("bid ratio: %s, ask ratio: %s", ratios.bidRatio.String(), ratios.askRatio.String()) + buyQuantity = s.Quantity.Mul(ratios.bidRatio) + sellQuantity = s.Quantity.Mul(ratios.askRatio) + log.Infof("buy quantity: %s, sell quantity: %s", buyQuantity.String(), sellQuantity.String()) + } + // check balance and generate orders amount := s.Quantity.Mul(buyPrice) if quoteBalance.Available.Compare(amount) > 0 { @@ -188,7 +209,7 @@ func (s *Strategy) generateOrders(ctx context.Context) ([]types.SubmitOrder, err Side: types.SideTypeBuy, Type: s.OrderType, Price: buyPrice, - Quantity: s.Quantity, + Quantity: buyQuantity, }) } else { log.Infof("not enough quote balance to buy, available: %s, amount: %s", quoteBalance.Available, amount) @@ -200,7 +221,7 @@ func (s *Strategy) generateOrders(ctx context.Context) ([]types.SubmitOrder, err Side: types.SideTypeSell, Type: s.OrderType, Price: sellPrice, - Quantity: s.Quantity, + Quantity: sellQuantity, }) } else { log.Infof("not enough base balance to sell, available: %s, quantity: %s", baseBalance.Available, s.Quantity)