From 58c819bd753ddd929f50c334bf57bcb0df1d90a0 Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 21 Jun 2022 01:05:13 +0800 Subject: [PATCH 1/2] bbgo: pull out PersistenceServiceFacade to singleton --- pkg/bbgo/environment.go | 14 ++++++-------- pkg/bbgo/persistence.go | 6 ++++++ pkg/bbgo/trader.go | 15 +++++++-------- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/pkg/bbgo/environment.go b/pkg/bbgo/environment.go index 8f49bc9ab..12569991c 100644 --- a/pkg/bbgo/environment.go +++ b/pkg/bbgo/environment.go @@ -69,7 +69,6 @@ const ( // Environment presents the real exchange data layer type Environment struct { - PersistenceServiceFacade *service.PersistenceServiceFacade DatabaseService *service.DatabaseService OrderService *service.OrderService TradeService *service.TradeService @@ -106,10 +105,7 @@ func NewEnvironment() *Environment { sessions: make(map[string]*ExchangeSession), startTime: now, - syncStatus: SyncNotStarted, - PersistenceServiceFacade: &service.PersistenceServiceFacade{ - Memory: service.NewMemoryService(), - }, + syncStatus: SyncNotStarted, } } @@ -276,7 +272,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 +284,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 +770,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 ) } From 19d8013f493f17a0f117e789232d5c0fefedf41d Mon Sep 17 00:00:00 2001 From: c9s Date: Tue, 21 Jun 2022 01:12:16 +0800 Subject: [PATCH 2/2] bbgo: optimize order cancel for back-testing --- pkg/bbgo/activeorderbook.go | 7 ++++++- pkg/bbgo/environment.go | 36 +++++++++++++++++++++++------------- pkg/cmd/backtest.go | 1 + 3 files changed, 30 insertions(+), 14 deletions(-) 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 12569991c..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,18 +79,18 @@ const ( // Environment presents the real exchange data layer type Environment struct { - 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 @@ -105,7 +115,7 @@ func NewEnvironment() *Environment { sessions: make(map[string]*ExchangeSession), startTime: now, - syncStatus: SyncNotStarted, + syncStatus: SyncNotStarted, } } 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}