Einführung in die PINE-Sprache FMZ Quant

Schriftsteller:Lydia., Erstellt: 2022-09-23 15:23:34, Aktualisiert: 2024-02-27 16:47:41

[TOC]

img

Einführung in die PINE-Sprache FMZ Quant

Unterstützendes Video-Tutorial:https://www.youtube.com/watch?v=CA3SwJQb_1g

FMZ Quant Trading Platform unterstützt das Schreiben, Backtesting und Live-Handel von Pine-Strategien in der Pine-Sprache und ist kompatibel mit niedrigeren Versionen der Pine-Sprache.Strategieplatzauf der FMZ Quant Trading Plattform (FMZ.COM).

FMZ unterstützt nicht nur die Pine-Sprache, sondern auch die leistungsstarke Zeichnungsfunktion der Pine-Sprache. Die verschiedenen Funktionen, reiche und praktische Werkzeuge, effiziente und bequeme Verwaltung auf der FMZ-Plattform verbessern die Praktikabilität der Pine-Strategie (Skript). Basierend auf der Kompatibilität mit der Pine-Sprache erweitert, optimiert und trimmt FMZ auch die Pine-Sprache bis zu einem gewissen Grad. Bevor wir offiziell in das Tutorial eintreten, werfen wir einen Blick darauf, welche Änderungen an der Pine-Sprache auf FMZ im Vergleich zur Originalversion vorgenommen wurden.

Ein kurzer Überblick über einige der offensichtlichen Unterschiede:

    1. Die Pine-Strategie auf FMZ, die Versionskennung am Anfang des Codes//@versionund derstrategy, indicatorAnweisungen am Anfang des Codes sind nicht zwingend zu schreiben, FMZ unterstützt nichtimportzu importierenlibraryFunktionieren für jetzt.

    Man kann sehen, dass einige Strategien so geschrieben sind:

    //@version=5
    indicator("My Script", overlay = true)
    src = close
    a = ta.sma(src, 5)
    b = ta.sma(src, 50)
    c = ta.cross(a, b)
    plot(a, color = color.blue)
    plot(b, color = color.black)
    plotshape(c, color = color.red)
    

    Oder schreiben Sie es so:

    //@version=5
    strategy("My Strategy", overlay=true)
    
    longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
    if (longCondition)
        strategy.entry("My Long Entry Id", strategy.long)
    
    shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
    if (shortCondition)
        strategy.entry("My Short Entry Id", strategy.short)
    

    Auf FMZ kann es vereinfacht werden:

    src = close
    a = ta.sma(src, 5)
    b = ta.sma(src, 50)
    c = ta.cross(a, b)
    plot(a, color = color.blue, overlay=true)
    plot(b, color = color.black, overlay=true)
    plotshape(c, color = color.red, overlay=true)
    

    Oder:

    longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
    if (longCondition)
        strategy.entry("My Long Entry Id", strategy.long)
    
    shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
    if (shortCondition)
        strategy.entry("My Short Entry Id", strategy.short)
    
    1. Einige handelsbezogene Einstellungen der Strategie (Skript) werden durch die Pine Language Trading Class Library Parameter auf der FMZ-Strategieoberfläche festgelegt.
    • Schlusskursmodell und Echtzeitpreismodell In der Handelsansicht können wir diecalc_on_every_tickParameter derstrategyFunktion, um das Strategie-Skript zu setzen, um die Strategie-Logik in Echtzeit auszuführen, wenn sich der Preis jedes Mal ändert.calc_on_every_tickParameter sollte auftrue. Diecalc_on_every_tickStandardparameter istfalse, d. h. die Strategie-Logik wird erst ausgeführt, wenn die aktuelle K-Line BAR der Strategie vollständig abgeschlossen ist. Auf FMZ wird es durch die Parameter der Pine Language Trading Class Library-Vorlage festgelegt.

      img

    • Numerische Präzisionskontrolle, wie Preis und Auftragsbetrag bei der Ausführung der Strategie, muss auf FMZ angegeben werden. In der Handelsansicht gibt es beim Platzieren von realen Handelsordern kein Genauigkeitsproblem, da es nur in der Simulation getestet werden kann. Auf FMZ ist es möglich, die Pine-Strategie im realen Handel auszuführen. Dann muss die Strategie in der Lage sein, die Preisgenauigkeit und die Auftragsbetragsgenauigkeit der Handelsvariante flexibel anzugeben. Die Genauigkeitseinstellungen steuern die Anzahl der Dezimalstellen in den relevanten Daten, um zu verhindern, dass die Daten die Auftragsvoraussetzungen der Börse nicht erfüllen und somit keine Bestellung aufgeben.

    • Futures-Kontraktcode Wenn das Handelsprodukt auf FMZ ein Vertrag ist, hat es zwei Attribute, sie sind Trading Pair und Contract Code. Neben der expliziten Einstellung des Handelspaares ist es auch notwendig, den spezifischen Vertragskode im Parameter Variety Code der Pine Language Trading Class Library Vorlage während des realen Handels und des Backtestings festzulegen. Zum Beispiel für einen Dauervertrag füllen Sieswap, und der Vertragscode hängt davon ab, ob die betriebliche Börse einen solchen Vertrag hat.quarterDiese Vertragscodes entsprechen den Futures-Kontraktcodes, die in FMZs Javascript/Python/C++-API-Dokument definiert sind.

    Für andere Einstellungen, wie z. B. Mindestbestellbetrag, Standardbestellbetrag usw., lesen Sie bitte die Parametereinführung aufVorlage von Argumenten für die Fachbibliothek der Kiefernsprachein der Dokumentation der Kiefersprache.

    1. Funktionen für FMZ-Erweiterungen:runtime.debug , runtime.log, runtime.errorfür das Debugging verwendet.

    3 Funktionen wurden zur Debugging-Plattform des FMZ hinzugefügt.

    • runtime.debug: Drucken Sie Variableninformationen auf der Konsole, die in der Regel nicht mit dieser Funktion verwendet wird.

    • runtime.log: Ausgabe im Protokoll. PINE-Sprachenspezifische Funktionen auf FMZ.

      runtime.log(1, 2, 3, close, high, ...), Multiple parameters can be passed.
      
    • runtime.error: Es wird bei Aufruf zu einem Laufzeitfehler mit der im Nachrichtenparameter angegebenen Fehlermeldung führen.

      runtime.error(message)
      
    1. DieoverlayParameter wird in einigen der Zeichnungsfunktionen erweitert

    In der Pine-Sprache auf FMZ sind die Zeichnungsfunktionenplot, plotshape, plotchar, etc. haben dieoverlayParameterunterstützung, die es ermöglicht, die Zeichnung auf dem Haupt- oder Teildiagramm anzugeben.overlayist auftrueauf der Hauptkarte zu zeichnen undfalseist so eingestellt, dass sie auf dem Unterdiagramm beruht, wodurch die Pine-Strategie auf FMZ das Hauptdiagramm und das Unterdiagramm gleichzeitig erstellen kann.

    1. Wert dersyminfo.mintickeingebaute Variable

    Die eingebaute Variable vonsyminfo.mintickist definiert als der Mindest-Tick-Wert für das aktuelle Symbol. Dieser Wert kann durch die Vorlageparameter-Präzisionswährung in der Pine Language Trading Class Library auf der FMZ gesteuert werdenBot/ZurückprüfungPreissteuerung Währung Genauigkeit Einstellung 2 bedeutet, dass der Preis beim Handel auf den zweiten Dezimalpunkt genau ist, und die minimale Preisänderungseinheit ist 0,01.syminfo.mintickist 0,01.

    1. Der durchschnittliche Preis in FMZ PINE Script sind alle inklusive Provision

    Beispielsweise beträgt der Auftragspreis 8000, die Verkaufsrichtung, die Menge beträgt 1 Los (Stück, Blatt), der durchschnittliche Preis nach der Transaktion beträgt nicht 8000, sondern unter 8000 (die Kosten beinhalten die Bearbeitungsgebühr).

