mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 01:01:56 +00:00
apply inventory-skew to xfixedmaker
This commit is contained in:
parent
f160ea856f
commit
7f0a4a9953
|
@ -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
|
||||
|
|
|
@ -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,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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())
|
||||
}
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in New Issue
Block a user