Eine Price-Action-Strategie, die auf Eröffnungslücken zwischen aufeinanderfolgenden Kerzen reagiert. Sie wartet darauf, dass eine neue Bar
über das vorherige Hoch oder Tief um eine konfigurierbare Pip-Distanz hinausöffnet, tritt in die Richtung der erwarteten Umkehr ein und
verwaltet den Trade mit festen Stops, Zielen und einem optionalen gestuften Trailing-Stop.
Funktionsweise
Die Strategie überwacht ein einzelnes Symbol mit dem gewählten Zeitrahmen.
Wenn eine neue Kerze gebildet wird, vergleicht sie den Eröffnungspreis mit der vorherigen Kerze:
Wenn die Eröffnung unter dem vorherigen Tief minus GapPips liegt, tritt die Strategie in eine Long-Position ein und erwartet einen bullischen Rücksetzer.
Wenn die Eröffnung über dem vorherigen Hoch plus GapPips liegt, tritt sie in eine Short-Position ein und antizipiert eine Abwärtskorrektur.
Im Trade wird das Risikomanagement vollständig innerhalb der Strategie verwaltet:
Ein fester Stop-Loss wird StopLossPips unterhalb (für Long) oder oberhalb (für Short) des Einstiegspreises gesetzt.
Ein fester Take-Profit wird TakeProfitPips vom Einstieg in Richtung des Trades gesetzt.
Ein Trailing-Stop kann aktiviert werden; er bewegt sich erst, nachdem der Preis um TrailingStopPips + TrailingStepPips vorgezogen hat, und sichert
dann Gewinne, indem er den Stop TrailingStopPips vom günstigsten Preis entfernt hält.
Schutzlevels werden bei jeder abgeschlossenen Kerze anhand der Hoch/Tief-Extremwerte ausgewertet, sodass Intrabar-Berührungen zuverlässig Ausstiege auslösen.
Offene Orders werden vor einer neuen Position storniert, und Positionsumkehrungen schließen automatisch die entgegengesetzte Seite.
Parameter
OrderVolume = 0.1 — Handelsvolumen in Lots für jede neue Position.
StopLossPips = 50 — Abstand vom Einstiegspreis zum Stop-Loss-Level in Pips. Auf 0 setzen zum Deaktivieren.
TakeProfitPips = 50 — Abstand vom Einstiegspreis zum Take-Profit-Level in Pips. Auf 0 setzen zum Deaktivieren.
TrailingStopPips = 5 — Größe des Trailing-Stops in Pips. Auf 0 setzen zum Deaktivieren.
TrailingStepPips = 5 — Minimale Preisverbesserung (in Pips), bevor sich der Trailing-Stop wieder bewegt.
GapPips = 1 — Minimale Eröffnungslücke, in Pips ausgedrückt, die zum Erzeugen eines Einstiegssignals erforderlich ist.
CandleType = 1-Stunden-Zeitrahmen — Kerzen, die für die Lückenerkennung und Positionsmanagement verwendet werden.
Implementierungshinweise
Pip-basierte Eingaben werden mit der Instrument-Tick-Größe in absolute Preisabstände umgerechnet. Fünfstellige und dreistellige Forex-
Kurse werden automatisch angepasst, um mit echten Pip-Werten zu arbeiten.
Die Trailing-Stop-Logik erfordert, dass TrailingStepPips positiv ist, wenn TrailingStopPips aktiviert ist; andernfalls wirft die Strategie
beim Start eine Ausnahme, was die ursprüngliche MQL-Validierung widerspiegelt.
Die Strategie bewertet Risikokontrollen nur bei fertigen Kerzen gemäß den Richtlinien der StockSharp High-Level-API.
Manuelle Stop- und Ziel-Verwaltung basiert auf Marktorders, es gibt also keine separaten Schutzorders im Orderbuch.
Standardeinstellungen setzen Forex-Instrumente voraus; passen Sie die Pip-Distanzen an, wenn Sie Assets mit unterschiedlicher Volatilität oder Tick-Größen handeln.
using System;
using System.Collections.Generic;
using Ecng.Common;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Gap trading strategy. Detects price gaps between candles and trades the gap fill.
/// </summary>
public class GapsStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<decimal> _gapPercent;
private decimal? _prevClose;
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public decimal GapPercent
{
get => _gapPercent.Value;
set => _gapPercent.Value = value;
}
public GapsStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame())
.SetDisplay("Candle Type", "Timeframe", "General");
_gapPercent = Param(nameof(GapPercent), 0.05m)
.SetDisplay("Gap Percent", "Minimum gap size as percentage", "Trading");
}
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = null;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = null;
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(ProcessCandle)
.Start();
StartProtection(
takeProfit: new Unit(2, UnitTypes.Percent),
stopLoss: new Unit(1, UnitTypes.Percent)
);
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle)
{
if (candle.State != CandleStates.Finished)
return;
if (_prevClose == null)
{
_prevClose = candle.ClosePrice;
return;
}
var prevClose = _prevClose.Value;
var open = candle.OpenPrice;
var close = candle.ClosePrice;
_prevClose = close;
if (prevClose == 0)
return;
var gapPct = (open - prevClose) / prevClose * 100;
// Gap up detected - sell expecting gap fill
if (gapPct > GapPercent && Position == 0)
{
SellMarket();
}
// Gap down detected - buy expecting gap fill
else if (gapPct < -GapPercent && Position == 0)
{
BuyMarket();
}
}
}
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
class gaps_strategy(Strategy):
def __init__(self):
super(gaps_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(5))) \
.SetDisplay("Candle Type", "Timeframe", "General")
self._gap_percent = self.Param("GapPercent", 0.05) \
.SetDisplay("Gap Percent", "Minimum gap size as percentage", "Trading")
self._prev_close = None
@property
def CandleType(self):
return self._candle_type.Value
@property
def GapPercent(self):
return self._gap_percent.Value
def OnReseted(self):
super(gaps_strategy, self).OnReseted()
self._prev_close = None
def OnStarted2(self, time):
super(gaps_strategy, self).OnStarted2(time)
self._prev_close = None
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._on_process).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, subscription)
self.DrawOwnTrades(area)
def _on_process(self, candle):
if candle.State != CandleStates.Finished:
return
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
if self._prev_close is None:
self._prev_close = close
return
prev_close = self._prev_close
self._prev_close = close
if prev_close == 0:
return
gap_pct = (open_price - prev_close) / prev_close * 100.0
gp = float(self.GapPercent)
# Gap up detected - sell expecting gap fill
if gap_pct > gp and self.Position == 0:
self.SellMarket()
# Gap down detected - buy expecting gap fill
elif gap_pct < -gp and self.Position == 0:
self.BuyMarket()
def CreateClone(self):
return gaps_strategy()