Grundlagen der Kiefernsprache

Wenn Sie mit dem Lernen der Grundlagen der Pine-Sprache beginnen, können einige Beispiele für Anweisungen und Code-Grammatik vorliegen, mit denen Sie nicht vertraut sind. Es spielt keine Rolle, ob Sie sie nicht verstehen, wir können uns zuerst mit den Konzepten vertraut machen und den Zweck des Tests verstehen, oder Sie können die Pine-Sprachdokumentation auf FMZ nach Anweisungen überprüfen. Folgen Sie dann dem Schritt für Schritt-Tutorial, um sich mit verschiedenen Grammatik, Anweisungen, Funktionen und integrierten Variablen vertraut zu machen.

Ausführung des Modells

Wenn man anfängt, die Pine-Sprache zu lernen, ist es sehr notwendig, die damit verbundenen Konzepte wie den Ausführungsvorgang des Pine-Sprach-Skriptprogramms zu verstehen. Die Pine-Sprachstrategie läuft auf der Grundlage des Charts. Man kann verstehen, dass die Pine-Sprachstrategie eine Reihe von Berechnungen und Operationen ist, die in der Reihenfolge der Zeitreihen auf dem Chart aus den frühesten Daten, die auf dem Chart geladen wurden, ausgeführt werden. Die Datenmenge, die das Chart zunächst lädt, ist begrenzt. Im realen Handel wird die maximale Datenmenge normalerweise auf der Grundlage des maximalen Datenvolumens bestimmt, das von der Austauschoberfläche zurückgegeben wird, und die maximale Datenmenge während des Backtests wird auf der Grundlage der Datenquelle des Backtesting-Systems bestimmt. Die linkste K-Zeilenecke auf dem Chart, das heißt die erste Datensammlung des Chartes, hat einen Indexwert von 0. Der Wert der K-Zeilenecke, in der dasbar_indexin der Pine-Sprache.

plot(bar_index, "bar_index")

img

DieplotDie Verwendung ist sehr einfach, es ist eine Linie auf dem Diagramm nach den Eingabeparametern zu zeichnen, die Eingabedaten istbar_index, und die Linie heißt:bar_index. Es kann gesehen werden, dass der Wert der Zeile mit dem Namen bar_index auf der ersten Bar 0 beträgt und mit zunehmender Bar um 1 nach rechts steigt.

Da die Einstellungen der Strategie unterschiedlich sind, unterscheiden sich die Modelldurchführungsmethoden der Strategie.closing price modelundreal-time price modelWir haben auch kurz die Konzepte von ihnen vorgestellt.

  • Modell für den Schlusspreis

    Wenn der Strategiecode ausgeführt wird, wird die Periode der aktuellen K-Line Bar vollständig ausgeführt, und wenn die K-Line geschlossen wird, ist die K-Line Periode abgeschlossen.

  • Echtzeitpreismodell

    Wenn der Strategiecode ausgeführt wird, unabhängig davon, ob die aktuelle K-Line Bar geschlossen ist oder nicht, wird die Pine-Strategie-Logik jedes Mal ausgeführt, wenn sich der Markt ändert, und das ausgelöste Handelssignal wird sofort ausgeführt.

