La X Bug Strategy es un sistema cruzado de media móvil convertido del asesor experto MQL4 con el mismo nombre. Compara dos promedios móviles simples calculados sobre el precio medio de las velas. Cuando la media rápida cruza por encima o por debajo de la media lenta, la estrategia abre una posición en la dirección del cruce. La implementación reproduce las características originales del Asesor Experto, incluida la inversión de señal opcional, el cierre automático de posición en señales opuestas y órdenes de protección basadas en pips.
Lógica de trading
Suscríbase al tipo de vela configurado (velas de un minuto por defecto) y calcule dos medias móviles simples: una línea rápida y una línea lenta. Los promedios utilizan el precio medio y respetan los cambios de indicador configurados.
Detecte un cruce alcista cuando el valor rápido actual está por encima del valor lento mientras que el valor rápido dos barras antes estaba por debajo del valor lento. Detecte un cruce bajista utilizando la condición opuesta.
Opcionalmente, invierta la señal de cruce cuando ReverseSignals esté habilitado para operar en la dirección opuesta.
Cuando CloseOnSignal está habilitado, cierre inmediatamente cualquier posición opuesta antes de ingresar una nueva con la nueva señal.
Ingrese posiciones largas en señales alcistas y posiciones cortas en señales bajistas. La estrategia evita apilar posiciones en la misma dirección; solo opera cuando la posición actual es plana o está alineada con la señal.
Gestión del riesgo
StopLossPips: establece una parada de protección absoluta en pips. El stop se expresa en pips enteros; El precio fraccionario (cotizaciones de 5 o 3 dígitos) se maneja automáticamente convirtiendo el valor del pip utilizando el paso del precio del valor.
TakeProfitPips: configura la distancia objetivo de ganancias en pips.
TrailingStopPips: cuando UseTrailingStop está habilitado, activa un trailing stop que comienza en la distancia de pips configurada una vez que la posición genera ganancias. El paso final coincide con la distancia final, replicando la lógica MetaTrader original.
Todas las órdenes de protección se gestionan a través de StartProtection con salidas de mercado para mantener la paridad con el experto MQL4.
Parámetros
Parámetro
Descripción
Predeterminado
OrderVolume
Volumen comercial base utilizado para las entradas al mercado.
0.1
StopLossPips
Distancia de stop-loss medida en pips; configúrelo en 0 para deshabilitarlo.
70
TakeProfitPips
Distancia de obtención de beneficios medida en pips; configúrelo en 0 para deshabilitarlo.
5000
UseTrailingStop
Habilita o deshabilita la gestión de trailing stop.
true
TrailingStopPips
Distancia de seguimiento en pips.
90
FastPeriod
Período de la media móvil rápida.
1
FastShift
Barras para desplazar la media móvil rápida antes de evaluar las señales.
0
SlowPeriod
Período de la media móvil lenta.
14
SlowShift
Barras para desplazar la media móvil lenta antes de evaluar las señales.
10
CloseOnSignal
Cerrar una posición contraria inmediatamente cuando aparezca una nueva señal.
true
ReverseSignals
Invierta la dirección de la señal para operar en contra del cruce.
false
AppliedPrice
Fuente del precio de las velas suministrada a las medias móviles.
Median
CandleType
Tipo de datos de vela para generación de señales.
1 minute período de tiempo
Notas
La conversión de pips multiplica el paso del precio por 10 para los símbolos cotizados con 5 o 3 decimales, coincidiendo con el comportamiento original del Asesor Experto.
No se proporciona ningún puerto Python; sólo la estrategia C# se incluye en este directorio.
Las paradas finales, las paradas y los objetivos son opcionales. Establezca los valores de pip correspondientes en cero para desactivarlos.
namespace StockSharp.Samples.Strategies;
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
/// <summary>
/// Moving average crossover strategy converted from the MQL4 expert "X bug".
/// Uses fast and slow SMA crossover for signal generation.
/// </summary>
public class XBugStrategy : Strategy
{
private readonly StrategyParam<int> _fastPeriod;
private readonly StrategyParam<int> _slowPeriod;
private readonly StrategyParam<bool> _reverseSignals;
private readonly StrategyParam<DataType> _candleType;
private SimpleMovingAverage _slowMa;
private decimal? _prevFast;
private decimal? _prevSlow;
private int _cooldown;
private int _candleCount;
public XBugStrategy()
{
_fastPeriod = Param(nameof(FastPeriod), 5)
.SetGreaterThanZero()
.SetDisplay("Fast MA period", "Length of the fast moving average.", "Indicators");
_slowPeriod = Param(nameof(SlowPeriod), 14)
.SetGreaterThanZero()
.SetDisplay("Slow MA period", "Length of the slow moving average.", "Indicators");
_reverseSignals = Param(nameof(ReverseSignals), false)
.SetDisplay("Reverse signals", "Invert buy and sell directions.", "Trading");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle type", "Primary timeframe used for signals.", "General");
}
public int FastPeriod
{
get => _fastPeriod.Value;
set => _fastPeriod.Value = value;
}
public int SlowPeriod
{
get => _slowPeriod.Value;
set => _slowPeriod.Value = value;
}
public bool ReverseSignals
{
get => _reverseSignals.Value;
set => _reverseSignals.Value = value;
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
=> [(Security, CandleType)];
protected override void OnReseted()
{
base.OnReseted();
_slowMa = default;
_prevFast = null;
_prevSlow = null;
_cooldown = 0;
_candleCount = 0;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
Volume = 0.001m;
_prevFast = null;
_prevSlow = null;
_cooldown = 0;
_candleCount = 0;
_slowMa = new SimpleMovingAverage { Length = SlowPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(_slowMa, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal slowValue)
{
if (candle.State != CandleStates.Finished)
return;
if (!_slowMa.IsFormed)
return;
_candleCount++;
if (_cooldown > 0)
{
_cooldown--;
return;
}
// Use close price as the "fast" value (period=1 effectively)
var fastValue = candle.ClosePrice;
if (_prevFast is null || _prevSlow is null)
{
_prevFast = fastValue;
_prevSlow = slowValue;
return;
}
var signal = 0;
if (fastValue > slowValue && _prevFast.Value <= _prevSlow.Value)
signal = 1;
else if (fastValue < slowValue && _prevFast.Value >= _prevSlow.Value)
signal = -1;
_prevFast = fastValue;
_prevSlow = slowValue;
if (signal == 0)
return;
if (ReverseSignals)
signal = -signal;
if (signal > 0 && Position <= 0)
{
BuyMarket();
_cooldown = 100;
}
else if (signal < 0 && Position >= 0)
{
SellMarket();
_cooldown = 100;
}
}
}
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.Strategies import Strategy
from StockSharp.Algo.Indicators import SimpleMovingAverage
class x_bug_strategy(Strategy):
def __init__(self):
super(x_bug_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle type", "Primary timeframe used for signals.", "General")
self._fast_period = self.Param("FastPeriod", 5) \
.SetDisplay("Fast MA period", "Length of the fast moving average.", "Indicators")
self._slow_period = self.Param("SlowPeriod", 14) \
.SetDisplay("Slow MA period", "Length of the slow moving average.", "Indicators")
self._reverse_signals = self.Param("ReverseSignals", False) \
.SetDisplay("Reverse signals", "Invert buy and sell directions.", "Trading")
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
@property
def ReverseSignals(self):
return self._reverse_signals.Value
def OnStarted2(self, time):
super(x_bug_strategy, self).OnStarted2(time)
from System import Decimal
self.Volume = Decimal(0.001)
self._prev_fast = None
self._prev_slow = None
self._slow_ma = SimpleMovingAverage()
self._slow_ma.Length = self.SlowPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._slow_ma, self.ProcessCandle).Start()
def ProcessCandle(self, candle, slow_val):
if candle.State != CandleStates.Finished:
return
if not self._slow_ma.IsFormed:
return
from System import Decimal
sv = Decimal(float(slow_val))
fast_value = candle.ClosePrice
if self._prev_fast is None or self._prev_slow is None:
self._prev_fast = fast_value
self._prev_slow = sv
return
signal = 0
if fast_value > sv and self._prev_fast <= self._prev_slow:
signal = 1
elif fast_value < sv and self._prev_fast >= self._prev_slow:
signal = -1
self._prev_fast = fast_value
self._prev_slow = sv
if signal == 0:
return
if self.ReverseSignals:
signal = -signal
if signal > 0 and self.Position <= 0:
self.BuyMarket()
elif signal < 0 and self.Position >= 0:
self.SellMarket()
def OnReseted(self):
super(x_bug_strategy, self).OnReseted()
self._prev_fast = None
self._prev_slow = None
def CreateClone(self):
return x_bug_strategy()