Esta estrategia es una conversión directa a StockSharp del asesor experto MACD "Sensitive" para MetaTrader 5. Combina cruces del MACD con herramientas de gestión de riesgo configurables (stop loss fijo, take profit y trailing stops basados en pips). El algoritmo funciona exclusivamente en velas completadas y usa la API de alto nivel para suscribirse al marco temporal deseado.
Indicadores y Datos
MACD (Moving Average Convergence Divergence) – configurado con longitudes de EMA rápida, lenta y de señal independientes.
Velas – marco temporal seleccionable por el usuario proporcionado a través del parámetro CandleType.
Condiciones de Entrada
Debe cerrarse una nueva vela para evitar ruido intrabarra.
Los valores del MACD se procesan desde la vinculación del indicador:
macd representa la línea principal del MACD.
signal es la línea de señal (EMA de la diferencia MACD).
Requisitos de entrada larga:
El MACD cruza por encima de la línea de señal (macd > signal mientras los valores anteriores satisfacían macd < signal).
El MACD permanece en territorio negativo (macd < 0).
La magnitud absoluta del MACD es mayor que MacdOpenLevel * Point, asegurando un desplazamiento significativo.
No hay posición larga activa (la posición neta es menor o igual a cero). Los cortos existentes se revierten enviando la cantidad necesaria.
Los requisitos de entrada corta son un espejo de la configuración larga:
El MACD cruza por debajo de la línea de señal permaneciendo positivo.
La magnitud absoluta del MACD supera el umbral configurado.
No existe posición corta abierta (la posición neta es mayor o igual a cero). Los largos existentes se aplanan antes de abrir el corto.
Gestión de Salida
Take Profit: Una vez abierta la operación, la estrategia almacena un nivel objetivo definido por TakeProfitPips. Si el máximo de una vela larga o el mínimo de una vela corta alcanza este nivel, la posición se cierra a mercado.
Stop Loss: Se calcula un stop de protección a partir de StopLossPips. Para largos, una caída del precio al nivel de stop activa una salida a mercado. Los cortos reaccionan a subidas del precio que alcanzan el stop.
Trailing Stop: Cuando TrailingStopPips es distinto de cero, el algoritmo activa una lógica de trailing después de que el precio avanza al menos TrailingStopPips + TrailingStepPips pips desde la entrada. Los movimientos posteriores ajustan el nivel de stop manteniendo siempre la distancia de trailing especificada desde el último cierre. El paso de trailing debe ser positivo siempre que el trailing stop esté habilitado; de lo contrario, la estrategia se detiene con un mensaje de error.
Cuando no hay posición activa, las variables de seguimiento internas se restablecen para prepararse para la próxima operación.
Dimensionamiento de Posición
Las cantidades de las órdenes se controlan mediante el parámetro de estrategia integrado Volume (predeterminado: 0.1). Las reversiones añaden automáticamente el valor absoluto de la posición actual al volumen deseado para cambiar de dirección en una sola orden de mercado.
Parámetros
Parámetro
Descripción
Predeterminado
FastLength
Período de EMA rápida utilizado por la línea principal del MACD.
12
SlowLength
Período de EMA lenta utilizado por la línea principal del MACD.
26
SignalLength
Período de EMA de señal para el MACD.
9
MacdOpenLevel
Magnitud mínima del MACD (en puntos de precio) requerida para activar operaciones.
3
StopLossPips
Distancia del stop de protección en pips.
35
TakeProfitPips
Distancia de take-profit en pips.
75
TrailingStopPips
Distancia de trailing stop en pips (0 deshabilita el trailing).
5
TrailingStepPips
Distancia adicional que debe moverse el precio antes de que se actualice el trailing stop.
5
CandleType
Tipo de vela fuente (marco temporal).
Velas de 1 minuto
Volume
Volumen de la orden, expresado en lotes/contratos según el instrumento.
0.1
Notas Adicionales
Los valores de pips y puntos del MACD se derivan del paso de precio del instrumento y su precisión decimal. El código ajusta los símbolos forex de 3 y 5 dígitos escalando el tamaño del pip en consecuencia.
Todos los comentarios dentro del código fuente están escritos en inglés, y la implementación usa solo las APIs de alto nivel de StockSharp de acuerdo con las directrices del proyecto.
La estrategia evita intencionalmente la gestión de llenados parciales y asume que las órdenes de mercado se ejecutan inmediatamente al ejecutarse en el simulador o en trading real. Se pueden agregar salvaguardas adicionales si es necesario.
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>
/// Sensitive MACD Trailing strategy. Uses EMA crossover (5/15).
/// </summary>
public class SensitiveMacdTrailingStrategy : 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 SensitiveMacdTrailingStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(1).TimeFrame()).SetDisplay("Candle Type", "Timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 5).SetGreaterThanZero().SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 15).SetGreaterThanZero().SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(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 fast, decimal slow)
{
if (candle.State != CandleStates.Finished) return;
if (!IsFormedAndOnlineAndAllowTrading()) { _prevFast = fast; _prevSlow = slow; return; }
if (_prevFast == null || _prevSlow == null) { _prevFast = fast; _prevSlow = slow; return; }
var prevAbove = _prevFast.Value > _prevSlow.Value;
var currAbove = fast > slow;
_prevFast = fast; _prevSlow = slow;
if (!prevAbove && currAbove && Position <= 0) { if (Position < 0) BuyMarket(); BuyMarket(); }
else if (prevAbove && !currAbove && Position >= 0) { if (Position > 0) SellMarket(); SellMarket(); }
}
}
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 sensitive_macd_trailing_strategy(Strategy):
def __init__(self):
super(sensitive_macd_trailing_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(1))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators")
self._slow_period = self.Param("SlowPeriod", 15) \
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators")
self._prev_fast = None
self._prev_slow = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def FastPeriod(self):
return self._fast_period.Value
@property
def SlowPeriod(self):
return self._slow_period.Value
def OnReseted(self):
super(sensitive_macd_trailing_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def OnStarted2(self, time):
super(sensitive_macd_trailing_strategy, self).OnStarted2(time)
self._prev_fast = None
self._prev_slow = None
fast = ExponentialMovingAverage()
fast.Length = self.FastPeriod
slow = ExponentialMovingAverage()
slow.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(fast, slow, self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawIndicator(area, fast)
self.DrawIndicator(area, slow)
self.DrawOwnTrades(area)
def _on_process(self, candle, fast_value, slow_value):
if candle.State != CandleStates.Finished:
return
fv = float(fast_value)
sv = float(slow_value)
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fv
self._prev_slow = sv
return
prev_above = self._prev_fast > self._prev_slow
curr_above = fv > sv
self._prev_fast = fv
self._prev_slow = sv
if not prev_above and curr_above and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif prev_above and not curr_above and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
def CreateClone(self):
return sensitive_macd_trailing_strategy()