Wenn die Pine-Sprachstrategie von links nach rechts auf dem Diagramm ausgeführt wird, werden die K-Linienbalken auf dem Diagramm inHistorical BarsundReal-time Bars:

  • Historische Kneipe

    Wenn die Strategie auf Tick Model gesetzt ist und beginnt zu exekutieren, alle K-Linie Bars auf dem Diagramm außer dem rechtsesten sindHistorical Bars. Die Strategie Logik wird nur einmal auf jedem ausgeführthistorical bar- Ich weiß nicht. Wenn die Strategie auf Bar Model eingestellt ist und die Ausführung beginnt, werden alle Balken auf dem Diagrammhistorical bars. Die Strategie Logik wird nur einmal auf jedem ausgeführthistorical bar.

    Berechnung auf der Grundlage historischer Bars: Der Strategie-Code wird einmal im Schließzustand der historischen Bar ausgeführt, und dann wird der Strategie-Code in der nächsten historischen Bar ausgeführt, bis alle historischen Bars einmal ausgeführt werden.

  • Bar in Echtzeit

    Wenn die Strategie bis zur letzten K-Linienbalke ganz rechts ausgeführt wird, ist die Balke eine Echtzeitbalke. Nachdem die Echtzeitbalke geschlossen ist, wird die Balke zu einer überschrittenen Echtzeitbalke (wird zu einer historischen Balke). Eine neue Echtzeitbalke wird ganz rechts im Chart generiert.

    Wenn die Strategie auf Tick Model eingestellt ist und mit der Ausführung beginnt, wird die Strategie-Logik für jede Marktänderung in Echtzeitbar einmal ausgeführt. Wenn die Strategie auf Bar Model eingestellt ist und mit der Ausführung beginnt, wird die Echtzeitleiste nicht auf dem Diagramm angezeigt.

    Berechnung auf Basis von Echtzeit-Bar: Wenn die Strategie auf Bar Model eingestellt ist und das Diagramm die Echtzeitbalken nicht anzeigt, wird der Strategiecode nur einmal ausgeführt, wenn die aktuelle Balke geschlossen wird. Wenn die Strategie auf Tick Model eingestellt ist, unterscheidet sich die Berechnung auf der Echtzeitleiste vollständig von der historischen Leiste, und der Strategiecode wird für jede Marktänderung auf Live-Handelsleisten einmal ausgeführt.high, low, closeDiese Daten werden in Echtzeit berechnet und werden in Echtzeit berechnet. Auf einer Echtzeit-Bar können sich diese Werte jedes Mal ändern, wenn sich der Markt in Echtzeit-Bars ändert.closestets den aktuellen letzten Preis darstellt undhighundlowDiese eingebauten Variablen stellen den Endwert des Echtzeitbalkens dar, als er zuletzt aktualisiert wurde.

    Rollback-Mechanismus bei der Ausführung von Strategien in Echtzeit Bar (Echtzeit-Preismodell): Während der Echtzeit-Bar-Ausführung wird das Zurücksetzen benutzerdefinierter Variablen vor jeder neuen Iteration der Strategie als Rollback bezeichnet.

    Aufmerksamkeit:

    /*backtest 
    ...
    ..
    .
    */
    

    Der Inhalt des Pakets ist die in Form eines Codes auf der FMZ-Plattform gespeicherte Backtest-Konfigurationsinformation.

    /*backtest
    start: 2022-06-03 09:00:00
    end: 2022-06-08 15:00:00
    period: 1m
    basePeriod: 1m
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
    
    var n = 0
    if not barstate.ishistory
        runtime.log("before n + 1, n:", n, " current bar_index:", bar_index)
        n := n + 1
        runtime.log("after n + 1, n:", n, " current bar_index:", bar_index)
      
    plot(n, title="n")
    

    img

Wir untersuchen nur die Szene während Echtzeit Bars ausgeführt, so dass wir dienot barstate.ishistoryAusdruck, um die Akkumulation der Variablen n nur in der Echtzeit-Bar zu begrenzen, undruntime.logFunktion zur Ausgabe der Informationen im Strategieprotokoll vor und nach dem Akkumulationsvorgang.plot, kann man sehen, dass n immer 0 ist, wenn die Strategie in historischen Bars ausgeführt wird. Wenn die Echtzeit-Bar ausgeführt wird, wird die Operation der Hinzufügung von 1 zu n ausgelöst, und die Operation der Hinzufügung von 1 zu n wird ausgeführt, wenn die Strategie in jeder Runde der Echtzeit-Bar ausgeführt wird. Aus der Log-Nachricht kann beobachtet werden, dass n auf den Wert zurückgesetzt wird, der von der vorherigen Bar-Ausführungsstrategie endgültig eingereicht wurde, wenn der Strategie-Code in jeder Runde erneut ausgeführt wird. Die n-Wert-Aktualisierung wird eingereicht, wenn der Strategie-Code zum letzten Mal auf der Echtzeit-Bar ausgeführt wird, so dass Sie sehen können, dass der Wert der Kurve n mit jeder Erhöhung von Bar um 1 steigt, die von der Echtzeit-Bar auf dem Diagramm beginnt.

Zusammenfassung:

  1. Der Strategiecode wird jedes Mal ausgeführt, wenn der Markt aktualisiert wird, wenn die Strategie in Echtzeit ausgeführt wird.
  2. Bei der Ausführung in Echtzeit-Bar werden die Variablen jedes Mal zurückgerollt, bevor der Strategiecode ausgeführt wird.
  3. Wenn die Variablen in Echtzeit ausgeführt werden, werden sie bei der Aktualisierung des Closings nur einmal eingereicht.

Aufgrund des Daten-Rollbacks können Zeichnungsvorgänge wie Kurven auf dem Diagramm auch zu einer Neuaufzeichnung führen.

var n = 0
if not barstate.ishistory
    runtime.log("before n + 1, n:", n, " current bar_index:", bar_index)
    n := open > close ? n + 1 : n
    runtime.log("after n + 1, n:", n, " current bar_index:", bar_index)
  
plot(n, title="n")

Bildschirmaufnahme der Zeit Aimg

Bildschirmaufnahme der Zeit Bimg

Wir haben nur den Satz geändert:n := open > close ? n + 1 : n, nur 1 zu n hinzufügen, wenn die aktuelle Echtzeit-Bar eine negative Linie ist (d. h. der Eröffnungspreis höher ist als der Schlusskurs). Es kann gesehen werden, dass im ersten Diagramm (Zeit A), da der Eröffnungspreis zu diesem Zeitpunkt höher als der Schlusskurs (negative Linie) war, n um 1 angesammelt wurde und der Wert von n auf der Chartkurve 5 war. Dann änderte sich der Markt und der Preis wurde wie im zweiten Diagramm (Zeit B) angezeigt aktualisiert. Zu diesem Zeitpunkt ist der Eröffnungspreis niedriger als der Schlusskurs (positive Linie) und der n-Wert rollt zurück, ohne um 1 zu steigen. Die Kurve von n im Diagramm wird ebenfalls sofort neu gezeichnet, und der Wert von n auf der Kurve ist 4. Daher sind die Signale, wie Crossup und Crossdown, die in Echtzeit-Bars angezeigt werden, unsicher und können sich ändern.

  • Variabler Kontext in Funktionen

    Lassen Sie uns die Variablen in der Pine-Sprachfunktion zusammen studieren. Gemäß einigen Beschreibungen in Pine-Tutorials haben die Variablen in der Funktion folgende Unterschiede zu den Variablen außerhalb der Funktion:

    Die Historie der in der Funktion Pine verwendeten Serienvariablen wird bei jedem aufeinanderfolgenden Aufruf der Funktion erstellt. Wenn die Funktion nicht auf jeder Stange aufgerufen wird, auf der das Skript ausgeführt wird, führt dies zu einer Diskrepanz zwischen den historischen Werten der Serie innerhalb und außerhalb des lokalen Blocks der Funktion. Wenn daher die Funktion nicht auf jeder Stange aufgerufen wird, beziehen sich die innerhalb und außerhalb der Funktion referenzierten Reihen mit dem gleichen Indexwert nicht auf den gleichen historischen Punkt.

    Wir werden es mit einem Testcode herausfinden, der auf FMZ läuft:

    /*backtest
    start: 2022-06-03 09:00:00
    end: 2022-06-08 15:00:00
    period: 1m
    basePeriod: 1m
    exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
    */
      
    f(a) => a[1]
    f2() => close[1]  
    
    oneBarInTwo = bar_index % 2 == 0
    plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")   
    plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")   
    plot(close[2], title = "close[2]", color = color.red, overlay = true)
    plot(close[1], title = "close[1]", color = color.green, overlay = true)
    

    Bildschirmfoto des Backtest-Führens

    img

    Der Testcode ist relativ einfach und dient hauptsächlich der Untersuchung der Daten, auf die mit zwei Methoden verwiesen wird, nämlich:f(a) => a[1]undf2() => close[1].

    • f(a) => a[1]: Mit der Methode der Übergabe von Parametern kehrt die Funktion zua[1] finally.

    • f2() => close[1]: Verwenden Sie die eingebaute Variableclosedirekt und die Funktion kehrt zuclose[1] finally.

