mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
Merge pull request #1193 from c9s/fix/schedule-quantity-truncation
FIX: [schedule] fix quantity truncation add minBaseBalance config
This commit is contained in:
commit
d7cafcb65a
|
@ -34,8 +34,11 @@ type Strategy struct {
|
||||||
// Side is the order side type, which can be buy or sell
|
// Side is the order side type, which can be buy or sell
|
||||||
Side types.SideType `json:"side,omitempty"`
|
Side types.SideType `json:"side,omitempty"`
|
||||||
|
|
||||||
|
UseLimitOrder bool `json:"useLimitOrder"`
|
||||||
|
|
||||||
bbgo.QuantityOrAmount
|
bbgo.QuantityOrAmount
|
||||||
|
|
||||||
|
MinBaseBalance fixedpoint.Value `json:"minBaseBalance"`
|
||||||
MaxBaseBalance fixedpoint.Value `json:"maxBaseBalance"`
|
MaxBaseBalance fixedpoint.Value `json:"maxBaseBalance"`
|
||||||
|
|
||||||
BelowMovingAverage *bbgo.MovingAverageSettings `json:"belowMovingAverage,omitempty"`
|
BelowMovingAverage *bbgo.MovingAverageSettings `json:"belowMovingAverage,omitempty"`
|
||||||
|
@ -161,55 +164,82 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
// calculate quote quantity for balance checking
|
// calculate quote quantity for balance checking
|
||||||
quoteQuantity := quantity.Mul(closePrice)
|
quoteQuantity := quantity.Mul(closePrice)
|
||||||
|
|
||||||
// execute orders
|
|
||||||
switch side {
|
|
||||||
case types.SideTypeBuy:
|
|
||||||
if !s.MaxBaseBalance.IsZero() {
|
|
||||||
if baseBalance, ok := session.GetAccount().Balance(s.Market.BaseCurrency); ok {
|
|
||||||
total := baseBalance.Total()
|
|
||||||
if total.Add(quantity).Compare(s.MaxBaseBalance) >= 0 {
|
|
||||||
quantity = s.MaxBaseBalance.Sub(total)
|
|
||||||
quoteQuantity = quantity.Mul(closePrice)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
|
quoteBalance, ok := session.GetAccount().Balance(s.Market.QuoteCurrency)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("can not place scheduled %s order, quote balance %s is empty", s.Symbol, s.Market.QuoteCurrency)
|
log.Errorf("can not place scheduled %s order, quote balance %s is empty", s.Symbol, s.Market.QuoteCurrency)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if quoteBalance.Available.Compare(quoteQuantity) < 0 {
|
|
||||||
bbgo.Notify("Can not place scheduled %s order: quote balance %s is not enough: %v < %v", s.Symbol, s.Market.QuoteCurrency, quoteBalance.Available, quoteQuantity)
|
|
||||||
log.Errorf("can not place scheduled %s order: quote balance %s is not enough: %v < %v", s.Symbol, s.Market.QuoteCurrency, quoteBalance.Available, quoteQuantity)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
case types.SideTypeSell:
|
|
||||||
baseBalance, ok := session.GetAccount().Balance(s.Market.BaseCurrency)
|
baseBalance, ok := session.GetAccount().Balance(s.Market.BaseCurrency)
|
||||||
if !ok {
|
if !ok {
|
||||||
log.Errorf("can not place scheduled %s order, base balance %s is empty", s.Symbol, s.Market.BaseCurrency)
|
log.Errorf("can not place scheduled %s order, base balance %s is empty", s.Symbol, s.Market.BaseCurrency)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
quantity = fixedpoint.Min(quantity, baseBalance.Available)
|
totalBase := baseBalance.Total()
|
||||||
|
|
||||||
|
// execute orders
|
||||||
|
switch side {
|
||||||
|
case types.SideTypeBuy:
|
||||||
|
|
||||||
|
if !s.MaxBaseBalance.IsZero() {
|
||||||
|
if totalBase.Add(quantity).Compare(s.MaxBaseBalance) >= 0 {
|
||||||
|
quantity = s.MaxBaseBalance.Sub(totalBase)
|
||||||
quoteQuantity = quantity.Mul(closePrice)
|
quoteQuantity = quantity.Mul(closePrice)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if s.Market.IsDustQuantity(quantity, closePrice) {
|
// if min base balance is defined
|
||||||
log.Warnf("%s: quantity %f is too small", s.Symbol, quantity.Float64())
|
if !s.MinBaseBalance.IsZero() && s.MinBaseBalance.Compare(totalBase) > 0 {
|
||||||
|
quantity = fixedpoint.Max(quantity, s.MinBaseBalance.Sub(totalBase))
|
||||||
|
quantity = fixedpoint.Max(quantity, s.Market.MinQuantity)
|
||||||
|
}
|
||||||
|
|
||||||
|
if quoteBalance.Available.Compare(quoteQuantity) < 0 {
|
||||||
|
log.Errorf("can not place scheduled %s order: quote balance %s is not enough: %v < %v", s.Symbol, s.Market.QuoteCurrency, quoteBalance.Available, quoteQuantity)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
bbgo.Notify("Submitting scheduled %s order with quantity %s at price %s", s.Symbol, quantity.String(), closePrice.String())
|
case types.SideTypeSell:
|
||||||
_, err := s.orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
|
quantity = fixedpoint.Min(quantity, baseBalance.Available)
|
||||||
|
|
||||||
|
// skip sell if we hit the minBaseBalance line
|
||||||
|
if !s.MinBaseBalance.IsZero() {
|
||||||
|
if totalBase.Sub(quantity).Compare(s.MinBaseBalance) < 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
quoteQuantity = quantity.Mul(closePrice)
|
||||||
|
}
|
||||||
|
|
||||||
|
// truncate quantity by its step size
|
||||||
|
quantity = s.Market.TruncateQuantity(quantity)
|
||||||
|
|
||||||
|
if s.Market.IsDustQuantity(quantity, closePrice) {
|
||||||
|
log.Warnf("%s: quantity %f is too small, skip order", s.Symbol, quantity.Float64())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
submitOrder := types.SubmitOrder{
|
||||||
Symbol: s.Symbol,
|
Symbol: s.Symbol,
|
||||||
Side: side,
|
Side: side,
|
||||||
Type: types.OrderTypeMarket,
|
Type: types.OrderTypeMarket,
|
||||||
Quantity: quantity,
|
Quantity: quantity,
|
||||||
Market: s.Market,
|
Market: s.Market,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
if s.UseLimitOrder {
|
||||||
|
submitOrder.Type = types.OrderTypeLimit
|
||||||
|
submitOrder.Price = closePrice
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := s.orderExecutor.GracefulCancel(ctx); err != nil {
|
||||||
|
log.WithError(err).Errorf("cancel order error")
|
||||||
|
}
|
||||||
|
|
||||||
|
bbgo.Notify("Submitting scheduled %s order with quantity %s at price %s", s.Symbol, quantity.String(), closePrice.String())
|
||||||
|
_, err := s.orderExecutor.SubmitOrders(ctx, submitOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
bbgo.Notify("Can not place scheduled %s order: submit error %s", s.Symbol, err.Error())
|
bbgo.Notify("Can not place scheduled %s order: submit error %s", s.Symbol, err.Error())
|
||||||
log.WithError(err).Errorf("can not place scheduled %s order error", s.Symbol)
|
log.WithError(err).Errorf("can not place scheduled %s order error", s.Symbol)
|
||||||
|
|
Loading…
Reference in New Issue
Block a user