La Estrategia de reversión de brechas es una adaptación directa del MetaTrader4 asesor experto gaps.mq4. El sistema monitorea velas de 15 minutos y baño.
ks para abrir brechas que ocurren fuera del rango máximo/bajo de la vela anterior. Cuando aparece tal brecha, la estrategia inmediatamente e
entra en el mercado en la dirección del movimiento de reversión a la media esperado.
La versión StockSharp sigue la lógica original y depende de la suscripción de vela de alto nivel API. Toda la gestión comercial es
se realiza con órdenes de mercado y no se colocan órdenes de protección fijas, lo que refleja el comportamiento encontrado en el código MQL.
Reglas de trading
Suscríbete a velas de 15 minutos (configurable a través del parámetro CandleType).
Mantenga el máximo y el mínimo de la vela completada anteriormente.
Cuando comienza una nueva vela:
Calcule el buffer de brecha: (MinGapSize + spreadInSteps) * pointValue.
Si el precio de apertura está por encima de previousHigh + gapBuffer, abra una posición corta.
Si el precio de apertura está por debajo de previousLow - gapBuffer, abra una posición larga.
Sólo se permite una operación por vela. Una vez que se realiza una orden, la estrategia espera la siguiente vela antes de generar una nueva vela.
señal.
El componente de diferencial utiliza la mejor oferta/demanda actual, si está disponible. Cuando no se proporcionan datos de cotización, la estrategia vuelve a caer en pecado.
Un pequeño paso en el precio como amortiguador conservador.
Parámetros
Parámetro
Predeterminado
Descripción
MinGapSize
1
Tamaño mínimo de brecha en los escalones de precios que se debe exceder antes de enviar un pedido.
GapVolume
0.1
Volumen de pedidos para entradas al mercado provocadas por brechas.
CandleType
15m TimeFrame
Tipo de vela utilizado para los cálculos (el valor predeterminado es velas de 15 minutos).
Todos los parámetros están registrados como StrategyParam<T> y admiten la optimización dentro de StockSharp Designer u otras herramientas.
Notas de implementación
Utiliza SubscribeCandles con Bind para procesar velas terminadas únicamente.
Recuerda el rango de la vela anterior para evitar volver a calcular la serie de datos.
Bloquea órdenes duplicadas en la misma vela rastreando el tiempo de apertura de la barra que desencadenó la operación.
La salida del gráfico dibuja las velas suscritas y las operaciones de estrategia para una inspección visual rápida.
Diferencias con la versión MQL
Los niveles de toma de ganancias y límite de pérdidas no se establecieron correctamente en el EA original (el código MQL pasó valores a los parámetros incorrectos)
. Por tanto, el puerto StockSharp mantiene el comportamiento de funcionamiento sin órdenes de protección.
El manejo de diferenciales ahora verifica las cotizaciones de oferta y demanda en tiempo real cuando están disponibles, lo que proporciona un margen más adaptable.
Requisitos
StockSharp API con acceso a los datos de velas para el instrumento seleccionado.
Las cotizaciones de nivel 1 son opcionales pero mejoran la detección de diferenciales.
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>
/// Gap Reversion strategy - detects gap openings and trades mean reversion.
/// Buys when candle opens below previous low (gap down reversion).
/// Sells when candle opens above previous high (gap up reversion).
/// Uses EMA as trend filter for exits.
/// </summary>
public class GapReversionStrategy : Strategy
{
private readonly StrategyParam<int> _emaPeriod;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevHigh;
private decimal _prevLow;
private bool _hasPrev;
public int EmaPeriod { get => _emaPeriod.Value; set => _emaPeriod.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public GapReversionStrategy()
{
_emaPeriod = Param(nameof(EmaPeriod), 20)
.SetDisplay("EMA Period", "EMA trend filter", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities() => [(Security, CandleType)];
protected override void OnReseted() { base.OnReseted(); _prevHigh = 0m; _prevLow = 0m; _hasPrev = false; }
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var ema = new ExponentialMovingAverage { Length = EmaPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ema, ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
}
private void ProcessCandle(ICandleMessage candle, decimal ema)
{
if (candle.State != CandleStates.Finished)
return;
if (!_hasPrev)
{
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
_hasPrev = true;
return;
}
var open = candle.OpenPrice;
var close = candle.ClosePrice;
// Gap down reversion - open below previous low, expect bounce
if (open < _prevLow && close > ema && Position == 0)
BuyMarket();
// Gap up reversion - open above previous high, expect pullback
else if (open > _prevHigh && close < ema && Position == 0)
SellMarket();
_prevHigh = candle.HighPrice;
_prevLow = candle.LowPrice;
}
}
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 ExponentialMovingAverage
from StockSharp.Algo.Strategies import Strategy
from StockSharp.Messages import Unit, UnitTypes
class gap_reversion_strategy(Strategy):
def __init__(self):
super(gap_reversion_strategy, self).__init__()
self._ema_period = self.Param("EmaPeriod", 20).SetDisplay("EMA Period", "EMA trend filter", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))).SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
@property
def ema_period(self): return self._ema_period.Value
@property
def candle_type(self): return self._candle_type.Value
def OnReseted(self):
super(gap_reversion_strategy, self).OnReseted()
self._prev_high = 0.0
self._prev_low = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(gap_reversion_strategy, self).OnStarted2(time)
self._has_prev = False
ema = ExponentialMovingAverage()
ema.Length = self.ema_period
subscription = self.SubscribeCandles(self.candle_type)
subscription.Bind(ema, self.process_candle).Start()
self.StartProtection(takeProfit=Unit(2, UnitTypes.Percent), stopLoss=Unit(1, UnitTypes.Percent))
def process_candle(self, candle, ema):
if candle.State != CandleStates.Finished:
return
if not self._has_prev:
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
self._has_prev = True
return
op = float(candle.OpenPrice)
close = float(candle.ClosePrice)
ema_val = float(ema)
if op < self._prev_low and close > ema_val and self.Position == 0:
self.BuyMarket()
elif op > self._prev_high and close < ema_val and self.Position == 0:
self.SellMarket()
self._prev_high = float(candle.HighPrice)
self._prev_low = float(candle.LowPrice)
def CreateClone(self):
return gap_reversion_strategy()