Merge pull request #1552 from c9s/kbearXD/dca2/quote-investment-modify

FIX: [dca2] all the profit will use in the first order of the next round
This commit is contained in:
kbearXD 2024-03-04 14:59:50 +08:00 committed by GitHub
commit 449c0abeb0
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 33 additions and 8 deletions

View File

@ -21,7 +21,7 @@ func (s *Strategy) placeOpenPositionOrders(ctx context.Context) error {
return err
}
orders, err := generateOpenPositionOrders(s.Market, s.ProfitStats.QuoteInvestment, price, s.PriceDeviation, s.MaxOrderCount, s.OrderGroupID)
orders, err := generateOpenPositionOrders(s.Market, s.QuoteInvestment, s.ProfitStats.TotalProfit, price, s.PriceDeviation, s.MaxOrderCount, s.OrderGroupID)
if err != nil {
return err
}
@ -60,8 +60,9 @@ func getBestPriceUntilSuccess(ctx context.Context, ex types.Exchange, symbol str
return ticker.Sell, nil
}
func generateOpenPositionOrders(market types.Market, quoteInvestment, price, priceDeviation fixedpoint.Value, maxOrderCount int64, orderGroupID uint32) ([]types.SubmitOrder, error) {
func generateOpenPositionOrders(market types.Market, quoteInvestment, profit, price, priceDeviation fixedpoint.Value, maxOrderCount int64, orderGroupID uint32) ([]types.SubmitOrder, error) {
factor := fixedpoint.One.Sub(priceDeviation)
profit = market.TruncatePrice(profit)
// calculate all valid prices
var prices []fixedpoint.Value
@ -86,7 +87,13 @@ func generateOpenPositionOrders(market types.Market, quoteInvestment, price, pri
var submitOrders []types.SubmitOrder
for i := 0; i < orderNum; i++ {
quantity := market.TruncateQuantity(notional.Div(prices[i]))
var quantity fixedpoint.Value
// all the profit will use in the first order
if i == 0 {
quantity = market.TruncateQuantity(notional.Add(profit).Div(prices[i]))
} else {
quantity = market.TruncateQuantity(notional.Div(prices[i]))
}
submitOrders = append(submitOrders, types.SubmitOrder{
Symbol: market.Symbol,
Market: market,

View File

@ -48,16 +48,17 @@ func TestGenerateOpenPositionOrders(t *testing.T) {
t.Run("case 1: all config is valid and we can place enough orders", func(t *testing.T) {
quoteInvestment := Number("10500")
profit := Number("300")
askPrice := Number("30000")
margin := Number("0.05")
submitOrders, err := generateOpenPositionOrders(strategy.Market, quoteInvestment, askPrice, margin, 4, strategy.OrderGroupID)
submitOrders, err := generateOpenPositionOrders(strategy.Market, quoteInvestment, profit, askPrice, margin, 4, strategy.OrderGroupID)
if !assert.NoError(err) {
return
}
assert.Len(submitOrders, 4)
assert.Equal(Number("30000"), submitOrders[0].Price)
assert.Equal(Number("0.0875"), submitOrders[0].Quantity)
assert.Equal(Number("0.0975"), submitOrders[0].Quantity)
assert.Equal(Number("28500"), submitOrders[1].Price)
assert.Equal(Number("0.092105"), submitOrders[1].Quantity)
assert.Equal(Number("27075"), submitOrders[2].Price)
@ -66,12 +67,29 @@ func TestGenerateOpenPositionOrders(t *testing.T) {
assert.Equal(Number("0.102055"), submitOrders[3].Quantity)
})
t.Run("case 2: some orders' price will below 0, so we should not create such order", func(t *testing.T) {
t.Run("case 2: profit need to be truncated to avoid precision problem", func(t *testing.T) {
quoteInvestment := Number("1000")
profit := Number("99.47871711")
askPrice := Number("40409.72")
margin := Number("0.1")
submitOrders, err := generateOpenPositionOrders(strategy.Market, quoteInvestment, profit, askPrice, margin, 2, strategy.OrderGroupID)
if !assert.NoError(err) {
return
}
assert.Len(submitOrders, 2)
assert.Equal(Number("40409.72"), submitOrders[0].Price)
assert.Equal(Number("0.014834"), submitOrders[0].Quantity)
assert.Equal(Number("36368.74"), submitOrders[1].Price)
assert.Equal(Number("0.013748"), submitOrders[1].Quantity)
})
t.Run("case 3: notional is too small, so we should decrease num of orders", func(t *testing.T) {
t.Run("case 3: some orders' price will below 0, so we should not create such order", func(t *testing.T) {
})
t.Run("case 4: quantity is too small, so we should decrease num of orders", func(t *testing.T) {
t.Run("case 4: notional is too small, so we should decrease num of orders", func(t *testing.T) {
})
t.Run("case 5: quantity is too small, so we should decrease num of orders", func(t *testing.T) {
})
}