Ver en GitHub

Dual Supertrend MACD

Dual Supertrend MACD combines two Supertrend indicators with a MACD filter. A long position is opened when price trades above both Supertrend lines and the MACD histogram is positive. Short positions appear when price is below both lines and the histogram is negative. Positions are closed once any Supertrend flips direction or the MACD histogram crosses zero.

Details

  • Data: Price candles.
  • Entry Criteria:
    • Long: Close > Supertrend1 && Close > Supertrend2 && MACD Histogram > 0
    • Short: Close < Supertrend1 && Close < Supertrend2 && MACD Histogram < 0
  • Exit Criteria:
    • Long: Close < Supertrend1 || Close < Supertrend2 || MACD Histogram < 0
    • Short: Close > Supertrend1 || Close > Supertrend2 || MACD Histogram > 0
  • Stops: None by default.
  • Default Values:
    • MacdFast = 12
    • MacdSlow = 26
    • MacdSignal = 9
    • OscillatorMaType = Exponential
    • SignalMaType = Exponential
    • AtrPeriod1 = 10
    • Factor1 = 3.0
    • AtrPeriod2 = 20
    • Factor2 = 5.0
    • TradeDirection = "Both"
  • Filters:
    • Category: Trend following
    • Direction: Configurable
    • Indicators: Supertrend, MACD
    • Complexity: Intermediate
    • Risk level: Medium
using System;
using System.Collections.Generic;

using Ecng.Common;

using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;

namespace StockSharp.Samples.Strategies;

public class DualSupertrendMacdStrategy : Strategy
{
	private readonly StrategyParam<int> _fastEmaPeriod;
	private readonly StrategyParam<int> _slowEmaPeriod;
	private readonly StrategyParam<DataType> _candleType;
	private decimal _prevFastEma;
	private decimal _prevSlowEma;

	public int FastEmaPeriod { get => _fastEmaPeriod.Value; set => _fastEmaPeriod.Value = value; }
	public int SlowEmaPeriod { get => _slowEmaPeriod.Value; set => _slowEmaPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public DualSupertrendMacdStrategy()
	{
		_fastEmaPeriod = Param(nameof(FastEmaPeriod), 120)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
		_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 450)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(1).TimeFrame())
			.SetDisplay("Candle Type", "Type of candles to use", "General");
	}

	public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
	{
		return [(Security, CandleType)];
	}

	protected override void OnReseted()
	{
		base.OnReseted();
		_prevFastEma = 0m;
		_prevSlowEma = 0m;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
		var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(fastEma, slowEma, ProcessCandle).Start();
		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, fastEma);
			DrawIndicator(area, slowEma);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, decimal fastEmaValue, decimal slowEmaValue)
	{
		if (candle.State != CandleStates.Finished) return;
		if (_prevFastEma == 0m || _prevSlowEma == 0m)
		{
			_prevFastEma = fastEmaValue;
			_prevSlowEma = slowEmaValue;
			return;
		}
		if (_prevFastEma <= _prevSlowEma && fastEmaValue > slowEmaValue && Position <= 0)
			BuyMarket();
		else if (_prevFastEma >= _prevSlowEma && fastEmaValue < slowEmaValue && Position >= 0)
			SellMarket();
		_prevFastEma = fastEmaValue;
		_prevSlowEma = slowEmaValue;
	}
}