mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
Merge pull request #1298 from c9s/c9s/grid2-fix-recover-active-orders
FIX: [grid2] fix active order recover, add start process delay
This commit is contained in:
commit
8adb0df656
|
@ -583,7 +583,9 @@ func (s *Strategy) handleOrderFilled(o types.Order) {
|
||||||
s.processFilledOrder(o)
|
s.processFilledOrder(o)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) checkRequiredInvestmentByQuantity(baseBalance, quoteBalance, quantity, lastPrice fixedpoint.Value, pins []Pin) (requiredBase, requiredQuote fixedpoint.Value, err error) {
|
func (s *Strategy) checkRequiredInvestmentByQuantity(
|
||||||
|
baseBalance, quoteBalance, quantity, lastPrice fixedpoint.Value, pins []Pin,
|
||||||
|
) (requiredBase, requiredQuote fixedpoint.Value, err error) {
|
||||||
// check more investment budget details
|
// check more investment budget details
|
||||||
requiredBase = fixedpoint.Zero
|
requiredBase = fixedpoint.Zero
|
||||||
requiredQuote = fixedpoint.Zero
|
requiredQuote = fixedpoint.Zero
|
||||||
|
@ -641,7 +643,9 @@ func (s *Strategy) checkRequiredInvestmentByQuantity(baseBalance, quoteBalance,
|
||||||
return requiredBase, requiredQuote, nil
|
return requiredBase, requiredQuote, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) checkRequiredInvestmentByAmount(baseBalance, quoteBalance, amount, lastPrice fixedpoint.Value, pins []Pin) (requiredBase, requiredQuote fixedpoint.Value, err error) {
|
func (s *Strategy) checkRequiredInvestmentByAmount(
|
||||||
|
baseBalance, quoteBalance, amount, lastPrice fixedpoint.Value, pins []Pin,
|
||||||
|
) (requiredBase, requiredQuote fixedpoint.Value, err error) {
|
||||||
|
|
||||||
// check more investment budget details
|
// check more investment budget details
|
||||||
requiredBase = fixedpoint.Zero
|
requiredBase = fixedpoint.Zero
|
||||||
|
@ -702,7 +706,9 @@ func (s *Strategy) checkRequiredInvestmentByAmount(baseBalance, quoteBalance, am
|
||||||
return requiredBase, requiredQuote, nil
|
return requiredBase, requiredQuote, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) calculateQuoteInvestmentQuantity(quoteInvestment, lastPrice fixedpoint.Value, pins []Pin) (fixedpoint.Value, error) {
|
func (s *Strategy) calculateQuoteInvestmentQuantity(
|
||||||
|
quoteInvestment, lastPrice fixedpoint.Value, pins []Pin,
|
||||||
|
) (fixedpoint.Value, error) {
|
||||||
// quoteInvestment = (p1 * q) + (p2 * q) + (p3 * q) + ....
|
// quoteInvestment = (p1 * q) + (p2 * q) + (p3 * q) + ....
|
||||||
// =>
|
// =>
|
||||||
// quoteInvestment = (p1 + p2 + p3) * q
|
// quoteInvestment = (p1 + p2 + p3) * q
|
||||||
|
@ -758,7 +764,9 @@ func (s *Strategy) calculateQuoteInvestmentQuantity(quoteInvestment, lastPrice f
|
||||||
return q, nil
|
return q, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) calculateBaseQuoteInvestmentQuantity(quoteInvestment, baseInvestment, lastPrice fixedpoint.Value, pins []Pin) (fixedpoint.Value, error) {
|
func (s *Strategy) calculateBaseQuoteInvestmentQuantity(
|
||||||
|
quoteInvestment, baseInvestment, lastPrice fixedpoint.Value, pins []Pin,
|
||||||
|
) (fixedpoint.Value, error) {
|
||||||
s.logger.Infof("calculating quantity by base/quote investment: %f / %f", baseInvestment.Float64(), quoteInvestment.Float64())
|
s.logger.Infof("calculating quantity by base/quote investment: %f / %f", baseInvestment.Float64(), quoteInvestment.Float64())
|
||||||
// q_p1 = q_p2 = q_p3 = q_p4
|
// q_p1 = q_p2 = q_p3 = q_p4
|
||||||
// baseInvestment = q_p1 + q_p2 + q_p3 + q_p4 + ....
|
// baseInvestment = q_p1 + q_p2 + q_p3 + q_p4 + ....
|
||||||
|
@ -1463,7 +1471,9 @@ func (s *Strategy) checkMinimalQuoteInvestment(grid *Grid) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) recoverGridWithOpenOrders(ctx context.Context, historyService types.ExchangeTradeHistoryService, openOrders []types.Order) error {
|
func (s *Strategy) recoverGridWithOpenOrders(
|
||||||
|
ctx context.Context, historyService types.ExchangeTradeHistoryService, openOrders []types.Order,
|
||||||
|
) error {
|
||||||
grid := s.newGrid()
|
grid := s.newGrid()
|
||||||
|
|
||||||
s.logger.Infof("GRID RECOVER: %s", grid.String())
|
s.logger.Infof("GRID RECOVER: %s", grid.String())
|
||||||
|
@ -1622,7 +1632,10 @@ func (s *Strategy) getGrid() *Grid {
|
||||||
|
|
||||||
// replayOrderHistory queries the closed order history from the API and rebuild the orderbook from the order history.
|
// replayOrderHistory queries the closed order history from the API and rebuild the orderbook from the order history.
|
||||||
// startTime, endTime is the time range of the order history.
|
// startTime, endTime is the time range of the order history.
|
||||||
func (s *Strategy) replayOrderHistory(ctx context.Context, grid *Grid, orderBook *bbgo.ActiveOrderBook, historyService types.ExchangeTradeHistoryService, startTime, endTime time.Time, lastOrderID uint64) error {
|
func (s *Strategy) replayOrderHistory(
|
||||||
|
ctx context.Context, grid *Grid, orderBook *bbgo.ActiveOrderBook, historyService types.ExchangeTradeHistoryService,
|
||||||
|
startTime, endTime time.Time, lastOrderID uint64,
|
||||||
|
) error {
|
||||||
// a simple guard, in reality, this startTime is not possible to exceed the endTime
|
// a simple guard, in reality, this startTime is not possible to exceed the endTime
|
||||||
// because the queries closed orders might still in the range.
|
// because the queries closed orders might still in the range.
|
||||||
orderIdChanged := true
|
orderIdChanged := true
|
||||||
|
@ -1951,10 +1964,6 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
session.UserDataStream.OnConnect(func() {
|
|
||||||
s.handleConnect(ctx, session)
|
|
||||||
})
|
|
||||||
|
|
||||||
// if TriggerPrice is zero, that means we need to open the grid when start up
|
// if TriggerPrice is zero, that means we need to open the grid when start up
|
||||||
if s.TriggerPrice.IsZero() {
|
if s.TriggerPrice.IsZero() {
|
||||||
// must call the openGrid method inside the OnStart callback because
|
// must call the openGrid method inside the OnStart callback because
|
||||||
|
@ -1966,13 +1975,25 @@ func (s *Strategy) Run(ctx context.Context, _ bbgo.OrderExecutor, session *bbgo.
|
||||||
s.logger.Infof("user data stream started, initializing grid...")
|
s.logger.Infof("user data stream started, initializing grid...")
|
||||||
|
|
||||||
if !bbgo.IsBackTesting {
|
if !bbgo.IsBackTesting {
|
||||||
go s.startProcess(ctx, session)
|
go time.AfterFunc(3*time.Second, func() {
|
||||||
|
s.startProcess(ctx, session)
|
||||||
|
})
|
||||||
} else {
|
} else {
|
||||||
s.startProcess(ctx, session)
|
s.startProcess(ctx, session)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
session.UserDataStream.OnConnect(func() {
|
||||||
|
if !bbgo.IsBackTesting {
|
||||||
|
// callback may block the stream execution, so we spawn the recover function to the background
|
||||||
|
// add (5 seconds + random <10 seconds jitter) delay
|
||||||
|
go time.AfterFunc(util.MillisecondsJitter(5*time.Second, 1000*10), func() {
|
||||||
|
s.recoverActiveOrders(ctx, session)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2117,16 +2138,29 @@ func (s *Strategy) newClientOrderID() string {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) handleConnect(ctx context.Context, session *bbgo.ExchangeSession) {
|
func (s *Strategy) recoverActiveOrders(ctx context.Context, session *bbgo.ExchangeSession) {
|
||||||
|
s.logger.Infof("recovering active orders after websocket connect")
|
||||||
|
|
||||||
grid := s.getGrid()
|
grid := s.getGrid()
|
||||||
if grid == nil {
|
if grid == nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// this lock avoids recovering the active orders while the openGrid is executing
|
||||||
|
s.mu.Lock()
|
||||||
|
defer s.mu.Unlock()
|
||||||
|
|
||||||
// TODO: move this logics into the active maker orders component, like activeOrders.Sync(ctx)
|
// TODO: move this logics into the active maker orders component, like activeOrders.Sync(ctx)
|
||||||
activeOrderBook := s.orderExecutor.ActiveMakerOrders()
|
activeOrderBook := s.orderExecutor.ActiveMakerOrders()
|
||||||
activeOrders := activeOrderBook.Orders()
|
activeOrders := activeOrderBook.Orders()
|
||||||
|
if len(activeOrders) == 0 {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
s.logger.Infof("found %d active orders to update...", len(activeOrders))
|
||||||
for _, o := range activeOrders {
|
for _, o := range activeOrders {
|
||||||
|
s.logger.Infof("updating %d order...", o.OrderID)
|
||||||
|
|
||||||
var updatedOrder *types.Order
|
var updatedOrder *types.Order
|
||||||
err := retry.GeneralBackoff(ctx, func() error {
|
err := retry.GeneralBackoff(ctx, func() error {
|
||||||
var err error
|
var err error
|
||||||
|
|
Loading…
Reference in New Issue
Block a user