Die Order Stabilization Strategy ist eine Umsetzung des MetaTrader-Expertenberaters hjueiisyx8lp2o379e_www_forex-instruments_info.mq4. Der ursprüngliche Roboter platziert ein Paar Stop-Orders rund um den aktuellen Preis und wartet auf einen Ausbruch. Sobald eine Position eröffnet wird, überwacht das System die jüngsten Kerzenkörper, um festzustellen, ob die Preisbewegung ins Stocken geraten („stabilisiert“) ist, und verlässt den Handel, wenn der Markt an Dynamik verliert oder eine vordefinierte Gewinnschwelle erreicht wird.
Dieser C#-Port behält die gleiche Logik bei, indem er das übergeordnete StockSharp API verwendet. Es basiert auf abgeschlossenen Kerzen statt auf rohen Ticks, was das Verhalten beim Backtesting und Live-Handel deterministisch macht.
Handelsregeln
Wenn keine offenen Positionen oder aktiven Aufträge vorhanden sind, legt die Strategie einen Kaufstopp oberhalb des Marktes und einen Verkaufsstopp unterhalb des Marktes fest. Die Entfernung wird in MetaTrader Punkten gemessen (normalerweise gleich einem Pip).
Wenn eine Stop-Order ausgeführt wird:
Der ausgeführte Auftrag eröffnet eine Position von OrderVolume Lots.
Die entgegengesetzte Stop-Order bleibt ausstehend, um einen Ausbruch in die andere Richtung abzufangen.
Während eine Position offen ist, überprüft die Strategie die Körpergröße der beiden zuletzt abgeschlossenen Kerzen:
Wenn der letzte Kerzenkörper kleiner als StabilizationPoints ist und der variable Gewinn höher als ProfitThreshold ist, wird die Position geschlossen und die entgegengesetzte ausstehende Order storniert.
Wenn zwei aufeinanderfolgende Kerzen kleiner als StabilizationPoints sind, wird der Handel unabhängig vom aktuellen Gewinn geschlossen.
Wenn der Gewinn AbsoluteFixation erreicht, wird der Handel sofort geschlossen.
Ausstehende Bestellungen werden nach ExpirationMinutes storniert und neu erstellt, es sei denn, der Wert ist auf Null gesetzt (unendliche Lebensdauer).
Parameter
Name
Beschreibung
Standard
OrderVolume
Handelsvolumen in Lots, das für beide Stop-Eingaben verwendet wird.
0.1
OrderDistancePoints
Abstand zwischen dem aktuellen Schlusskurs und jeder Stop-Order, ausgedrückt in MetaTrader Punkten.
20
ProfitThreshold
Mindesterforderlicher variabler Gewinn (Kontowährung), bevor ein durch Stabilisierung ausgelöster Ausstieg zulässig ist.
-2
AbsoluteFixation
Gewinnniveau (Kontowährung), das einen sofortigen Ausstieg erzwingt.
30
StabilizationPoints
Maximale Kerzenkörpergröße (Punkte), die einen flachen Markt signalisiert.
25
ExpirationMinutes
Lebensdauer ausstehender Stop-Orders in Minuten. 0 deaktiviert den Ablauf.
20
CandleType
Kerzentyp, der zur Bewertung der Stabilisierung verwendet wird (standardmäßig 5-Minuten-Zeitrahmen).
TimeFrame(5m)
Konvertierungshinweise
Der ursprüngliche Fachberater operierte mit Chart-Ticks. Dieser Port wertet nur fertige Kerzen aus, wobei die Logik erhalten bleibt und gleichzeitig reproduzierbare Backtests gewährleistet werden.
MetaTrader „Punkte“ werden dem StockSharp PriceStep zugeordnet. Fehlt dem Instrument eine Preisstufe, wird eine Stufe von 1 angenommen.
Der Gewinn wird mithilfe von PriceStep und StepPrice angenähert, um Preisbewegungen in die Kontowährung umzurechnen.
Alle Codekommentare wurden in Englisch umgeschrieben und die Parametermetadaten enthalten benutzerfreundliche Beschreibungen mit Gruppierung.
Nutzung
Fügen Sie die Strategie zu Ihrer StockSharp-Lösung hinzu und weisen Sie das gewünschte Wertpapier und Portfolio zu.
Konfigurieren Sie die Parameter, insbesondere den Zeitrahmen der Kerze und die Entfernung in Punkten, um sie an die Eigenschaften des Instruments anzupassen.
Starten Sie die Strategie. Es wird gepaarte Stop-Orders einreichen und Positionen gemäß der oben beschriebenen Stabilisierungslogik verwalten.
Weitere Ideen
Experimentieren Sie mit verschiedenen Kerzenintervallen, um Reaktionsfähigkeit und Geräuschfilterung in Einklang zu bringen.
Kombinieren Sie die Strategie mit Volatilitätsfiltern (ATR, Bollinger-Bänder), um den Handel während extrem ruhiger Sitzungen zu vermeiden.
Erweitern Sie die Logik mit Trailing Stops oder teilweisen Positionsausstiegen, sobald Sie sich dem absoluten Gewinnziel nähern.
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>
/// Order stabilization strategy - trades breakouts after periods of low volatility.
/// When candle body is small (stabilization), waits for a directional breakout.
/// Goes long on bullish breakout candle after stabilization, short on bearish.
/// </summary>
public class OrderStabilizationStrategy : Strategy
{
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<decimal> _stabilizationFactor;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevBody;
private decimal _prevAtr;
private bool _hasPrev;
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public decimal StabilizationFactor { get => _stabilizationFactor.Value; set => _stabilizationFactor.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public OrderStabilizationStrategy()
{
_atrPeriod = Param(nameof(AtrPeriod), 14)
.SetDisplay("ATR Period", "ATR period for volatility", "Indicators");
_stabilizationFactor = Param(nameof(StabilizationFactor), 0.5m)
.SetDisplay("Stabilization Factor", "Body must be less than ATR * factor for stabilization", "Indicators");
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
public override IEnumerable<(Security sec, DataType dt)> GetWorkingSecurities()
{
return [(Security, CandleType)];
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevBody = 0m;
_prevAtr = 0m;
_hasPrev = false;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_hasPrev = false;
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
}
private void ProcessCandle(ICandleMessage candle, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
var body = Math.Abs(candle.ClosePrice - candle.OpenPrice);
var threshold = atrValue * StabilizationFactor;
if (!_hasPrev)
{
_prevBody = body;
_prevAtr = atrValue;
_hasPrev = true;
return;
}
var prevThreshold = _prevAtr * StabilizationFactor;
var wasStabilized = _prevBody < prevThreshold;
// After stabilization, trade breakout candle
if (wasStabilized && body > threshold)
{
var bullish = candle.ClosePrice > candle.OpenPrice;
if (bullish && Position <= 0)
{
if (Position < 0)
BuyMarket();
BuyMarket();
}
else if (!bullish && Position >= 0)
{
if (Position > 0)
SellMarket();
SellMarket();
}
}
_prevBody = body;
_prevAtr = atrValue;
}
}
import clr
clr.AddReference("StockSharp.Messages")
clr.AddReference("StockSharp.Algo")
clr.AddReference("StockSharp.Algo.Indicators")
clr.AddReference("StockSharp.Algo.Strategies")
from System import TimeSpan, Math
from StockSharp.Messages import DataType, CandleStates
from StockSharp.Algo.Indicators import AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class order_stabilization_strategy(Strategy):
"""Trades breakouts after periods of low volatility (stabilization).
When previous candle body is small relative to ATR, waits for directional breakout.
Goes long on bullish breakout candle, short on bearish."""
def __init__(self):
super(order_stabilization_strategy, self).__init__()
self._atr_period = self.Param("AtrPeriod", 14) \
.SetDisplay("ATR Period", "ATR period for volatility", "Indicators")
self._stabilization_factor = self.Param("StabilizationFactor", 0.5) \
.SetDisplay("Stabilization Factor", "Body must be less than ATR * factor for stabilization", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Candle timeframe", "General")
self._prev_body = 0.0
self._prev_atr = 0.0
self._has_prev = False
@property
def CandleType(self):
return self._candle_type.Value
@CandleType.setter
def CandleType(self, value):
self._candle_type.Value = value
@property
def AtrPeriod(self):
return self._atr_period.Value
@property
def StabilizationFactor(self):
return self._stabilization_factor.Value
def OnReseted(self):
super(order_stabilization_strategy, self).OnReseted()
self._prev_body = 0.0
self._prev_atr = 0.0
self._has_prev = False
def OnStarted2(self, time):
super(order_stabilization_strategy, self).OnStarted2(time)
self._has_prev = False
atr = AverageTrueRange()
atr.Length = self.AtrPeriod
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(atr, self._process_candle).Start()
def _process_candle(self, candle, atr_value):
if candle.State != CandleStates.Finished:
return
atr_val = float(atr_value)
close = float(candle.ClosePrice)
open_price = float(candle.OpenPrice)
body = abs(close - open_price)
factor = float(self.StabilizationFactor)
threshold = atr_val * factor
if not self._has_prev:
self._prev_body = body
self._prev_atr = atr_val
self._has_prev = True
return
prev_threshold = self._prev_atr * factor
was_stabilized = self._prev_body < prev_threshold
# After stabilization, trade breakout candle
if was_stabilized and body > threshold:
bullish = close > open_price
if bullish and self.Position <= 0:
if self.Position < 0:
self.BuyMarket()
self.BuyMarket()
elif not bullish and self.Position >= 0:
if self.Position > 0:
self.SellMarket()
self.SellMarket()
self._prev_body = body
self._prev_atr = atr_val
def CreateClone(self):
return order_stabilization_strategy()