Auf GitHub ansehen

SMC Trader Camel CCI MACD Strategy

Overview

This strategy is a StockSharp port of the MetaTrader 4 expert advisor "Steve Cartwright Trader Camel CCI MACD". It reproduces the original trading logic based on a camel-style exponential moving average channel, a MACD trend filter and Commodity Channel Index (CCI) thresholds. Trades are executed on completed candles to ensure deterministic behaviour and to stay close to the bar-by-bar workflow of the MQL version.

Trading Logic

  1. Indicators
    • Two exponential moving averages (EMA) with the same period are applied to candle highs and lows to form the camel channel. A breakout of the previous close beyond these envelopes signals momentum strength.
    • A standard MACD indicator (fast EMA, slow EMA and signal line) is used to confirm the underlying trend direction.
    • A CCI indicator validates momentum strength using overbought/oversold levels at ±100 by default.
  2. Long entries
    • Previous candle close is above the camel high EMA.
    • Previous MACD main value is above zero and above the signal line.
    • Previous CCI value is above the positive threshold.
    • No active position is open and no exit occurred within the current candle timeframe (prevents rapid re-entry).
  3. Short entries
    • Previous candle close is below the camel low EMA.
    • Previous MACD main value is below zero and below the signal line.
    • Previous CCI value is below the negative threshold.
    • Same flat-position and cooldown conditions as for long setups.
  4. Exits
    • Long positions close when the previous MACD main value crosses below the signal line or when the previous CCI value drops below the positive threshold.
    • Short positions close when the previous MACD main value crosses above the signal line.
    • After any exit, a cooldown equal to one candle duration is enforced before new entries.

The strategy trades once per bar at most because every decision is based on data from the previous completed candle.

Parameters

Parameter Description Default
CandleType Candle data type/timeframe used for all indicators. 1-hour time frame
CamelLength Length of the high/low EMA channel. 34
CciPeriod Length of the CCI filter. 20
MacdFastPeriod Fast EMA length for MACD. 12
MacdSlowPeriod Slow EMA length for MACD. 26
MacdSignalPeriod Signal smoothing period for MACD. 9
CciThreshold Absolute CCI level that must be exceeded for entries (applied symmetrically). 100

All parameters are optimizable through the StockSharp optimizer thanks to the SetOptimize calls.

Risk Management

  • Orders are sent via BuyMarket and SellMarket, inheriting the strategy Volume property.
  • StartProtection() is enabled to initialise standard StockSharp protection helpers.
  • No fixed stop-loss or take-profit is defined in the original algorithm; exits rely solely on indicator signals.

Charting

The strategy automatically plots the camel EMA channel, MACD and CCI indicators, together with own trades, which replicates the visual cues used in the MT4 implementation.

Notes

  • The cooldown timer uses the candle duration derived from CandleType.Arg. Ensure that CandleType contains a TimeSpan argument when you change the timeframe.
  • Because all decisions are based on previous-bar values, the order of operations mirrors the iMACD, iCCI and iMA (with shift=1) calls in the source EA.
namespace StockSharp.Samples.Strategies;

using System;
using System.Collections.Generic;

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

/// <summary>
/// Strategy combining CCI and MACD signal crossover with EMA trend filter.
/// Buy when MACD crosses above signal with CCI positive and price above EMA.
/// Sell when MACD crosses below signal with CCI negative and price below EMA.
/// </summary>
public class SmcTraderCamelCciMacd1Strategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _emaLength;
	private readonly StrategyParam<int> _macdFastPeriod;
	private readonly StrategyParam<int> _macdSlowPeriod;
	private readonly StrategyParam<int> _macdSignalPeriod;
	private readonly StrategyParam<int> _cciPeriod;

	private decimal? _prevMacdMain;
	private decimal? _prevMacdSignal;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int EmaLength { get => _emaLength.Value; set => _emaLength.Value = value; }
	public int MacdFastPeriod { get => _macdFastPeriod.Value; set => _macdFastPeriod.Value = value; }
	public int MacdSlowPeriod { get => _macdSlowPeriod.Value; set => _macdSlowPeriod.Value = value; }
	public int MacdSignalPeriod { get => _macdSignalPeriod.Value; set => _macdSignalPeriod.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }

	public SmcTraderCamelCciMacd1Strategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");

		_emaLength = Param(nameof(EmaLength), 34)
			.SetDisplay("EMA Length", "Trend EMA period", "Indicators");

		_macdFastPeriod = Param(nameof(MacdFastPeriod), 12)
			.SetDisplay("MACD Fast", "Fast EMA for MACD", "Indicators");

		_macdSlowPeriod = Param(nameof(MacdSlowPeriod), 26)
			.SetDisplay("MACD Slow", "Slow EMA for MACD", "Indicators");

		_macdSignalPeriod = Param(nameof(MacdSignalPeriod), 9)
			.SetDisplay("MACD Signal", "Signal line period", "Indicators");

		_cciPeriod = Param(nameof(CciPeriod), 20)
			.SetDisplay("CCI Period", "CCI period", "Indicators");
	}

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

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();

		_prevMacdMain = null;
		_prevMacdSignal = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);

		_prevMacdMain = null;
		_prevMacdSignal = null;

		var ema = new ExponentialMovingAverage { Length = EmaLength };
		var macd = new MovingAverageConvergenceDivergenceSignal
		{
			Macd =
			{
				ShortMa = { Length = MacdFastPeriod },
				LongMa = { Length = MacdSlowPeriod }
			},
			SignalMa = { Length = MacdSignalPeriod }
		};
		var cci = new CommodityChannelIndex { Length = CciPeriod };

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

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

		if (!macdValue.IsFinal || !cciValue.IsFinal || !emaValue.IsFinal)
			return;

		if (macdValue is not MovingAverageConvergenceDivergenceSignalValue macdData)
			return;

		if (macdData.Macd is not decimal macdMain || macdData.Signal is not decimal macdSignal)
			return;

		var cci = cciValue.ToDecimal();
		var emaVal = emaValue.ToDecimal();

		if (_prevMacdMain is not decimal prevMain || _prevMacdSignal is not decimal prevSignal)
		{
			_prevMacdMain = macdMain;
			_prevMacdSignal = macdSignal;
			return;
		}

		var macdBullCross = prevMain <= prevSignal && macdMain > macdSignal;
		var macdBearCross = prevMain >= prevSignal && macdMain < macdSignal;

		// Long: MACD bullish cross + CCI > 0 + price above EMA
		if (Position <= 0 && macdBullCross && cci > 0 && candle.ClosePrice > emaVal)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		// Short: MACD bearish cross + CCI < 0 + price below EMA
		else if (Position >= 0 && macdBearCross && cci < 0 && candle.ClosePrice < emaVal)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}

		_prevMacdMain = macdMain;
		_prevMacdSignal = macdSignal;
	}
}