Skip to content

Commit

Permalink
fix AverageDepthPrice and add test TestPriceVolumeSlice_AverageDepthP…
Browse files Browse the repository at this point in the history
…rice

thanks to @DaniilSokolyuk, this should fix #1861

see #1861
  • Loading branch information
c9s committed Dec 14, 2024
1 parent 7ba94db commit 6ab2a2b
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 4 deletions.
46 changes: 46 additions & 0 deletions pkg/strategy/xdepthmaker/strategy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -75,3 +75,49 @@ func TestStrategy_generateMakerOrders(t *testing.T) {
{Side: types.SideTypeSell, Price: Number("25300"), Quantity: Number("0.275845")},
}, orders)
}

func TestPriceVolumeSlice_AverageDepthPrice(t *testing.T) {
book := types.NewSliceOrderBook("BTCUSDT")
book.Update(types.SliceOrderBook{
Symbol: "BTCUSDT",
Asks: PriceVolumeSliceFromText(`
59400,0.5123
59402,0.0244
59405,0.0413
59450,0.02821
60000,3
`),
Bids: PriceVolumeSliceFromText(`
59399,0.3441 // = 20,439.1959
59398,0.221 // = 13,126.958
59395,0.000123 // = 7.305585
59390,0.03312 // = 1,966.9968
59000,3 // = 177,000
// sum = 212,540.456285
`),
Time: time.Now(),
LastUpdateId: 0,
})

t.Run("test average price by base quantity", func(t *testing.T) {
// Test buying 2 BTC
buyPrice := book.Asks.AverageDepthPrice(fixedpoint.NewFromFloat(2))
assert.InDelta(t, 59818.9699, 0.001, buyPrice.Float64())

// Test selling 2 BTC
sellPrice := book.Bids.AverageDepthPrice(fixedpoint.NewFromFloat(2))
assert.InDelta(t, 59119.1096, 0.001, sellPrice.Float64())
})

t.Run("test average price by quote quantity", func(t *testing.T) {
// Test buying with ~119637.9398 quote
buyPrice := book.Asks.AverageDepthPriceByQuote(fixedpoint.NewFromFloat(119637.9398), 0)
assert.InDelta(t, 59899.6009, buyPrice.Float64(), 0.001)

// Test selling with ~118238.219281 quote
sellPrice := book.Bids.AverageDepthPriceByQuote(fixedpoint.NewFromFloat(118238.219281), 0)
assert.InDelta(t, 59066.2024, sellPrice.Float64(), 0.001)

assert.Less(t, sellPrice.Float64(), buyPrice.Float64(), "the sell price should be lower than the buy price")
})
}
7 changes: 7 additions & 0 deletions pkg/testing/testhelper/pricevolumeslice.go
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ func PriceVolumeSliceFromText(str string) (slice types.PriceVolumeSlice) {
lines := strings.Split(str, "\n")
for _, line := range lines {
line = strings.TrimSpace(line)

// strip comments
commentIdx := strings.Index(line, "//")
if commentIdx >= 0 {
line = line[:commentIdx]
}

if len(line) == 0 {
continue
}
Expand Down
12 changes: 8 additions & 4 deletions pkg/types/price_volume_slice.go
Original file line number Diff line number Diff line change
Expand Up @@ -265,13 +265,16 @@ func (slice PriceVolumeSlice) AverageDepthPriceByQuote(requiredDepthInQuote fixe
totalQuantity := fixedpoint.Zero

l := len(slice)
if maxLevel > 0 && l > maxLevel {
l = maxLevel
if maxLevel > 0 {
l = min(l, maxLevel)
}

for i := 0; i < l; i++ {
pv := slice[i]
quoteAmount := fixedpoint.Mul(pv.Volume, pv.Price)

// quoteAmount is the total quote amount of the current price level
quoteAmount := pv.Volume.Mul(pv.Price)

totalQuoteAmount = totalQuoteAmount.Add(quoteAmount)
totalQuantity = totalQuantity.Add(pv.Volume)

Expand Down Expand Up @@ -321,11 +324,12 @@ func (slice PriceVolumeSlice) AverageDepthPrice(requiredQuantity fixedpoint.Valu
pv := slice[i]
if pv.Volume.Compare(rq) >= 0 {
totalAmount = totalAmount.Add(rq.Mul(pv.Price))
rq = fixedpoint.Zero
break
}

rq = rq.Sub(pv.Volume)
totalAmount = totalAmount.Add(pv.Volume.Mul(pv.Price))
rq = rq.Sub(pv.Volume)
}

return totalAmount.Div(requiredQuantity.Sub(rq))
Expand Down

0 comments on commit 6ab2a2b

Please sign in to comment.