mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 14:55:16 +00:00
Merge pull request #1119 from c9s/feature/grids/recover-from-trades
FEATURE: make PinOrderMap's key from string to Pin
This commit is contained in:
commit
294c09b9e8
|
@ -4,11 +4,12 @@ import (
|
|||
"fmt"
|
||||
"strings"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
// PinOrderMap store the pin-order's relation, we will change key from string to fixedpoint.Value when FormatString fixed
|
||||
type PinOrderMap map[string]types.Order
|
||||
type PinOrderMap map[fixedpoint.Value]types.Order
|
||||
|
||||
// AscendingOrders get the orders from pin order map and sort it in asc order
|
||||
func (m PinOrderMap) AscendingOrders() []types.Order {
|
||||
|
@ -41,7 +42,7 @@ func (m PinOrderMap) String() string {
|
|||
|
||||
sb.WriteString("================== PIN ORDER MAP ==================\n")
|
||||
for pin, order := range m {
|
||||
sb.WriteString(fmt.Sprintf("%s -> %s\n", pin, order.String()))
|
||||
sb.WriteString(fmt.Sprintf("%+v -> %s\n", pin, order.String()))
|
||||
}
|
||||
sb.WriteString("================== END OF PIN ORDER MAP ==================\n")
|
||||
return sb.String()
|
||||
|
|
|
@ -1465,11 +1465,11 @@ func (s *Strategy) verifyFilledGrid(pins []Pin, pinOrders PinOrderMap, filledOrd
|
|||
s.debugOrders("filled orders", filledOrders)
|
||||
|
||||
for _, filledOrder := range filledOrders {
|
||||
price := s.Market.FormatPrice(filledOrder.Price)
|
||||
price := filledOrder.Price
|
||||
if o, exist := pinOrders[price]; !exist {
|
||||
return fmt.Errorf("the price (%s) is not in pins", price)
|
||||
return fmt.Errorf("the price (%+v) is not in pins", price)
|
||||
} else if o.OrderID != 0 {
|
||||
return fmt.Errorf("there is already an order at this price (%s)", price)
|
||||
return fmt.Errorf("there is already an order at this price (%+v)", price)
|
||||
} else {
|
||||
pinOrders[price] = filledOrder
|
||||
}
|
||||
|
@ -1479,10 +1479,9 @@ func (s *Strategy) verifyFilledGrid(pins []Pin, pinOrders PinOrderMap, filledOrd
|
|||
|
||||
side := types.SideTypeBuy
|
||||
for _, pin := range pins {
|
||||
price := s.Market.FormatPrice(fixedpoint.Value(pin))
|
||||
order, exist := pinOrders[price]
|
||||
order, exist := pinOrders[fixedpoint.Value(pin)]
|
||||
if !exist {
|
||||
return fmt.Errorf("there is no order at price (%s)", price)
|
||||
return fmt.Errorf("there is no order at price (%+v)", pin)
|
||||
}
|
||||
|
||||
// if there is order with OrderID = 0, means we hit the empty pin
|
||||
|
@ -1516,13 +1515,12 @@ func (s *Strategy) buildPinOrderMap(pins []Pin, openOrders []types.Order) (PinOr
|
|||
pinOrderMap := make(PinOrderMap)
|
||||
|
||||
for _, pin := range pins {
|
||||
priceStr := s.Market.FormatPrice(fixedpoint.Value(pin))
|
||||
pinOrderMap[priceStr] = types.Order{}
|
||||
pinOrderMap[fixedpoint.Value(pin)] = types.Order{}
|
||||
}
|
||||
|
||||
for _, openOrder := range openOrders {
|
||||
priceStr := s.Market.FormatPrice(openOrder.Price)
|
||||
v, exist := pinOrderMap[priceStr]
|
||||
pin := openOrder.Price
|
||||
v, exist := pinOrderMap[pin]
|
||||
if !exist {
|
||||
return nil, fmt.Errorf("the price of the order (id: %d) is not in pins", openOrder.OrderID)
|
||||
}
|
||||
|
@ -1531,7 +1529,7 @@ func (s *Strategy) buildPinOrderMap(pins []Pin, openOrders []types.Order) (PinOr
|
|||
return nil, fmt.Errorf("there are duplicated open orders at the same pin")
|
||||
}
|
||||
|
||||
pinOrderMap[priceStr] = openOrder
|
||||
pinOrderMap[pin] = openOrder
|
||||
}
|
||||
|
||||
return pinOrderMap, nil
|
||||
|
@ -1590,8 +1588,8 @@ func (s *Strategy) buildFilledPinOrderMapFromTrades(ctx context.Context, history
|
|||
}
|
||||
|
||||
// checked the trade's order is filled order
|
||||
priceStr := s.Market.FormatPrice(order.Price)
|
||||
v, exist := pinOrdersOpen[priceStr]
|
||||
pin := order.Price
|
||||
v, exist := pinOrdersOpen[pin]
|
||||
if !exist {
|
||||
return nil, fmt.Errorf("the price of the order with the same GroupID is not in pins")
|
||||
}
|
||||
|
@ -1602,13 +1600,13 @@ func (s *Strategy) buildFilledPinOrderMapFromTrades(ctx context.Context, history
|
|||
}
|
||||
|
||||
// check the order's creation time
|
||||
if pinOrder, exist := pinOrdersFilled[priceStr]; exist && pinOrder.CreationTime.Time().After(order.CreationTime.Time()) {
|
||||
if pinOrder, exist := pinOrdersFilled[pin]; exist && pinOrder.CreationTime.Time().After(order.CreationTime.Time()) {
|
||||
// do not replace the pin order if the order's creation time is not after pin order's creation time
|
||||
// this situation should not happen actually, because the trades is already sorted.
|
||||
s.logger.Infof("pinOrder's creation time (%s) should not be after order's creation time (%s)", pinOrder.CreationTime, order.CreationTime)
|
||||
continue
|
||||
}
|
||||
pinOrdersFilled[priceStr] = *order
|
||||
pinOrdersFilled[pin] = *order
|
||||
|
||||
// wait 100 ms to avoid rate limit
|
||||
time.Sleep(100 * time.Millisecond)
|
||||
|
|
|
@ -1100,7 +1100,7 @@ func Test_buildPinOrderMap(t *testing.T) {
|
|||
assert.Len(m, 11)
|
||||
|
||||
for pin, order := range m {
|
||||
if pin == s.FormatPrice(openOrders[0].Price) {
|
||||
if pin == openOrders[0].Price {
|
||||
assert.Equal(openOrders[0].OrderID, order.OrderID)
|
||||
} else {
|
||||
assert.Equal(uint64(0), order.OrderID)
|
||||
|
@ -1184,19 +1184,19 @@ func Test_getOrdersFromPinOrderMapInAscOrder(t *testing.T) {
|
|||
assert := assert.New(t)
|
||||
now := time.Now()
|
||||
pinOrderMap := PinOrderMap{
|
||||
"1000": types.Order{
|
||||
number("1000"): types.Order{
|
||||
OrderID: 1,
|
||||
CreationTime: types.Time(now.Add(1 * time.Hour)),
|
||||
UpdateTime: types.Time(now.Add(5 * time.Hour)),
|
||||
},
|
||||
"1100": types.Order{},
|
||||
"1200": types.Order{},
|
||||
"1300": types.Order{
|
||||
number("1100"): types.Order{},
|
||||
number("1200"): types.Order{},
|
||||
number("1300"): types.Order{
|
||||
OrderID: 3,
|
||||
CreationTime: types.Time(now.Add(3 * time.Hour)),
|
||||
UpdateTime: types.Time(now.Add(6 * time.Hour)),
|
||||
},
|
||||
"1400": types.Order{
|
||||
number("1400"): types.Order{
|
||||
OrderID: 2,
|
||||
CreationTime: types.Time(now.Add(2 * time.Hour)),
|
||||
UpdateTime: types.Time(now.Add(4 * time.Hour)),
|
||||
|
@ -1220,20 +1220,20 @@ func Test_verifyFilledGrid(t *testing.T) {
|
|||
|
||||
t.Run("valid grid with buy/sell orders", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{
|
||||
number("100.00"): types.Order{
|
||||
OrderID: 1,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"200.00": types.Order{},
|
||||
"300.00": types.Order{
|
||||
number("200.00"): types.Order{},
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{
|
||||
number("400.00"): types.Order{
|
||||
OrderID: 4,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
|
@ -1245,45 +1245,45 @@ func Test_verifyFilledGrid(t *testing.T) {
|
|||
})
|
||||
t.Run("valid grid with only buy orders", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{
|
||||
number("100.00"): types.Order{
|
||||
OrderID: 1,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"200.00": types.Order{
|
||||
number("200.00"): types.Order{
|
||||
OrderID: 2,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"300.00": types.Order{
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{},
|
||||
number("400.00"): types.Order{},
|
||||
}
|
||||
|
||||
assert.NoError(s.verifyFilledGrid(s.grid.Pins, pinOrderMap, nil))
|
||||
})
|
||||
t.Run("valid grid with only sell orders", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{},
|
||||
"200.00": types.Order{
|
||||
number("100.00"): types.Order{},
|
||||
number("200.00"): types.Order{
|
||||
OrderID: 2,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"300.00": types.Order{
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{
|
||||
number("400.00"): types.Order{
|
||||
OrderID: 4,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
|
@ -1295,15 +1295,15 @@ func Test_verifyFilledGrid(t *testing.T) {
|
|||
})
|
||||
t.Run("invalid grid with multiple empty pins", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{
|
||||
number("100.00"): types.Order{
|
||||
OrderID: 1,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"200.00": types.Order{},
|
||||
"300.00": types.Order{},
|
||||
"400.00": types.Order{
|
||||
number("200.00"): types.Order{},
|
||||
number("300.00"): types.Order{},
|
||||
number("400.00"): types.Order{
|
||||
OrderID: 4,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
|
@ -1315,25 +1315,25 @@ func Test_verifyFilledGrid(t *testing.T) {
|
|||
})
|
||||
t.Run("invalid grid without empty pin", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{
|
||||
number("100.00"): types.Order{
|
||||
OrderID: 1,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"200.00": types.Order{
|
||||
number("200.00"): types.Order{
|
||||
OrderID: 2,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"300.00": types.Order{
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{
|
||||
number("400.00"): types.Order{
|
||||
OrderID: 4,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
|
@ -1345,20 +1345,20 @@ func Test_verifyFilledGrid(t *testing.T) {
|
|||
})
|
||||
t.Run("invalid grid with Buy-empty-Sell-Buy order", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{
|
||||
number("100.00"): types.Order{
|
||||
OrderID: 1,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"200.00": types.Order{},
|
||||
"300.00": types.Order{
|
||||
number("200.00"): types.Order{},
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{
|
||||
number("400.00"): types.Order{
|
||||
OrderID: 4,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
|
@ -1370,45 +1370,45 @@ func Test_verifyFilledGrid(t *testing.T) {
|
|||
})
|
||||
t.Run("invalid grid with Sell-empty order", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{
|
||||
number("100.00"): types.Order{
|
||||
OrderID: 1,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"200.00": types.Order{
|
||||
number("200.00"): types.Order{
|
||||
OrderID: 2,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"300.00": types.Order{
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeSell,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{},
|
||||
number("400.00"): types.Order{},
|
||||
}
|
||||
|
||||
assert.Error(s.verifyFilledGrid(s.grid.Pins, pinOrderMap, nil))
|
||||
})
|
||||
t.Run("invalid grid with empty-Buy order", func(t *testing.T) {
|
||||
pinOrderMap := PinOrderMap{
|
||||
"100.00": types.Order{},
|
||||
"200.00": types.Order{
|
||||
number("100.00"): types.Order{},
|
||||
number("200.00"): types.Order{
|
||||
OrderID: 2,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"300.00": types.Order{
|
||||
number("300.00"): types.Order{
|
||||
OrderID: 3,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
},
|
||||
},
|
||||
"400.00": types.Order{
|
||||
number("400.00"): types.Order{
|
||||
OrderID: 4,
|
||||
SubmitOrder: types.SubmitOrder{
|
||||
Side: types.SideTypeBuy,
|
||||
|
|
Loading…
Reference in New Issue
Block a user