Strategie erzeugt unrealistisch gute Ergebnisse durch Blick in die Zukunft

Eines unserer Hauptziele bei der Entwicklung von Pine ist es, den Usern so viele nützliche Tools wie möglich zur Verfügung zu stellen. Diese Werkzeuge können eine Vielzahl von unterschiedlichen Verwendungen haben. Mit bestimmten Manipulationen erlauben einige Indikatoren und Chart-Typen, Daten aus den zukünftigen Balken oder Trades zu extrahieren (relativ zum aktuell bearbeiteten Balken). Da ein Trader diese Daten im realen Handel nicht erhalten kann, können Strategien, die darum herum aufgebaut sind, beim Backtesting unrealistisch profitable Ergebnisse produzieren, während diese Trades im Echtzeithandel Verluste wären. Der Fehler, Informationen aus der Zukunft in den Strategien zu verwenden, wird auch Look-ahead Bias genannt.

Einige TradingView User neigen aus Unwissenheit oder in böser Absicht dazu, Ideen und Skript-Publikationen zu erstellen, die diese Funktion ausnutzen. TradingView kann die Funktion selbst nicht entfernen, da sie in einigen Fällen nützlich sein kann, aber gleichzeitig fühlen wir uns verpflichtet, alle User vor diesem Verhalten zu warnen.

Strategien, die Kerzen im japanischen Stil verwenden

Ein sehr häufiger Grund für dieses Verhalten ist das Strategie-Backtesting auf Charts im japanischen Stil (Renko, Kagi, etc.). Das Problem ergibt sich aus der Tatsache, dass die Strategy Backtesting Engine jeden Balken als 4 Transaktionen betrachtet, mit den Preisen von Open, High, Low und Close (wie bei einem regulären Candlestick Chart). Aus diesem Grund kann die Strategy Backtesting Engine auf einem Renko Chart eine Position zu einem Preis eingeben/verlassen, der in der Realität nicht existiert. Wenn Sie außerdem einen Wert für die Box-Größe festlegen, der kleiner als der Mintick ist, ist es möglich, zu prüfen, ob der nächste Preis höher oder niedriger als der aktuelle sein wird und die Position im Voraus eingeben/verlassen, bevor die Backtesting-Engine den realen Preis verarbeitet.

//@version=4
strategy("My Strategy", overlay=true)
if close < close[1]
    strategy.entry("ShortEntryId", strategy.short)
strategy.close("ShortEntryId", when = close > close[1])

if close > close[1]
    strategy.entry("LongEntryId", strategy.long)
strategy.close("LongEntryId", when = close < close[1])

Wie Sie auf dem Screenshot sehen können, kann diese einfache Strategie, Trades zu Preisen tätigen die sehr nahe an den Maximal-/Minimalpreisen liegen.

Strategien, die den Parameter calc_on_order_fills = true verwenden

Wenn der Parameter calc_on_order_fills = true in der Strategiefunktion angegeben ist, führt die Backtesting Engine eine zusätzliche Berechnung innerhalb des Balkens durch, nachdem die Order ausgeführt wurde (im Gegensatz zur üblichen Situation, in der die Strategie nur beim Schließen des Balkens berechnet wird). Gleichzeitig erhält die Strategie während der Berechnung Zugriff auf viele zusätzliche Balkenparameter, z.B. Hoch- und Tiefwerte. Dies ermöglicht es Ihnen, eine Strategie zu schreiben, die beim Backtesting eine hervorragende Leistung zeigt:

//@version=4
strategy("CalcOnOrderFillsStrategy", overlay=true, calc_on_order_fills=true)

// a variable is used to prevent double entry on the same bar
var lastTimeEntry = 0

longCondition = close > sma(close, 14)  and lastTimeEntry != time
if longCondition
    strategy.entry("LongEntryId", strategy.long)

strategy.exit("exitId", "LongEntryId", limit=high)
lastTimeEntry := time

Auf dem Screenshot können Sie sehen, dass der Einstieg zum Eröffnungskurs eines Balkens erfolgt und der Ausstieg zum Höchststand desselben Balkens stattfindet. Das heißt, während der Berechnung, nachdem die Order ausgeführt wurde, haben wir den strategy.exit-Grenzpreis gleich dem Höchststand des aktuellen Balkens gesetzt, was wir im realen Handel nicht tun können. 

Der Parameter lookahead = barmerge.lookahead_on in security und jeder security vor Pine v3

Die Sicherheitsfunktion in Pine ermöglicht es Ihnen, Daten von anderen Symbolen und/oder Zeitrahmen anzufordern. Abhängig von der Implementierung kann dies der Strategie erlauben, Daten aus der Zukunft zu erhalten: wenn man z.B. den Close oder High eines Tagesbalkens anfordert, könnte die Strategie beim Backtesting diese Werte gleich zu Beginn des Tages kennen. 

Vor Version 3 gab die Sicherheitsfunktion den Wert aus dem höheren Zeitrahmen zurück, noch bevor dieser zugänglich sein sollte. In Version 3 wurde dieses Verhalten behoben, aber aus Kompatibilitätsgründen wurde der Parameter lookahead zur Sicherheitsfunktion hinzugefügt. Er ist standardmäßig false (d. h., die Zukunftsvision ist ausgeschaltet), aber Sie können ihn aktivieren, indem Sie den Wert des Parameters lookahead auf barmerge.lookahead_on) setzen.

Ein Beispiel für eine profitable Strategie, die mit dieser Funktion erstellt wurde:

//@version=4
strategy("My Strategy", overlay=true)
dayStart = security(syminfo.tickerid, "1D", time, lookahead=barmerge.lookahead_on)
dayHigh = security(syminfo.tickerid, "1D", high, lookahead=barmerge.lookahead_on)
dayLow = security(syminfo.tickerid, "1D", low, lookahead=barmerge.lookahead_on)

// entry at first bar of a day
if time == dayStart
    // distance to daily high is further, so we can earn more
    if abs(open - dayHigh) > abs(open - dayLow)
        strategy.entry("LongEntryId", strategy.long)
        strategy.exit("exitLongId", "LongEntryId", limit=dayHigh)
    else
        strategy.entry("ShortEntryId", strategy.short)
        strategy.exit("exitShortId", "ShortEntryId", limit=dayLow)
        
plot(dayHigh)
plot(dayLow)

Beim ersten Balken analysieren wir, ob sich der Preis im Vergleich zum Eröffnungskurs mehr nach oben oder nach unten bewegen wird, und auf dieser Grundlage gehen wir eine Long- oder Short-Position ein und verlassen sie dann zum maximalen bzw. minimalen Preis des Tages. 

Beachten Sie, dass nicht in allen Fällen, in denen security() das Argument barmerge.lookahead_on hat, in die Zukunft geschaut wird: Wenn wir zum Beispiel den obigen Code ändern würden, indem wir time/high/low innerhalb von security() durch time[1]/high[1]/low[1] ersetzen, würden wir Werte für die Bars erhalten, die bereits geschlossen sind. Dies wird oft von erfahrenen Programmierern verwendet, um Daten aus security() zu erhalten, ohne das Risiko eines Lookaheads. 

Dies sind im Moment alle bekannten Möglichkeiten für eine Strategie, in die Zukunft zu schauen. Wir hoffen, dass diese Beschreibung Ihnen ermöglicht, Strategien zu erstellen, die diese Mängel nicht haben, sowie veröffentlichte Strategien zu meiden, deren Autoren diese Eigenschaften in ihren Ideen ausnutzen.