Die VLT Trader-Strategie ist eine StockSharp-Umsetzung des MetaTrader 4-Expertenberaters „VLT_TRADER“. Die ursprüngliche Idee sucht nach einem Zeitraum mit extrem geringer Volatilität und bereitet dann einen Ausbruchsstraddle um die jüngste Kerze herum vor. Wenn die zuletzt abgeschlossene Kerze im Vergleich zu einer konfigurierbaren Anzahl früherer Kerzen die kleinste Spanne aufweist, positioniert die Strategie Stop-Orders oberhalb und unterhalb dieser Kerze in Erwartung einer Volatilitätsausweitung.
Handelslogik
Abonnieren Sie die konfigurierte Kerzenserie und berechnen Sie die Spanne (Hoch minus Tief) für jeden Balken.
Verfolgen Sie den Mindestbereich zwischen den vorherigen LookbackCandles-Balken mithilfe des Lowest-Indikators.
Sobald die zuletzt abgeschlossene Kerze eine kleinere Spanne als dieses historische Minimum aufweist, bereiten Sie die Breakout-Orders für die folgende Sitzung vor.
Platzieren Sie einen Kaufstopp über dem vorherigen Hoch plus EntryOffsetPoints und einen Verkaufsstopp unter dem vorherigen Tief minus dem gleichen Offset.
Fügen Sie jeder ausstehenden Bestellung Stopps und Ziele mit fester Entfernung hinzu (StopLossPoints und TakeProfitPoints).
Lassen Sie beide ausstehenden Bestellungen aktiv. Welche Seite zuerst auslöst, wird zu einer Marktposition, während der gegenüberliegende Stop im Buch bleibt und später aktiviert werden kann, wenn sich der Markt umkehrt.
Wenn eine ausstehende Order ausgeführt oder storniert wird, wird die entsprechende Referenz gelöscht, sodass neue Straddles erstellt werden können, nachdem alle Positionen und Orders geschlossen wurden.
Risikomanagement
Die Handelsgröße wird durch OrderVolume gesteuert und auf den Volumenschritt und die Limits des Instruments gerundet.
Stop-Loss- und Take-Profit-Abstände werden in Preisschritten (Punkten) ausgedrückt und mithilfe des PriceStep des Instruments in tatsächliche Preise umgerechnet.
Parameter
Parameter
Beschreibung
OrderVolume
Bei der Erstellung der ausstehenden Aufträge verwendete Losgröße.
EntryOffsetPoints
Beim Platzieren von Stop-Einträgen werden dem vorherigen Hoch/Tief zusätzliche Punkte hinzugefügt.
TakeProfitPoints
Jeder Bestellung ist eine Gewinnspanne beigefügt.
StopLossPoints
Jeder Bestellung ist eine Stop-Loss-Distanz beigefügt.
LookbackCandles
Anzahl der vorherigen Kerzen, die zur Messung der minimalen historischen Spanne verwendet wurden.
CandleType
Zeitrahmen der Kerzenserie, die die Strategie speist.
Notizen
Die Strategie erfordert ein gültiges PriceStep auf dem Instrument; andernfalls werden keine Bestellungen aufgegeben.
Da Stop- und Take-Profit-Level zusammen mit den ausstehenden Aufträgen übermittelt werden, können die Ausführungspreise in StockSharp je nach den Ausführungsregeln des Brokers geringfügig von MetaTrader abweichen.
Die Implementierung basiert ausschließlich auf High-Level-APIs (SubscribeCandles + Bind) und dem Standardindikator Lowest, um die Volatilitätsprüfung des Originals EA widerzuspiegeln.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
public class VltTraderStraddleStrategy : Strategy
{
private readonly StrategyParam<int> _channelPeriod;
private readonly StrategyParam<int> _atrPeriod;
private readonly StrategyParam<int> _cooldownCandles;
private readonly StrategyParam<DataType> _candleType;
private decimal _prevClose;
private decimal _prevMid;
private bool _hasPrev;
private int _cooldownRemaining;
public int ChannelPeriod { get => _channelPeriod.Value; set => _channelPeriod.Value = value; }
public int AtrPeriod { get => _atrPeriod.Value; set => _atrPeriod.Value = value; }
public int CooldownCandles { get => _cooldownCandles.Value; set => _cooldownCandles.Value = value; }
public DataType CandleType { get => _candleType.Value; set => _candleType.Value = value; }
public VltTraderStraddleStrategy()
{
_channelPeriod = Param(nameof(ChannelPeriod), 48).SetDisplay("Channel Period", "Breakout lookback", "Indicators");
_atrPeriod = Param(nameof(AtrPeriod), 14).SetDisplay("ATR Period", "ATR lookback", "Indicators");
_cooldownCandles = Param(nameof(CooldownCandles), 150).SetDisplay("Cooldown", "Candles between signals", "General");
_candleType = Param(nameof(CandleType), TimeSpan.FromMinutes(5).TimeFrame()).SetDisplay("Candle Type", "Candle timeframe", "General");
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_prevClose = default;
_prevMid = default;
_hasPrev = default;
_cooldownRemaining = default;
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_prevClose = 0;
_prevMid = 0;
_hasPrev = false;
_cooldownRemaining = 0;
var highest = new Highest { Length = ChannelPeriod };
var lowest = new Lowest { Length = ChannelPeriod };
var atr = new AverageTrueRange { Length = AtrPeriod };
var subscription = SubscribeCandles(CandleType);
subscription.Bind(highest, lowest, atr, ProcessCandle).Start();
}
private void ProcessCandle(ICandleMessage candle, decimal highest, decimal lowest, decimal atr)
{
if (candle.State != CandleStates.Finished) return;
var close = candle.ClosePrice;
var mid = (highest + lowest) / 2;
if (!_hasPrev) { _prevClose = close; _prevMid = mid; _hasPrev = true; return; }
if (_cooldownRemaining > 0)
{
_cooldownRemaining--;
_prevClose = close;
_prevMid = mid;
return;
}
if (_prevClose <= _prevMid && close > mid && Position <= 0)
{
if (Position < 0) BuyMarket();
BuyMarket();
_cooldownRemaining = CooldownCandles;
}
else if (_prevClose >= _prevMid && close < mid && Position >= 0)
{
if (Position > 0) SellMarket();
SellMarket();
_cooldownRemaining = CooldownCandles;
}
_prevClose = close;
_prevMid = mid;
}
}