diff --git a/pkg/indicator/ewma.go b/pkg/indicator/ewma.go index 3e027b6a49..1eb539ee8f 100644 --- a/pkg/indicator/ewma.go +++ b/pkg/indicator/ewma.go @@ -27,28 +27,27 @@ func (inc *EWMA) calculateAndUpdate(kLines []types.KLine) { var index = len(kLines) - 1 var lastK = kLines[index] - - // see https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp - var multiplier = 2.0 / float64(inc.Window+1) - if inc.EndTime != zeroTime && lastK.EndTime.Before(inc.EndTime) { return } - inc.EndTime = kLines[index].EndTime - var recentK = kLines[index-(inc.Window-1) : index+1] - if len(inc.Values) > 0 { - var previousEWMA = inc.Values[len(inc.Values)-1] - var ewma = lastK.Close*multiplier + previousEWMA*(1-multiplier) - inc.Values.Push(ewma) - inc.EmitUpdate(ewma) - } else { - // The first EWMA is actually SMA - var sma = calculateSMA(recentK) - inc.Values.Push(sma) - inc.EmitUpdate(sma) + var multiplier = 2.0 / float64(inc.Window+1) + var val = calculateEWMA(recentK, multiplier) + // val = calculateSMA(recentK) + inc.Values.Push(val) + inc.EndTime = lastK.EndTime + inc.EmitUpdate(val) +} + +// see https://www.investopedia.com/ask/answers/122314/what-exponential-moving-average-ema-formula-and-how-ema-calculated.asp +func calculateEWMA(kLines []types.KLine, multiplier float64) float64 { + var end = len(kLines) - 1 + if end == 0 { + return kLines[0].Close } + + return kLines[end].Close*multiplier + (1-multiplier)*calculateEWMA(kLines[:end-1], multiplier) } type KLineWindowUpdater interface { diff --git a/pkg/strategy/movingstop/strategy.go b/pkg/strategy/movingstop/strategy.go index a998fa2429..3bda7ba570 100644 --- a/pkg/strategy/movingstop/strategy.go +++ b/pkg/strategy/movingstop/strategy.go @@ -30,6 +30,10 @@ func init() { type Strategy struct { *bbgo.Graceful + // The notification system will be injected into the strategy automatically. + // This field will be injected automatically since it's a single exchange strategy. + *bbgo.Notifiability + SourceExchangeName string `json:"sourceExchange"` TargetExchangeName string `json:"targetExchange"` @@ -196,11 +200,9 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se } - lastPrice, _ := session.LastPrice(s.Symbol) - s.place(ctx, &orderExecutor, session, indicator, lastPrice) - session.Stream.OnOrderUpdate(s.handleOrderUpdate) + // session.Stream.OnKLineClosed sourceSession.Stream.OnKLineClosed(func(kline types.KLine) { // skip k-lines from other symbols @@ -225,5 +227,9 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se s.clear(ctx, session) }) + if lastPrice, ok := session.LastPrice(s.Symbol) ; ok { + s.place(ctx, &orderExecutor, session, indicator, lastPrice) + } + return nil }