MultiTimeframeEmaAlignmentStrategy es un puerto StockSharp del MetaTrader 4 asesores expertos 1h-4h-1d.mq4 de la carpeta MQL/7713. El robot original alinea promedios móviles exponenciales rápidos y lentos en tres períodos de tiempo y aplica una gestión protectora del dinero a través de niveles fijos de stop loss, takeprofit y trailing stop. Esta versión de C# sigue la misma idea de alto nivel al tiempo que aprovecha los enlaces de indicadores y los ayudantes de pedidos de alto nivel de StockSharp.
Lógica de trading
La estrategia se suscribe a tres series de velas simultáneamente: M1 (marco temporal de señal), M5 (filtro a medio plazo) y M30 (confirmación de tendencia de marco temporal superior).
Cada serie alimenta un par de promedios móviles exponenciales (EMA) con longitudes configurables (por defecto 8 y 64).
Una configuración alcista requiere que el EMA rápido se mantenga por encima del EMA lento en los tres marcos temporales. Además, el EMA rápida no debe perder impulso (valor actual mayor o igual al valor anterior y también por encima del valor de hace ShiftDepth barras).
Una configuración bajista requiere que el EMA rápido se mantenga por debajo del EMA lento en los tres períodos de tiempo, con el EMA rápido disminuyendo en impulso.
Las órdenes se activan al cierre de la vela M1 cuando se cumplen las comprobaciones de alineación e impulso. Las señales largas solo se permiten cuando no hay una posición larga abierta (o una posición corta existente se cierra primero) y viceversa.
Esta interpretación recrea la intención de las condiciones MT4 con el nivel alto API de StockSharp. Las comparaciones de MQL "cambio de MA" se emula a través del búfer ShiftDepth que rastrea los valores de EMA unas cuantas velas atrás y garantiza que el impulso sea consistente con la dirección de entrada.
Gestión del riesgo
El tamaño de la posición está controlado por el parámetro TradeVolume (3 lotes predeterminados como el EA original).
Las distancias opcionales de parada de pérdidas y toma de ganancias se proporcionan en pips. Se convierten a precios a través del PriceStep del instrumento (vuelve a 0.0001 cuando falta).
El trailing stop replica el comportamiento del EA al acercar el precio stop al mercado cada vez que la operación avanza lo suficiente.
Los parámetros de riesgo se pueden alternar de forma independiente, coincidiendo con los indicadores StopLossMode, TakeProfitMode y TrailingStopMode del script MQL.
Parámetros
Parámetro
Descripción
Predeterminado
TradeVolume
Volumen de pedidos utilizado por BuyMarket / SellMarket. Refleja la entrada Lots.
3
FastLength
EMA período para la línea rápida.
8
SlowLength
EMA período para la línea lenta.
64
ShiftDepth
Número de velas históricas utilizadas para emular las comparaciones de cambios de media móvil MQL.
3
UseStopLoss
Habilita stop loss fijo.
true
StopLossPips
Distancia de stop loss expresada en pips.
75
UseTakeProfit
Permite tomar ganancias.
true
TakeProfitPips
Distancia de toma de ganancias expresada en pips.
150
UseTrailingStop
Permite la gestión de trailing stop.
true
TrailingStopPips
Distancia de seguimiento en pips.
30
M1CandleType
Tipo de vela para el período de tiempo de la señal (predeterminado 1 minuto).
1m
M5CandleType
Tipo de vela para el filtro intermedio (por defecto 5 minutos).
5m
M30CandleType
Tipo de vela para el período de tiempo más alto (predeterminado 30 minutos).
30m
Notas de uso
Adjunte la estrategia a un instrumento y asegúrese de que los datos históricos estén disponibles para los tres períodos de tiempo para permitir que se completen los buffers EMA.
El parámetro ShiftDepth debe permanecer al menos 2 para que la estrategia pueda validar el impulso a corto plazo.
Cuando UseTrailingStop está activo sin UseStopLoss, la lógica de seguimiento aún inicializa un valor de parada una vez que la operación se mueve a favor.
Debido a que StockSharp se ejecuta al cierre de la vela, los resultados pueden diferir ligeramente de la ejecución tick a tick de la versión MT4, especialmente en mercados volátiles. El comportamiento central de alineación de tendencias permanece intacto.
Notas de conversión
Los cálculos de los indicadores se basan exclusivamente en el mecanismo Bind de StockSharp; no se utilizan recopilaciones manuales del historial de indicadores.
La gestión de pedidos se implementa con ayudantes de alto nivel (BuyMarket, SellMarket) y seguimiento de precios interno en lugar de llamadas directas OrderSend.
Las notificaciones de correo y los controles de deslizamiento del script MQL se omiten porque están fuera del alcance de StockSharp.
Archivos
CS/MultiTimeframeEmaAlignmentStrategy.cs – implementación de la estrategia principal de C#.
README_ru.md – Documentación rusa.
README_zh.md – Documentación china.
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>
/// Multi-Timeframe EMA Alignment strategy - fast/slow EMA crossover with trend EMA filter.
/// Buys when fast EMA crosses above slow EMA while close is above trend EMA.
/// Sells when fast EMA crosses below slow EMA while close is below trend EMA.
/// </summary>
public class MultiTimeframeEmaAlignmentStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _trendPeriod;
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 int TrendPeriod { get => _trendPeriod.Value; set => _trendPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public MultiTimeframeEmaAlignmentStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_trendPeriod = Param(nameof(TrendPeriod), 100)
.SetDisplay("Trend EMA", "Trend EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevFast = 0m; _prevSlow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fast = new ExponentialMovingAverage { Length = FastPeriod };
var slow = new ExponentialMovingAverage { Length = SlowPeriod };
var trend = new ExponentialMovingAverage { Length = TrendPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, trend, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow, decimal trend)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
if (_prevFast <= _prevSlow && fast > slow && close > trend && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow && close < trend && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevFast = fast;
_prevSlow = slow;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class multi_timeframe_ema_alignment_strategy(Strategy):
def __init__(self):
super(multi_timeframe_ema_alignment_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 10).SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 30).SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._trend_period = self.Param("TrendPeriod", 100).SetDisplay("Trend EMA", "Trend EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
@property
def fast_period(self): return self._fast_period.Value
@property
def slow_period(self): return self._slow_period.Value
@property
def trend_period(self): return self._trend_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(multi_timeframe_ema_alignment_strategy, self).OnReseted()
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
def OnStarted2(self, time):
super(multi_timeframe_ema_alignment_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
trend = ExponentialMovingAverage()
trend.Length = self.trend_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, trend, self.process_candle).Start()
def process_candle(self, candle, fast, slow, trend):
if candle.State != CandleStates.Finished: return
close = float(candle.ClosePrice)
f = float(fast); s = float(slow); t = float(trend)
if not self._has_prev:
self._prev_fast = f; self._prev_slow = s; self._has_prev = True; return
if self._prev_fast <= self._prev_slow and f > s and close > t and self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and close < t and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return multi_timeframe_ema_alignment_strategy()