Die Gap-Reversion-Strategie ist eine direkte Portierung des MetaTrader 4 Expertenberaters gaps.mq4. Das System überwacht 15-Minuten-Kerzen und Toilette
ks für das Öffnen von Lücken, die außerhalb des Hoch-/Tief-Bereichs der vorherigen Kerze auftreten. Wenn eine solche Lücke auftritt, wird die Strategie sofort, z
Bringt den Markt in die Richtung der erwarteten Mean-Reversion-Bewegung.
Die StockSharp-Version folgt der ursprünglichen Logik und stützt sich dabei auf das High-Level-Kerzenabonnement API. Das gesamte Handelsmanagement ist
Dies erfolgt mit Marktaufträgen und es werden keine festen Schutzaufträge erteilt, was das Verhalten im MQL-Code widerspiegelt.
Handelsregeln
Abonnieren Sie 15-Minuten-Kerzen (konfigurierbar über den Parameter CandleType).
Behalten Sie das Hoch und Tief der zuvor abgeschlossenen Kerze bei.
Wenn eine neue Kerze beginnt:
Berechnen Sie den Lückenpuffer: (MinGapSize + spreadInSteps) * pointValue.
Wenn der Eröffnungspreis überpreviousHigh + gapBuffer liegt, eröffnen Sie eine Short-Position.
Wenn der Eröffnungspreis unterpreviousLow - gapBuffer liegt, eröffnen Sie eine Long-Position.
Es ist nur ein Trade pro Kerze erlaubt. Sobald eine Order aufgegeben wurde, wartet die Strategie auf die nächste Kerze, bevor sie eine neue Kerze generiert
ignal.
Die Spread-Komponente verwendet den aktuell besten Geld-/Briefkurs, sofern verfügbar. Wenn keine Kursdaten bereitgestellt werden, fällt die Strategie auf eine Sünde zurück
gle-Preisschritt als konservativer Puffer.
Parameter
Parameter
Standard
Beschreibung
MinGapSize
1
Mindestlückengröße in Preisschritten, die vor dem Absenden einer Bestellung überschritten werden muss.
GapVolume
0.1
Auftragsvolumen für durch Lücken ausgelöste Markteintritte.
CandleType
15m TimeFrame
Für Berechnungen verwendeter Kerzentyp (standardmäßig 15-Minuten-Kerzen).
Alle Parameter sind als StrategyParam<T> registriert und unterstützen die Optimierung im StockSharp Designer oder anderen Tools.
Implementierungshinweise
Verwendet SubscribeCandles mit Bind, um nur fertige Kerzen zu verarbeiten.
Merkt sich den Bereich der vorherigen Kerze, um eine Neuberechnung der Datenreihen zu vermeiden.
Blockiert doppelte Orders auf derselben Kerze, indem die Öffnungszeit des Balkens verfolgt wird, der den Handel ausgelöst hat.
Die Diagrammausgabe zeichnet die abonnierten Kerzen und die Strategiegeschäfte zur schnellen visuellen Überprüfung.
Unterschiede zur MQL-Version
Take-Profit- und Stop-Loss-Level wurden im ursprünglichen EA nicht richtig festgelegt (der MQL-Code hat Werte an die falschen Parameter übergeben)
. Der Port StockSharp behält daher das Verhalten bei, dass er ohne Schutzbefehle ausgeführt wird.
Bei der Spread-Verarbeitung werden jetzt Geld-/Briefkurse in Echtzeit überprüft, sofern verfügbar, wodurch ein anpassungsfähigerer Puffer bereitgestellt wird.
Anforderungen
StockSharp API mit Zugriff auf Kerzendaten für das ausgewählte Instrument.
Kurse der Stufe 1 sind optional, verbessern jedoch die Spread-Erkennung.
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()