Die[]Das Symbol wird verwendet, um auf den historischen Wert der Datenreihe zu verweisen, und close[1] bezieht sich auf die Schlusskursdaten auf der Bar vor dem aktuellen Schlusskurs.

  • plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")Zeichnen Sie ein Zeichen A, die Farbe ist rot, es wird gezogen, wenn oneBarInTwo wahr ist, und die gezeichnete Position (auf der Y-Achse) ist: der Wert, der vonf(close).

  • plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")Zeichnen Sie ein Zeichen B, die Farbe ist grün, es wird nur gezogen, wenn oneBarInTwo wahr ist, und die gezeichnete Position (auf der Y-Achse) ist: der Wert, der vonf2().

  • plot(close[2], title = "close[2]", color = color.red, overlay = true)Zeichnen Sie eine Linie, die Farbe ist rot, und die gezeichnete Position (auf der Y-Achse) ist:close[2], der der Schlusskurs des zweiten Balkens vor dem aktuellen Balken ist (bei Zählung von 2 Balken links).

  • plot(close[1], title = "close[1]", color = color.green, overlay = true)Zeichnen Sie eine Linie, die Farbe ist grün, und die gezeichnete Position (auf der Y-Achse) ist:close[1], der der Schlusskurs des ersten Balkens vor dem aktuellen Balken ist (mit 1 Balken nach links gezählt).

Aus dem Screenshot des Strategie-Backtesting ist zu sehen, dass zwar sowohl die Funktionf(a) => a[1]verwendet, um den A-Marker und die Funktion zu zeichnenf2() => close[1]Die Markerposition von A und B auf dem Diagramm unterscheidet sich völlig. Die Position des A-Marker fällt immer auf die rote Linie, die die Linie ist, die der Code in der Strategie zeichnet.plot(close[2], title = "close[2]", color = color.red, overlay = true), die Daten zur Zeichnung der Linie sindclose[2].

img

Der Grund ist zu berechnen, ob die A und B Marker durch den Index der K-Line Bar, dh die eingebaute Variable zu ziehenbar_indexDie A und B Marker werden nicht auf jeder K-Linienbalke gezogen (die Funktionsberechnung wird beim Zeichnen aufgerufen).f(a) => a[1]wird nicht gleich dem von der Funktion angegebenen Wert seinf2() => close[1]wenn die Funktion nicht auf jedem Bar aufgerufen wird (auch wenn beide den gleichen Index verwenden wie [1]).

  • Einige eingebaute Funktionen müssen auf jedem Bar berechnet werden, um ihre Ergebnisse richtig zu berechnen

    Um diese Situation mit einem einfachen Beispiel zu veranschaulichen:

    res = close > close[1] ? ta.barssince(close < close[1]) : -1
    plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)
    

    Wir schreiben den Funktionscode.ta.barssince(close < close[1])in einem ternären Operatorcondition ? value1 : value2. Dadurch wird die Ta.barssince-Funktion nur dann aufgerufen, wennclose > close[1]Aber dieta.barssinceFunktion ist es, die Anzahl der K-Linien seit dem letzten Mal zu berechnenclose < close[1]Wenn die Funktion ta.barssince aufgerufen wird, ist sie immer close > close[1], das heißt, der aktuelle Schlusskurs ist größer als der Schlusskurs des vorherigen Bar. Wenn die Funktion ta.barssince aufgerufen wird, wird die Bedingung close < close [1] nicht festgelegt und es gibt keine aktuelle Position, an der sie stattfindet.

    ta.barssince: Bei Aufruf gibt die Funktion na zurück, wenn die Bedingung noch nie vor der aktuellen K-Zeile erfüllt wurde.

Wie in der Tabelle gezeigt:

img

Wenn also das Diagramm gezeichnet wird, werden nur die Daten mit einem Wert für die Res-Variable (-1) gezeichnet.

Um dieses Problem zu vermeiden, nehmen wir einfach dieta.barssince(close < close[1])Funktion aus dem ternären Operator aufrufen und schreiben Sie es außerhalb aller möglichen bedingten Zweige, so dass es Berechnungen auf jeder K-Line Bar durchführen.

a = ta.barssince(close < close[1])
res = close > close[1] ? a : -1
plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)

Zeitreihen

