-
-
Notifications
You must be signed in to change notification settings - Fork 345
Closed
Labels
bugSomething isn't workingSomething isn't working
Description
What do AverageDepthPrice and AverageDepthPriceByQuote methods actually do? I don't really understand I wrote a simple test and expect quite predictable results.
func Test_OrderBookPriceCalculation(t *testing.T) {
book := NewSliceOrderBook("BTC")
book.Update(SliceOrderBook{
Symbol: "BTC",
Asks: PriceVolumeSlice{
{Price: fixedpoint.NewFromFloat(60000), Volume: fixedpoint.NewFromFloat(3)},
{Price: fixedpoint.NewFromFloat(59450), Volume: fixedpoint.NewFromFloat(0.02821)},
{Price: fixedpoint.NewFromFloat(59405), Volume: fixedpoint.NewFromFloat(0.0413)},
{Price: fixedpoint.NewFromFloat(59402), Volume: fixedpoint.NewFromFloat(0.0244)},
{Price: fixedpoint.NewFromFloat(59400), Volume: fixedpoint.NewFromFloat(0.5123)},
},
Bids: PriceVolumeSlice{
{Price: fixedpoint.NewFromFloat(59399), Volume: fixedpoint.NewFromFloat(0.3441)},
{Price: fixedpoint.NewFromFloat(59398), Volume: fixedpoint.NewFromFloat(0.221)},
{Price: fixedpoint.NewFromFloat(59395), Volume: fixedpoint.NewFromFloat(0.000123)},
{Price: fixedpoint.NewFromFloat(59390), Volume: fixedpoint.NewFromFloat(0.03312)},
{Price: fixedpoint.NewFromFloat(59000), Volume: fixedpoint.NewFromFloat(3)},
},
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.Equal(t, "59818.9699", buyPrice.String()) // 197353.9529206 ?
// Test selling 2 BTC
sellPrice := book.Bids.AverageDepthPrice(fixedpoint.NewFromFloat(2))
assert.Equal(t, "59119.10964055", sellPrice.String()) //197609.43348078 ?
})
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.Equal(t, "59818.9699", buyPrice.String()) //59899.60091065 ?
// Test selling with ~118238.219281 quote
sellPrice := book.Bids.AverageDepthPriceByQuote(fixedpoint.NewFromFloat(118238.219281), 0)
assert.Equal(t, "59119.10993609", sellPrice.String()) // 59899.60091065?
})
}
i tried fixing these methods, could you please check
func (slice PriceVolumeSlice) AverageDepthPrice(requiredQuantity fixedpoint.Value) fixedpoint.Value {
if len(slice) == 0 {
return fixedpoint.Zero
}
// Return first price if it can fulfill entire quantity
if slice[0].Volume.Compare(requiredQuantity) >= 0 {
return slice[0].Price
}
totalAmount := fixedpoint.Zero
totalVolume := fixedpoint.Zero
// Calculate weighted average price
for _, pv := range slice {
volume := fixedpoint.Min(pv.Volume, requiredQuantity)
totalVolume = totalVolume.Add(volume)
totalAmount = totalAmount.Add(pv.Price.Mul(volume))
requiredQuantity = requiredQuantity.Sub(volume)
if requiredQuantity.IsZero() {
break
}
}
return totalAmount.Div(totalVolume)
}
func (slice PriceVolumeSlice) AverageDepthPriceByQuote(requiredDepthInQuote fixedpoint.Value, maxLevel int) fixedpoint.Value {
if len(slice) == 0 {
return fixedpoint.Zero
}
remainingQuote := requiredDepthInQuote
totalQuoteAmount := fixedpoint.Zero
totalQuantity := fixedpoint.Zero
l := len(slice)
if maxLevel > 0 && l > maxLevel {
l = maxLevel
}
for i := 0; i < len(slice) && (maxLevel == 0 || i < maxLevel); i++ {
pv := slice[i]
quoteVolume := pv.Price.Mul(pv.Volume)
if remainingQuote.Compare(quoteVolume) >= 0 {
totalQuantity = totalQuantity.Add(pv.Volume)
totalQuoteAmount = totalQuoteAmount.Add(quoteVolume)
remainingQuote = remainingQuote.Sub(quoteVolume)
} else {
baseAmount := remainingQuote.Div(pv.Price)
totalQuantity = totalQuantity.Add(baseAmount)
totalQuoteAmount = totalQuoteAmount.Add(remainingQuote)
remainingQuote = fixedpoint.Zero
break
}
}
if totalQuantity.IsZero() {
return fixedpoint.Zero
}
return totalQuoteAmount.Div(totalQuantity)
}
Metadata
Metadata
Assignees
Labels
bugSomething isn't workingSomething isn't working