Puerto del experto MetaTrader AddOn_TrailingStop. La estrategia no abre posiciones por sí sola y solo ajusta los trailingstops para una posición neta existente.
como funciona
Se suscribe a los datos de Level1 para monitorear las mejores ofertas y solicitar cotizaciones más recientes.
Calcula el tamaño del pip a partir de los decimales de seguridad para que las entradas se comporten como en MetaTrader (4/5 dígitos = 0,0001 pip, 2/3 dígitos = 0,01 pip).
Cuando se abre una posición larga y el precio de oferta avanza TrailingStartPips pips, la estrategia mueve el trailing stop interno a Bid - TrailingStartPips pips.
El stop largo sólo avanza cuando el nuevo nivel es al menos TrailingStepPips pips más alto que el stop anterior.
Cuando se abre una posición corta y el precio de venta cae TrailingStartPips pips, la estrategia mueve el trailing stop interno a Ask + TrailingStartPips pips.
La parada corta solo avanza cuando el nuevo nivel es al menos TrailingStepPips pips más bajo que la parada anterior.
Si la cotización actual cruza el trailing stop, la estrategia cierra toda la posición en el mercado y restablece su estado.
Parámetros
EnableTrailing (predeterminado verdadero): habilita o deshabilita la administración de trailing stop.
TrailingStartPips (predeterminado 15): se requiere ganancia en pips antes de que se active el seguimiento.
TrailingStepPips (predeterminado 5): se requiere ganancia adicional en pips antes de que el stop pueda moverse nuevamente.
MagicNumber (predeterminado 0): identificador mantenido para lograr paridad con el experto MQL. Es informativo porque StockSharp opera en la posición de la estrategia actual.
Notas
Requiere una fuente de datos configurada Security, Portfolio y Nivel 1.
Diseñado para complementar otras estrategias que manejan entradas.
Utiliza StrategyParam<T> para que cada entrada pueda optimizarse o exponerse en la interfaz de usuario.
Envía órdenes BuyMarket/SellMarket cuando se alcanza el trailing stop porque StockSharp gestiona automáticamente las órdenes de protección después de salir de la posición.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// AddOn Trailing Stop strategy: EMA crossover with trailing logic.
/// Buys when fast EMA crosses above slow EMA, sells on cross below.
/// </summary>
public class AddOnTrailingStopStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _hasPrev;
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 AddOnTrailingStopStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 10)
.SetGreaterThanZero()
.SetDisplay("Fast EMA", "Fast EMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 30)
.SetGreaterThanZero()
.SetDisplay("Slow EMA", "Slow EMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_hasPrev = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_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 fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished) return;
if (_hasPrev)
{
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
BuyMarket();
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
SellMarket();
}
else
{
if (fastValue > slowValue && Position <= 0)
BuyMarket();
else if (fastValue < slowValue && Position >= 0)
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
_hasPrev = true;
}
}