diff --git a/pkg/strategy/buyandhold/strategy.go b/pkg/strategy/buyandhold/strategy.go index 39e4e69d15..ed753252db 100644 --- a/pkg/strategy/buyandhold/strategy.go +++ b/pkg/strategy/buyandhold/strategy.go @@ -21,23 +21,41 @@ func init() { type Strategy struct { Symbol string `json:"symbol"` - Interval string `json:"interval"` + Interval types.Interval `json:"interval"` BaseQuantity float64 `json:"baseQuantity"` MinDropPercentage fixedpoint.Value `json:"minDropPercentage"` MinDropChange fixedpoint.Value `json:"minDropChange"` + + MovingAverageWindow int `json:"movingAverageWindow"` } func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) { - session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.Interval}) + session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: string(s.Interval)}) } func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, session *bbgo.ExchangeSession) error { + if s.Interval == "" { + s.Interval = types.Interval5m + } + + if s.MovingAverageWindow == 0 { + s.MovingAverageWindow = 99 + } + // buy when price drops -8% market, ok := session.Market(s.Symbol) if !ok { return fmt.Errorf("market %s is not defined", s.Symbol) } + standardIndicatorSet, ok := session.StandardIndicatorSet(s.Symbol) + if !ok { + return fmt.Errorf("standardIndicatorSet is nil, symbol %s", s.Symbol) + } + + var iw = types.IntervalWindow{Interval: s.Interval, Window: s.MovingAverageWindow} + var ema = standardIndicatorSet.EWMA(iw) + session.Stream.OnKLine(func(kline types.KLine) { // skip k-lines from other symbols if kline.Symbol != s.Symbol { @@ -61,6 +79,11 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se return } + if kline.Close > ema.Last() { + log.Warnf("kline close price %f is above EMA %s %f", kline.Close, ema.IntervalWindow, ema.Last()) + return + } + changeP := change / kline.Open if s.MinDropPercentage != 0 {