From 7f0a4a9953c655b2b5fc1d8c26f77cf29aee0168 Mon Sep 17 00:00:00 2001 From: narumi <4680567+narumiruna@users.noreply.github.com> Date: Thu, 21 Dec 2023 16:34:05 +0800 Subject: [PATCH] apply inventory-skew to xfixedmaker --- config/xfixedmaker.yaml | 9 +++-- pkg/strategy/fixedmaker/inventory_skew.go | 8 ++--- .../fixedmaker/inventory_skew_test.go | 20 +++++------ pkg/strategy/fixedmaker/strategy.go | 6 ++-- pkg/strategy/xfixedmaker/strategy.go | 33 +++++++++++++++---- 5 files changed, 51 insertions(+), 25 deletions(-) diff --git a/config/xfixedmaker.yaml b/config/xfixedmaker.yaml index bfee2e771..b1ebaf01f 100644 --- a/config/xfixedmaker.yaml +++ b/config/xfixedmaker.yaml @@ -6,6 +6,7 @@ sessions: binance: exchange: binance envVarPrefix: binance + publicOnly: true backtest: startTime: "2023-01-01" @@ -25,11 +26,11 @@ crossExchangeStrategies: - xfixedmaker: tradingExchange: max symbol: BTCUSDT - interval: 5m + interval: 1m halfSpread: 0.01% quantity: 0.005 orderType: LIMIT_MAKER - dryRun: false + dryRun: true referenceExchange: binance referencePriceEMA: @@ -44,3 +45,7 @@ crossExchangeStrategies: 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 0dafe474a..dae68e7c4 100644 --- a/pkg/strategy/fixedmaker/inventory_skew.go +++ b/pkg/strategy/fixedmaker/inventory_skew.go @@ -12,8 +12,8 @@ var ( ) type InventorySkewBidAskRatios struct { - bidRatio fixedpoint.Value - askRatio fixedpoint.Value + BidRatio fixedpoint.Value + AskRatio fixedpoint.Value } // https://hummingbot.org/strategy-configs/inventory-skew/ @@ -46,8 +46,8 @@ func (s *InventorySkew) CalculateBidAskRatios(quantity fixedpoint.Value, price f askAdjustment := interp(baseValue, leftLimit, rightLimit, zero, two).Clamp(zero, two) return &InventorySkewBidAskRatios{ - bidRatio: bidAdjustment, - askRatio: askAdjustment, + BidRatio: bidAdjustment, + AskRatio: askAdjustment, } } diff --git a/pkg/strategy/fixedmaker/inventory_skew_test.go b/pkg/strategy/fixedmaker/inventory_skew_test.go index 8c7313997..cd40931a1 100644 --- a/pkg/strategy/fixedmaker/inventory_skew_test.go +++ b/pkg/strategy/fixedmaker/inventory_skew_test.go @@ -21,8 +21,8 @@ func Test_InventorySkew_CalculateBidAskRatios(t *testing.T) { baseBalance: fixedpoint.NewFromFloat(1.0), quoteBalance: fixedpoint.NewFromFloat(1000), want: &InventorySkewBidAskRatios{ - bidRatio: fixedpoint.NewFromFloat(1.0), - askRatio: fixedpoint.NewFromFloat(1.0), + BidRatio: fixedpoint.NewFromFloat(1.0), + AskRatio: fixedpoint.NewFromFloat(1.0), }, }, { @@ -31,8 +31,8 @@ func Test_InventorySkew_CalculateBidAskRatios(t *testing.T) { baseBalance: fixedpoint.NewFromFloat(1.0), quoteBalance: fixedpoint.NewFromFloat(1200), want: &InventorySkewBidAskRatios{ - bidRatio: fixedpoint.NewFromFloat(1.5), - askRatio: fixedpoint.NewFromFloat(0.5), + BidRatio: fixedpoint.NewFromFloat(1.5), + AskRatio: fixedpoint.NewFromFloat(0.5), }, }, { @@ -41,8 +41,8 @@ func Test_InventorySkew_CalculateBidAskRatios(t *testing.T) { baseBalance: fixedpoint.NewFromFloat(0.0), quoteBalance: fixedpoint.NewFromFloat(10000), want: &InventorySkewBidAskRatios{ - bidRatio: fixedpoint.NewFromFloat(2.0), - askRatio: fixedpoint.NewFromFloat(0.0), + BidRatio: fixedpoint.NewFromFloat(2.0), + AskRatio: fixedpoint.NewFromFloat(0.0), }, }, { @@ -51,8 +51,8 @@ func Test_InventorySkew_CalculateBidAskRatios(t *testing.T) { baseBalance: fixedpoint.NewFromFloat(2.0), quoteBalance: fixedpoint.NewFromFloat(0.0), want: &InventorySkewBidAskRatios{ - bidRatio: fixedpoint.NewFromFloat(0.0), - askRatio: fixedpoint.NewFromFloat(2.0), + BidRatio: fixedpoint.NewFromFloat(0.0), + AskRatio: fixedpoint.NewFromFloat(2.0), }, }, } @@ -63,7 +63,7 @@ func Test_InventorySkew_CalculateBidAskRatios(t *testing.T) { TargetBaseRatio: fixedpoint.NewFromFloat(0.5), } got := s.CalculateBidAskRatios(c.quantity, c.price, c.baseBalance, c.quoteBalance) - assert.Equal(t, c.want.bidRatio.Float64(), got.bidRatio.Float64()) - assert.Equal(t, c.want.askRatio.Float64(), got.askRatio.Float64()) + assert.Equal(t, c.want.BidRatio.Float64(), got.BidRatio.Float64()) + assert.Equal(t, c.want.AskRatio.Float64(), got.AskRatio.Float64()) } } diff --git a/pkg/strategy/fixedmaker/strategy.go b/pkg/strategy/fixedmaker/strategy.go index f08f6c4b4..8046636a8 100644 --- a/pkg/strategy/fixedmaker/strategy.go +++ b/pkg/strategy/fixedmaker/strategy.go @@ -195,9 +195,9 @@ func (s *Strategy) generateOrders(ctx context.Context) ([]types.SubmitOrder, err 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("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()) } diff --git a/pkg/strategy/xfixedmaker/strategy.go b/pkg/strategy/xfixedmaker/strategy.go index 2e018f571..45d1bd78a 100644 --- a/pkg/strategy/xfixedmaker/strategy.go +++ b/pkg/strategy/xfixedmaker/strategy.go @@ -10,6 +10,7 @@ import ( "github.com/c9s/bbgo/pkg/bbgo" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/strategy/common" + "github.com/c9s/bbgo/pkg/strategy/fixedmaker" "github.com/c9s/bbgo/pkg/types" ) @@ -35,9 +36,10 @@ type Strategy struct { OrderType types.OrderType `json:"orderType"` DryRun bool `json:"dryRun"` - ReferenceExchange string `json:"referenceExchange"` - ReferencePriceEMA types.IntervalWindow `json:"referencePriceEMA"` - OrderPriceLossThreshold fixedpoint.Value `json:"orderPriceLossThreshold"` + ReferenceExchange string `json:"referenceExchange"` + ReferencePriceEMA types.IntervalWindow `json:"referencePriceEMA"` + OrderPriceLossThreshold fixedpoint.Value `json:"orderPriceLossThreshold"` + InventorySkew fixedmaker.InventorySkew `json:"inventorySkew"` market types.Market activeOrderBook *bbgo.ActiveOrderBook @@ -73,6 +75,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 } @@ -155,7 +161,7 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se } 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") } } @@ -212,6 +218,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 { @@ -221,7 +242,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 { @@ -238,7 +259,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("ref price risk control triggered, not placing sell order")