Esta estrategia transfiere el asesor experto MetaTrader "_HPCS_IntFourth_MT4_EA_V01_WE" al API de alto nivel de StockSharp. El script original abre inmediatamente una posición larga, aplica niveles protectores de stop-loss y take-profit medidos en MetaTrader pips y cierra la operación con fuerza después de un breve período de tenencia. La versión C# reproduce el mismo comportamiento al combinar el administrador de protección integrado con un temporizador de un segundo que monitorea el tiempo transcurrido desde la entrada.
Lógica de trading
Inicialización
Cuando comienza la estrategia, calcula el tamaño del pip MetaTrader a partir del valor PriceStep y la precisión decimal (los símbolos de 5 y 3 dígitos usan un multiplicador de 10x).
El asistente de alto nivel StartProtection está configurado con las distancias solicitadas de toma de ganancias y límite de pérdidas. La distancia de stop-loss incluye el buffer adicional que el EA original aplica usando OrderModify.
El volumen es fijo y proviene del parámetro OrderVolume.
Entrada
Una orden de compra de mercado único se envía inmediatamente después de que se lanza la estrategia. No se realizan más entradas.
Una vez que se informa el primer llenado, la estrategia almacena el tiempo de ejecución.
Salir
Un cronómetro comprueba la posición abierta cada segundo.
Cuando el período de tenencia alcanza CloseDelaySeconds, la estrategia cierra la posición larga con una orden de venta de mercado si la exposición sigue siendo positiva.
El administrador de protección mantiene automáticamente las órdenes protectoras de stop-loss y take-profit mediante salidas de mercado.
La lógica solo opera en la dirección larga, reflejando el comportamiento del script MetaTrader.
Parámetros
Nombre
Descripción
Predeterminado
Optimizable
OrderVolume
Volumen fijo utilizado al enviar la orden de compra inicial del mercado.
1
No
StopLossPips
Distancia base de MetaTrader pips aplicada al stop-loss inicial.
10
No
ExtraStopPips
Búfer de MetaTrader pips adicional restado de la parada después de la entrada.
10
No
TakeProfitPips
MetaTrader distancia del pip del objetivo de ganancias.
10
No
CloseDelaySeconds
Tiempo en segundos antes de que la posición se cierre con fuerza. 0 desactiva la salida del temporizador.
30
No
Notas de implementación
El asistente de tamaño de pip multiplica el PriceStep informado por 10 para instrumentos de 3 y 5 decimales para que los valores de los parámetros mantengan la misma escala que en MetaTrader.
StartProtection utiliza UnitTypes.Price distancias para que las órdenes de protección operen con salidas de mercado, exactamente como lo hizo EA con OrderClose.
OnNewMyTrade registra la primera operación de compra completada para iniciar la cuenta regresiva del período de tenencia y restablece el estado cuando la posición está completamente cerrada.
El cronómetro se ejecuta a intervalos de un segundo para replicar la verificación de tiempo original OnTick sin ser sensible a la inactividad del mercado.
Todos los comentarios del código están escritos en inglés para cumplir con las pautas del repositorio.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Port of the "_HPCS_IntFourth_MT4_EA_V01_WE" MetaTrader expert advisor.
/// Uses SMA crossover to enter positions with time-based exit.
/// </summary>
public class HpcsInter4Strategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private decimal _prevFast;
private decimal _prevSlow;
private bool _isFirstValue = true;
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 HpcsInter4Strategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(60).TimeFrame())
.SetDisplay("Candle Type", "Time frame for calculation", "General");
_fastPeriod = Param(nameof(FastPeriod), 20)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 50)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevFast = 0;
_prevSlow = 0;
_isFirstValue = true;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevFast = 0;
_prevSlow = 0;
_isFirstValue = true;
var fastSma = new ExponentialMovingAverage { Length = FastPeriod };
var slowSma = new ExponentialMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(fastSma, slowSma, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, fastSma);
DrawIndicator(area, slowSma);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal fastValue, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!IsFormedAndOnlineAndAllowTrading())
return;
if (_isFirstValue)
{
_prevFast = fastValue;
_prevSlow = slowValue;
_isFirstValue = false;
return;
}
// Fast crosses above slow - buy
if (_prevFast <= _prevSlow && fastValue > slowValue && Position <= 0)
{
BuyMarket();
}
// Fast crosses below slow - sell
else if (_prevFast >= _prevSlow && fastValue < slowValue && Position >= 0)
{
SellMarket();
}
_prevFast = fastValue;
_prevSlow = slowValue;
}
}