La estrategia de protección cruzada EMA 5/8 replica el asesor experto MetaTrader 5_8macrossv2.mq4 al comparar dos promedios móviles configurables en el mismo símbolo. Un cruce alcista del promedio móvil rápido por encima del lento abre posiciones largas, mientras que un cruce bajista abre posiciones cortas. La versión portada sigue StockSharp patrones de alto nivel y agrega administración opcional de obtención de ganancias, stop-loss y trailing-stop.
Lógica de trading
Se calculan dos medias móviles sobre la suscripción de vela seleccionada. De forma predeterminada, una MA exponencial de 5 períodos en precios de cierre se compara con una MA exponencial de 8 períodos en precios de apertura.
Cuando la MA rápida cruza por encima de la MA lenta en la última vela terminada, la estrategia abre o revierte a una posición larga. Si una posición corta está activa, su volumen se incluye en la nueva orden de compra del mercado para invertir la dirección.
Cuando la MA rápida cruza por debajo de la MA lenta, la estrategia abre o invierte en una posición corta usando la misma lógica de normalización de volumen.
Los parámetros de desplazamiento MA emulan el desplazamiento horizontal original. Los valores positivos retrasan la señal tantas velas cerradas; los valores negativos se redondean a cero porque los valores desplazados hacia adelante no están disponibles en los datos en tiempo real.
Gestión del riesgo
Las distancias de toma de ganancias y stop-loss se expresan en pips (escalones de precio). Cuando se abre una posición larga, los niveles de protección se colocan por encima y por debajo del precio de entrada respectivamente; La lógica refleja los cortos.
El trailing stop (también en pips) ajusta constantemente el nivel de protección a medida que el precio se mueve a favor de la posición. En el caso de posiciones largas, el trailing stop sólo se mueve hacia arriba; para los cortos, solo se mueve hacia abajo.
Si se cumple alguna condición de protección en una vela terminada (obtención de ganancias alta, stop-loss baja o nivel de seguimiento), la estrategia sale de la posición con una orden de mercado y restablece su estado interno.
Parámetros
Nombre
Tipo
Predeterminado
Descripción
TradeVolume
decimal
0.1
Volumen de pedidos para nuevas entradas. La estrategia agrega el tamaño absoluto de la posición al revertir.
TakeProfitPips
decimal
40
Distancia desde la entrada en pips para cerrar la posición con beneficio. Establezca en 0 para desactivar.
StopLossPips
decimal
0
Distancia desde la entrada en pips para stop-loss de protección. Establezca en 0 para desactivar.
TrailingStopPips
decimal
0
Distancia del trailing-stop en pips. Establezca en 0 para desactivar.
FastPeriod
int
5
Período de la media móvil rápida.
FastShift
int
-1
Desplazamiento horizontal para el MA rápido. Los valores negativos se tratan como cero en este puerto.
FastMethod
MovingAverageMethod
Exponential
Algoritmo de suavizado para el MA rápido (Simple, Exponencial, Suavizado, LinearWeighted).
FastPrice
AppliedPrice
Close
Precio de vela utilizado para el MA rápido.
SlowPeriod
int
8
Período de la media móvil lenta.
SlowShift
int
0
Desplazamiento horizontal para la MA lenta.
SlowMethod
MovingAverageMethod
Exponential
Algoritmo de suavizado para el MA lento.
SlowPrice
AppliedPrice
Open
Precio de vela utilizado para la MA lenta.
CandleType
DataType
TimeSpan.FromMinutes(30).TimeFrame()
Serie de velas utilizadas para los cálculos.
Notas
La conversión mantiene la lógica centrada en las velas terminadas para evitar señales prematuras.
Los trailingstops y los objetivos de ganancias se calculan con Security.PriceStep; si un símbolo no lo define, los parámetros de riesgo permanecen inactivos.
La versión de Python se omite intencionalmente según los requisitos de la tarea.
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>
/// 5/8 MA Cross Protect strategy - EMA(5) and EMA(8) crossover.
/// Buys when EMA(5) crosses above EMA(8).
/// Sells when EMA(5) crosses below EMA(8).
/// </summary>
public class FiveEightMaCrossProtectStrategy : 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 FiveEightMaCrossProtectStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 8)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).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 subscription = SubscribeCandles(CandleType);
subscription
.Bind(fast, slow, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevFast = fast;
_prevSlow = slow;
_hasPrev = true;
return;
}
if (_prevFast <= _prevSlow && fast > slow && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (_prevFast >= _prevSlow && fast < slow && 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 five_eight_ma_cross_protect_strategy(Strategy):
def __init__(self):
super(five_eight_ma_cross_protect_strategy, self).__init__()
self._fast_period = self.Param("FastPeriod", 5).SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 8).SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))).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 candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(five_eight_ma_cross_protect_strategy, self).OnReseted()
self._prev_fast = 0.0; self._prev_slow = 0.0; self._has_prev = False
def OnStarted2(self, time):
super(five_eight_ma_cross_protect_strategy, self).OnStarted2(time)
self._has_prev = False
fast = ExponentialMovingAverage()
fast.Length = self.fast_period
slow = ExponentialMovingAverage()
slow.Length = self.slow_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(fast, slow, self.process_candle).Start()
def process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished: return
f = float(fast); s = float(slow)
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 self.Position <= 0:
if self.Position < 0: self.BuyMarket()
self.BuyMarket()
elif self._prev_fast >= self._prev_slow and f < s and self.Position >= 0:
if self.Position > 0: self.SellMarket()
self.SellMarket()
self._prev_fast = f; self._prev_slow = s
def CreateClone(self): return five_eight_ma_cross_protect_strategy()