Ver en GitHub

Estrategia de perforación de nube oscura CCI

Descripción general

This strategy is a StockSharp port of the MetaTrader Expert_ADC_PL_CCI advisor. Escanea la acción del precio en busca de reversiones de velas de Piercing Line y Dark Cloud Cover y utiliza el índice del canal de productos básicos (CCI) como confirmación. Una vez que se detecta un patrón válido junto con una lectura extrema de CCI, la estrategia abre una posición de mercado en la dirección de la reversión y luego sale cuando el CCI sale de su zona extrema.

Indicadores

  • Índice del canal de productos básicos (CCI): confirma los extremos del impulso y produce las condiciones de salida.
  • Longitud promedio del cuerpo (SMA): mide el tamaño del cuerpo de la vela para validar velas "largas" dentro de la definición del patrón.
  • Average close price (SMA): acts as a simple trend filter that mirrors the moving average used in the original MQL logic.

Reglas de trading

Entrada

  • Bullish signal (Piercing Line):
    1. Previous candle must be a long bearish candle that opens above its close.
    2. La última vela debe ser una vela alcista larga que se abra por debajo del mínimo anterior y cierre dentro del cuerpo anterior, por encima de su punto medio pero por debajo de la apertura anterior.
    3. The midpoint of the older candle has to be below the moving average to confirm a short-term downtrend.
    4. The most recent completed CCI value must be less than or equal to -EntryConfirmationLevel (default 50).
    5. If a short position exists it is fully closed before entering long.
  • Señal bajista (Cubierta de nubes oscuras): lógica reflejada de la señal alcista con una vela alcista larga seguida de una vela bajista larga que se abre, penetra el cuerpo anterior y cierra por debajo de su punto medio mientras CCI es mayor o igual a EntryConfirmationLevel.

Salir

  • Posiciones largas: se cierran cuando el CCI cruza por debajo de ExitLevel o cruza por debajo de -ExitLevel desde arriba, lo que indica que el impulso se ha normalizado.
  • Short positions: closed when the CCI crosses up above -ExitLevel or above ExitLevel from below.

Dimensionamiento de posiciones

  • Uses the base Volume property. Cuando la señal requiere revertir una posición existente, la estrategia agrega automáticamente el tamaño absoluto de la posición actual al volumen de la orden, asegurando un cambio completo.

Parámetros

Nombre Descripción Predeterminado
CandleType Tipo de vela y período de tiempo utilizado para la detección. 1H período de tiempo
CciPeriod Longitud retrospectiva del índice del canal de productos básicos. 49
AverageBodyPeriod Número de velas para la media móvil del tamaño corporal. 11
EntryConfirmationLevel Absolute CCI level that validates pattern entries. 50
ExitLevel Absolute CCI level that triggers position exits. 80

Notas

  • The strategy processes only finished candles and ignores partial updates.
  • No stop-loss or take-profit orders are set automatically; exits are purely signal based as in the original expert advisor.
  • Ensure the instrument has a price step configured because the equality tolerance of the candlestick logic depends on the security settings.
namespace StockSharp.Samples.Strategies;

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

/// <summary>
/// Dark Cloud Piercing CCI strategy: trades Dark Cloud Cover and Piercing Line
/// candlestick patterns confirmed by CCI indicator levels.
/// </summary>
public class DarkCloudPiercingCciStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _cciPeriod;
	private readonly StrategyParam<decimal> _entryLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

	private readonly List<ICandleMessage> _candles = new();
	private decimal _prevCci;
	private bool _hasPrevCci;
	private int _candlesSinceTrade;

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int CciPeriod { get => _cciPeriod.Value; set => _cciPeriod.Value = value; }
	public decimal EntryLevel { get => _entryLevel.Value; set => _entryLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public DarkCloudPiercingCciStrategy()
	{
		_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");
		_entryLevel = Param(nameof(EntryLevel), 50m)
			.SetDisplay("Entry Level", "CCI level for confirmation", "Signals");
		_signalCooldownCandles = Param(nameof(SignalCooldownCandles), 6)
			.SetGreaterThanZero()
			.SetDisplay("Signal Cooldown", "Bars to wait between trades", "Trading");
	}

	/// <inheritdoc />
	protected override void OnReseted()
	{
		base.OnReseted();
		_candles.Clear();
		_prevCci = 0m;
		_hasPrevCci = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

	/// <inheritdoc />
	protected override void OnStarted2(DateTime time)
	{
		base.OnStarted2(time);
		_candles.Clear();
		_hasPrevCci = false;
		_candlesSinceTrade = SignalCooldownCandles;
		var cci = new CommodityChannelIndex { Length = CciPeriod };
		var subscription = SubscribeCandles(CandleType);
		subscription.Bind(cci, ProcessCandle).Start();

		StartProtection(
			takeProfit: new Unit(2, UnitTypes.Percent),
			stopLoss: new Unit(1, UnitTypes.Percent)
		);
	}

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

		_candles.Add(candle);
		if (_candles.Count > 5)
			_candles.RemoveAt(0);

		if (_candles.Count >= 2 && _hasPrevCci)
		{
			var curr = _candles[^1];
			var prev = _candles[^2];

			// Piercing Line: prev bearish, curr bullish, curr opens below prev low, closes above midpoint
			var isPiercing = prev.OpenPrice > prev.ClosePrice
				&& curr.ClosePrice > curr.OpenPrice
				&& curr.OpenPrice < prev.LowPrice
				&& curr.ClosePrice > (prev.OpenPrice + prev.ClosePrice) / 2m;

			// Dark Cloud Cover: prev bullish, curr bearish, curr opens above prev high, closes below midpoint
			var isDarkCloud = prev.ClosePrice > prev.OpenPrice
				&& curr.OpenPrice > curr.ClosePrice
				&& curr.OpenPrice > prev.HighPrice
				&& curr.ClosePrice < (prev.OpenPrice + prev.ClosePrice) / 2m;

			if (isPiercing && cciValue < -EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && cciValue > EntryLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevCci = cciValue;
		_hasPrevCci = true;
	}
}