grid2: fix extendLowerPrice method and tests

This commit is contained in:
c9s 2022-11-08 16:14:04 +08:00
parent 75c088eb9c
commit f98c00b7aa
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 46 additions and 40 deletions

View File

@ -17,6 +17,9 @@ type Grid struct {
// TickSize is the price tick size, this is used for truncating price
TickSize fixedpoint.Value `json:"tickSize"`
// Spread is a immutable number
Spread fixedpoint.Value `json:"spread"`
// Pins are the pinned grid prices, from low to high
Pins []Pin `json:"pins"`
@ -46,14 +49,17 @@ func buildPinCache(pins []Pin) map[Pin]struct{} {
}
func NewGrid(lower, upper, size, tickSize fixedpoint.Value) *Grid {
height := upper.Sub(lower)
spread := height.Div(size)
grid := &Grid{
UpperPrice: upper,
LowerPrice: lower,
Size: size,
TickSize: tickSize,
Spread: spread,
}
var spread = grid.Spread()
var pins = calculateArithmeticPins(lower, upper, spread, tickSize)
grid.addPins(pins)
return grid
@ -63,11 +69,6 @@ func (g *Grid) Height() fixedpoint.Value {
return g.UpperPrice.Sub(g.LowerPrice)
}
// Spread returns the spread of each grid
func (g *Grid) Spread() fixedpoint.Value {
return g.Height().Div(g.Size)
}
func (g *Grid) Above(price fixedpoint.Value) bool {
return price.Compare(g.UpperPrice) > 0
}
@ -86,31 +87,34 @@ func (g *Grid) HasPin(pin Pin) (ok bool) {
}
func (g *Grid) ExtendUpperPrice(upper fixedpoint.Value) (newPins []Pin) {
spread := g.Spread()
startPrice := g.UpperPrice.Add(spread)
for p := startPrice; p.Compare(upper) <= 0; p = p.Add(spread) {
newPins = append(newPins, Pin(p))
}
newPins = calculateArithmeticPins(g.UpperPrice, upper, g.Spread, g.TickSize)
g.UpperPrice = upper
g.addPins(newPins)
return newPins
}
func (g *Grid) ExtendLowerPrice(lower fixedpoint.Value) (newPins []Pin) {
spread := g.Spread()
startPrice := g.LowerPrice.Sub(spread)
for p := startPrice; p.Compare(lower) >= 0; p = p.Sub(spread) {
newPins = append(newPins, Pin(p))
if lower.Compare(g.LowerPrice) >= 0 {
return nil
}
n := g.LowerPrice.Sub(lower).Div(g.Spread).Floor()
lower = g.LowerPrice.Sub(g.Spread.Mul(n))
newPins = calculateArithmeticPins(lower, g.LowerPrice.Sub(g.Spread), g.Spread, g.TickSize)
g.LowerPrice = lower
g.addPins(newPins)
return newPins
}
func (g *Grid) TopPin() Pin {
return g.Pins[len(g.Pins)-1]
}
func (g *Grid) BottomPin() Pin {
return g.Pins[0]
}
func (g *Grid) addPins(pins []Pin) {
g.Pins = append(g.Pins, pins...)

View File

@ -45,48 +45,50 @@ func TestGrid_HasPin(t *testing.T) {
func TestGrid_ExtendUpperPrice(t *testing.T) {
upper := number(500.0)
lower := number(100.0)
size := number(100.0)
grid := NewGrid(lower, upper, size, number(2.0))
size := number(40.0)
grid := NewGrid(lower, upper, size, number(0.01))
originalSpread := grid.Spread
assert.Equal(t, number(10.0), originalSpread)
assert.Len(t, grid.Pins, 40) // (1000-500) / 4
newPins := grid.ExtendUpperPrice(number(1000.0))
assert.Equal(t, originalSpread, grid.Spread)
assert.Len(t, newPins, 125) // (1000-500) / 4
assert.Equal(t, fixedpoint.NewFromFloat(4), grid.Spread)
if assert.Len(t, grid.Pins, 226) {
assert.Equal(t, fixedpoint.NewFromFloat(100.0), grid.Pins[0])
assert.Equal(t, fixedpoint.NewFromFloat(1000.0), grid.Pins[225])
}
assert.Len(t, newPins, 51) // (1000-500) / 4
}
func TestGrid_ExtendLowerPrice(t *testing.T) {
upper := fixedpoint.NewFromFloat(3000.0)
lower := fixedpoint.NewFromFloat(2000.0)
size := fixedpoint.NewFromFloat(100.0)
grid := NewGrid(lower, upper, size, number(2.0))
size := fixedpoint.NewFromFloat(10.0)
grid := NewGrid(lower, upper, size, number(0.01))
// spread = (3000 - 2000) / 100.0
expectedSpread := fixedpoint.NewFromFloat(10.0)
assert.Equal(t, Pin(number(2000.0)), grid.BottomPin(), "bottom pin should be 1000.0")
assert.Equal(t, Pin(number(3000.0)), grid.TopPin(), "top pin should be 3000.0")
assert.Len(t, grid.Pins, 11)
// spread = (3000 - 2000) / 10.0
expectedSpread := fixedpoint.NewFromFloat(100.0)
assert.Equal(t, expectedSpread, grid.Spread)
originalSpread := grid.Spread
newPins := grid.ExtendLowerPrice(fixedpoint.NewFromFloat(1000.0))
assert.Equal(t, originalSpread, grid.Spread)
t.Logf("newPins: %+v", newPins)
// 100 = (2000-1000) / 10
if assert.Len(t, newPins, 100) {
assert.Equal(t, fixedpoint.NewFromFloat(2000.0)-expectedSpread, newPins[99])
if assert.Len(t, newPins, 10) {
assert.Equal(t, Pin(number(1000.0)), newPins[0])
assert.Equal(t, Pin(number(1900.0)), newPins[len(newPins)-1])
}
assert.Equal(t, expectedSpread, grid.Spread)
if assert.Len(t, grid.Pins, 201) {
assert.Equal(t, fixedpoint.NewFromFloat(1000.0), grid.Pins[0])
assert.Equal(t, fixedpoint.NewFromFloat(3000.0), grid.Pins[200])
}
newPins2 := grid.ExtendLowerPrice(
fixedpoint.NewFromFloat(1000.0 - 1.0))
assert.Len(t, newPins2, 0) // should have no new pin generated
if assert.Len(t, grid.Pins, 21) {
assert.Equal(t, Pin(number(1000.0)), grid.BottomPin(), "bottom pin should be 1000.0")
assert.Equal(t, Pin(number(3000.0)), grid.TopPin(), "top pin should be 3000.0")
}
}
func Test_calculateArithmeticPins(t *testing.T) {