Das Konzept der Zeitreihe ist in der Pine-Sprache sehr wichtig, und es ist ein Konzept, das wir verstehen müssen, wenn wir die Pine-Sprache lernen. Zeitreihe ist kein Typ, sondern eine grundlegende Struktur für die Speicherung kontinuierlicher Werte von Variablen im Laufe der Zeit. Wir wissen, dass Pine-Skripte auf Diagrammen basieren, und der grundlegendste Inhalt, der im Diagramm angezeigt wird, ist das K-Liniendiagramm. Zeitreihe, bei der jeder Wert mit einem Zeitstempel einer K-Linienbalke verknüpft ist.openist eine eingebaute Variable (eingebaute) der Pine-Sprache, und ihre Struktur besteht darin, die Zeitreihe des Eröffnungspreises jedes K-Line Bar zu speichern.openrepräsentiert die Eröffnungspreise aller K-Line Bars von der ersten Bar am Anfang des aktuellen K-Line-Charts bis zur Bar, wo das aktuelle Skript ausgeführt wird.openWenn Sie sich auf historische Werte in einer Zeitreihe beziehen möchten, müssen Sie die[]Wenn die Pine-Strategie auf einem bestimmten K-Line-Bar ausgeführt wird, verwendenopen[1]der Eröffnungspreis des vorherigen K-Linienbalkens (d. h. der Eröffnungspreis des vorherigen K-Linienzeitraums), der sich auf dieopenZeitreihe, auf der dieses K-Linienzeichen gerade vom Skript ausgeführt wird.

  • Variablen auf Zeitreihen sind sehr praktisch für die Berechnung Nehmen wir die eingebaute Funktion.ta.cumZum Beispiel:

    ta.cum
    
    Cumulative (total) sum of `source`. In other words it's a sum of all elements of `source`.
    ta.cum(source) → series float
    RETURNS
    Total sum series.
    ARGUMENTS
    source (series int/float)
    SEE ALSO
    math.sum
    

    Prüfcode:

    v1 = 1
    v2 = ta.cum(v1)
    plot(v1, title="v1")
    plot(v2, title="v2")
    plot(bar_index+1, title="bar_index")
    

    Es gibt viele eingebaute Funktionen wieta.cumDas ist ein System, das Daten über Zeitreihen direkt verarbeiten kann.ta.cumist die Akkumulation der Werte, die den Variablen entsprechen, die auf jeder K-Linienbalke übergeben werden, und als nächstes verwenden wir ein Diagramm, um es einfacher zu verstehen.

    Strategiebetriebsprozess Eingebettete Variable bar_index V1 V2
    Die Strategie läuft auf der ersten K-Line Bar 0 1 1
    Die Strategie läuft auf der zweiten K-Line Bar 1 1 2
    Die Strategie läuft auf der dritten K-Line Bar 2 1 3
    Die Strategie läuft auf der N + 1 K-Linienleiste N 1 N+1

    Es kann gesehen werden, dass v1, v2 und sogar bar_index alle Zeitreihenstrukturen sind, und es gibt entsprechende Daten für jeden Balken. Ob der Testcode das Bar-Modell oder das Tick-Modell verwendet, der einzige Unterschied besteht darin, ob die Echtzeit-Bar auf dem Diagramm angezeigt wird. Für einen schnellen Backtest verwenden wir das Tick-Modell zum Testen.

    img

    Weil die Variable v1 ist 1 auf jedem Bar, wenn dieta.cum(v1)Wenn die Funktion auf der ersten K-Linie Bar ausgeführt wird, gibt es nur die erste Bar, so dass das Berechnungsresultat 1 ist und der Variablen v2 zugeordnet wird. Wann?ta.cum(v1)Wenn die Berechnung auf der zweiten K-Linie Bar ausgeführt wird, gibt es bereits 2 K-Linie Bars (die eingebaute Variable bar_index, die der ersten entspricht, ist 0, und die zweite, die der eingebauten Variable bar_index entspricht, ist 1), so dass das Berechnungsresultat 2 ist, das der Variable v2 zugeordnet wird, und so weiter.bar_indexwird von 0 erhöht, dannbar_index + 1Wir können auch sehen, dass die Linienv2undbar_indexSie überschneiden sich tatsächlich.

    img

    Auch ich kann dieta.cumIch habe eine eingebaute Funktion, um die Summe der Schlusskurs für alle Bars auf dem aktuellen Diagramm zu berechnen.ta.cum(close), Wenn die Strategie auf die Echtzeit-Bar in der äußersten rechten Seite läuft, wird das Ergebnis berechnet durchta.cum(close)ist die Summe der Schlusskurse aller Balken auf dem Diagramm (wenn sie nicht nach rechts läuft, wird sie nur bis zum aktuellen Balken angesammelt).

    Variablen der Zeitreihen können auch mit Hilfe von Operatoren berechnet werden, z. B. mit dem Code:ta.sma(high - low, 14), subtrahieren Sie die eingebaute Variablehigh(der höchste Preis der K-Line Bar) vonlow(der niedrigste Preis von K-Line Bar), und schließlich dieta.smaFunktion zur Berechnung des Durchschnittswerts.

  • Das Ergebnis eines Funktionsanrufs hinterlässt auch Spuren von Werten in der Zeitreihe.

    v1 = ta.highest(high, 10)[1]
    v2 = ta.highest(high[1], 10)
    plot(v1, title="v1", overlay=true)
    plot(v2, title="v2", overlay=true)
    

    Der Testcode wird während des Backtests ausgeführt, und es kann beobachtet werden, daß die Werte vonv1undv2Das Ergebnis, das durch den Funktionsanruf berechnet wird, hinterlässt Spuren des Wertes in der Zeitreihe, wie z.B. dieta.highest(high, 10)in dem Codeta.highest(high, 10)[1]Das durch den Funktionsruf berechnete Ergebnis kann auch [1] verwendet werden, um sich auf seinen historischen Wert zu beziehen.ta.highest(high, 10)entspricht dem vorherigen Balken des aktuellen Balkens, ist das Berechnungsergebnista.highest(high[1], 10)Also...ta.highest(high[1], 10)undta.highest(high, 10)[1]sind exakt gleichwertig.

    Verwenden Sie eine andere Zeichnungsfunktion zur Ausgabe der Informationsüberprüfung:

    a = ta.highest(close, 10)[1]
    b = ta.highest(close[1], 10)
    plotchar(true, title="a", char=str.tostring(a), location=location.abovebar, color=color.red, overlay=true)
    plotchar(true, title="b", char=str.tostring(b), location=location.belowbar, color=color.green, overlay=true)
    

    Wir können sehen, dass die Werte der Variablen a und b in der Zeitreihe über und unter den entsprechenden Bars angezeigt werden. Wir können diesen Zeichnungscode während des Lernprozesses behalten, da wir oft Informationen auf dem Diagramm für Beobachtungen während des Backtests und des Experimentierens ausgeben müssen.

    img

Skriptstruktur

Allgemeine Struktur

Im Anfangsteil des Tutorials haben wir einige Unterschiede bei der Verwendung der Pine-Sprache auf FMZ und Trading View zusammengefasst.indicator(), strategy(), undlibrary()Natürlich, um mit früheren Versionen von Pine-Skripten kompatibel zu sein, müssen Strategien wie://@version=5, indicator(), strategy()Einige Strategie-Einstellungen können auch eingestellt werden, indem Parameter in diestrategy() function.

<version>
<declaration_statement>
<code>

Die<version>Versionskontrollinformationen können weggelassen werden.

Anmerkungen

Die Kiefersprache verwendet//als ein einzeliges Kommentarzeichen, da die Pine-Sprache kein mehrzeliges Kommentarzeichen hat. FMZ erweitert das Kommentarzeichen/**/für mehrzeilige Kommentare.

Code

Zeilen im Skript, die keine Kommentare oder Compilerrichtlinien sind, sind Anweisungen, die den Algorithmus des Skript implementieren.

  • Variable Angabe
  • Umzuweisung von Variablen
  • Funktionserklärung
  • Eingebaute Funktionsanrufe, benutzerdefinierte Funktionsanrufe
  • if, for, whileoderswitchStruktur

Die Auskünfte können auf verschiedene Weise angeordnet werden

  • Einige Anweisungen können in einer Zeile ausgedrückt werden, wie z. B. die meisten Variablendeklarationen, Zeilen, die nur einen Funktionsanruf enthalten, oder einzeilige Funktionsdeklarationen. Andere, wie Strukturen, erfordern immer mehrere Zeilen, weil sie einen lokalen Block erfordern.
  • Anweisungen im globalen Bereich eines Skripts (d. h. Teile, die nicht Teil eines lokalen Blocks sind) können nicht mit einemspaceoder ```tab` (Tab-Taste). Ihr erster Zeichen muss auch der erste Zeichen der Zeile sein. Zeilen, die an der ersten Position beginnen, werden per Definition Teil des globalen Bereichs des Skriptes.
  • Eine Struktur- oder mehrzeilige Funktionserklärung erfordert immer einelocal blockEin lokaler Block muss durch einen Tab oder vier Leerzeichen eingelegt werden (andernfalls wird er als der verknüpfte Code der vorherigen Zeile analysiert, d.h. als der kontinuierliche Inhalt der vorherigen Zeile beurteilt), und jeder lokale Block definiert einen anderen lokalen Bereich.
  • Mehrere Einzeilinienaussagen können mit Kommas (,) als Trennzeichen in einer Zeile verknüpft werden.
  • Eine Zeile kann Kommentare enthalten oder nur Kommentare haben.
  • Linien können auch verpackt werden (auf mehreren Linien fortgesetzt).

