Ver en GitHub

Estrategia Ultra MFI de Gestión Monetaria Recontada

Descripción general

La Estrategia Ultra MFI MMRec es un port directo del asesor experto de MetaTrader 5 Exp_UltraMFI_MMRec. Combina un oscilador de Índice de Flujo de Dinero (MFI) suavizado en múltiples pasos con gestión del dinero basada en rachas. Dos contadores internos acumulan cuántas capas de suavizado apuntan hacia arriba o hacia abajo. Los cruces entre estos contadores generan señales de trading, mientras que los resultados recientes de las operaciones determinan si la siguiente posición usa el tamaño de posición normal o reducido.

Lógica de trading

  1. Indicador base – se calcula un Índice de Flujo de Dinero con longitud configurable en el tipo de vela seleccionado.
  2. Suavizado escalonado – el valor MFI se pasa a través de una escalera de medias móviles. Cada paso aumenta la longitud de suavizado en un incremento fijo. Los métodos de suavizado admitidos son Simple, Exponencial, Suavizado, Linealmente Ponderado y medias móviles Jurik (otros modos específicos de MT5 no están disponibles en StockSharp).
  3. Contadores direccionales – para cada barra la estrategia compara la salida actual y anterior de cada paso de suavizado. Si el paso está subiendo, el contador alcista aumenta, de lo contrario aumenta el bajista. Ambos contadores se suavizan de nuevo por una media móvil final.
  4. Desplazamiento de señal – las reglas de trading operan en barras terminadas. Un SignalShift configurable le indica a la estrategia cuántas velas cerradas mirar hacia atrás al comparar los contadores, imitando el comportamiento de MT5 al usar SignalBar=1.
  5. Entradas y salidas
    • Si la barra anterior mostró toros más fuertes (bulls > bears) y la última barra muestra un cruce a bulls < bears, la estrategia abre una posición larga. La misma condición también cierra cualquier posición corta abierta.
    • Si la barra anterior mostró osos más fuertes y la última barra cambia a bulls > bears, la estrategia abre una posición corta y cierra cualquier posición larga abierta.
    • El stop-loss y take-profit opcionales (basados en porcentaje) pueden gestionarse a través de StartProtection.
  6. Gestión del dinero – el siguiente tamaño de orden depende de los últimos resultados de operaciones por dirección. Después de cerrar cada posición se inspecciona el PnL realizado:
    • La estrategia almacena las operaciones de compra más recientes BuyTotalTrigger y cuenta cuántas fueron pérdidas. Cuando el conteo alcanza BuyLossTrigger, la siguiente orden de compra usa ReducedVolume, de lo contrario usa NormalVolume.
    • La misma lógica se aplica independientemente para las operaciones de venta con SellTotalTrigger y SellLossTrigger.

Parámetros

  • CandleType – tipo de datos del instrumento (marco temporal) usado para la generación de señales.
  • MfiPeriod – longitud del oscilador Índice de Flujo de Dinero.
  • StepSmoothing / FinalSmoothing – tipo de media móvil para los pasos de la escalera y los contadores finales.
  • StartLength / StepSize / StepsTotal – geometría de la escalera de suavizado (primera longitud, incremento, número de pasos).
  • FinalSmoothingLength – longitud de la etapa de suavizado del contador.
  • SignalShift – número de barras completadas a mirar hacia atrás al evaluar señales.
  • NormalVolume / ReducedVolume – tamaño de operación para condiciones normales y después de una racha perdedora.
  • BuyTotalTrigger / BuyLossTrigger – profundidad de historial y umbral de pérdida para cambiar la siguiente operación larga a tamaño reducido.
  • SellTotalTrigger / SellLossTrigger – configuraciones análogas para operaciones cortas.
  • AllowLongEntries / AllowShortEntries / AllowLongExits / AllowShortExits – habilitar o deshabilitar entradas y salidas para cada dirección.
  • TakeProfitPercent / StopLossPercent – niveles de protección opcionales basados en porcentaje.

Notas de uso

  • El suavizado escalonado requiere suficientes velas históricas para llenar cada media móvil. Espere hasta que la estrategia esté completamente formada antes de confiar en las señales.
  • Dado que StockSharp no proporciona suavizadores específicos de MT5 como JurX, Parabolic, VIDYA o AMA, se usan las alternativas compatibles más cercanas. El suavizado Jurik es un buen valor predeterminado que reproduce la sensación original del indicador UltraMFI.
  • La gestión del dinero se basa en el PnL realizado. Asegúrese de que sus backtests incluyan la ejecución de órdenes para que el PnL realizado se actualice después de cada cierre de posición.
  • Este port mantiene el comportamiento de solo entrar en nuevas posiciones cuando la posición actual es plana. Cuando aparece una señal de reversión mientras se mantiene la posición opuesta, la estrategia primero sale de la operación existente y entrará en la siguiente barra elegible una vez que esté plana.
using System;
using System.Collections.Generic;

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

namespace StockSharp.Samples.Strategies;

/// <summary>
/// Ultra MFI MMRec strategy. Uses EMA crossover as signal generator.
/// </summary>
public class UltraMfiMmRecStrategy : Strategy
{
	private readonly StrategyParam<DataType> _candleType;
	private readonly StrategyParam<int> _fastPeriod;
	private readonly StrategyParam<int> _slowPeriod;

	private decimal? _prevFast;
	private decimal? _prevSlow;

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

	public int FastPeriod
	{
		get => _fastPeriod.Value;
		set => _fastPeriod.Value = value;
	}

	public int SlowPeriod
	{
		get => _slowPeriod.Value;
		set => _slowPeriod.Value = value;
	}

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

		_fastPeriod = Param(nameof(FastPeriod), 8)
			.SetGreaterThanZero()
			.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");

		_slowPeriod = Param(nameof(SlowPeriod), 21)
			.SetGreaterThanZero()
			.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
	}

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

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

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

		_prevFast = null;
		_prevSlow = null;

		var fast = new ExponentialMovingAverage { Length = FastPeriod };
		var slow = new ExponentialMovingAverage { Length = SlowPeriod };

		var subscription = SubscribeCandles(CandleType);
		subscription
			.Bind(fast, slow, ProcessCandle)
			.Start();

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

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

		if (!IsFormedAndOnlineAndAllowTrading())
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		if (_prevFast == null || _prevSlow == null)
		{
			_prevFast = fastVal;
			_prevSlow = slowVal;
			return;
		}

		var prevAbove = _prevFast.Value > _prevSlow.Value;
		var currAbove = fastVal > slowVal;

		_prevFast = fastVal;
		_prevSlow = slowVal;

		if (!prevAbove && currAbove && Position <= 0)
		{
			if (Position < 0)
				BuyMarket();
			BuyMarket();
		}
		else if (prevAbove && !currAbove && Position >= 0)
		{
			if (Position > 0)
				SellMarket();
			SellMarket();
		}
	}
}