package common import ( "fmt" "github.com/c9s/bbgo/pkg/fixedpoint" ) var ( zero = fixedpoint.Zero two = fixedpoint.NewFromFloat(2.0) ) type InventorySkewBidAskRatios struct { BidRatio fixedpoint.Value AskRatio fixedpoint.Value } // https://hummingbot.org/strategy-configs/inventory-skew/ // https://github.com/hummingbot/hummingbot/blob/31fc61d5e71b2c15732142d30983f3ea2be4d466/hummingbot/strategy/pure_market_making/inventory_skew_calculator.pyx type InventorySkew struct { InventoryRangeMultiplier fixedpoint.Value `json:"inventoryRangeMultiplier"` 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) inventoryRange := s.InventoryRangeMultiplier.Mul(quantity.Mul(two)).Mul(price) leftLimit := s.TargetBaseRatio.Mul(totalValue).Sub(inventoryRange) rightLimit := s.TargetBaseRatio.Mul(totalValue).Add(inventoryRange) bidAdjustment := interp(baseValue, leftLimit, rightLimit, two, zero).Clamp(zero, two) askAdjustment := interp(baseValue, leftLimit, rightLimit, zero, two).Clamp(zero, two) return &InventorySkewBidAskRatios{ BidRatio: bidAdjustment, AskRatio: askAdjustment, } } func interp(x, x0, x1, y0, y1 fixedpoint.Value) fixedpoint.Value { return y0.Add(x.Sub(x0).Mul(y1.Sub(y0)).Div(x1.Sub(x0))) }