Esta estrategia replica el sistema de medias móviles "arcoíris" del experto MQL original.
Utiliza once medias móviles exponenciales junto con filtros MACD y ADX.
Cómo funciona
Calcular EMA(2), EMA(3), EMA(5), EMA(8), EMA(13), EMA(21), EMA(34), EMA(55), EMA(89), EMA(144) y EMA(233) sobre precios de cierre.
Calcular MACD (Rápido, Lento, Señal) y usar la línea de señal.
Calcular ADX para medir la fuerza de la tendencia.
Comprar cuando:
La línea de señal MACD está por encima de cero.
Todas las EMA están estrictamente ascendentes (cada EMA más rápida por encima de la más lenta).
El valor ADX está por encima del umbral.
Vender cuando:
La línea de señal MACD está por debajo de cero.
Todas las EMA están estrictamente descendentes.
El valor ADX está por encima del umbral.
Las posiciones se invierten cuando aparece una señal opuesta.
Parámetros
Nombre
Descripción
FastMacd
Período de EMA rápida para MACD.
SlowMacd
Período de EMA lenta para MACD.
SignalPeriod
Período de la línea de señal para MACD.
AdxPeriod
Período para el indicador ADX.
AdxThreshold
Valor mínimo de ADX requerido para operar.
CandleType
Marco temporal de velas utilizado para los cálculos.
Notas
La estrategia usa órdenes de mercado mediante BuyMarket y SellMarket.
Solo se mantiene una posición a la vez; una señal opuesta invierte la posición.
Esta es una conversión directa de la estrategia MQL original sin la lógica opcional de martingala.
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>
/// EMA rainbow trend following strategy.
/// </summary>
public class MagnaRapaxCopperStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
public int FastPeriod { get => _fastPeriod.Value; set => _fastPeriod.Value = value; }
public int SlowPeriod { get => _slowPeriod.Value; set => _slowPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MagnaRapaxCopperStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 13)
.SetGreaterThanZero()
.SetDisplay("Fast Period", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 34)
.SetGreaterThanZero()
.SetDisplay("Slow Period", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle type", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
SubscribeCandles(CandleType)
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fastVal, decimal slowVal)
{
if (candle.State != CandleStates.Finished) return;
if (!_hasPrev)
{
_prevFast = fastVal;
_prevSlow = slowVal;
_hasPrev = true;
return;
}
var crossUp = _prevFast <= _prevSlow && fastVal > slowVal;
var crossDown = _prevFast >= _prevSlow && fastVal < slowVal;
if (crossUp && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
}
else if (crossDown && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
}
_prevFast = fastVal;
_prevSlow = slowVal;
}
}