diff --git a/pkg/bbgo/activeorderbook.go b/pkg/bbgo/activeorderbook.go index b241f9640..e720e46fd 100644 --- a/pkg/bbgo/activeorderbook.go +++ b/pkg/bbgo/activeorderbook.go @@ -69,9 +69,14 @@ func (b *ActiveOrderBook) waitAllClear(ctx context.Context, waitTime, timeout ti // GracefulCancel cancels the active orders gracefully func (b *ActiveOrderBook) GracefulCancel(ctx context.Context, ex types.Exchange) error { - waitTime := CancelOrderWaitTime + // optimize order cancel for back-testing + if IsBackTesting { + orders := b.Orders() + return ex.CancelOrders(context.Background(), orders...) + } log.Debugf("[ActiveOrderBook] gracefully cancelling %s orders...", b.Symbol) + waitTime := CancelOrderWaitTime startTime := time.Now() // ensure every order is cancelled diff --git a/pkg/bbgo/environment.go b/pkg/bbgo/environment.go index 8f49bc9ab..9fc84e783 100644 --- a/pkg/bbgo/environment.go +++ b/pkg/bbgo/environment.go @@ -37,6 +37,16 @@ func init() { rand.Seed(time.Now().UnixNano()) } +// IsBackTesting is a global variable that indicates the current environment is back-test or not. +var IsBackTesting = false + +var BackTestService *service.BacktestService + +func SetBackTesting(s *service.BacktestService) { + BackTestService = s + IsBackTesting = true +} + var LoadedExchangeStrategies = make(map[string]SingleExchangeStrategy) var LoadedCrossExchangeStrategies = make(map[string]CrossExchangeStrategy) @@ -69,19 +79,18 @@ const ( // Environment presents the real exchange data layer type Environment struct { - PersistenceServiceFacade *service.PersistenceServiceFacade - DatabaseService *service.DatabaseService - OrderService *service.OrderService - TradeService *service.TradeService - ProfitService *service.ProfitService - PositionService *service.PositionService - BacktestService *service.BacktestService - RewardService *service.RewardService - MarginService *service.MarginService - SyncService *service.SyncService - AccountService *service.AccountService - WithdrawService *service.WithdrawService - DepositService *service.DepositService + DatabaseService *service.DatabaseService + OrderService *service.OrderService + TradeService *service.TradeService + ProfitService *service.ProfitService + PositionService *service.PositionService + BacktestService *service.BacktestService + RewardService *service.RewardService + MarginService *service.MarginService + SyncService *service.SyncService + AccountService *service.AccountService + WithdrawService *service.WithdrawService + DepositService *service.DepositService // startTime is the time of start point (which is used in the backtest) startTime time.Time @@ -107,9 +116,6 @@ func NewEnvironment() *Environment { startTime: now, syncStatus: SyncNotStarted, - PersistenceServiceFacade: &service.PersistenceServiceFacade{ - Memory: service.NewMemoryService(), - }, } } @@ -276,7 +282,8 @@ func (environ *Environment) ConfigurePersistence(conf *PersistenceConfig) error return err } - environ.PersistenceServiceFacade.Redis = service.NewRedisPersistenceService(conf.Redis) + redisPersistence := service.NewRedisPersistenceService(conf.Redis) + PersistenceServiceFacade.Redis = redisPersistence } if conf.Json != nil { @@ -287,7 +294,8 @@ func (environ *Environment) ConfigurePersistence(conf *PersistenceConfig) error } } - environ.PersistenceServiceFacade.Json = &service.JsonPersistenceService{Directory: conf.Json.Directory} + jsonPersistence := &service.JsonPersistenceService{Directory: conf.Json.Directory} + PersistenceServiceFacade.Json = jsonPersistence } return nil @@ -772,7 +780,7 @@ func (environ *Environment) ConfigureNotificationSystem(userConfig *Config) erro } } - var persistence = environ.PersistenceServiceFacade.Get() + var persistence = PersistenceServiceFacade.Get() err := environ.setupInteraction(persistence) if err != nil { diff --git a/pkg/bbgo/persistence.go b/pkg/bbgo/persistence.go index 100b29428..9756e4253 100644 --- a/pkg/bbgo/persistence.go +++ b/pkg/bbgo/persistence.go @@ -17,6 +17,12 @@ type PersistenceSelector struct { Type string `json:"type" yaml:"type"` } +var DefaultPersistenceServiceFacade = &service.PersistenceServiceFacade{ + Memory: service.NewMemoryService(), +} + +var PersistenceServiceFacade = DefaultPersistenceServiceFacade + // Persistence is used for strategy to inject the persistence. type Persistence struct { PersistenceSelector *PersistenceSelector `json:"persistence,omitempty" yaml:"persistence,omitempty"` diff --git a/pkg/bbgo/trader.go b/pkg/bbgo/trader.go index c0d0cbca8..eeea025a1 100644 --- a/pkg/bbgo/trader.go +++ b/pkg/bbgo/trader.go @@ -327,11 +327,11 @@ func (trader *Trader) LoadState() error { return nil } - if trader.environment.PersistenceServiceFacade == nil { + if PersistenceServiceFacade == nil { return nil } - ps := trader.environment.PersistenceServiceFacade.Get() + ps := PersistenceServiceFacade.Get() log.Infof("loading strategies states...") @@ -364,11 +364,11 @@ func (trader *Trader) SaveState() error { return nil } - if trader.environment.PersistenceServiceFacade == nil { + if PersistenceServiceFacade == nil { return nil } - ps := trader.environment.PersistenceServiceFacade.Get() + ps := PersistenceServiceFacade.Get() log.Infof("saving strategies states...") return trader.IterateStrategies(func(strategy StrategyID) error { @@ -387,10 +387,9 @@ var defaultPersistenceSelector = &PersistenceSelector{ } func (trader *Trader) injectCommonServices(s interface{}) error { - persistenceFacade := trader.environment.PersistenceServiceFacade persistence := &Persistence{ PersistenceSelector: defaultPersistenceSelector, - Facade: persistenceFacade, + Facade: PersistenceServiceFacade, } // a special injection for persistence selector: @@ -404,7 +403,7 @@ func (trader *Trader) injectCommonServices(s interface{}) error { return fmt.Errorf("field Persistence is not a struct element, %s given", field) } - if err := injectField(elem, "Facade", persistenceFacade, true); err != nil { + if err := injectField(elem, "Facade", PersistenceServiceFacade, true); err != nil { return err } @@ -426,6 +425,6 @@ func (trader *Trader) injectCommonServices(s interface{}) error { trader.environment.AccountService, trader.environment, persistence, - persistenceFacade, // if the strategy use persistence facade separately + PersistenceServiceFacade, // if the strategy use persistence facade separately ) } diff --git a/pkg/cmd/backtest.go b/pkg/cmd/backtest.go index 783275279..363d2d282 100644 --- a/pkg/cmd/backtest.go +++ b/pkg/cmd/backtest.go @@ -160,6 +160,7 @@ var BacktestCmd = &cobra.Command{ backtestService := &service.BacktestService{DB: environ.DatabaseService.DB} environ.BacktestService = backtestService + bbgo.SetBackTesting(backtestService) if len(sessionName) > 0 { userConfig.Backtest.Sessions = []string{sessionName}