Ver en GitHub

Estrategia de IMF CDC PL

Descripción general

La Estrategia CDC PL MFI reproduce el MetaTrader asesor experto Expert_ADC_PL_MFI (MQL/299) en StockSharp. Busca los patrones de inversión de dos velas Dark Cloud Cover y Piercing Line y valida cada señal con el oscilador Money Flow Index (MFI). La estrategia utiliza los mismos períodos de indicador y umbrales de nivel que el experto original, agrega protección opcional de stop-loss y take-profit en unidades de pip y cierra posiciones cuando la IMF cruza niveles de reversión configurables.

Lógica de trading

  1. Suscríbase al tipo de vela configurado (velas de una hora por defecto) y calcule un índice de flujo de dinero con el período especificado. Mantenga promedios móviles simples del tamaño del cuerpo de la vela y los precios de cierre para replicar los filtros de tendencia y volatilidad originales.
  2. Cuando se forma un patrón alcista Piercing Line (brecha por debajo del mínimo anterior, cierre alcista por encima del punto medio de la vela bajista anterior, ambas velas más grandes que el cuerpo promedio y el cierre anterior por debajo del promedio de la tendencia) y el valor actual de MFI está por debajo del LongEntryLevel (predeterminado 40), ingrese o cambie a una posición larga.
  3. Cuando se forma un patrón bajista Cubierta de nubes oscuras (brecha por encima del máximo anterior, cierre bajista por debajo del punto medio de la vela alcista anterior, ambas velas más grandes que el cuerpo promedio y el cierre anterior por encima del promedio de la tendencia) y el valor actual de MFI está por encima del ShortEntryLevel (predeterminado 60), ingrese o cambie a una posición corta.
  4. Monitorear a la IMF para cerrar posiciones de manera proactiva:
    • Cierre las posiciones cortas cuando la IMF cruce por encima de ExitLowerLevel (30) o ExitUpperLevel (70).
    • Cierre posiciones largas cuando la IMF cruce por debajo de ExitUpperLevel (70) o ExitLowerLevel (30).
  5. Las órdenes de protección son opcionales. Cuando TakeProfitPips o StopLossPips son mayores que cero, la estrategia llama a StartProtection con las compensaciones de precio correspondientes (distancia del pip multiplicada por el paso del precio del valor).

Parámetros

Parámetro Descripción Predeterminado
CandleType Tipo de datos de vela utilizado para la detección de patrones. 1 hour período de tiempo
MfiPeriod Longitud del oscilador del índice de flujo de dinero. 49
BodyAveragePeriod Período de la media móvil del cuerpo de la vela utilizado para calificar velas "largas". 11
LongEntryLevel Umbral de MFI que confirma configuraciones alcistas de Piercing Line. 40
ShortEntryLevel Umbral de MFI que confirma configuraciones bajistas de Dark Cloud Cover. 60
ExitLowerLevel Menor nivel de IFM que desencadena la cobertura de posiciones cortas. 30
ExitUpperLevel Nivel superior de MFI que desencadena el cierre de posiciones largas. 70
StopLossPips Distancia de stop-loss opcional en pips (0 desactiva la protección). 50
TakeProfitPips Distancia de toma de ganancias opcional en pips (0 desactiva la protección). 50

Notas

  • El volumen predeterminado es 1 lote. Cuando la estrategia cambia de dirección, envía una orden de mercado única del tamaño de cerrar la posición existente y abrir la nueva, coincidiendo con el comportamiento MQL.
  • La detección de patrones refleja la lógica MetaTrader: solo se evalúan las velas completadas, las brechas deben ocurrir más allá del máximo/mínimo anterior y un promedio móvil simple impone la condición de tendencia predominante.
  • Los valores del índice de flujo de dinero provienen directamente del indicador consolidado. No se requiere almacenamiento en búfer manual del historial del indicador; la estrategia almacena solo los valores más recientes para detectar cruces de umbrales.
  • No se proporciona ningún puerto Python; only the C# implementation is included in this directory.
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>
/// CDC PL MFI strategy: Dark Cloud Cover and Piercing Line candlestick patterns
/// confirmed by Money Flow Index levels.
/// </summary>
public class CdcPlMfiStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _mfiPeriod;
	private readonly StrategyParam<decimal> _longLevel;
	private readonly StrategyParam<decimal> _shortLevel;
	private readonly StrategyParam<int> _signalCooldownCandles;

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

	public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
	public int MfiPeriod { get => _mfiPeriod.Value; set => _mfiPeriod.Value = value; }
	public decimal LongLevel { get => _longLevel.Value; set => _longLevel.Value = value; }
	public decimal ShortLevel { get => _shortLevel.Value; set => _shortLevel.Value = value; }
	public int SignalCooldownCandles { get => _signalCooldownCandles.Value; set => _signalCooldownCandles.Value = value; }

	public CdcPlMfiStrategy()
	{
		_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
			.SetDisplay("Candle Type", "Candle timeframe", "General");
		_mfiPeriod = Param(nameof(MfiPeriod), 14)
			.SetGreaterThanZero()
			.SetDisplay("MFI Period", "Money Flow Index period", "Indicators");
		_longLevel = Param(nameof(LongLevel), 40m)
			.SetDisplay("Long Level", "MFI below this for long entry", "Signals");
		_shortLevel = Param(nameof(ShortLevel), 60m)
			.SetDisplay("Short Level", "MFI above this for short entry", "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();
		_prevMfi = 0m;
		_hasPrevMfi = false;
		_candlesSinceTrade = SignalCooldownCandles;
	}

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

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

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

		if (_candlesSinceTrade < SignalCooldownCandles)
			_candlesSinceTrade++;

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

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

			// Piercing Line: prev bearish, curr bullish, 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, 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 && mfiValue < LongLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				BuyMarket();
				_candlesSinceTrade = 0;
			}
			else if (isDarkCloud && mfiValue > ShortLevel && Position == 0 && _candlesSinceTrade >= SignalCooldownCandles)
			{
				SellMarket();
				_candlesSinceTrade = 0;
			}
		}

		_prevMfi = mfiValue;
		_hasPrevMfi = true;
	}
}