diff --git a/cmd/bbgo-lorca/main.go b/cmd/bbgo-lorca/main.go index 3fa818dc3..f9c44c200 100644 --- a/cmd/bbgo-lorca/main.go +++ b/cmd/bbgo-lorca/main.go @@ -102,6 +102,11 @@ func main() { return } + if err := trader.LoadState() ; err != nil { + log.WithError(err).Error("failed to load strategy states") + return + } + // for setup mode, we don't start the trader go func() { if err := trader.Run(ctx); err != nil { diff --git a/cmd/bbgo-webview/main.go b/cmd/bbgo-webview/main.go index c3b1f27d7..215d6d73e 100644 --- a/cmd/bbgo-webview/main.go +++ b/cmd/bbgo-webview/main.go @@ -110,6 +110,11 @@ func main() { return } + if err := trader.LoadState() ; err != nil { + log.WithError(err).Error("failed to load strategy states") + return + } + // for setup mode, we don't start the trader if err := trader.Run(ctx); err != nil { log.WithError(err).Error("failed to start trader") diff --git a/pkg/bbgo/trader.go b/pkg/bbgo/trader.go index f5bcdb2c4..5944e6486 100644 --- a/pkg/bbgo/trader.go +++ b/pkg/bbgo/trader.go @@ -248,15 +248,6 @@ func (trader *Trader) RunSingleExchangeStrategy(ctx context.Context, strategy Si } } - // Before we run the strategy we need to load the state from the persistence layer: - // 1) scan the struct fields and find the persistence field - // 2) load the data and set the value into the persistence field. - - ps := trader.environment.PersistenceServiceFacade.Get() - if err := loadPersistenceFields(strategy, strategy.ID(), ps); err != nil { - return err - } - return strategy.Run(ctx, orderExecutor, session) } @@ -322,7 +313,6 @@ func (trader *Trader) Run(ctx context.Context) error { router.executors[sessionID] = orderExecutor } - ps := trader.environment.PersistenceServiceFacade.Get() for _, strategy := range trader.crossExchangeStrategies { rs := reflect.ValueOf(strategy) @@ -336,10 +326,6 @@ func (trader *Trader) Run(ctx context.Context) error { return err } - if err := loadPersistenceFields(strategy, strategy.ID(), ps); err != nil { - return err - } - if err := strategy.CrossRun(ctx, router, trader.environment.sessions); err != nil { return err } @@ -348,6 +334,72 @@ func (trader *Trader) Run(ctx context.Context) error { return trader.environment.Connect(ctx) } +func (trader *Trader) LoadState() error { + if trader.environment.BacktestService != nil { + return nil + } + + if trader.environment.PersistenceServiceFacade == nil { + return nil + } + + ps := trader.environment.PersistenceServiceFacade.Get() + + log.Infof("loading strategies states...") + for _, strategies := range trader.exchangeStrategies { + for _, strategy := range strategies { + if err := loadPersistenceFields(strategy, strategy.ID(), ps); err != nil { + return err + } + } + } + for _, strategy := range trader.crossExchangeStrategies { + if err := loadPersistenceFields(strategy, strategy.ID(), ps); err != nil { + return err + } + } + + return nil +} + +func (trader *Trader) SaveState() error { + if trader.environment.BacktestService != nil { + return nil + } + + if trader.environment.PersistenceServiceFacade == nil { + return nil + } + + ps := trader.environment.PersistenceServiceFacade.Get() + + log.Infof("saving strategies states...") + for _, strategies := range trader.exchangeStrategies { + for _, strategy := range strategies { + id := callID(strategy) + if len(id) == 0 { + continue + } + + if err := storePersistenceFields(strategy, id, ps); err != nil { + return err + } + } + } + for _, strategy := range trader.crossExchangeStrategies { + id := callID(strategy) + if len(id) == 0 { + continue + } + + if err := storePersistenceFields(strategy, id, ps); err != nil { + return err + } + } + + return nil +} + var defaultPersistenceSelector = &PersistenceSelector{ StoreID: "default", Type: "memory", diff --git a/pkg/cmd/run.go b/pkg/cmd/run.go index b2415c304..9dd4c4014 100644 --- a/pkg/cmd/run.go +++ b/pkg/cmd/run.go @@ -189,6 +189,10 @@ func runConfig(basectx context.Context, cmd *cobra.Command, userConfig *bbgo.Con return err } + if err := trader.LoadState(); err != nil { + return err + } + if err := trader.Run(ctx); err != nil { return err } @@ -228,6 +232,10 @@ func runConfig(basectx context.Context, cmd *cobra.Command, userConfig *bbgo.Con trader.Graceful.Shutdown(shutdownCtx) cancelShutdown() + if err := trader.SaveState(); err != nil { + log.WithError(err).Errorf("can not save strategy states") + } + for _, session := range environ.Sessions() { if err := session.MarketDataStream.Close(); err != nil { log.WithError(err).Errorf("[%s] market data stream close error", session.Name)