La estrategia Simple MACD EA es una adaptación directa del clásico asesor experto MetaTrader "Simple MACD EA". El enfoque utiliza dos promedios móviles exponenciales (EMA) para emular el histograma MACD y determinar la tendencia dominante en velas de un minuto. Las posiciones largas se abren cuando el EMA rápido (período 100) cruza por encima del EMA lento (nivel MACD definido por el usuario). Las posiciones cortas se abren cuando el EMA rápido cae por debajo del EMA lento. Sólo se mantiene una posición en cualquier momento.
Lógica de gestión comercial
Detección de tendencias: La diferencia entre el EMA de 100 períodos y el MACD EMA configurable define la dirección de la tendencia actual (+1, 0, -1). Una reversión de negativo a positivo abre una posición larga. Una reversión de positivo a negativo abre una posición corta.
Confirmación de impulso: La estrategia realiza un seguimiento de la diferencia entre el MACD EMA y un EMA (MACD level + 1) ligeramente más lento. Si la diferencia con respecto a la operación actual se reduce después de que el precio se haya movido al menos cinco puntos en beneficio, la posición se cierra anticipadamente.
Protección basada en el tiempo: Después de que una operación permanece abierta durante un número de ciclos de evaluación definido por el usuario, el sistema activa una parada suave que reduce la tolerancia al movimiento adverso del precio en relación con el precio de entrada.
Salida dinámica: Una vez que la operación genera ganancias y permanece activa durante suficientes ciclos, se activa un stop dinámico interno. El nivel de parada sigue el precio según la cantidad de puntos configurados y se puede actualizar una cantidad limitada de veces. Si se alcanza el límite, la posición se cierra.
Salida de inversión de tendencia: Cuando la señal de tendencia cambia en la dirección opuesta mientras el precio ya tiene cinco puntos de ganancia, la posición se cierra inmediatamente.
Parámetros
Tipo de vela: período de tiempo utilizado para los cálculos EMA (predeterminado: velas de 1 minuto).
Volumen – Volumen de pedidos para nuevas entradas.
MACD Nivel: longitud de EMA que define el componente lento MACD. Un EMA secundario con longitud MACD Level + 1 se deriva automáticamente.
Trailing Stop – Distancia en puntos para la salida final. Establezca en cero para desactivar.
Actualizaciones finales: número máximo de ajustes de trailing stop por operación.
Ciclos de espera: número de evaluaciones de velas que se deben esperar antes de que se active la parada suave adaptativa.
Notas adicionales
La estrategia siempre aplana la posición actual antes de invertir la dirección.
La información del paso de precio del valor seleccionado se utiliza para traducir distancias basadas en puntos en precios reales.
La implementación se basa en la suscripción de vela de alto nivel de StockSharp API y no pone en cola los buffers de indicadores personalizados.
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>
/// Simple MACD EA strategy using fast/slow EMA difference for trend detection.
/// Buy when EMA difference crosses above zero, sell when it crosses below zero.
/// </summary>
public class SimpleMacdEaStrategy : Strategy
{
private readonly StrategyParam<int> _fastEmaPeriod;
private readonly StrategyParam<int> _slowEmaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevDiff;
private bool _hasPrev;
public int FastEmaPeriod
{
get => _fastEmaPeriod.Value;
set => _fastEmaPeriod.Value = value;
}
public int SlowEmaPeriod
{
get => _slowEmaPeriod.Value;
set => _slowEmaPeriod.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public SimpleMacdEaStrategy()
{
_fastEmaPeriod = Param(nameof(FastEmaPeriod), 12)
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowEmaPeriod = Param(nameof(SlowEmaPeriod), 26)
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevDiff = 0m;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var fastEma = new ExponentialMovingAverage { Length = FastEmaPeriod };
var slowEma = new ExponentialMovingAverage { Length = SlowEmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastEma, slowEma, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal fast, decimal slow)
{
if (candle.State != CandleStates.Finished)
return;
var diff = fast - slow;
if (!_hasPrev)
{
_prevDiff = diff;
_hasPrev = true;
return;
}
// Buy: MACD crosses above zero
var longSignal = _prevDiff <= 0 && diff > 0;
// Sell: MACD crosses below zero
var shortSignal = _prevDiff >= 0 && diff < 0;
if (Position <= 0 && longSignal)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (Position >= 0 && shortSignal)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevDiff = diff;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
class simple_macd_ea_strategy(Strategy):
"""Simple MACD EA using fast/slow EMA difference for trend detection.
Buy when EMA difference crosses above zero, sell when it crosses below zero."""
def __init__(self):
super(simple_macd_ea_strategy, self).__init__()
self._fast_ema_period = self.Param("FastEmaPeriod", 12) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_ema_period = self.Param("SlowEmaPeriod", 26) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_diff = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def FastEmaPeriod(self):
return self._fast_ema_period.Value
@property
def SlowEmaPeriod(self):
return self._slow_ema_period.Value
def OnReseted(self):
super(simple_macd_ea_strategy, self).OnReseted()
self._prev_diff = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(simple_macd_ea_strategy, self).OnStarted2(time)
self._has_prev = False
fast_ema = ExponentialMovingAverage()
fast_ema.Length = self.FastEmaPeriod
slow_ema = ExponentialMovingAverage()
slow_ema.Length = self.SlowEmaPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast_ema, slow_ema, self._process_candle).Start()
def _process_candle(self, candle, fast, slow):
if candle.State != CandleStates.Finished:
return
diff = float(fast) - float(slow)
if not self._has_prev:
self._prev_diff = diff
self._has_prev = True
return
# Buy: MACD crosses above zero
long_signal = self._prev_diff <= 0 and diff > 0
# Sell: MACD crosses below zero
short_signal = self._prev_diff >= 0 and diff < 0
if self.Position <= 0 and long_signal:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self.Position >= 0 and short_signal:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_diff = diff
def CreateClone(self):
return simple_macd_ea_strategy()