Zum Beispiel enthält es drei lokale Blöcke, einen in der kundenspezifischen Funktionsdeklaration und zwei in der Variablendeklaration mit der if-Struktur, wie folgt:

indicator("", "", true)             // declaration statement (global scope), can be omitted

barIsUp() =>                        // function declaration (global scope)
    close > open                    // local block (local scope)

plotColor = if barIsUp()            // variable declaration (global scope)
    color.green                     // local block (local scope)
else
    color.red                       // local block (local scope)

runtime.log("color", color = plotColor)  // Call a built-in function to output the log (global scope)

Zeilenbrechungscode

Lange Linien können über mehrere Linien aufgeteilt oder umwickelt werden. Eine umwickelte Linie muss durch eine beliebige Anzahl von Leerzeichen eingelegt werden, solange sie nicht ein Vielfaches von 4 ist (diese Grenzen werden verwendet, um lokale Blöcke einzulegen).

a = open + high + low + close

Es kann so verpackt werden (beachten Sie, dass die Anzahl der durchgeschlagenen Leerzeichen pro Zeile kein Vielfaches von 4 sein kann):

a = open +
      high +
          low +
             close

Ein langer Plot ((() Anruf kann wie folgt verpackt werden:

close1 = request.security(syminfo.tickerid, "D", close)      // syminfo.tickerid daily level closing price data series for the current trading pair
close2 = request.security(syminfo.tickerid, "240", close)    // syminfo.tickerid 240-minute level closing price data series for the current trading pair
plot(ta.correlation(close, open, 100),                       // line-long plot() calls can be wrapped
   color = color.new(color.purple, 40),
   style = plot.style_area,
   trackprice = true)

Behauptungen in benutzerdefinierten Funktionsdeklarationen können ebenfalls eingewürft werden. Da jedoch ein lokaler Block mit einer Einzugslösung in der Grammatik (4 Leerzeichen oder 1 Tab) beginnen muss, muss die Fortsetzung einer Behauptung bei der Aufteilung auf die nächste Zeile mit mehr als einer Einzugslösung beginnen (nicht gleich 4 Vielfachen von Leerzeichen). Zum Beispiel:

test(c, o) =>
    ret = c > o ?
       (c > o+5000 ? 
          1 :
              0):
       (c < o-5000 ? 
          -1 : 
              0)
           
                   
a = test(close, open)
plot(a, title="a")

Marker und Betreiber

Markierungen

Bevor wir Variablen erkennen, müssen wir zuerst das Konzept von Marker verstehen.FunktionundVariable(verwendet, um Variablen und Funktionen zu benennen).FunktionenWir werden in unseren späteren Tutorials sehen, lassen Sie uns zuerst etwas über Marker lernen.

    1. Markierungen müssen mit einem Großbuchstaben beginnen.(A-Z)oder kleinbuchstaben(a-z)Brief oder Unterstriche(_)als erstes Zeichen des Marker.
    1. Das nächste Zeichen nach dem ersten Zeichen eines Marker kann einSchreiben, Unterstreichen, oderZahl.
    1. Die Benennung von Markern ist groß- und kleinfühlig.

Wie beispielsweise folgende benannte Marker:

fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown  // Wrong naming! It used a numeric character as the leading character of the marker

Wie die meisten Programmiersprachen hat auch die Pine-Sprache Schreibvorschläge.

    1. Alle Großbuchstaben werden verwendet, um Konstanten zu benennen.
    1. VerwendenUnterer Kamelkastenfür andere Markernamen.
// name variables, constants
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7

// name functions
zeroOne(boolValue) => boolValue ? 1 : 0

Betreiber

Operatoren sind einige Operationssymbole, die in Programmiersprachen verwendet werden, um Ausdrücke zu konstruieren, und Ausdrücke sind Rechenregeln, die für bestimmte Rechenzwecke entwickelt wurden, wenn wir Strategien schreiben.

Zuweisungsoperatoren, arithmetische Operatoren, Vergleichsoperatoren, logische Operatoren,? :Drittlandbetreiber,[]historische Referenzoperatoren.

Die Arithmetikoperatoren nehmen*als Beispiel unterscheidet es sich von dem Typproblem, das durch das Rückgabeergebnis des Pine-Sprachoperators in der Trading View verursacht wird. Der folgende Testcode wird bereitgestellt:

//@version=5
indicator("")
lenInput = input.int(14, "Length")
factor = year > 2020 ? 3 : 1
adjustedLength = lenInput * factor
ma = ta.ema(close, adjustedLength)  // Compilation error!
plot(ma)

Bei der Ausführung dieses Skripts in der Trading View tritt ein Kompilierungsfehler auf.adjustedLength = lenInput * factorDas Ergebnis ist:series intTyp (Serie), aber der zweite Parameter der Funktionta.emaAber es gibt keine solchen strengen Einschränkungen für FMZ, der obige Code kann normal ausgeführt werden.

Lassen Sie uns die Verwendung verschiedener Operatoren zusammen betrachten.

Zuweisungsbetreiber

Es gibt zwei Arten von Zuweisungsoperatoren:=, :=, die wir in mehreren Beispielen am Anfang des Tutorials gesehen haben.

Die=Variablen, die mit einer Variablen initialisiert, deklariert und zugewiesen werden=Dies sind gültige Variablerdeklarationen:

a = close           // Use built-in variables to assign values to a
b = 10000           // Use numerical assignment
c = "test"          // Use string assignment
d = color.green     // Use color value assignment
plot(a, title="a")
plot(b, title="b")
plotchar(true, title="c", char=str.tostring(c), color=d, overlay=true)

Beachten Sie, dass die Zuweisunga = close, ist die Variable a für jeden Bar der aktuelle Schlusskurs (Schlusskurs) des Bar. Sonstige Variablenb, c, dsind unverändert und können im Backtestsystem auf FMZ getestet werden, wobei die Ergebnisse auf der Tabelle zu sehen sind.

:=Es kann einfach verstanden werden, dass die:=Der Operator wird verwendet, um die Werte von Variablen zu ändern, die deklariert und initialisiert wurden. Wenn wir die:=Wenn der Operator einen Wert einer nicht initialisierten oder deklarierten Variablen zuweist, verursacht er einen Fehler, zum Beispiel:

a := 0

Daher ist die:=der Zuweisungsoperator wird im Allgemeinen verwendet, um vorhandene Variablen neu zuzuweisen, z. B.:

a = close > open 
b = 0 
if a
    b := b + 1

plot(b)

Beurteilen, obclose > openDer Code im lokalen Block der if-Anweisung ist der Code, der in der Anweisung verwendet wird.b := b + 1wird ausgeführt, und der Zuordnung Operator:=Wir verwenden dann die Plot-Funktion, um den Wert der Variablen b auf jede BAR der Zeitreihen auf dem Diagramm zu ziehen und sie in eine Linie zu verbinden.

Wir denken, dass wenn eine positive Linie BAR erscheint, b sich weiterhin um 1 ansammeln wird? Natürlich nicht, hier erklären und initialisieren wir die Variable b als 0 ohne Schlüsselwortbezeichnung.b=0Wir können also sehen, dass das Ergebnis dieses Codes darin besteht, die Variable b jedes Mal auf 0 zurückzusetzen, wenn die Variable a wahr ist, d.h. im Einklang mitclose > open, dann wird b um 1 erhöht, wenn der Code in dieser Runde ausgeführt wird, und b ist 1 wenn die Plot-Funktion zieht, aber b wird bei der Ausführung des Codes in der nächsten Runde auf 0 neu zugewiesen.

Wenn es um Zuweisungsoperatoren geht, müssen wir zwei Schlüsselwörter erweitern:var, varip

  • Ver-

    In der Tat haben wir dieses Schlüsselwort in früheren Tutorials gesehen und verwendet, aber wir haben es damals nicht ausführlich diskutiert.

    var ist ein Schlüsselwort, das zur Zuordnung und einmaligen Initialisierung von Variablen verwendet wird. Im Allgemeinen führt die Variablenzuweisungsgrammatik, die das Schlüsselwort var nicht enthält, dazu, dass der Variablenwert jedes Mal überschrieben wird, wenn die Daten aktualisiert werden. Im Gegensatz dazu können Variablen, die mit dem Schlüsselwort var zugewiesen werden, trotz Datenaktualisierungen zustand behalten.

    Wir verwenden immer noch dieses Beispiel, aber wir verwenden dievarSchlüsselwort bei der Zuweisung eines Wertes an b hier.

    a = close > open 
    var b = 0 
    if a
        b := b + 1
    
    plot(b)
    

    DievarDas Schlüsselwort erlaubt der Variablen b, nur die anfängliche Zuordnung auszuführen, und dann wird sie b nicht jedes Mal, wenn die Strategie-Logik ausgeführt wird, auf 0 zurücksetzen, so dass aus der Linie, die zur Laufzeit gezogen wurde, beobachtet werden kann, dass b die Anzahl der positiven Linien-BARs ist, die erschienen sind, wenn die aktuelle K-Linie-BAR zurück getestet wurde.

    Variablen, die von var deklariert werden, können nicht nur im globalen Bereich geschrieben werden, sondern auch in Codeblöcken, wie in diesem Beispiel:

    strategy(overlay=true)
    var a = close
    var b = 0.0
    var c = 0.0
    var green_bars_count = 0
    if close > open
        var x = close
        b := x
        green_bars_count := green_bars_count + 1
        if green_bars_count >= 10
            var y = close
            c := y
    plot(a, title = "a")
    plot(b, title = "b")
    plot(c, title = "c")
    

    Die Variable a enthält den Schlusskurs des ersten Balkens der Reihe. Die Variable b enthält den Schlusskurs der ersten grünen Preisleiste in der Reihe. Die Variable c enthält den Schlusskurs des zehnten grünen Balkens in der Reihe.

  • Variation

    Wir sehen das SchlüsselwortvaripZum ersten Mal können wir uns die Beschreibung dieses Schlüsselworts ansehen:

    varip (var intrabar persist) ist ein Schlüsselwort für die Zuordnung und einmalige Initialisierung von Variablen.

    Ist es schwierig zu verstehen? Es spielt keine Rolle, wir erklären es durch ein Beispiel, es ist leicht zu verstehen.

    strategy(overlay=true)
    
    // test var varip
    var i = 0
    varip ii = 0  
    
    // Print the i and ii changed in each round of the strategy logic on the chart
    plotchar(true, title="ii", char=str.tostring(ii), location=location.abovebar, color=color.red)
    plotchar(true, title="i", char=str.tostring(i), location=location.belowbar, color=color.green)  
    
    // Increment i and ii by 1 for each round of logic execution
    i := i + 1
    ii := ii + 1
    

    Dieser Testcode hat unterschiedliche Leistungen auf Bar-Modell und Tick-Modell:

    Strichmodell: Erinnern Sie sich, dass die Strategie-Ausführung, die wir früher erklärt in historische BAR-Stufe und Echtzeit-BAR-Stufe unterteilt ist?i, iiin dervar, varipEs kann daher gesehen werden, dass die auf der K-Linie BAR des Backtest-Ergebnisses angezeigten Zahlen um 1 nach einem erhöht werden. Wenn die historische K-Linie-Stufe endet, beginnt die Echtzeit-K-Linie-Stufe. Die von var und varip deklarierten Variablen beginnen unterschiedliche Veränderungen zu erleiden. Da es sich um ein Barmodell handelt, wird der Strategie-Code für jede Preisänderung in einer K-Linie BAR einmal ausgeführt.i := i + 1undii := ii + 1Der Unterschied besteht darin, dass ii jedes Mal geändert wird. Obwohl i jedes Mal geändert wird, wird der vorherige Wert wiederhergestellt, wenn die Strategie-Logik in der nächsten Runde ausgeführt wird (erinnern Sie sich an den Rollback-Mechanismus, den wir im vorherigen Kapitel Model Execution erklärt haben?), und der Wert von i wird nicht aktualisiert, bis die aktuelle K-Linie BAR abgeschlossen ist (dh der vorherige Wert wird nicht wiederhergestellt, wenn die Strategie-Logik in der nächsten Runde ausgeführt wird).

    Tick-Modell: Da das Tick-Modell die Strategie-Logik nur einmal pro K-Line BAR ausführt, verhalten sich die durch var und varip deklarierten Variablen im Schlusskursmodell im obigen Beispiel genau gleich, wobei sie für jede K-Line BAR während der historischen K-Line-Phase und der Echtzeit-K-Line-Phase um 1 zunehmen.

Arithmetische Operatoren
Betreiber Beschreibung
+ Ergänzung
- Subtraktion
* Multiplikation
/ Abteilung
% Modul

Die+und-Andere arithmetische Operatoren können nur als binäre Operatoren verwendet werden und es wird einen Fehler melden, wenn es als unare Operatoren verwendet wurde.

  1. Beide Seiten des arithmetischen Operators sind numerischer Typ, das Ergebnis ist je nach Ergebnis der Operation ein numerischer Typ, eine ganze Zahl oder ein Gleitkomma.
  2. Wenn einer der Operanden eine Zeichenfolge ist und der Operator+, das Ergebnis der Berechnung ist eine Zeichenfolge, der Wert wird in die Zeichenfolgeform umgewandelt, und dann werden die Zeichenfolge zusammengefügt. Wenn es sich um einen anderen arithmetischen Operator handelt, wird versucht, die Zeichenfolge in einen Wert umzuwandeln und dann die Operation fortzuführen.
  3. Wenn einer der Operanden na ist, ist das Ergebnis der Berechnung der Nullwertna, und es wird NaN anzeigen, wenn es auf FMZ gedruckt wird.
a = 1 + 1 
b = 1 + 1.1
c = 1 + "1.1"
d = "1" + "1.1"
e = 1 + na 

runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e)   
// a: 2 , b: 2.1 , c: 11.1 , d: 11.1 , e: NaN

Die Pine-Sprache auf FMZ unterscheidet sich etwas von der Pine-Sprache auf Trading View, die Pine-Sprache auf FMZ ist nicht sehr streng in Bezug auf Variabletypen.

a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A" 

plot(a)
plot(b)
plot(c)

Es funktioniert auf FMZ, meldet jedoch einen Typfehler in der Trading-Ansicht. Wenn beide Operanden des arithmetischen Operators Zeichenfolgen sind, wandelt das System die Zeichenfolgen in numerische Werte um und berechnet sie dann. Wenn eine nicht-numerische Zeichenfolge nicht berechnet werden kann, ist das Ergebnis der Systemoperation ein Nullwertna.

Vergleichsoperatoren

Die Vergleichsoperatoren sind alle binäre Operatoren.

Betreiber Beschreibung
< <
> >
<= <=
>= >=
== ==
!= !=

Prüfbeispiel:

a = 1 > 2 
b = 1 < 2 
c = "1" <= 2 
d = "1" >= 2 
e = 1 == 1 
f = 2 != 1 
g = open > close 
h = na > 1 
i = 1 > na

runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e, ", f:", f, ", g:", g, ", h:", h, ", i:", i)   
// a: false , b: true , c: true , d: false , e: true , f: true , g: false , h: false , i: false

