GitHub で見る

Caudate X Period Candle TM Plus Strategy

Overview

The strategy replicates the logic of the Caudate X Period Candle TM Plus expert advisor. It smooths the candle open, high, low and close prices with a configurable moving average, builds a Donchian-style range and classifies each finished candle into one of six color codes depending on the position of the body inside the range. Long entries are triggered by the bullish lower-tail colors (0 or 1), while short entries are triggered by the bearish upper-tail colors (5 or 6). Opposite color groups are used to exit existing positions.

Trading rules

  1. Subscribe to the selected candle series and smooth each component with the chosen moving average.
  2. Compute the highest high and lowest low of the smoothed highs and lows over the specified Donchian Period, then expand the range so that it always contains the smoothed open and close.
  3. Determine the candle color:
    • Colors 0/1 – body near the top of the range (lower tail).
    • Colors 2/4 – body centered inside the range.
    • Colors 5/6 – body near the bottom of the range (upper tail).
  4. Evaluate the color of the bar offset by Signal Bar (default 1 uses the previous completed candle).
  5. Open positions when the color belongs to the entry group and the opposite position is not active.
  6. Close positions when the color belongs to the exit group or the maximum holding time expires.
  7. Optional stop-loss and take-profit offsets are set through the built-in protection module.

Parameters

Parameter Description
Candle Type Time frame used for signal calculations.
Donchian Period Number of candles for the smoothed high/low range.
Signal Bar Number of bars to delay signal evaluation (0 = current bar).
Smoothing Method Moving average applied to OHLC prices (SMA, EMA, SMMA, LWMA, Jurik JJMA approximation, Kaufman AMA).
MA Length Length of the smoothing filter.
MA Phase Reserved for JJMA compatibility (not used by StockSharp averages).
Enable Long/Short Entries Toggle opening new long or short positions.
Enable Long/Short Exits Toggle closing existing long or short positions on signals.
Enable Time Exit Enable the maximum holding time filter.
Time Exit (minutes) Holding duration before a forced exit.
Stop Loss (points) Stop-loss distance in price steps (multiplied by Security.PriceStep).
Take Profit (points) Take-profit distance in price steps.

Notes

  • Signal Bar = 1 matches the MQL5 expert behaviour by acting on the last fully closed candle.
  • When stop or target distances are greater than zero the strategy calls StartProtection with absolute offsets based on the instrument price step.
  • MA Phase is kept for compatibility but is not consumed by the StockSharp moving-average implementations.
  • Set the base order size through the inherited Strategy.Volume property; the implementation always closes opposite positions before opening a new one.
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;

/// <summary>
/// Caudate X Period Candle TM Plus strategy (simplified). Detects candle body/tail
/// patterns using ATR-based filtering and EMA trend direction.
/// </summary>
public class CaudateXPeriodCandleTmPlusStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _atrLength;
	private readonly StrategyParam<int> _emaLength;

	public DataType CandleType
	{
		get => _candleType.Value;
		set => _candleType.Value = value;
	}

	public int AtrLength
	{
		get => _atrLength.Value;
		set => _atrLength.Value = value;
	}

	public int EmaLength
	{
		get => _emaLength.Value;
		set => _emaLength.Value = value;
	}

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

		_atrLength = Param(nameof(AtrLength), 14)
			.SetGreaterThanZero()
			.SetDisplay("ATR Length", "ATR period", "Indicators");

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

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

		var atr = new AverageTrueRange { Length = AtrLength };
		var ema = new ExponentialMovingAverage { Length = EmaLength };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(atr, ema, (ICandleMessage candle, decimal atrValue, decimal emaValue) =>
			{
				if (candle.State != CandleStates.Finished)
					return;

				if (!IsFormedAndOnlineAndAllowTrading())
					return;

				if (atrValue <= 0)
					return;

				var close = candle.ClosePrice;
				var body = Math.Abs(close - candle.OpenPrice);

				// Strong body candle in the trend direction.
				if (body > atrValue * 0.75m)
				{
					if (close > candle.OpenPrice && close > emaValue && Position <= 0)
						BuyMarket();
					else if (close < candle.OpenPrice && close < emaValue && Position >= 0)
						SellMarket();
				}
			})
			.Start();

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