diff --git a/pkg/bbgo/order_executor_general.go b/pkg/bbgo/order_executor_general.go index a3ce04572..2a0b1c1df 100644 --- a/pkg/bbgo/order_executor_general.go +++ b/pkg/bbgo/order_executor_general.go @@ -108,6 +108,7 @@ func (e *GeneralOrderExecutor) GracefulCancel(ctx context.Context) error { return err } + e.tradeCollector.Process() return nil } @@ -119,3 +120,8 @@ func (e *GeneralOrderExecutor) ClosePosition(ctx context.Context, percentage fix return e.SubmitOrders(ctx, *submitOrder) } + + +func (e *GeneralOrderExecutor) TradeCollector() *TradeCollector { + return e.tradeCollector +} diff --git a/pkg/strategy/bollmaker/strategy.go b/pkg/strategy/bollmaker/strategy.go index 597834ed8..9d15c34f3 100644 --- a/pkg/strategy/bollmaker/strategy.go +++ b/pkg/strategy/bollmaker/strategy.go @@ -25,7 +25,6 @@ const ID = "bollmaker" const stateKey = "state-v1" -var defaultFeeRate = fixedpoint.NewFromFloat(0.001) var notionModifier = fixedpoint.NewFromFloat(1.1) var two = fixedpoint.NewFromInt(2) @@ -155,9 +154,7 @@ type Strategy struct { Position *types.Position `json:"position,omitempty" persistence:"position"` ProfitStats *types.ProfitStats `json:"profitStats,omitempty" persistence:"profit_stats"` - activeMakerOrders *bbgo.ActiveOrderBook - orderStore *bbgo.OrderStore - tradeCollector *bbgo.TradeCollector + orderExecutor *bbgo.GeneralOrderExecutor groupID uint32 @@ -244,13 +241,7 @@ func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Valu bbgo.Notify("Submitting %s %s order to close position by %v", s.Symbol, side.String(), percentage, submitOrder) - createdOrders, err := s.session.Exchange.SubmitOrders(ctx, submitOrder) - if err != nil { - log.WithError(err).Errorf("can not place position close order") - } - - s.orderStore.Add(createdOrders...) - s.activeMakerOrders.Add(createdOrders...) + err := s.orderExecutor.SubmitOrders(ctx, submitOrder) return err } @@ -479,12 +470,7 @@ func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExec submitOrders[i] = adjustOrderQuantity(submitOrders[i], s.Market) } - createdOrders, err := orderExecutor.SubmitOrders(ctx, submitOrders...) - if err != nil { - log.WithError(err).Errorf("can not place ping pong orders") - } - s.orderStore.Add(createdOrders...) - s.activeMakerOrders.Add(createdOrders...) + _ = s.orderExecutor.SubmitOrders(ctx, submitOrders...) } func (s *Strategy) hasLongSet() bool { @@ -507,17 +493,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se s.OnSuspend(func() { s.Status = types.StrategyStatusStopped - - // Cancel all order - if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil { - log.WithError(err).Errorf("graceful cancel order error") - bbgo.Notify("graceful cancel order error") - } else { - bbgo.Notify("All orders are cancelled.") - } - - s.tradeCollector.Process() - + _ = s.orderExecutor.GracefulCancel(ctx) _ = s.Persistence.Sync(s) }) @@ -593,48 +569,21 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se s.Position.Strategy = ID s.Position.StrategyInstanceID = instanceID + s.orderExecutor = bbgo.NewGeneralOrderExecutor(session, s.Symbol, ID, instanceID, s.Position) + s.orderExecutor.BindEnvironment(s.Environment) + s.orderExecutor.BindProfitStats(s.ProfitStats) + s.orderExecutor.Bind() + s.stopC = make(chan struct{}) - s.activeMakerOrders = bbgo.NewActiveOrderBook(s.Symbol) - s.activeMakerOrders.BindStream(session.UserDataStream) - - s.orderStore = bbgo.NewOrderStore(s.Symbol) - s.orderStore.BindStream(session.UserDataStream) - - s.tradeCollector = bbgo.NewTradeCollector(s.Symbol, s.Position, s.orderStore) - - s.tradeCollector.OnTrade(func(trade types.Trade, profit, netProfit fixedpoint.Value) { - bbgo.Notify(trade) - s.ProfitStats.AddTrade(trade) - - if profit.Compare(fixedpoint.Zero) == 0 { - s.Environment.RecordPosition(s.Position, trade, nil) - } else { - log.Infof("%s generated profit: %v", s.Symbol, profit) - p := s.Position.NewProfit(trade, profit, netProfit) - p.Strategy = ID - p.StrategyInstanceID = instanceID - bbgo.Notify(&p) - - s.ProfitStats.AddProfit(p) - bbgo.Notify(s.ProfitStats) - - s.Environment.RecordPosition(s.Position, trade, &p) - } - }) - - s.tradeCollector.OnPositionUpdate(func(position *types.Position) { - log.Infof("position changed: %s", s.Position) - bbgo.Notify(s.Position) - + // TODO: migrate persistance to singleton + s.orderExecutor.TradeCollector().OnPositionUpdate(func(position *types.Position) { if err := s.Persistence.Sync(s); err != nil { log.WithError(err).Errorf("can not sync state to persistence") } }) - s.tradeCollector.BindStream(session.UserDataStream) - - s.SmartStops.RunStopControllers(ctx, session, s.tradeCollector) + s.SmartStops.RunStopControllers(ctx, session, s.orderExecutor.TradeCollector()) if s.Environment.IsBackTesting() { log.Warn("turning of useTickerPrice option in the back-testing environment...") @@ -682,12 +631,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se } } - if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil { - log.WithError(err).Errorf("graceful cancel order error") - } - - // check if there is a canceled order had partially filled. - s.tradeCollector.Process() + _ = s.orderExecutor.GracefulCancel(ctx) if s.UseTickerPrice { ticker, err := s.session.Exchange.QueryTicker(ctx, s.Symbol) @@ -710,11 +654,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se defer wg.Done() close(s.stopC) - if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil { - log.WithError(err).Errorf("graceful cancel order error") - } - - s.tradeCollector.Process() + _ = s.orderExecutor.GracefulCancel(ctx) }) return nil