Wie wir sehen können, ist der Vergleichsoperator sehr einfach zu bedienen, aber dies ist auch der Operator, den wir am häufigsten verwenden, wenn wir Strategien schreiben.close, open, usw. Wie bei dem Betreiber gibt es einen Unterschied bezüglich der Pine-Sprache zwischen FMZ und Trading View.d = "1" >= 2wird keinen Fehler auf FMZ melden, und es wird ausgeführt, indem die Zeichenfolge zuerst in einen Wert umgewandelt und dann die Operation verglichen wird.

Logische Operatoren
Betreiber Codezeichen Beschreibung
- Nein. - Nein. Unarer Operator, nicht Operationen
und und Binäre Operatoren und Operationen
oder oder Binäre Operatoren oder Operationen

Wenn es um logische Operatoren geht, dann müssen wir über echte Werte Tabellen sprechen. dasselbe wie wir in der Highschool gelernt haben, hier testen und lernen wir einfach in unserem Backtesting-System:

a = 1 == 1  // An expression formed by using comparison operators, the result is a Boolean value
b = 1 != 1
c = not b   // Logical not operators
d = not a   // Logical not operators

runtime.log("test the logical operator:and", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a and c:", a and c)
runtime.log("a:", a, ", b:", b, ", a and b:", a and b)
runtime.log("b:", b, ", c:", c, ", b and c:", b and c)
runtime.log("d:", d, ", b:", b, ", d and b:", d and b)

runtime.log("test the logical operator:or", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a or c:", a or c)
runtime.log("a:", a, ", b:", b, ", a or b:", a or b)
runtime.log("b:", b, ", c:", c, ", b or c:", b or c)
runtime.log("d:", d, ", b:", b, ", d or b:", d or b)

runtime.error("stop")

Um keine Nachrichten zu überdrucken, wir werfen einen Fehler mit derruntime.error("stop")Danach können wir die Ausgabeinformationen beobachten, und wir können feststellen, dass der gedruckte Inhalt tatsächlich mit der wahren Werttabelle identisch ist.

Tierbetreiber

Ternäre Ausdrücke mit dem ternären Operator? :kombiniert mit Operandencondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseWir haben sie auch in den vorherigen Lektionen benutzt. Der sogenannte ternäre Ausdruck, ternärer Operator bedeutet, dass es drei Operanden gibt.

In dercondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalse, conditionist die Urteilsbedingung. Wenn sie wahr ist, ist der Wert des Ausdrucks:valueWhenConditionIsTrueWenn.conditionist falsch, dann ist der Wert des AusdrucksvalueWhenConditionIsFalse.

Beispiel für eine praktische Demonstration:

a = close > open
b = a ? "positive line" : "negative line"
c = not a ? "negative line" : "positive line"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)

Was tun, wenn wir auf einen Doji stoßen? Es spielt keine Rolle! Ternäre Ausdrücke können auch verschachtelt werden, wie wir es in dem vorherigen Tutorial getan haben.

a = close > open
b = a ? math.abs(close-open) > 30 ? "positive line" : "doji" : math.abs(close-open) > 30 ? "negative line" : "doji"
c = not a ? math.abs(close-open) > 30 ? "negative line" : "doji" : math.abs(close-open) > 30 ? "positive line" : "doji"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)

