Skip to content

Commit 62eed96

Browse files
committed
grid2: round down quoteQuantity/baseQuantity after the fee reduction
1 parent b04492a commit 62eed96

File tree

2 files changed

+25
-24
lines changed

2 files changed

+25
-24
lines changed

pkg/strategy/grid2/strategy.go

+23-22
Original file line numberDiff line numberDiff line change
@@ -401,25 +401,14 @@ func (s *Strategy) processFilledOrder(o types.Order) {
401401
// will be used for calculating quantity
402402
orderExecutedQuoteAmount := o.Quantity.Mul(executedPrice)
403403

404-
// collect trades
405-
feeQuantityReduction := fixedpoint.Zero
406-
feeCurrency := ""
407-
feePrec := 2
408-
409-
// feeQuantityReduction calculation is used to reduce the order quantity
404+
// collect trades for fee
405+
// fee calculation is used to reduce the order quantity
410406
// because when 1.0 BTC buy order is filled without FEE token, then we will actually get 1.0 * (1 - feeRate) BTC
411407
// if we don't reduce the sell quantity, than we might fail to place the sell order
412-
feeQuantityReduction, feeCurrency = s.aggregateOrderFee(o)
408+
fee, feeCurrency := s.aggregateOrderFee(o)
413409
s.logger.Infof("GRID ORDER #%d %s FEE: %s %s",
414410
o.OrderID, o.Side,
415-
feeQuantityReduction.String(), feeCurrency)
416-
417-
feeQuantityReduction, feePrec = roundUpMarketQuantity(s.Market, feeQuantityReduction, feeCurrency)
418-
s.logger.Infof("GRID ORDER #%d %s FEE (rounding precision %d): %s %s",
419-
o.OrderID, o.Side,
420-
feePrec,
421-
feeQuantityReduction.String(),
422-
feeCurrency)
411+
fee.String(), feeCurrency)
423412

424413
switch o.Side {
425414
case types.SideTypeSell:
@@ -437,9 +426,15 @@ func (s *Strategy) processFilledOrder(o types.Order) {
437426
if s.Compound || s.EarnBase {
438427
// if it's not using the platform fee currency, reduce the quote quantity for the buy order
439428
if feeCurrency == s.Market.QuoteCurrency {
440-
orderExecutedQuoteAmount = orderExecutedQuoteAmount.Sub(feeQuantityReduction)
429+
orderExecutedQuoteAmount = orderExecutedQuoteAmount.Sub(fee)
441430
}
442431

432+
// for quote amount, always round down with price precision to prevent the quote currency fund locking rounding issue
433+
origQuoteAmount := orderExecutedQuoteAmount
434+
orderExecutedQuoteAmount = orderExecutedQuoteAmount.Round(s.Market.PricePrecision, fixedpoint.Down)
435+
436+
s.logger.Infof("round down buy order quote quantity %s to %s by quote quantity precision %d", origQuoteAmount.String(), orderExecutedQuoteAmount.String(), s.Market.PricePrecision)
437+
443438
newQuantity = fixedpoint.Max(orderExecutedQuoteAmount.Div(newPrice), s.Market.MinQuantity)
444439
} else if s.QuantityOrAmount.Quantity.Sign() > 0 {
445440
newQuantity = s.QuantityOrAmount.Quantity
@@ -449,10 +444,6 @@ func (s *Strategy) processFilledOrder(o types.Order) {
449444
profit = s.calculateProfit(o, newPrice, newQuantity)
450445

451446
case types.SideTypeBuy:
452-
if feeCurrency == s.Market.BaseCurrency {
453-
newQuantity = newQuantity.Sub(feeQuantityReduction)
454-
}
455-
456447
newSide = types.SideTypeSell
457448
if !s.ProfitSpread.IsZero() {
458449
newPrice = newPrice.Add(s.ProfitSpread)
@@ -462,9 +453,19 @@ func (s *Strategy) processFilledOrder(o types.Order) {
462453
}
463454
}
464455

456+
if feeCurrency == s.Market.BaseCurrency {
457+
newQuantity = newQuantity.Sub(fee)
458+
}
459+
460+
// if EarnBase is enabled, we should sell less to get the same quote amount back
465461
if s.EarnBase {
466-
newQuantity = fixedpoint.Max(orderExecutedQuoteAmount.Div(newPrice).Sub(feeQuantityReduction), s.Market.MinQuantity)
462+
newQuantity = fixedpoint.Max(orderExecutedQuoteAmount.Div(newPrice).Sub(fee), s.Market.MinQuantity)
467463
}
464+
465+
// always round down the base quantity for placing sell order to avoid the base currency fund locking issue
466+
origQuantity := newQuantity
467+
newQuantity = newQuantity.Round(s.Market.VolumePrecision, fixedpoint.Down)
468+
s.logger.Infof("round down sell order quantity %s to %s by base quantity precision %d", origQuantity.String(), newQuantity.String(), s.Market.VolumePrecision)
468469
}
469470

470471
orderForm := types.SubmitOrder{
@@ -1869,4 +1870,4 @@ func roundUpMarketQuantity(market types.Market, v fixedpoint.Value, c string) (f
18691870
}
18701871

18711872
return v.Round(prec, fixedpoint.Up), prec
1872-
}
1873+
}

pkg/strategy/grid2/strategy_test.go

+2-2
Original file line numberDiff line numberDiff line change
@@ -706,7 +706,7 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
706706
Type: types.OrderTypeLimit,
707707
Side: types.SideTypeBuy,
708708
Price: number(11_000.0),
709-
Quantity: number(0.09999999),
709+
Quantity: number(0.09999909),
710710
TimeInForce: types.TimeInForceGTC,
711711
Market: s.Market,
712712
Tag: orderTag,
@@ -797,7 +797,7 @@ func TestStrategy_handleOrderFilled(t *testing.T) {
797797
Symbol: "BTCUSDT",
798798
Type: types.OrderTypeLimit,
799799
Price: number(12_000.0),
800-
Quantity: number(0.09998999),
800+
Quantity: number(0.09999),
801801
Side: types.SideTypeSell,
802802
TimeInForce: types.TimeInForceGTC,
803803
Market: s.Market,

0 commit comments

Comments
 (0)