Auf GitHub ansehen

AML CCI Meeting Lines Strategy

This strategy reproduces the MetaTrader 5 expert "Expert_AML_CCI" inside the StockSharp high-level framework. The original robot combines the Japanese candlestick pattern "Meeting Lines" with a Commodity Channel Index (CCI) filter and uses the Expert Advisor engine to weight bullish and bearish votes. The StockSharp port keeps the same confirmation logic, translates the candlestick pattern detection into pure candle arithmetic, and exposes all thresholds as optimizer-friendly parameters.

How it works

  • Data source – The strategy subscribes to a configurable time-frame candle series (30-minute candles by default) using SubscribeCandles. Every finished candle is dispatched together with the synchronized CCI value via the high-level Bind pipeline, so no manual indicator management is required.
  • Core indicator – A single CommodityChannelIndex with period CciPeriod mirrors the MetaTrader oscillator. Its values are cached internally to compare the two most recent completed readings, replicating the CCI(1) and CCI(2) calls from MQL.
  • Candlestick logic – The helper methods rebuild the "Bullish Meeting Lines" and "Bearish Meeting Lines" checks. They compute the moving average of body lengths over AverageBodyPeriod candles (default 3) and enforce the long-body and equal-close requirements from the original CML_CCI filter. Because StockSharp delivers completed candles, the pattern is evaluated exactly when the second candle of the pattern closes – the same moment the MQL expert casts its 80-point vote.
  • Entry rules
    • Long positions require a bullish Meeting Lines formation and the latest completed CCI value to stay below or equal to LongEntryCciLevel (−50 by default). If an opposite short is open, the order size automatically includes the absolute value of the current position to flip direction, matching the EA behaviour.
    • Short positions mirror the logic: a bearish Meeting Lines pattern plus a CCI value above or equal to ShortEntryCciLevel (+50 by default).
  • Exit rules – Instead of the Expert Advisor's voting weights, the port uses explicit flattening orders. Positions are closed when the CCI crosses the extreme band defined by ExtremeCciLevel (80 by default):
    • Shorts exit when the CCI jumps upward through −Extreme or drops back below +Extreme.
    • Longs exit when the CCI falls below +Extreme or plunges through −Extreme. These rules reflect the 40 vote branch inside LongCondition and ShortCondition in the MQL signal class.
  • Risk management – The strategy leaves protective stops to the caller. It is compatible with StockSharp's StartProtection helper if a stop-loss or take-profit needs to be attached externally.

Parameters

Parameter Description Default
CandleType Time-frame of the source candles. 30-minute time frame
CciPeriod Length of the Commodity Channel Index. 18
AverageBodyPeriod Number of candles used to compute the average body size for pattern validation. 3
LongEntryCciLevel Oversold level that confirms bullish Meeting Lines. −50
ShortEntryCciLevel Overbought level that confirms bearish Meeting Lines. +50
ExtremeCciLevel Absolute extreme band for CCI exit crossovers. 80

All numeric parameters expose optimizer ranges identical to the EA defaults so the strategy can be tuned through StockSharp's optimization tools.

Usage notes

  1. Attach the strategy to a security and set the desired Volume before starting.
  2. Optionally tweak the thresholds to match the original money-management profile or to adjust sensitivity.
  3. The chart integration draws candles, the CCI curve, and executed trades for quick visual validation of the pattern detection.

By focusing on the same candlestick+CCI combination, this StockSharp implementation delivers a faithful port of the Expert Advisor while staying within the recommended high-level API style.

namespace StockSharp.Samples.Strategies;

using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;

/// <summary>
/// Meeting Lines + CCI strategy.
/// Buys on bullish meeting lines with low CCI, sells on bearish meeting lines with high CCI.
/// </summary>
public class AmlCciMeetingLinesStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _cciLow;
	private readonly StrategyParam<decimal> _cciHigh;

	private ICandleMessage _prevCandle;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal CciLow { get => _cciLow.Value; set => _cciLow.Value = value; }
	public decimal CciHigh { get => _cciHigh.Value; set => _cciHigh.Value = value; }

	public AmlCciMeetingLinesStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_cciPeriod = Param(nameof(CciPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("CCI Period", "CCI period", "Indicators");
		_cciLow = Param(nameof(CciLow), -50m)
			.SetDisplay("CCI Low", "CCI level for bullish entry", "Signals");
		_cciHigh = Param(nameof(CciHigh), 50m)
			.SetDisplay("CCI High", "CCI level for bearish entry", "Signals");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_prevCandle = null;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_prevCandle = null;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();
	}

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

		if (_prevCandle != null)
		{
			var avgBody = (Math.Abs(candle.ClosePrice - candle.OpenPrice) +
						   Math.Abs(_prevCandle.ClosePrice - _prevCandle.OpenPrice)) / 2m;

			if (avgBody > 0)
			{
				var prevBearish = _prevCandle.OpenPrice > _prevCandle.ClosePrice;
				var currBullish = candle.ClosePrice > candle.OpenPrice;
				var closesNear = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;

				// Bullish meeting lines
				if (prevBearish && currBullish && closesNear && cciValue < CciLow && Position <= 0)
					BuyMarket();

				var prevBullish = _prevCandle.ClosePrice > _prevCandle.OpenPrice;
				var currBearish = candle.OpenPrice > candle.ClosePrice;
				var closesNear2 = Math.Abs(candle.ClosePrice - _prevCandle.ClosePrice) < avgBody * 0.3m;

				// Bearish meeting lines
				if (prevBullish && currBearish && closesNear2 && cciValue > CciHigh && Position >= 0)
					SellMarket();
			}
		}

		_prevCandle = candle;
	}
}