From e097421b7bc4b69686cb02b9204eef67a865d632 Mon Sep 17 00:00:00 2001 From: zenix Date: Wed, 13 Jul 2022 17:08:57 +0900 Subject: [PATCH] feature: export canvas path for drift strategy. fix exit/entry order and fix missing columns from json parsing --- config/drift.yaml | 1 + pkg/strategy/drift/strategy.go | 58 +++++++++++++++++++--------------- 2 files changed, 33 insertions(+), 26 deletions(-) diff --git a/config/drift.yaml b/config/drift.yaml index 698b70b75..e30c9d3c5 100644 --- a/config/drift.yaml +++ b/config/drift.yaml @@ -10,6 +10,7 @@ exchangeStrategies: - on: binance drift: + canvasPath: "./output.png" symbol: ETHUSDT # kline interval for indicators interval: 15m diff --git a/pkg/strategy/drift/strategy.go b/pkg/strategy/drift/strategy.go index 560fe5b5c..259c98b6f 100644 --- a/pkg/strategy/drift/strategy.go +++ b/pkg/strategy/drift/strategy.go @@ -41,7 +41,8 @@ type Strategy struct { midPrice fixedpoint.Value lock sync.RWMutex - stoploss float64 `json:"stoploss"` + Stoploss fixedpoint.Value `json:"stoploss"` + CanvasPath string `json:"canvasPath"` ExitMethods bbgo.ExitMethodSet `json:"exits"` Session *bbgo.ExchangeSession @@ -241,15 +242,35 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se driftPred = s.drift.Predict(3) atr = s.atr.Last() price := s.GetLastPrice() + pricef := price.Float64() avg := s.Position.AverageCost.Float64() + stoploss := s.Stoploss.Float64() - shortCondition := (driftPred <= 0 && drift[0] <= 0) && (s.Position.IsClosed() || s.Position.IsDust(fixedpoint.Max(price, source))) - longCondition := (driftPred >= 0 && drift[0] >= 0) && (s.Position.IsClosed() || s.Position.IsDust(fixedpoint.Min(price, source))) - exitShortCondition := ((drift[1] < 0 && drift[0] >= 0) || avg+atr/2 <= price.Float64() || avg*(1.+s.stoploss) <= price.Float64()) && - (!s.Position.IsClosed() && !s.Position.IsDust(fixedpoint.Max(price, source))) - exitLongCondition := ((drift[1] > 0 && drift[0] < 0) || avg-atr/2 >= price.Float64() || avg*(1.-s.stoploss) >= price.Float64()) && - (!s.Position.IsClosed() && !s.Position.IsDust(fixedpoint.Min(price, source))) + shortCondition := (driftPred <= 0 && drift[0] <= 0) + longCondition := (driftPred >= 0 && drift[0] >= 0) + exitShortCondition := ((drift[1] < 0 && drift[0] >= 0) || avg+atr/2 <= pricef || avg*(1.+stoploss) <= pricef) && + (!s.Position.IsClosed() && !s.Position.IsDust(fixedpoint.Max(price, source))) && !longCondition + exitLongCondition := ((drift[1] > 0 && drift[0] < 0) || avg-atr/2 >= pricef || avg*(1.-stoploss) >= pricef) && + (!s.Position.IsClosed() && !s.Position.IsDust(fixedpoint.Min(price, source))) && !shortCondition + if exitShortCondition { + if s.ActiveOrderBook.NumOfOrders() > 0 { + if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { + log.WithError(err).Errorf("cannot cancel orders") + return + } + } + _, _ = s.ClosePosition(ctx) + } + if exitLongCondition { + if s.ActiveOrderBook.NumOfOrders() > 0 { + if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { + log.WithError(err).Errorf("cannot cancel orders") + return + } + } + _, _ = s.ClosePosition(ctx) + } if shortCondition { if s.ActiveOrderBook.NumOfOrders() > 0 { if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { @@ -282,15 +303,6 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se return } } - if exitShortCondition { - if s.ActiveOrderBook.NumOfOrders() > 0 { - if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { - log.WithError(err).Errorf("cannot cancel orders") - return - } - } - _, _ = s.ClosePosition(ctx) - } if longCondition { if s.ActiveOrderBook.NumOfOrders() > 0 { if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { @@ -326,15 +338,6 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se return } } - if exitLongCondition { - if s.ActiveOrderBook.NumOfOrders() > 0 { - if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { - log.WithError(err).Errorf("cannot cancel orders") - return - } - } - _, _ = s.ClosePosition(ctx) - } }) bbgo.OnShutdown(func(ctx context.Context, wg *sync.WaitGroup) { @@ -348,7 +351,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se canvas.Plot("drift", s.drift, dynamicKLine.StartTime, 100) canvas.Plot("zero", types.NumberSeries(0), dynamicKLine.StartTime, 100) canvas.Plot("price", priceLine.Minus(mean).Mul(ratio), dynamicKLine.StartTime, 100) - f, _ := os.Create("output.png") + f, err := os.Create(s.CanvasPath) + if err != nil { + log.Errorf("%v cannot create on %s", err, s.CanvasPath) + } defer f.Close() canvas.Render(chart.PNG, f) wg.Done()