Konvertierung des MetaTrader 4 Expert Advisors Spazm (8683) zum StockSharp High Level API.
Handeln Sie adaptive Ausbrüche, indem Sie den letzten Schlusskurs mit Umschlägen in Volatilitätsgröße um das letzte Swing-Hoch und Swing-Tief vergleichen.
Behält optionale Diagrammanmerkungen bei, die aufeinanderfolgende bullische und bärische Pivots verbinden, genau wie die ursprüngliche MQL-Visualisierung.
Datenvorbereitung
Die Strategie abonniert die Kerzenserie, die durch den Parameter CandleType für das aktive Wertpapier angegeben wird.
Jede fertige Kerze liefert die Rohbereichsprobe, die zur Volatilitätsschätzung verwendet wird:
Standardmäßig beträgt der Bereich High - Low.
Wenn UseOpenCloseRange aktiviert ist, wird stattdessen die absolute Körpergröße |Open - Close| verwendet.
Das Bereichsbeispiel wird mithilfe des Instruments PriceStep in Preisschritte umgewandelt, sodass die Logik über alle Symbole hinweg invariant bleibt.
Der durch UseWeightedVolatility definierte Indikator verarbeitet die Folge von Bereichsproben:
Deaktiviert → einfacher gleitender Durchschnitt mit der Länge VolatilityPeriod.
Aktiviert → linear gewichteter gleitender Durchschnitt (mehr Gewicht für aktuelle Kerzen).
Der geglättete Bereich (ausgedrückt in Schritten) wird mit VolatilityMultiplier multipliziert und schließlich auf Preiseinheiten zurückskaliert. Der resultierende Wert ist die adaptive Breakout-Schwelle, die auf beide Seiten des Marktes angewendet wird.
Während der Aufwärmphase zeichnet die Strategie auch die jüngsten Extremhochs und Extremtiefs mit ihren Zeitstempeln auf. Sobald VolatilityPeriod * 3 Kerzen verarbeitet sind, bestimmt das relative Timing dieser Extreme die anfängliche Trendrichtung.
Parameter
Name
Standard
Beschreibung
Volume
1
Das Auftragsvolumen wird immer dann gesendet, wenn die Strategie eine Position eröffnet oder umkehrt.
VolatilityMultiplier
5
Auf die durchschnittliche Volatilität angewendeter Multiplikator, um die Ausbruchsdistanz zu ermitteln.
VolatilityPeriod
24
Anzahl der Kerzen, die sowohl für den Volatilitätsschätzer als auch für das Setzen der anfänglichen Swing-Extreme verwendet werden.
UseWeightedVolatility
false
Schaltet den Volatilitätsschätzer von einem einfachen auf einen linear gewichteten gleitenden Durchschnitt um.
UseOpenCloseRange
false
Verwendet bei der Messung der Volatilität die absolute Eröffnungs-/Schlussbewegung anstelle des Hoch-Tief-Bereichs.
StopLossMultiplier
0
Auf den Ausbruchsschwellenwert angewendeter Multiplikator, um einen Schutzstoppabstand zu berechnen. Es werden mindestens drei Preisstufen durchgesetzt. Auf 0 setzen, um Stopps zu deaktivieren.
DrawSwingLines
true
Wenn die Strategie aktiviert ist, zeichnet sie eine Linie zwischen den neuesten bullischen und bärischen Pivots und ahmt die MQL-Objekte nach.
CandleType
4 hour time frame
Kerzentyp (Zeitrahmen oder anderer Datentyp), der die Berechnungen speist.
Handelslogik
Initialisierung
Während die ersten VolatilityPeriod * 3-Kerzen verarbeitet werden, aktualisiert die Strategie _highestPrice, _lowestPrice, _highestTime und _lowestTime, um die neuesten Extreme zu erfassen.
Nachdem genügend Kerzen eingetroffen sind, definiert das neuere der beiden Extreme den anfänglichen Trend: Wenn das letzte Tief neuer als das letzte Hoch ist, beginnt die Strategie im bullischen Modus, andernfalls beginnt sie im bärischen Modus.
Die Extremwerte werden auch als erstes Swing-Ankerpaar gespeichert, sodass Diagrammlinien unmittelbar nach dem Aufwärmen gezeichnet werden können.
Volatilitätsverfolgung
Jede fertige Kerze verschiebt ihren Bereich in den ausgewählten gleitenden Durchschnitt, um den adaptiven Schwellenwert zu erzeugen.
Der Schwellenwert liegt immer bei mindestens einem Preisschritt, um Null-Distanz-Umschläge zu vermeiden.
Schaukelwartung
Bei jeder Kerze aktualisiert der Algorithmus das gespeicherte Swing-Hoch und Swing-Tief, sobald ein neues absolutes Hoch oder Tief gedruckt wird.
Wenn sich der Trend umkehrt, wird das relevante Extrem als Pivot aufgezeichnet und, sofern die Diagrammerstellung aktiviert ist, durch eine Linie mit dem gegenüberliegenden Pivot verbunden.
Breakout-Regeln
Bullisches Regime (_isTrendUp == true): Ein Schlusskurs unter _highestPrice - threshold löst eine Umkehr zu Short aus. Die Ordergröße beträgt Volume + |Position|, sodass das bestehende Engagement abgeflacht und in einem Aufruf eine neue Short-Position eröffnet wird.
Bärisches Regime (_isTrendUp == false): Ein Schlusskurs über _lowestPrice + threshold spiegelt die Logik wider und kehrt sich in einen Long-Kurs um.
Management stoppen
Wenn StopLossMultiplier größer als Null ist, wird der Einstiegspreis um threshold * StopLossMultiplier ausgeglichen (begrenzt auf mindestens drei Preisschritte), um ein synthetisches Stop-Level abzuleiten.
Wenn eine Kerze mit ihrem Tief den Long-Stop oder mit ihrem Hoch den Short-Stop durchbricht, wird die Position durch eine Marktorder abgeflacht.
Infrastruktur
StartProtection() aktiviert integrierte StockSharp-Sicherheitsmechanismen, sobald die Strategie gestartet wird.
Alle Aktionen werden durch fertige Kerzen gesteuert, um den balkenweisen Neuberechnungszyklus des ursprünglichen Expertenberaters nachzuahmen.
Unterschiede zur MQL-Version
Der MetaTrader-Experte führt bei jedem Tick eine Neuberechnung durch, während dieser Port mit abgeschlossenen Kerzen arbeitet, da Kerzenabonnements die idiomatische Datenquelle auf der hohen Ebene API sind.
Brokerspezifische Einschränkungen wie MODE_STOPLEVEL sind nicht verfügbar; Stattdessen wird der Stop-Offset durch drei Preisschritte begrenzt, um einen konservativen Fallback zu ermöglichen.
Aufträge werden umgekehrt, indem die Schluss- und Eröffnungsbeträge in einem einzigen BuyMarket/SellMarket-Aufruf zusammengefasst werden, anstatt über bestehende Positionen zu iterieren.
Die Visualisierung basiert auf StockSharp-Diagrammprimitiven (DrawLine) anstelle von Plattformobjekten, die Anordnung der Pivot-zu-Pivot-Linien entspricht jedoch der ursprünglichen Indikatorausgabe.
Hinweise zur Verwendung
Stellen Sie sicher, dass die ausgewählte Sicherheit einen gültigen PriceStep bereitstellt. Wenn der Code fehlt, lautet er standardmäßig 1, was für bestimmte Instrumente möglicherweise angepasst werden muss.
Da die Strategie von abgeschlossenen Kerzen abhängt, verringern extrem kleine Zeitrahmen die Zuverlässigkeit der Volatilitätsschätzung. Erwägen Sie, CandleType an den ursprünglich von EA verwendeten Zeitrahmen anzupassen (standardmäßig H4).
Stopps sind optional. Wenn Sie StopLossMultiplier auf Null belassen, wird das unbegrenzte Risikomanagement aus dem Skript MQL repliziert.
Der Algorithmus ist von Natur aus trendorientiert und schreibt keine Take-Profit-Ziele vor; Ausstiege erfolgen nur durch Regimeumkehr oder Stop-Loss-Aktivierung.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// Volatility breakout strategy that tracks swing extremes and reverses
/// when price breaks beyond an ATR-based volatility band.
/// </summary>
public class SpazmVolatilityBreakoutStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _atrLength;
private readonly StrategyParam<decimal> _multiplier;
private decimal _swingHigh;
private decimal _swingLow;
private bool _trendUp;
private bool _initialized;
public SpazmVolatilityBreakoutStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(30).TimeFrame())
.SetDisplay("Candle Type", "Timeframe for analysis.", "General");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "Period for ATR volatility.", "Indicators");
_multiplier = Param(nameof(Multiplier), 2.0m)
.SetDisplay("Multiplier", "ATR multiplier for breakout threshold.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
public decimal Multiplier
{
get => _multiplier.Value;
set => _multiplier.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_swingHigh = 0;
_swingLow = decimal.MaxValue;
_trendUp = true;
_initialized = false;
}
/// <inheritdoc />
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawIndicator(area, atr);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal atrValue)
{
if (candle.State != CandleStates.Finished)
return;
if (atrValue <= 0)
return;
var close = candle.ClosePrice;
var high = candle.HighPrice;
var low = candle.LowPrice;
var threshold = atrValue * Multiplier;
if (!_initialized)
{
_swingHigh = high;
_swingLow = low;
_initialized = true;
return;
}
if (_trendUp)
{
// Track swing high
if (high > _swingHigh)
_swingHigh = high;
// Reversal: price breaks below swing high minus threshold
if (close < _swingHigh - threshold)
{
_trendUp = false;
_swingLow = low;
// Enter short on trend reversal
if (Position > 0)
SellMarket();
if (Position == 0)
SellMarket();
}
}
else
{
// Track swing low
if (low < _swingLow)
_swingLow = low;
// Reversal: price breaks above swing low plus threshold
if (close > _swingLow + threshold)
{
_trendUp = true;
_swingHigh = high;
// Enter long on trend reversal
if (Position < 0)
BuyMarket();
if (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.Indicators import AverageTrueRange
from StockSharp.Algo.Strategies import Strategy
class spazm_volatility_breakout_strategy(Strategy):
def __init__(self):
super(spazm_volatility_breakout_strategy, self).__init__()
self._atr_length = self.Param("AtrLength", 14).SetDisplay("ATR Length", "Period for ATR volatility", "Indicators")
self._multiplier = self.Param("Multiplier", 2.0).SetDisplay("Multiplier", "ATR multiplier for breakout threshold", "Indicators")
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromMinutes(30))).SetDisplay("Candle Type", "Timeframe", "General")
@property
def CandleType(self): return self._candle_type.Value
@CandleType.setter
def CandleType(self, value): self._candle_type.Value = value
def OnReseted(self):
super(spazm_volatility_breakout_strategy, self).OnReseted()
self._swing_high = 0
self._swing_low = 999999999
self._trend_up = True
self._initialized = False
def OnStarted2(self, time):
super(spazm_volatility_breakout_strategy, self).OnStarted2(time)
self._swing_high = 0
self._swing_low = 999999999
self._trend_up = True
self._initialized = False
atr = AverageTrueRange()
atr.Length = self._atr_length.Value
sub = self.SubscribeCandles(self.CandleType)
sub.Bind(atr, self.OnProcess).Start()
area = self.CreateChartArea()
if area is not None:
self.DrawCandles(area, sub)
self.DrawIndicator(area, atr)
self.DrawOwnTrades(area)
def OnProcess(self, candle, atr_val):
if candle.State != CandleStates.Finished:
return
if atr_val <= 0:
return
close = float(candle.ClosePrice)
high = float(candle.HighPrice)
low = float(candle.LowPrice)
threshold = atr_val * self._multiplier.Value
if not self._initialized:
self._swing_high = high
self._swing_low = low
self._initialized = True
return
if self._trend_up:
if high > self._swing_high:
self._swing_high = high
if close < self._swing_high - threshold:
self._trend_up = False
self._swing_low = low
if self.Position > 0:
self.SellMarket()
if self.Position == 0:
self.SellMarket()
else:
if low < self._swing_low:
self._swing_low = low
if close > self._swing_low + threshold:
self._trend_up = True
self._swing_high = high
if self.Position < 0:
self.BuyMarket()
if self.Position == 0:
self.BuyMarket()
def CreateClone(self):
return spazm_volatility_breakout_strategy()