La Estrategia ENewsLuckyw es un sistema de ruptura basado en el tiempo convertido del asesor experto MetaTrader e-News-Lucky$. A una hora programada, envía órdenes buy-stop y sell-stop alrededor del precio actual, las centra continuamente mientras ambas órdenes están activas y realiza una gestión de posiciones que imita la lógica MQL original. Las salidas protectoras, el seguimiento opcional y la limpieza al final del día completan el flujo de trabajo.
Lógica de trading
Colocación combinada programada. En SetOrdersTime la estrategia cancela cualquier orden pendiente restante, mide el cierre de la vela actual y coloca órdenes stop simétricas a DistancePips del precio de mercado.
Actualización continua de órdenes. Cuando ambas órdenes pendientes están activas, se realinean en cada vela terminada, manteniendo el straddle centrado en el precio como lo hizo el experto original en cada nueva barra.
Preparación de entrada. Los niveles de stop-loss y take-profit opcionales se calculan previamente para que puedan adjuntarse inmediatamente cuando se abre una posición. Las órdenes pendientes opuestas se eliminan tan pronto como aparece una posición.
Protección de seguimiento. Si UseTrailing está habilitado, la orden de parada se mueve TrailingStopPips siempre que la posición haya avanzado al menos TrailingStepPips. Con ProfitTrailing activado, el seguimiento comienza solo después de que las ganancias exceden la distancia de seguimiento, replicando el interruptor "ProfitTrailing" de MQL.
Limpieza de sesión. A las DeleteOrdersTime todas las órdenes pendientes se cancelan y cualquier posición abierta se cierra para evitar mantener el riesgo durante la noche.
Parámetros
Nombre
Descripción
Volume
Volumen de órdenes en lotes utilizados para ambas órdenes stop.
StopLossPips
Distancia de parada protectora. Cero desactiva la parada.
TakeProfitPips
Distancia de toma de ganancias opcional. Cero desactiva el objetivo.
DistancePips
Compensación del precio actual para las órdenes stop de ruptura.
UseTrailing
Permite detener el seguimiento una vez que la posición está abierta.
ProfitTrailing
Requiere que el beneficio no realizado supere la distancia de seguimiento antes de mover el stop.
TrailingStopPips
Distancia entre el precio y el trailing stop.
TrailingStepPips
Se necesita una mejora mínima antes de que se actualice nuevamente el trailing stop.
SetOrdersTime
Hora del día en que se coloca la silla a horcajadas.
DeleteOrdersTime
Hora del día para cancelar órdenes y cerrar posiciones.
CandleType
Suscripción de vela utilizada para el seguimiento del tiempo y el mantenimiento de pedidos.
Notas de uso
Adjunte la estrategia al instrumento deseado y configure CandleType para que coincida con el tamaño de barra que desea usar para el mantenimiento (el valor predeterminado es velas de 1 minuto).
Establezca los parámetros de programación para alinearlos con su evento noticioso o sesión comercial.
Ajustar distancias y controles de riesgo según la volatilidad del instrumento. Para los símbolos de Forex, asegúrese de que el paso del precio esté configurado correctamente para que StopLossPips, TakeProfitPips y DistancePips se traduzcan en las compensaciones de precio esperadas.
El sistema de seguimiento utiliza órdenes stop y límite para las salidas. Si su lugar no admite estos tipos de órdenes, reemplácelas con salidas de mercado u órdenes simuladas antes de publicarlas.
La estrategia realiza un reinicio diario por fecha. Si lo ejecuta hasta la medianoche en la zona horaria del intercambio, asegúrese de que la sesión de negociación abarque un solo día de negociación.
Notas de conversión
La estrategia refleja el flujo de trabajo del experto MQL: colocación programada (SetOrders), mantenimiento por hora (ModifyOrders), eliminación de órdenes pendientes en conflicto (DeleteOppositeOrders), lógica de seguimiento (TrailingPositions) y limpieza al final del día.
Los cálculos de precios con reconocimiento de diferencial del código MQL se aproximan utilizando el último cierre de vela porque StockSharp normaliza los precios con respecto al PriceStep del instrumento.
Se omitieron todas las configuraciones de sonido, número de cuenta y color del guión original porque no tienen equivalente en el nivel alto de StockSharp API.
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>
/// ENews Lucky strategy - momentum breakout with ATR filter.
/// Buys when close breaks above recent high with strong momentum.
/// Sells when close breaks below recent low with strong momentum.
/// </summary>
public class ENewsLuckywStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<int> _momentumPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevMid;
private bool _hasPrev;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public int MomentumPeriod { get => _momentumPeriod.Value; set => _momentumPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public ENewsLuckywStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 15)
.SetDisplay("Channel Period", "Highest/Lowest period", "Indicators");
_momentumPeriod = Param(nameof(MomentumPeriod), 10)
.SetDisplay("Momentum Period", "Momentum period", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevClose = 0m; _prevMid = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var momentum = new Momentum { Length = MomentumPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(highest, lowest, momentum, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest, decimal momentum)
{
if (candle.State != CandleStates.Finished)
return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev)
{
_prevClose = close;
_prevMid = mid;
_hasPrev = true;
return;
}
// Breakout above midpoint with positive momentum
if (_prevClose <= _prevMid && close > mid && momentum > 0 && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
// Breakout below midpoint with negative momentum
else if (_prevClose >= _prevMid && close < mid && momentum < 0 && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
_prevClose = close;
_prevMid = mid;
}
}
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 Highest, Lowest, Momentum
from StockSharp.Algo.Strategies import Strategy
class e_news_luckyw_strategy(Strategy):
def __init__(self):
super(e_news_luckyw_strategy, self).__init__()
self._channel_period = self.Param("ChannelPeriod", 15) \
.SetDisplay("Channel Period", "Highest/Lowest period", "Indicators")
self._momentum_period = self.Param("MomentumPeriod", 10) \
.SetDisplay("Momentum Period", "Momentum period", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
@property
def channel_period(self):
return self._channel_period.Value
@property
def momentum_period(self):
return self._momentum_period.Value
@property
def candle_type(self):
return self._candle_type.Value
def OnReseted(self):
super(e_news_luckyw_strategy, self).OnReseted()
self._prev_close = 0.0
self._prev_mid = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(e_news_luckyw_strategy, self).OnStarted2(time)
self._has_prev = False
highest = Highest()
highest.Length = self.channel_period
lowest = Lowest()
lowest.Length = self.channel_period
momentum = Momentum()
momentum.Length = self.momentum_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(highest, lowest, momentum, self.process_candle).Start()
def process_candle(self, candle, highest, lowest, momentum):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
high_val = float(highest)
low_val = float(lowest)
mom_val = float(momentum)
mid = (high_val + low_val) / 2.0
if not self._has_prev:
self._prev_close = close
self._prev_mid = mid
self._has_prev = True
return
if self._prev_close <= self._prev_mid and close > mid and mom_val > 0 and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif self._prev_close >= self._prev_mid and close < mid and mom_val < 0 and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_close = close
self._prev_mid = mid
def CreateClone(self):
return e_news_luckyw_strategy()