2022-11-03 05:41:47 +00:00
|
|
|
package grid2
|
|
|
|
|
|
|
|
import (
|
2022-11-03 16:26:28 +00:00
|
|
|
"math"
|
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
|
|
)
|
|
|
|
|
|
|
|
type Grid struct {
|
|
|
|
UpperPrice fixedpoint.Value `json:"upperPrice"`
|
|
|
|
LowerPrice fixedpoint.Value `json:"lowerPrice"`
|
|
|
|
|
|
|
|
// Spread is the spread of each grid
|
|
|
|
Spread fixedpoint.Value `json:"spread"`
|
|
|
|
|
|
|
|
// Size is the number of total grids
|
|
|
|
Size fixedpoint.Value `json:"size"`
|
|
|
|
|
|
|
|
// Pins are the pinned grid prices, from low to high
|
2022-11-03 16:26:28 +00:00
|
|
|
Pins []Pin `json:"pins"`
|
2022-11-03 05:41:47 +00:00
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
pinsCache map[Pin]struct{} `json:"-"`
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
type Pin fixedpoint.Value
|
|
|
|
|
|
|
|
func calculateArithmeticPins(lower, upper, size, tickSize fixedpoint.Value) []Pin {
|
|
|
|
var height = upper.Sub(lower)
|
|
|
|
var spread = height.Div(size)
|
|
|
|
|
|
|
|
var pins []Pin
|
|
|
|
for p := lower; p.Compare(upper) <= 0; p = p.Add(spread) {
|
|
|
|
// tickSize here = 0.01
|
|
|
|
pp := math.Trunc(p.Float64()/tickSize.Float64()) * tickSize.Float64()
|
|
|
|
pins = append(pins, Pin(fixedpoint.NewFromFloat(pp)))
|
|
|
|
}
|
|
|
|
|
|
|
|
return pins
|
|
|
|
}
|
2022-11-03 05:41:47 +00:00
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
func buildPinCache(pins []Pin) map[Pin]struct{} {
|
|
|
|
cache := make(map[Pin]struct{}, len(pins))
|
|
|
|
for _, pin := range pins {
|
|
|
|
cache[pin] = struct{}{}
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
return cache
|
|
|
|
}
|
|
|
|
|
|
|
|
func NewGrid(lower, upper, size, tickSize fixedpoint.Value) *Grid {
|
|
|
|
var height = upper.Sub(lower)
|
|
|
|
var spread = height.Div(size)
|
|
|
|
var pins = calculateArithmeticPins(lower, upper, size, tickSize)
|
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
grid := &Grid{
|
|
|
|
UpperPrice: upper,
|
|
|
|
LowerPrice: lower,
|
2022-11-03 16:26:28 +00:00
|
|
|
Size: size,
|
|
|
|
Spread: spread,
|
2022-11-03 05:41:47 +00:00
|
|
|
Pins: pins,
|
2022-11-03 16:26:28 +00:00
|
|
|
pinsCache: buildPinCache(pins),
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
2022-11-03 16:26:28 +00:00
|
|
|
|
2022-11-03 05:41:47 +00:00
|
|
|
return grid
|
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Grid) Above(price fixedpoint.Value) bool {
|
2022-11-03 16:26:28 +00:00
|
|
|
return price.Compare(g.UpperPrice) > 0
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Grid) Below(price fixedpoint.Value) bool {
|
2022-11-03 16:26:28 +00:00
|
|
|
return price.Compare(g.LowerPrice) < 0
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Grid) OutOfRange(price fixedpoint.Value) bool {
|
2022-11-03 16:26:28 +00:00
|
|
|
return price.Compare(g.LowerPrice) < 0 || price.Compare(g.UpperPrice) > 0
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
func (g *Grid) updatePinsCache() {
|
2022-11-03 16:26:28 +00:00
|
|
|
g.pinsCache = buildPinCache(g.Pins)
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
func (g *Grid) HasPin(pin Pin) (ok bool) {
|
2022-11-03 05:41:47 +00:00
|
|
|
_, ok = g.pinsCache[pin]
|
|
|
|
return ok
|
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
func (g *Grid) ExtendUpperPrice(upper fixedpoint.Value) (newPins []Pin) {
|
2022-11-03 05:41:47 +00:00
|
|
|
g.UpperPrice = upper
|
|
|
|
|
|
|
|
// since the grid is extended, the size should be updated as well
|
|
|
|
g.Size = (g.UpperPrice - g.LowerPrice).Div(g.Spread).Floor()
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
lastPinPrice := fixedpoint.Value(g.Pins[len(g.Pins)-1])
|
|
|
|
for p := lastPinPrice.Add(g.Spread); p <= g.UpperPrice; p += g.Spread {
|
|
|
|
newPins = append(newPins, Pin(p))
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g.Pins = append(g.Pins, newPins...)
|
|
|
|
g.updatePinsCache()
|
|
|
|
return newPins
|
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
func (g *Grid) ExtendLowerPrice(lower fixedpoint.Value) (newPins []Pin) {
|
2022-11-03 05:41:47 +00:00
|
|
|
g.LowerPrice = lower
|
|
|
|
|
|
|
|
// since the grid is extended, the size should be updated as well
|
|
|
|
g.Size = (g.UpperPrice - g.LowerPrice).Div(g.Spread).Floor()
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
firstPinPrice := fixedpoint.Value(g.Pins[0])
|
|
|
|
numToAdd := (firstPinPrice.Sub(g.LowerPrice)).Div(g.Spread).Floor()
|
2022-11-03 05:41:47 +00:00
|
|
|
if numToAdd == 0 {
|
|
|
|
return newPins
|
|
|
|
}
|
|
|
|
|
2022-11-03 16:26:28 +00:00
|
|
|
for p := firstPinPrice.Sub(g.Spread.Mul(numToAdd)); p.Compare(firstPinPrice) < 0; p = p.Add(g.Spread) {
|
|
|
|
newPins = append(newPins, Pin(p))
|
2022-11-03 05:41:47 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
g.Pins = append(newPins, g.Pins...)
|
|
|
|
g.updatePinsCache()
|
|
|
|
return newPins
|
|
|
|
}
|