Esta estrategia replica el experto MetaTrader "Día y hora específicos del Asesor Experto".
Coloca órdenes de compra y/o venta en una marca de tiempo programada y, opcionalmente, elimina cada exposición en otra marca de tiempo.
La versión StockSharp mantiene el comportamiento original de gestión de riesgos, incluidos trailingstops opcionales y movimientos de equilibrio.
Lógica central
Programación
OpenTime – momento en el que se crean las órdenes.
CloseTime – momento en el que las posiciones se aplanan y las órdenes pendientes se pueden eliminar.
Ambas comprobaciones aceptan una ventana de un minuto, que coincide con la comparación TimeToString(..., TIME_MINUTES) utilizada en el código MT4.
Realización de pedidos
OrderPlacement elige entre órdenes de mercado, stop o límite.
OpenBuyOrders / OpenSellOrders habilita las direcciones deseadas.
OrderDistancePoints compensa el precio de las órdenes pendientes en una cantidad de puntos (pips).
PendingExpireMinutes cancela los pedidos pendientes automáticamente cuando finaliza su ventana de validez.
Gestión de volumen
LotSizing = Manual envía el ManualVolume fijo.
LotSizing = Automatic calcula el volumen a partir del valor actual de la cartera y el tamaño del contrato del instrumento:
volume = (portfolio / contractSize) * RiskFactor.
El resultado se alinea con Security.VolumeStep y se fija entre MinVolume/MaxVolume cuando esté disponible.
Lógica de protección
StopLossPoints y TakeProfitPoints traducen las distancias originales basadas en puntos a precios absolutos utilizando el tamaño del pip del instrumento.
TrailingStopEnabled + TrailingStepPoints y BreakEvenEnabled mueven la parada de protección exactamente como el script MQL, utilizando actualizaciones de oferta/demanda como activadores.
Cuando se alcanzan las condiciones de límite de pérdidas o toma de ganancias, la posición se cierra con una orden de mercado, reflejando el comportamiento de MT4 de modificar los límites a un nuevo precio.
Fase de cierre
Cuando CloseOwnOrders o CloseAllOrders está habilitado, la estrategia sale de cualquier posición abierta en la ventana de cierre.
DeletePendingOrders elimina todas las órdenes pendientes restantes al mismo tiempo.
Parámetros
Nombre
Descripción
OpenTime, CloseTime
Marcas de tiempo UTC para entrar y salir del mercado.
OrderPlacement
Colocación de órdenes de mercado, stop o límite.
OpenBuyOrders, OpenSellOrders
Instrucciones para activar.
TakeProfitPoints, StopLossPoints
Distancias de protección expresadas en puntos (0 inhabilitaciones).
TrailingStopEnabled, TrailingStepPoints
Habilite el trailing stop y defina el avance mínimo antes de moverlo.
BreakEvenEnabled, BreakEvenAfterPoints
Cambie el límite al punto de equilibrio una vez que la ganancia supere el umbral.
Controla cómo se cierran al final las posiciones y órdenes pendientes.
Notas
La clase reside en el espacio de nombres StockSharp.Samples.Strategies con sangría de tabulación como lo exigen las pautas del proyecto.
Los datos de nivel 1 se utilizan para reproducir la lógica sensible a la oferta y la demanda de la versión MQL (parada dinámica, colocación de orden pendiente).
La configuración de MagicNumber de MT4 no es necesaria porque StockSharp ya aísla las órdenes estratégicas.
Uso
Compile el proyecto a través de AlgoTrading.sln y adjunte la estrategia a un par de valores/cartera.
Ajuste el cronograma, el tipo de orden y los parámetros de riesgo según sea necesario.
Inicie la estrategia antes de OpenTime; Los pedidos se enviarán automáticamente una vez que comience la ventana.
Mantenga la estrategia ejecutándose hasta después de CloseTime si desea que se active el paso de aplanamiento automático.
namespace StockSharp.Samples.Strategies;
using System;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.Messages;
/// <summary>
/// Specific Day Time strategy: SMA crossover with time filter.
/// Trades only during specific hours, using fast/slow SMA crossover.
/// </summary>
public class SpecificDayTimeStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<int> _tradeHour;
private readonly StrategyParam<int> _cooldownBars;
private int _cooldown;
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 int TradeHour { get => _tradeHour.Value; set => _tradeHour.Value = value; }
public int CooldownBars { get => _cooldownBars.Value; set => _cooldownBars.Value = value; }
public SpecificDayTimeStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
_fastPeriod = Param(nameof(FastPeriod), 8)
.SetGreaterThanZero()
.SetDisplay("Fast SMA", "Fast SMA period", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 21)
.SetGreaterThanZero()
.SetDisplay("Slow SMA", "Slow SMA period", "Indicators");
_tradeHour = Param(nameof(TradeHour), 12)
.SetDisplay("Trade Hour", "Hour when entries are allowed", "Trading")
.SetRange(0, 23);
_cooldownBars = Param(nameof(CooldownBars), 8)
.SetGreaterThanZero()
.SetDisplay("Cooldown Bars", "Bars to wait between orders", "Trading");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_cooldown = 0;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_cooldown = 0;
var fast = new SimpleMovingAverage { Length = FastPeriod };
var slow = new SimpleMovingAverage { 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 (_cooldown > 0)
_cooldown--;
var bullishTrend = fastValue > slowValue;
var bearishTrend = fastValue < slowValue;
if (_cooldown == 0 && candle.OpenTime.Hour == TradeHour)
{
if (bullishTrend && Position <= 0)
{
BuyMarket();
_cooldown = CooldownBars;
}
else if (bearishTrend && Position >= 0)
{
SellMarket();
_cooldown = CooldownBars;
}
}
else if (_cooldown == 0)
{
if (Position > 0 && bearishTrend)
{
SellMarket();
_cooldown = CooldownBars;
}
else if (Position < 0 && bullishTrend)
{
BuyMarket();
_cooldown = CooldownBars;
}
}
}
}