Ver en GitHub

Color XMACD Candle Strategy

This strategy is a StockSharp implementation of the "ColorXMACDCandle" expert advisor. It trades using the MACD indicator and interprets color changes of the histogram or its signal line as entry signals.

Idea

The strategy analyzes the slope of a MACD component:

  • Histogram mode – A new histogram bar that rises above the previous bar signals growing bullish momentum. A new bar that falls below the previous bar signals bearish momentum.
  • Signal line mode – The slope of the MACD signal line is used instead. An upward slope acts as a buy signal, while a downward slope acts as a sell signal.

When the chosen component turns upward and was not rising previously, any short position can be closed and a new long position may be opened. When the component turns downward and was not falling previously, any long position can be closed and a short position may be opened.

The behaviour of opening and closing positions is controlled by separate parameters, allowing the user to enable or disable each action independently.

Parameters

  • Mode – Source of signals: Histogram or SignalLine.
  • FastPeriod – Fast EMA period for MACD.
  • SlowPeriod – Slow EMA period for MACD.
  • SignalPeriod – MACD signal smoothing period.
  • EnableBuyOpen – Allow opening long positions.
  • EnableSellOpen – Allow opening short positions.
  • EnableBuyClose – Allow closing long positions.
  • EnableSellClose – Allow closing short positions.
  • CandleType – Candle type for calculations.

Trading Rules

  1. Subscribe to the selected candle series and calculate the MACD indicator.
  2. Track the slope of the histogram or signal line depending on the selected mode.
  3. When the slope turns upward, close any short position (if allowed) and optionally open a long position.
  4. When the slope turns downward, close any long position (if allowed) and optionally open a short position.

The strategy does not include stop loss or take profit mechanisms. Risk management can be added separately if required.

using System;
using System.Linq;
using System.Collections.Generic;

using Ecng.Common;
using Ecng.Collections;
using Ecng.Serialization;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Strategy that reacts to slope changes of the MACD histogram.
/// Buys when histogram slope turns up, sells when it turns down.
/// </summary>
public class ColorXMacdCandleStrategy : Strategy
{
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;
	private readonly StrategyParam<int> _signalPeriod;
	private readonly StrategyParam<DataType> _candleType;

	private ExponentialMovingAverage _signalMa;
	private decimal? _prevHist;
	private decimal? _prevPrevHist;

	public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
	public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
	public int SignalPeriod { get => _signalPeriod.Value; set => _signalPeriod.Value = value; }
	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }

	public ColorXMacdCandleStrategy()
	{
		_fastPeriod = Param(nameof(FastPeriod), 12)
			.SetGreaterThanZero()
			.SetDisplay("Fast Period", "Fast EMA period", "MACD");

		_slowPeriod = Param(nameof(SlowPeriod), 26)
			.SetGreaterThanZero()
			.SetDisplay("Slow Period", "Slow EMA period", "MACD");

		_signalPeriod = Param(nameof(SignalPeriod), 9)
			.SetGreaterThanZero()
			.SetDisplay("Signal Period", "Signal line period", "MACD");

		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
			.SetDisplay("Candle Type", "Candle type for calculations", "Common");
	}

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

	protected override void OnReseted()
	{
		base.OnReseted();
		_signalMa = null;
		_prevHist = null;
		_prevPrevHist = null;
	}

	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		var macd = new MovingAverageConvergenceDivergence();
		macd.ShortMa.Length = FastPeriod;
		macd.LongMa.Length = SlowPeriod;

		_signalMa = new ExponentialMovingAverage { Length = SignalPeriod };
		Indicators.Add(_signalMa);

		var subscription = SubscribeCandles(CandleType);
		subscription
			.BindEx(macd, ProcessCandle)
			.Start();

		var area = CreateChartArea();
		if (area != null)
		{
			DrawCandles(area, subscription);
			DrawIndicator(area, macd);
			DrawOwnTrades(area);
		}
	}

	private void ProcessCandle(ICandleMessage candle, IIndicatorValue macdValue)
	{
		if (candle.State != CandleStates.Finished)
			return;

		if (!macdValue.IsFormed)
			return;

		var macdLine = macdValue.GetValue<decimal>();
		var signalResult = _signalMa.Process(macdValue);

		if (!signalResult.IsFormed)
			return;

		var signalLine = signalResult.GetValue<decimal>();
		var hist = macdLine - signalLine;

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevPrevHist = _prevHist;
			_prevHist = hist;
			return;
		}

		if (_prevHist is decimal ph && _prevPrevHist is decimal pph)
		{
			var wasRising = ph > pph;
			var nowRising = hist > ph;

			// Histogram slope turns up -> buy
			if (!wasRising && nowRising && Position <= 0)
				BuyMarket();
			// Histogram slope turns down -> sell
			else if (wasRising && !nowRising && Position >= 0)
				SellMarket();
		}

		_prevPrevHist = _prevHist;
		_prevHist = hist;
	}
}