Merge pull request #1390 from c9s/narumi/rebalance/fix

FIX: [rebalance] fix buy quantity
This commit is contained in:
なるみ 2023-11-03 19:53:15 +08:00 committed by GitHub
commit d4ac18241c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -40,7 +40,6 @@ type Strategy struct {
DryRun bool `json:"dryRun"` DryRun bool `json:"dryRun"`
OnStart bool `json:"onStart"` // rebalance on start OnStart bool `json:"onStart"` // rebalance on start
session *bbgo.ExchangeSession
symbols []string symbols []string
markets map[string]types.Market markets map[string]types.Market
activeOrderBook *bbgo.ActiveOrderBook activeOrderBook *bbgo.ActiveOrderBook
@ -97,11 +96,9 @@ func (s *Strategy) Validate() error {
func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {} func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {}
func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error { func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.ExchangeSession) error {
s.session = session
s.markets = make(map[string]types.Market) s.markets = make(map[string]types.Market)
for _, symbol := range s.symbols { for _, symbol := range s.symbols {
market, ok := s.session.Market(symbol) market, ok := session.Market(symbol)
if !ok { if !ok {
return fmt.Errorf("market %s not found", symbol) return fmt.Errorf("market %s not found", symbol)
} }
@ -112,7 +109,7 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
s.MultiMarketStrategy.Initialize(ctx, s.Environment, session, s.markets, ID) s.MultiMarketStrategy.Initialize(ctx, s.Environment, session, s.markets, ID)
s.activeOrderBook = bbgo.NewActiveOrderBook("") s.activeOrderBook = bbgo.NewActiveOrderBook("")
s.activeOrderBook.BindStream(s.session.UserDataStream) s.activeOrderBook.BindStream(session.UserDataStream)
session.UserDataStream.OnStart(func() { session.UserDataStream.OnStart(func() {
if s.OnStart { if s.OnStart {
@ -137,7 +134,7 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
func (s *Strategy) rebalance(ctx context.Context) { func (s *Strategy) rebalance(ctx context.Context) {
// cancel active orders before rebalance // cancel active orders before rebalance
if err := s.session.Exchange.CancelOrders(ctx, s.activeOrderBook.Orders()...); err != nil { if err := s.Session.Exchange.CancelOrders(ctx, s.activeOrderBook.Orders()...); err != nil {
log.WithError(err).Errorf("failed to cancel orders") log.WithError(err).Errorf("failed to cancel orders")
} }
@ -174,7 +171,7 @@ func (s *Strategy) queryMidPrices(ctx context.Context) (types.ValueMap, error) {
continue continue
} }
ticker, err := s.session.Exchange.QueryTicker(ctx, currency+s.QuoteCurrency) ticker, err := s.Session.Exchange.QueryTicker(ctx, currency+s.QuoteCurrency)
if err != nil { if err != nil {
return nil, err return nil, err
} }
@ -186,7 +183,7 @@ func (s *Strategy) queryMidPrices(ctx context.Context) (types.ValueMap, error) {
func (s *Strategy) selectBalances() (types.BalanceMap, error) { func (s *Strategy) selectBalances() (types.BalanceMap, error) {
m := make(types.BalanceMap) m := make(types.BalanceMap)
balances := s.session.GetAccount().Balances() balances := s.Session.GetAccount().Balances()
for currency := range s.TargetWeights { for currency := range s.TargetWeights {
balance, ok := balances[currency] balance, ok := balances[currency]
if !ok { if !ok {
@ -235,28 +232,36 @@ func (s *Strategy) generateOrder(ctx context.Context) (*types.SubmitOrder, error
quantity = quantity.Abs() quantity = quantity.Abs()
} }
if s.MaxAmount.Float64() > 0 { ticker, err := s.Session.Exchange.QueryTicker(ctx, symbol)
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, midPrice, s.MaxAmount) if err != nil {
log.Infof("adjust quantity %s (%s %s @ %s) by max amount %s", return nil, err
quantity.String(),
symbol,
side.String(),
midPrice.String(),
s.MaxAmount.String())
} }
var price fixedpoint.Value
if side == types.SideTypeBuy { if side == types.SideTypeBuy {
quantity = fixedpoint.Min(quantity, balances[s.QuoteCurrency].Available.Div(midPrice)) price = ticker.Buy
quantity = fixedpoint.Min(quantity, balances[s.QuoteCurrency].Available.Div(ticker.Sell))
} else if side == types.SideTypeSell { } else if side == types.SideTypeSell {
price = ticker.Sell
quantity = fixedpoint.Min(quantity, balances[market.BaseCurrency].Available) quantity = fixedpoint.Min(quantity, balances[market.BaseCurrency].Available)
} }
if market.IsDustQuantity(quantity, midPrice) { if s.MaxAmount.Float64() > 0 {
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, price, s.MaxAmount)
log.Infof("adjusted quantity %s (%s %s @ %s) by max amount %s",
quantity.String(),
symbol,
side.String(),
price.String(),
s.MaxAmount.String())
}
if market.IsDustQuantity(quantity, price) {
log.Infof("quantity %s (%s %s @ %s) is dust quantity, skip", log.Infof("quantity %s (%s %s @ %s) is dust quantity, skip",
quantity.String(), quantity.String(),
symbol, symbol,
side.String(), side.String(),
midPrice.String()) price.String())
continue continue
} }
@ -265,7 +270,7 @@ func (s *Strategy) generateOrder(ctx context.Context) (*types.SubmitOrder, error
Side: side, Side: side,
Type: s.OrderType, Type: s.OrderType,
Quantity: quantity, Quantity: quantity,
Price: midPrice, Price: price,
}, nil }, nil
} }
return nil, nil return nil, nil