Die FT TIME BIGDOG-Strategie ist ein London-Session-Breakout-System, das aus dem MetaTrader 4 Expert Advisor FT_TIME_BIGDOG.mq4 (Verzeichnis MQL/9259) konvertiert wurde.
Es misst den Konsolidierungsbereich, der sich zwischen den konfigurierten Start- und Stoppstunden bildet, und platziert dann Stop-Orders oberhalb und unterhalb dieses Bereichs, sobald sich das Fenster schließt.
Die StockSharp-Version behält das ursprüngliche Verhalten bei und stellt gleichzeitig konfigurierbare Parameter für Breakout-Timing, Orderentfernung und Risikomanagement bereit.
Handelslogik
An jedem Handelstag zeichnet die Strategie das höchste Hoch und das niedrigste Tief der fertigen Kerzen auf, deren Öffnungszeit zwischen StartHour und StopHour (einschließlich) liegt.
Wenn die akkumulierte Spanne nach Ablauf der Stop-Hour-Kerze kleiner als RangeLimitPoints ist, werden zwei ausstehende Stop-Orders zugelassen:
Ein Kaufstopp beim Rekordhoch.
Ein Verkaufsstopp beim aufgezeichneten Tief.
Aufträge werden nur erstellt, wenn der Marktpreis mindestens OrderBufferPoints vom Einstiegsniveau entfernt ist. Sofern verfügbar, werden die besten Geld-/Briefkurse verwendet, andernfalls wird der letzte Kerzenschluss verwendet.
Jede ausstehende Order beinhaltet einen Schutzstopp auf der gegenüberliegenden Seite der Spanne und einen durch TakeProfitPoints definierten Take-Profit-Offset.
Wenn eine Position eröffnet wird, wird die entgegengesetzte ausstehende Order storniert. Die aktive Position wird anhand abgeschlossener Kerzen überwacht: Wenn der Preis das gespeicherte Stop-Loss- oder Take-Profit-Niveau berührt, wird die Position zum Marktwert geschlossen.
Der Zyklus läuft höchstens einmal pro Tag; Der gesamte Status wird zu Beginn des nächsten Handelstages zurückgesetzt.
Parameter
Parameter
Standard
Beschreibung
StartHour
14
Stunde (0–23), die den Beginn des Akkumulationsfensters markiert.
StopHour
16
Stunde, in der ausstehende Orders berechtigt werden. Muss größer oder gleich StartHour sein.
RangeLimitPoints
50
Maximale Breite des Sitzungsbereichs in Brokerpunkten (Punkte × PointMultiplier). Bei größeren Sortimenten werden keine Bestellungen aufgegeben.
TakeProfitPoints
50
Auf ausgelöste Positionen angewendete Take-Profit-Distanz, ausgedrückt in Broker-Punkten.
OrderBufferPoints
20
Erforderlicher Mindestabstand zwischen dem Marktpreis und einer ausstehenden Order. Verhindert, dass Bestellungen zu nahe am aktuellen Preis platziert werden.
PointMultiplier
1
Auf die Punktgröße des Instruments angewendeter Multiplikator. Für fünfstellige Forex-Symbole auf 10 einstellen.
Volume
0,1
Ordervolumen für beide Stop-Orders.
CandleType
1 Stunde
Kerzenreihe zur Reichweitenmessung und Antriebssignalauswertung.
Risiko- und Handelsmanagement
Der Stop-Loss für Long-Trades entspricht dem Sitzungstief; Der Stop-Loss für Short-Trades entspricht dem Sitzungshoch.
Take-Profit-Level werden aus dem Breakout-Preis unter Verwendung von TakeProfitPoints und der Punktgröße des Instruments berechnet.
Alle Risikokontrollen werden bei Kerzenschlussereignissen durchgeführt; Intrabar-Exkursionen über die Stop-Level hinaus können zu verzögerten Ausstiegen führen.
Unterschiede zum ursprünglichen Expert Advisor
Die MetaTrader-Version arbeitet mit Tick-Ereignissen, während dieser Port auf fertigen Kerzen und Level-1-Updates basiert. Das Verhalten innerhalb einer Kerze kann daher geringfügig abweichen.
Bei der Punktumrechnung wird Security.PriceStep multipliziert mit PointMultiplier verwendet. Überprüfen Sie diese Kombination, bevor Sie sie live ausführen.
Bestellungen werden nur aufgegeben, wenn StartHour <= StopHour. In diesem Port werden keine Mitternachtsfenster unterstützt.
Nutzungshinweise
Weisen Sie die gewünschte Sicherheit zu und stellen Sie sicher, dass Daten der Ebene 1 für genaue Pufferprüfungen verfügbar sind.
Konfigurieren Sie die Handelszeiten entsprechend der Zeitzone des Brokers.
Führen Sie zunächst eine Simulation durch, um die Punktkonvertierung und das Timing im Verhältnis zu Ihrem Datenfeed zu validieren.
Setzen Sie die Strategie zurück oder stoppen Sie sie, bevor Sie ausstehende Aufträge manuell ändern, um Konflikte im Status zu vermeiden.
Dateien
CS/FtTimeBigdogStrategy.cs – Kernimplementierung von StockSharp mit detaillierten Inline-Kommentaren.
MQL/9259/FT_TIME_BIGDOG.mq4 – ursprüngliche MetaTrader-Quelle, die für die Konvertierung verwendet wurde.
using System;
using StockSharp.Algo.Indicators;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.Messages;
namespace StockSharp.Samples.Strategies;
/// <summary>
/// FT Time Bigdog: Range breakout using N-bar high/low channel with ATR stops.
/// </summary>
public class FtTimeBigdogStrategy : Strategy
{
private readonly StrategyParam<DataType> _candleType;
private readonly StrategyParam<int> _channelLength;
private readonly StrategyParam<int> _atrLength;
private decimal _entryPrice;
private decimal _highest;
private decimal _lowest;
private int _barCount;
private readonly decimal[] _highs = new decimal[20];
private readonly decimal[] _lows = new decimal[20];
public FtTimeBigdogStrategy()
{
_candleType = Param(nameof(CandleType), TimeSpan.FromHours(4).TimeFrame())
.SetDisplay("Candle Type", "Timeframe.", "General");
_channelLength = Param(nameof(ChannelLength), 20)
.SetDisplay("Channel Length", "Lookback for high/low channel.", "Indicators");
_atrLength = Param(nameof(AtrLength), 14)
.SetDisplay("ATR Length", "ATR period.", "Indicators");
}
public DataType CandleType
{
get => _candleType.Value;
set => _candleType.Value = value;
}
public int ChannelLength
{
get => _channelLength.Value;
set => _channelLength.Value = value;
}
public int AtrLength
{
get => _atrLength.Value;
set => _atrLength.Value = value;
}
/// <inheritdoc />
protected override void OnReseted()
{
base.OnReseted();
_entryPrice = 0;
_barCount = 0;
_highest = 0;
_lowest = 0;
Array.Clear(_highs, 0, _highs.Length);
Array.Clear(_lows, 0, _lows.Length);
}
protected override void OnStarted2(DateTime time)
{
base.OnStarted2(time);
_entryPrice = 0;
_barCount = 0;
_highest = 0;
_lowest = 0;
Array.Clear(_highs, 0, _highs.Length);
Array.Clear(_lows, 0, _lows.Length);
var atr = new AverageTrueRange { Length = AtrLength };
var subscription = SubscribeCandles(CandleType);
subscription
.Bind(atr, ProcessCandle)
.Start();
var area = CreateChartArea();
if (area != null)
{
DrawCandles(area, subscription);
DrawOwnTrades(area);
}
}
private void ProcessCandle(ICandleMessage candle, decimal atrVal)
{
if (candle.State != CandleStates.Finished)
return;
var len = Math.Min(ChannelLength, _highs.Length);
var idx = _barCount % len;
_highs[idx] = candle.HighPrice;
_lows[idx] = candle.LowPrice;
_barCount++;
if (_barCount < len || atrVal <= 0)
return;
var high = decimal.MinValue;
var low = decimal.MaxValue;
for (var i = 0; i < len; i++)
{
if (_highs[i] > high) high = _highs[i];
if (_lows[i] < low) low = _lows[i];
}
var prevHigh = _highest;
var prevLow = _lowest;
_highest = high;
_lowest = low;
if (prevHigh == 0 || prevLow == 0)
return;
var close = candle.ClosePrice;
if (Position > 0)
{
if (close >= _entryPrice + atrVal * 3m || close <= _entryPrice - atrVal * 2m)
{
SellMarket();
_entryPrice = 0;
}
}
else if (Position < 0)
{
if (close <= _entryPrice - atrVal * 3m || close >= _entryPrice + atrVal * 2m)
{
BuyMarket();
_entryPrice = 0;
}
}
if (Position == 0)
{
if (close > prevHigh)
{
_entryPrice = close;
BuyMarket();
}
else if (close < prevLow)
{
_entryPrice = close;
SellMarket();
}
}
}
}
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
from StockSharp.Algo.Indicators import AverageTrueRange
class ft_time_bigdog_strategy(Strategy):
def __init__(self):
super(ft_time_bigdog_strategy, self).__init__()
self._candle_type = self.Param("CandleType", DataType.TimeFrame(TimeSpan.FromHours(4))) \
.SetDisplay("Candle Type", "Timeframe.", "General")
self._channel_length = self.Param("ChannelLength", 20) \
.SetDisplay("Channel Length", "Lookback for high/low channel.", "Indicators")
self._atr_length = self.Param("AtrLength", 14) \
.SetDisplay("ATR Length", "ATR period.", "Indicators")
self._entry_price = 0.0
self._highest = 0.0
self._lowest = 0.0
self._bar_count = 0
self._highs = []
self._lows = []
@property
def CandleType(self):
return self._candle_type.Value
@property
def ChannelLength(self):
return self._channel_length.Value
@property
def AtrLength(self):
return self._atr_length.Value
def OnStarted2(self, time):
super(ft_time_bigdog_strategy, self).OnStarted2(time)
self._entry_price = 0.0
self._bar_count = 0
self._highest = 0.0
self._lowest = 0.0
self._highs = [0.0] * 20
self._lows = [0.0] * 20
self._atr = AverageTrueRange()
self._atr.Length = self.AtrLength
subscription = self.SubscribeCandles(self.CandleType)
subscription.Bind(self._atr, self.ProcessCandle).Start()
def ProcessCandle(self, candle, atr_val):
if candle.State != CandleStates.Finished:
return
av = float(atr_val)
length = min(self.ChannelLength, 20)
idx = self._bar_count % length
self._highs[idx] = float(candle.HighPrice)
self._lows[idx] = float(candle.LowPrice)
self._bar_count += 1
if self._bar_count < length or av <= 0:
return
high = max(self._highs[i] for i in range(length))
low = min(self._lows[i] for i in range(length))
prev_high = self._highest
prev_low = self._lowest
self._highest = high
self._lowest = low
if prev_high == 0 or prev_low == 0:
return
close = float(candle.ClosePrice)
if self.Position > 0:
if close >= self._entry_price + av * 3.0 or close <= self._entry_price - av * 2.0:
self.SellMarket()
self._entry_price = 0.0
elif self.Position < 0:
if close <= self._entry_price - av * 3.0 or close >= self._entry_price + av * 2.0:
self.BuyMarket()
self._entry_price = 0.0
if self.Position == 0:
if close > prev_high:
self._entry_price = close
self.BuyMarket()
elif close < prev_low:
self._entry_price = close
self.SellMarket()
def OnReseted(self):
super(ft_time_bigdog_strategy, self).OnReseted()
self._entry_price = 0.0
self._bar_count = 0
self._highest = 0.0
self._lowest = 0.0
self._highs = []
self._lows = []
def CreateClone(self):
return ft_time_bigdog_strategy()