diff --git a/pkg/strategy/grid2/grid.go b/pkg/strategy/grid2/grid.go index baed325f2..d075ed2be 100644 --- a/pkg/strategy/grid2/grid.go +++ b/pkg/strategy/grid2/grid.go @@ -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...) diff --git a/pkg/strategy/grid2/grid_test.go b/pkg/strategy/grid2/grid_test.go index 12992ea8a..df89c6b53 100644 --- a/pkg/strategy/grid2/grid_test.go +++ b/pkg/strategy/grid2/grid_test.go @@ -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) {