In Wirklichkeit entspricht es dem Ersatz vonvalueWhenConditionIsTrueundvalueWhenConditionIsFalseincondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalsemit einem anderen dreifachen Ausdruck.

Historischer Betreiber

Verwenden Sie den historischen Operator[]Diese historischen Werte sind die Werte der Variablen auf der K-Linienleiste vor der aktuellen K-Linienleiste, als das Skript ausgeführt wurde.[]Der Operator wird nach Variablen, Ausdrücken und Funktionsanrufen verwendet.[]Wenn ich zum Beispiel den Schlusskurs der letzten K-Line BAR zitieren möchte, schreiben wir es wie folgt:close[1].

Wir haben in den vorherigen Lektionen so etwas gesehen:

high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)

Die[]Der Operator kann nur einmal für denselben Wert verwendet werden, also ist es falsch, ihn so zu schreiben, und ein Fehler wird gemeldet:

a = close[1][2]   // error

Hier könnte jemand sagen, dass der Betreiber[]ist für die Seriestruktur verwendet, scheint es, dass die Seriestruktur (Serie) ist ähnlich wie Array! Lassen Sie uns ein Beispiel verwenden, um den Unterschied zwischen Reihen und Arrays in der Pine-Sprache zu veranschaulichen.

strategy("test", overlay=true)

a = close
b = close[1]
c = b[1]

plot(a, title="a")
plot(b, title="b")
plot(c, title="c")

a = close[1][2]wird einen Fehler melden, aber:

b = close[1]
c = b[1]

Aber wenn es getrennt geschrieben wird, wird es keinen Fehler melden.b = close [1], b sollte ein Wert sein, aberc = b[1], b kann immer noch verwendet werden, um den historischen Wert erneut mit dem History-Operator zu beziehen. Es kann gesehen werden, dass das Konzept der Reihe in der Pine-Sprache nicht so einfach ist wie ein Array. Es kann als der historische Wert auf der letzten Bar von close (zu b zugewiesen) verstanden werden, b ist auch eine Zeitreihenstruktur (Zeitreihen) und seine h


Mehr