2022-11-25 10:07:02 +00:00
|
|
|
//go:build !dnum
|
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
package grid2
|
|
|
|
|
|
|
|
import (
|
|
|
|
"testing"
|
|
|
|
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
|
|
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
|
|
)
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
func number(a interface{}) fixedpoint.Value {
|
2022-11-08 12:23:25 +00:00
|
|
|
switch v := a.(type) {
|
|
|
|
case string:
|
|
|
|
return fixedpoint.MustNewFromString(v)
|
|
|
|
case int:
|
|
|
|
return fixedpoint.NewFromInt(int64(v))
|
|
|
|
case int64:
|
|
|
|
return fixedpoint.NewFromInt(int64(v))
|
|
|
|
case float64:
|
|
|
|
return fixedpoint.NewFromFloat(v)
|
2022-11-03 16:26:28 +00:00
|
|
|
}
|
|
|
|
|
2022-11-08 12:23:25 +00:00
|
|
|
return fixedpoint.Zero
|
2022-11-03 16:26:28 +00:00
|
|
|
}
|
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
func TestNewGrid(t *testing.T) {
|
|
|
|
upper := fixedpoint.NewFromFloat(500.0)
|
|
|
|
lower := fixedpoint.NewFromFloat(100.0)
|
2023-01-16 10:34:08 +00:00
|
|
|
size := fixedpoint.NewFromFloat(101.0)
|
2022-11-08 12:23:25 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
2022-11-09 11:43:14 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
2022-11-09 10:56:33 +00:00
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
assert.Equal(t, upper, grid.UpperPrice)
|
|
|
|
assert.Equal(t, lower, grid.LowerPrice)
|
|
|
|
assert.Equal(t, fixedpoint.NewFromFloat(4), grid.Spread)
|
|
|
|
if assert.Len(t, grid.Pins, 101) {
|
2022-11-08 12:09:07 +00:00
|
|
|
assert.Equal(t, Pin(number(100.0)), grid.Pins[0])
|
|
|
|
assert.Equal(t, Pin(number(500.0)), grid.Pins[100])
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestGrid_HasPin(t *testing.T) {
|
|
|
|
upper := fixedpoint.NewFromFloat(500.0)
|
|
|
|
lower := fixedpoint.NewFromFloat(100.0)
|
2023-01-16 10:34:08 +00:00
|
|
|
size := fixedpoint.NewFromFloat(101.0)
|
2022-11-08 12:23:25 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
2022-11-09 11:43:14 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
2022-11-03 05:41:47 +00:00
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
assert.True(t, grid.HasPin(Pin(number(100.0))))
|
|
|
|
assert.True(t, grid.HasPin(Pin(number(500.0))))
|
|
|
|
assert.False(t, grid.HasPin(Pin(number(101.0))))
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestGrid_ExtendUpperPrice(t *testing.T) {
|
2022-11-03 16:26:28 +00:00
|
|
|
upper := number(500.0)
|
|
|
|
lower := number(100.0)
|
2023-01-16 10:34:08 +00:00
|
|
|
size := number(5.0)
|
2022-11-08 08:14:04 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
2022-11-09 11:43:14 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
2022-11-09 10:56:33 +00:00
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
originalSpread := grid.Spread
|
2022-11-08 08:14:04 +00:00
|
|
|
|
2022-11-08 12:27:55 +00:00
|
|
|
t.Logf("pins: %+v", grid.Pins)
|
|
|
|
assert.Equal(t, number(100.0), originalSpread)
|
2023-01-16 10:34:08 +00:00
|
|
|
assert.Len(t, grid.Pins, 5)
|
2022-11-08 08:14:04 +00:00
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
newPins := grid.ExtendUpperPrice(number(1000.0))
|
2022-11-08 12:27:55 +00:00
|
|
|
assert.Len(t, grid.Pins, 10)
|
|
|
|
assert.Len(t, newPins, 5)
|
2022-11-03 05:41:47 +00:00
|
|
|
assert.Equal(t, originalSpread, grid.Spread)
|
2022-11-08 12:27:55 +00:00
|
|
|
t.Logf("pins: %+v", grid.Pins)
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func TestGrid_ExtendLowerPrice(t *testing.T) {
|
|
|
|
upper := fixedpoint.NewFromFloat(3000.0)
|
|
|
|
lower := fixedpoint.NewFromFloat(2000.0)
|
2023-01-16 10:34:08 +00:00
|
|
|
size := fixedpoint.NewFromFloat(11.0)
|
2022-11-08 08:14:04 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
2022-11-09 11:43:14 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
2022-11-08 08:14:04 +00:00
|
|
|
|
|
|
|
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)
|
2022-11-03 05:41:47 +00:00
|
|
|
|
2022-11-08 08:14:04 +00:00
|
|
|
// spread = (3000 - 2000) / 10.0
|
|
|
|
expectedSpread := fixedpoint.NewFromFloat(100.0)
|
2022-11-03 05:41:47 +00:00
|
|
|
assert.Equal(t, expectedSpread, grid.Spread)
|
|
|
|
|
|
|
|
originalSpread := grid.Spread
|
|
|
|
newPins := grid.ExtendLowerPrice(fixedpoint.NewFromFloat(1000.0))
|
|
|
|
assert.Equal(t, originalSpread, grid.Spread)
|
|
|
|
|
2022-11-08 08:14:04 +00:00
|
|
|
t.Logf("newPins: %+v", newPins)
|
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
// 100 = (2000-1000) / 10
|
2022-11-08 08:14:04 +00:00
|
|
|
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])
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
assert.Equal(t, expectedSpread, grid.Spread)
|
|
|
|
|
2022-11-08 08:14:04 +00:00
|
|
|
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")
|
|
|
|
}
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
2022-11-03 16:26:28 +00:00
|
|
|
|
2022-11-09 08:20:40 +00:00
|
|
|
func TestGrid_NextLowerPin(t *testing.T) {
|
|
|
|
upper := number(500.0)
|
|
|
|
lower := number(100.0)
|
2023-01-16 10:34:08 +00:00
|
|
|
size := number(5.0)
|
2022-11-09 08:20:40 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
2022-11-09 11:43:14 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
2022-11-09 10:56:33 +00:00
|
|
|
|
2022-11-09 08:20:40 +00:00
|
|
|
t.Logf("pins: %+v", grid.Pins)
|
|
|
|
|
|
|
|
next, ok := grid.NextLowerPin(number(200.0))
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.Equal(t, Pin(number(100.0)), next)
|
|
|
|
|
|
|
|
next, ok = grid.NextLowerPin(number(150.0))
|
|
|
|
assert.False(t, ok)
|
|
|
|
assert.Equal(t, Pin(fixedpoint.Zero), next)
|
|
|
|
}
|
|
|
|
|
2023-02-15 06:42:01 +00:00
|
|
|
func TestGrid_HasPrice(t *testing.T) {
|
2023-02-15 06:57:21 +00:00
|
|
|
t.Run("case1", func(t *testing.T) {
|
|
|
|
upper := number(500.0)
|
|
|
|
lower := number(100.0)
|
|
|
|
size := number(5.0)
|
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
|
|
|
grid.CalculateArithmeticPins()
|
|
|
|
|
|
|
|
assert.True(t, grid.HasPrice(number(500.0)), "upper price")
|
|
|
|
assert.True(t, grid.HasPrice(number(100.0)), "lower price")
|
|
|
|
assert.True(t, grid.HasPrice(number(200.0)), "found 200 price ok")
|
|
|
|
assert.True(t, grid.HasPrice(number(300.0)), "found 300 price ok")
|
|
|
|
})
|
|
|
|
|
|
|
|
t.Run("case2", func(t *testing.T) {
|
|
|
|
upper := number(0.9)
|
|
|
|
lower := number(0.1)
|
|
|
|
size := number(7.0)
|
|
|
|
grid := NewGrid(lower, upper, size, number(0.00000001))
|
|
|
|
grid.CalculateArithmeticPins()
|
|
|
|
|
|
|
|
assert.Equal(t, []Pin{
|
|
|
|
Pin(number(0.1)),
|
|
|
|
Pin(number(0.23333333)),
|
|
|
|
Pin(number(0.36666666)),
|
|
|
|
Pin(number(0.49999999)),
|
|
|
|
Pin(number(0.63333332)),
|
|
|
|
Pin(number(0.76666665)),
|
|
|
|
Pin(number(0.9)),
|
|
|
|
}, grid.Pins)
|
|
|
|
|
|
|
|
assert.False(t, grid.HasPrice(number(200.0)), "out of range")
|
|
|
|
assert.True(t, grid.HasPrice(number(0.9)), "upper price")
|
|
|
|
assert.True(t, grid.HasPrice(number(0.1)), "lower price")
|
|
|
|
assert.True(t, grid.HasPrice(number(0.49999999)), "found 0.49999999 price ok")
|
|
|
|
})
|
2023-02-15 08:03:24 +00:00
|
|
|
|
|
|
|
t.Run("case3", func(t *testing.T) {
|
|
|
|
upper := number(0.9)
|
|
|
|
lower := number(0.1)
|
|
|
|
size := number(7.0)
|
2023-02-15 08:05:45 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.0001))
|
2023-02-15 08:03:24 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
|
|
|
|
|
|
|
assert.Equal(t, []Pin{
|
|
|
|
Pin(number(0.1)),
|
2023-02-15 08:05:45 +00:00
|
|
|
Pin(number(0.2333)),
|
|
|
|
Pin(number(0.3666)),
|
|
|
|
Pin(number(0.5000)),
|
|
|
|
Pin(number(0.6333)),
|
|
|
|
Pin(number(0.7666)),
|
2023-02-15 08:03:24 +00:00
|
|
|
Pin(number(0.9)),
|
|
|
|
}, grid.Pins)
|
|
|
|
|
|
|
|
assert.False(t, grid.HasPrice(number(200.0)), "out of range")
|
|
|
|
assert.True(t, grid.HasPrice(number(0.9)), "upper price")
|
|
|
|
assert.True(t, grid.HasPrice(number(0.1)), "lower price")
|
|
|
|
assert.True(t, grid.HasPrice(number(0.5)), "found 0.5 price ok")
|
2023-02-15 08:05:45 +00:00
|
|
|
assert.True(t, grid.HasPrice(number(0.2333)), "found 0.2333 price ok")
|
2023-02-15 08:03:24 +00:00
|
|
|
})
|
|
|
|
|
2023-02-15 14:32:55 +00:00
|
|
|
t.Run("case4", func(t *testing.T) {
|
|
|
|
upper := number(90.0)
|
|
|
|
lower := number(10.0)
|
|
|
|
size := number(7.0)
|
|
|
|
grid := NewGrid(lower, upper, size, number(0.001))
|
|
|
|
grid.CalculateArithmeticPins()
|
|
|
|
|
|
|
|
assert.Equal(t, []Pin{
|
|
|
|
Pin(number("10.0")),
|
|
|
|
Pin(number("23.333")),
|
|
|
|
Pin(number("36.666")),
|
|
|
|
Pin(number("50.00")),
|
|
|
|
Pin(number("63.333")),
|
|
|
|
Pin(number("76.666")),
|
|
|
|
Pin(number("90.0")),
|
|
|
|
}, grid.Pins)
|
|
|
|
|
|
|
|
assert.False(t, grid.HasPrice(number(200.0)), "out of range")
|
|
|
|
assert.True(t, grid.HasPrice(number("36.666")), "found 36.666 price ok")
|
|
|
|
})
|
|
|
|
|
2023-02-15 06:42:01 +00:00
|
|
|
}
|
|
|
|
|
2022-11-09 08:20:40 +00:00
|
|
|
func TestGrid_NextHigherPin(t *testing.T) {
|
|
|
|
upper := number(500.0)
|
|
|
|
lower := number(100.0)
|
2023-01-16 10:34:08 +00:00
|
|
|
size := number(5.0)
|
2022-11-09 08:20:40 +00:00
|
|
|
grid := NewGrid(lower, upper, size, number(0.01))
|
2022-11-09 11:43:14 +00:00
|
|
|
grid.CalculateArithmeticPins()
|
2022-11-09 08:20:40 +00:00
|
|
|
t.Logf("pins: %+v", grid.Pins)
|
|
|
|
|
|
|
|
next, ok := grid.NextHigherPin(number(100.0))
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.Equal(t, Pin(number(200.0)), next)
|
|
|
|
|
|
|
|
next, ok = grid.NextHigherPin(number(400.0))
|
|
|
|
assert.True(t, ok)
|
|
|
|
assert.Equal(t, Pin(number(500.0)), next)
|
|
|
|
|
|
|
|
next, ok = grid.NextHigherPin(number(500.0))
|
|
|
|
assert.False(t, ok)
|
|
|
|
assert.Equal(t, Pin(fixedpoint.Zero), next)
|
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
func Test_calculateArithmeticPins(t *testing.T) {
|
|
|
|
type args struct {
|
|
|
|
lower fixedpoint.Value
|
|
|
|
upper fixedpoint.Value
|
|
|
|
size fixedpoint.Value
|
|
|
|
tickSize fixedpoint.Value
|
|
|
|
}
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
args args
|
|
|
|
want []Pin
|
|
|
|
}{
|
|
|
|
{
|
2022-11-08 10:11:04 +00:00
|
|
|
// (3000-1000)/30 = 66.6666666
|
2022-11-03 16:26:28 +00:00
|
|
|
name: "simple",
|
|
|
|
args: args{
|
|
|
|
lower: number(1000.0),
|
|
|
|
upper: number(3000.0),
|
|
|
|
size: number(30.0),
|
|
|
|
tickSize: number(0.01),
|
|
|
|
},
|
|
|
|
want: []Pin{
|
|
|
|
Pin(number(1000.0)),
|
|
|
|
Pin(number(1066.660)),
|
|
|
|
Pin(number(1133.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number("1200.00")),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(1266.660)),
|
|
|
|
Pin(number(1333.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number(1400.000)),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(1466.660)),
|
|
|
|
Pin(number(1533.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number(1600.000)),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(1666.660)),
|
|
|
|
Pin(number(1733.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number(1800.000)),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(1866.660)),
|
|
|
|
Pin(number(1933.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number(2000.000)),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(2066.660)),
|
|
|
|
Pin(number(2133.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number("2200.00")),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(2266.660)),
|
|
|
|
Pin(number(2333.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number("2400.00")),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(2466.660)),
|
|
|
|
Pin(number(2533.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number("2600.00")),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(2666.660)),
|
|
|
|
Pin(number(2733.330)),
|
2023-02-01 10:56:01 +00:00
|
|
|
Pin(number(2800.000)),
|
2022-11-03 16:26:28 +00:00
|
|
|
Pin(number(2866.660)),
|
|
|
|
Pin(number(2933.330)),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
2022-11-08 10:11:04 +00:00
|
|
|
spread := tt.args.upper.Sub(tt.args.lower).Div(tt.args.size)
|
2022-11-25 10:07:02 +00:00
|
|
|
pins := calculateArithmeticPins(tt.args.lower, tt.args.upper, spread, tt.args.tickSize)
|
|
|
|
for i := 0; i < len(tt.want); i++ {
|
|
|
|
assert.InDelta(t, fixedpoint.Value(tt.want[i]).Float64(),
|
|
|
|
fixedpoint.Value(pins[i]).Float64(),
|
|
|
|
0.001,
|
|
|
|
"calculateArithmeticPins(%v, %v, %v, %v)", tt.args.lower, tt.args.upper, tt.args.size, tt.args.tickSize)
|
|
|
|
}
|
2022-11-03 16:26:28 +00:00
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|