Inventor Quantitative PINE Language Einführungs-Tutorial
Video-Tutorials:
Wie schwer ist es, mit dem Trading-View in die Quantifizierungs-Sprache zu kommen?
Die Inventor-Quantitative-Trading-Plattform unterstützt die Programmierung in der Sprache Pine, unterstützt die Rückmeldung, die Real-Time-Betriebsstrategie der Sprache Pine und ist kompatibel mit niedrigeren Versionen der Sprache Pine.StrategieplatzEs gibt eine Vielzahl von Pine-Strategien, die gesammelt und übertragen wurden.
FMZ unterstützt nicht nur die Pine-Sprache, sondern auch die leistungsstarke Diagrammfunktion der Pine-Sprache. Die Funktionen der FMZ-Plattform, die vielfältigen praktischen Tools, die effiziente und einfache Verwaltung, verbessern auch die Funktionalität der Pine-Strategie.
Einige der deutlichsten Unterschiede sind:
-
- Die Pine-Strategie auf der FMZ, Versionskennzeichen am Anfang des Codes
//@versionBeginnt mit dem Codestrategy、indicatorDie Sätze sind nicht obligatorisch und werden von FMZ vorerst nicht unterstützt.importImportierenlibraryFunktion.
Einige der Strategien, die wir sehen können, lauten:
pine//@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 wie es heißt:
pine//@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 der FMZ kann es sich so vereinfachen:
pinesrc = 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:
pinelongCondition = 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) - Die Pine-Strategie auf der FMZ, Versionskennzeichen am Anfang des Codes
-
- Strategie ((Skript) Einige der Transaktions-bezogenen Einstellungen werden durch die Parameter "Pine-Sprache-Trading-Klassenlager" in der FMZ-Strategie-Schnittstelle eingestellt.
-
Schlusskursmodelle und Echtzeit-Preismodelle
In der Trading View können wir durchstrategyFunktioncalc_on_every_tickDie Parameter setzen die Strategie-Skripte, die die Strategie-Logik in Echtzeit bei jeder Preisänderung ausführen, wobeicalc_on_every_tickDie Parameter sollten so eingestellt werden:true◦ Standardcalc_on_every_tickDer Parameter istfalseDas bedeutet, dass die Strategie-Logik nur ausgeführt wird, wenn die aktuelle K-Linie BAR abgelaufen ist.
Auf der FMZ wird die Einstellung über die Parameter der Template "Pine Language Exchange Classroom" vorgenommen. -
Die Präzision von Zahlen wie Preis und Bestellmenge bei der Ausführung der Strategie muss auf der FMZ festgelegt werden.
In der Trading-View gibt es keine Probleme mit der Ordnungs-Genauigkeit, da nur Simulationen möglich sind. In der FMZ ist es möglich, die Pine-Strategie in der Realität auszuführen. Dann ist eine Strategie erforderlich, die die Preisgenauigkeit der Handelsarten und die Ordnungsgrößen flexibel festlegt. Diese Genauigkeits-Einstellungen steuern die kleinen Zahlen der relevanten Daten, um zu vermeiden, dass die Daten nicht den Anforderungen der Börsenanzeige entsprechen, wodurch keine Bestellung möglich ist. -
Code für den Terminkontrakt
Wenn es sich um einen Vertrag handelt, hat die Handelsvariante auf der FMZ zwei Eigenschaften: "Handelspaar" und "Vertragscode". Zusätzlich zur klaren Einstellung des Handelspaares auf dem Display und bei der Rückmeldung muss auch der spezifische Vertragscode in den Parametern "Variety Code" der Pine-Sprach-Handelsbibliothek-Vorlage eingestellt werden.swap, Vertragskodex, je nachdem, ob die Börse, die betrieben wird, einen solchen Vertrag hat. Zum Beispiel können alle Quartalsverträge für einige Geschäfte hier ausgefüllt werdenquarter❚ Die Codes für diese Verträge stimmen mit den Codes für Futures-Verträge überein, die in der Dokumentation der Javascript/python/c++ Language API von FMZ definiert sind.
Weitere Einstellungen, wie z. B. Minimum Order Quantity, Default Order Quantity, etc. finden Sie in der Dokumentation für die Sprache Pine."Pine-Sprachen-Klassenbörse"Einführung in die Parameter
-
3、
runtime.debug、runtime.log、runtime.errorFunktion der FMZ-Erweiterung zum Debuggen <unk>Auf der FMZ-Plattform wurden drei Funktionen für die Debugging hinzugefügt.
-
runtime.debug: Im Allgemeinen kann diese Funktion nicht verwendet werden, um Variablen auf der Steuerung zu drucken. -
runtime.logInhalte in der Log-Ausgabe. FMZ PINE-Sprache spezielle Funktionen.pineruntime.log(1, 2, 3, close, high, ...),可以传多个参数。 -
runtime.error: wird aufgerufen, was zu einem Betriebsfehler führt und die Fehlermeldung mit sich bringt, die in den Message-Parametern angegeben ist.pineruntime.error(message)
-
-
- Teile der Graphik-Funktion erweitert
overlayParameter
Pine-Sprache auf der FMZ, Grafikfunktion
plot、plotshape、plotcharEs gibt noch mehr.overlayParameter-Unterstützung, die es erlaubt, Bilder in der Haupt- oder Untergrafik zu bestimmen.overlayaufstellentrueDas Bild ist in der Hauptkarte, auffalseDie Funktion "Draw in sub-graphs" ermöglicht es, die Hauptgraphie und die Subgraphie gleichzeitig zu zeichnen, wenn die Pine-Strategie auf der FMZ funktioniert. - Teile der Graphik-Funktion erweitert
-
5、
syminfo.mintickVariablen für die eingebauten Variablensyminfo.mintickDie eingebaute Variable ist definiert als die Mindestmessung der aktuellen Sorte. In der FMZFestes Angebot/BacktestingDie Präzision der Preise wird durch die Schablonenparameter in der "Pine Language Trading Classroom" in der Oberfläche gesteuert. Die Präzision der Preise wird mit 2 eingestellt, d. h. der Preis ist auf die zweite Stelle der kleinen Zahl exakt, wenn der Preis mit 0,01 der kleinste Änderung der Einheit handelt.syminfo.mintickDer Wert von <unk> {\displaystyle <unk>} ist 0.01 <unk> {\displaystyle 0.01} -
- Die Durchschnittspreise in FMZ PINE Script sind alle inklusive Gebühren.
Zum Beispiel: Der Auftragswert ist 8000, die Verkaufsrichtung, die Anzahl von 1 Hand ((einfach), der Durchschnittspreis nach dem Abschluss ist nicht 8000, weniger als 8000 ((die Kosten beinhalten die Verfahrensgebühren)).
Grundlagen der Pine-Sprache
Wenn wir anfangen, die Grundlagen der Pine-Sprache zu lernen, sind die Anweisungen in einigen Beispielen und die Code-Grammatik möglicherweise nicht vertraut. Es spielt keine Rolle, dass wir nicht verstehen. Wir können uns zuerst mit den Konzepten vertraut machen, den Testzweck verstehen, oder wir können die Pine-Sprachdokumentation von FMZ einsehen.
Modelldurchführung
Bei der Einführung in die Pine-Sprache ist es sehr notwendig, die entsprechenden Konzepte wie die Ausführung von Pine-Skriptprogrammen zu verstehen. Die Pine-Sprachstrategie kann als eine Reihe von Berechnungen und Vorgängen verstanden werden, die auf einer Grafik in chronologischer Reihenfolge durchgeführt werden, beginnend mit den frühesten Daten, die bereits in der Grafik geladen sind.bar_indexVerweist auf den Indexwert der K-Zeile Bar, die bei Ausführung des Pine-Skriptes aktuell ist.
pine
plot(bar_index, "bar_index")
plotDie Funktion ist eine der Funktionen, die wir in Zukunft am häufigsten verwenden werden.bar_indexDie Linie heißtbar_index。 Die Linie bar_index auf der ersten Bar hat einen Wert von 0 und steigt mit dem Bar-Zuwachs nach rechts um 1。
Das Modell der Strategie wird in unterschiedlicher Weise ausgeführt, je nachdem, wie die Strategie eingerichtet ist.收盘价模型Und实时价模型Die Konzepte von Schlusskursmodellen und Echtzeitkursmodellen haben wir bereits kurz vorgestellt.
-
Schlusskursmodell
Wenn der Strategiecode ausgeführt wird, ist der Zyklus der aktuellen K-Linie-Bar vollständig ausgeführt, und wenn die K-Linie geschlossen wird, ist der K-Linie-Zyklus abgeschlossen. An diesem Punkt wird die Pine-Strategie-Logik ausgeführt, und das ausgelöste Transaktionssignal wird beim Beginn der nächsten K-Linie-Bar ausgeführt.
-
Echtzeit-Preismodell
Wenn der Strategiecode ausgeführt wird, wird die aktuelle K-Linie Bar, unabhängig davon, ob sie geschlossen ist oder nicht, bei jeder Bewegung die Pine-Strategie-Logik ausgeführt, und das ausgelöste Handelssignal wird sofort ausgeführt.
Wenn die Pine-Sprache-Strategie von links nach rechts auf der Grafik ausgeführt wird, wird die K-Linie-Bar auf der Grafik unterteilt in历史BarUnd实时BarDas war's.
-
Geschichte der Bar
Wenn die Strategie als "Real-Time-Price-Modell" eingestellt wird, werden alle K-Linienbars in der Grafik, mit Ausnahme der K-Linienbar auf der rechten Seite, ausgeführt
历史BarStrategische Logik in jeder Wurzel历史BarNur einmal ausgeführt.
Wenn die Strategie als "Endpreismodell" eingestellt ist und die Ausführung beginnt, sind alle Bars auf dem Diagramm历史BarStrategische Logik in jeder Wurzel历史BarNur einmal ausgeführt.Berechnung basierend auf der History Bar:
Der Strategiecode wird einmal in der History Bar ausgeführt, und der Strategiecode wird dann in der nächsten History Bar ausgeführt, bis alle History Bars einmal ausgeführt sind. -
Echtzeit-Bar
Wenn die Strategie auf die letzte K-Zeile Bar rechts durchgeführt wird, ist diese Bar die Echtzeit-Bar. Wenn die Echtzeit-Bar geschlossen wird, wird diese Bar zu einer vergangenen Echtzeit-Bar (in die Historik-Bar umgewandelt). Die rechte Seite des Diagramms erzeugt eine neue Echtzeit-Bar.
Wenn die Strategie als "Echtzeit-Preismodell" eingestellt ist, wird für jede Änderung der Situation in der Echtzeit-Bar eine Strategie-Logik ausgeführt.
Wenn die Strategie als "Endpreismodell" eingestellt ist, wird die Bar in Echtzeit nicht angezeigt, wenn die Ausführung beginnt.Auf Basis der Berechnung von Bar in Echtzeit:
Wenn die Strategie als "Schlusskursmodell" eingestellt ist und die Bar nicht in Echtzeit angezeigt wird, wird der Strategiecode nur einmal beim Schlusskurs der aktuellen Bar ausgeführt.
Wenn die Strategie als "real-time-Price-Modell" eingestellt ist, ist die Berechnung auf der Real-Time-Bar und die Berechnung auf der History-Bar völlig unterschiedlich. Jede Änderung auf der Real-Time-Bar führt einen Strategie-Code aus.high、low、closeIn der historischen Bar sind die Werte fest, in der Echtzeit Bar können sie sich ändern, wenn sich die Situation ändert. Daher können auch die Daten wie die Indikatoren, die auf diesen Werten basieren, in Echtzeit geändert werden.closeEs ist ein sehr interessantes Thema, aber es ist auch ein sehr wichtiges Thema.highUndlowStets die höchsten und niedrigsten Werte seit dem Beginn der aktuellen Live-Bar. Diese eingebauten Variablen stellen die Endwerte der letzten Aktualisierung der Live-Bar dar.Der Rücklaufmechanismus bei der Ausführung der Strategie auf der Live-Bar (Real-Time-Preismodell):
Bei der Realtime-Bar-Ausführung wird bei jeder neuen Ausführung der Strategie eine Variable, die vom Benutzer definiert wurde, vor dem Zurücksetzen ausgeführt. Um den Zurücksetzungsmechanismus mit einem Beispiel zu verstehen, testen wir den Code.Beachten:
/*backtest ... .. . */Das Paket enthält die Rückmeldungskonfiguration, die in Codeform auf der FMZ-Plattform gespeichert ist.
pine/*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("n + 1之前, n:", n, " 当前bar_index:", bar_index) n := n + 1 runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index) plot(n, title="n")Wir untersuchten nur Szenen, die in der Echtzeit-Bar ausgeführt wurden, also benutzten wir
not barstate.ishistoryAusdrucksbeschränkungen werden nur für die Variablen n in Echtzeit in Bar erstellt und vor und nach der Ausführung der Aggregation verwendetruntime.logFunktions-Ausgabe-Informationen in der Strategie-Log.plotDie gezeichnete Kurve n zeigt, dass die Strategie in der historischen Bar immer 0 war. Die Aktion n + 1 wurde ausgelöst, als die Strategie in der realen Bar ausgeführt wurde, und die Aktion n + 1 wurde bei jeder Ausführung der Strategie in der realen Bar ausgeführt. Aus den Login-Informationen lässt sich erkennen, dass bei jeder erneuten Ausführung des Strategiecodes in der realen Bar der Wert n auf den Wert der letzten Ausführung der Strategie in der letzten Ausführung der Strategie zurückgesetzt wird.Zusammenfassend:
- Wenn die Strategie in der Echtzeit-Bar ausgeführt wird, wird der Strategiecode bei jeder Aktualisierung ausgeführt.
- Bei der Ausführung in der Real-Time-Bar werden die Variablen vor jeder Ausführung des Strategiecodes zurückgerollt.
- Wenn die Variablen in der Echtzeit-Bar ausgeführt werden, werden sie bei der Erneuerung des Abschlusses eingereicht.
Da die Daten rückläufig sind, können auch Grafikoperationen wie Kurven auf dem Diagramm zu einer Neugestaltung führen, z. B. wenn wir den Testcode, den wir gerade getestet haben, ändern:
pinevar n = 0 if not barstate.ishistory runtime.log("n + 1之前, n:", n, " 当前bar_index:", bar_index) n := open > close ? n + 1 : n runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index) plot(n, title="n")Wir haben nur den Satz geändert:
n := open > close ? n + 1 : nIn der ersten Zeichnung (Moment A) wurde n 1 hinzugefügt, da der Eröffnungspreis höher war als der Schließungspreis (Moment B). Die Grafikkurve n zeigte den Wert 5 . Als sich dann die Situation änderte, wurde der Preis aktualisiert, wie in der zweiten Zeichnung (Moment B) gezeigt. Die Grafikkurve n wurde sofort neu gezeichnet, und die Kurve n wurde sofort neu gezeichnet, als die Kurve n 4 war. -
Variablen in einer Funktion
Im Folgenden untersuchen wir die Variablen in den Funktionen der Sprache Pine. Gemäß der Beschreibung in einigen Pine-Tutorials unterscheiden sich die Variablen in der Funktion von den Variablen außerhalb der Funktion wie folgt:
Die Historie der in der Pine-Funktion verwendeten Serienvariablen wird bei jedem aufeinanderfolgenden Aufruf der Funktion erstellt. Wenn keine Funktion in jeder Spalte des Skriptes aufgerufen wird, führt dies zu einer Differenz zwischen den Historien innerhalb und außerhalb der lokalen Block der Funktion. Wenn die Funktion also nicht in jeder Spalte aufgerufen wird, werden die Serien mit den gleichen Indexwerten, die innerhalb und außerhalb der Funktion referenziert werden, nicht auf die gleichen Historienpunkte verweisen.
Ist das etwas, was schwer zu verstehen ist? Es ist in Ordnung, wir haben es durch einen Testcode, der auf FMZ läuft, herausgefunden:
pine/*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)Bildschirmherstellung der Rückmeldung
Der Testcode ist relativ einfach und basiert hauptsächlich auf Daten, die in zwei Arten zitiert werden:
f(a) => a[1]Undf2() => close[1]。-
f(a) => a[1]Die Funktion wird als letztes zurückgegeben.a[1]。 -
f2() => close[1]Verwenden Sie die Variablen direkt:closeDie Funktion wird als letztes zurückgegeben.close[1]。
[]Das Symbol für die Referenzierung auf die historischen Werte der Variablen der Datenreihe, close[1] bezieht sich auf die Schlusskosten der aktuellen Schlusskosten auf der vorangegangenen Bar.-
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 von A bis Z, rot, wenn oneBarInTwo wahr ist, und die Position (auf der Y-Achse) istf(close)Die zurückgegebenen Werte: -
plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")
Zeichne ein Zeichen in B<unk>, die Farbe ist grün, wenn oneBarInTwo wahr ist, und zeichne die Position (auf der Y-Achse) als:f2()Die zurückgegebenen Werte: -
plot(close[2], title = "close[2]", color = color.red, overlay = true)
Die Zeichnung ist rot und zeigt die Position (auf der Y-Achse) wie folgt:close[2]Das ist der Schlusskurs auf der aktuellen Bar (Zweite Linke). -
plot(close[1], title = "close[1]", color = color.green, overlay = true)
Die Farbe ist grün und die Position (auf der Y-Achse) ist:close[1]Das ist der Schlusskurs auf der aktuellen Bar (die erste Linksradie).
Durch die Strategie Rückverfolgung Run Screenshot zu sehen, obwohl die Funktion verwendet wird, um die Markierung von Diagramm A
f(a) => a[1]Funktionen, die mit dem Zeichen B markiert werdenf2() => close[1]Es ist alles.[1] um die historischen Daten in der Datenreihe zu zitieren, aber die Markierung von "A" und "B" auf der Grafik ist völlig unterschiedlich. Die Markierung von "A" fällt immer auf die rote Linie, also auf den Code in der Strategieplot(close[2], title = "close[2]", color = color.red, overlay = true)Die Daten, die in der Zeile verwendet werden, sind:close[2]。Der Grund dafür ist, dass die Indexierung durch die K-Linie Bar, die in-Variablen
bar_indexBerechnen, ob die Markierungen "A" und "B" gezeichnet werden. Die Markierungen "A" und "B" werden nicht auf jeder K-Linien-Bar gezeichnet.f(a) => a[1]Wenn die Funktion nicht auf jeder Bar aufgerufen wird, werden die Werte, die auf diese Weise zitiert werden, mit der Funktion verknüpft.f2() => close[1]Diese Methode verwendet unterschiedliche Referenzwerte, auch wenn[1] mit der gleichen Indexierung). -
-
Einige eingebaute Funktionen müssen auf jeder Bar berechnet werden, um ihre Ergebnisse richtig berechnen zu können.
Ein einfaches Beispiel:
pineres = close > close[1] ? ta.barssince(close < close[1]) : -1 plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)Wir rufen die Funktion in Code auf.
ta.barssince(close < close[1])Schreiben Sie es in einem dreifachen Operator.condition ? value1 : value2Das hat zur Folge, dass nur inclose > close[1]Wenn Sie die ta.barssince-Funktion aufrufen.ta.barssinceDie Funktion wird berechnet von der letztenclose < close[1]Die Anzahl der K-Zeilen, die bei der Erstellung vorhanden waren.[1], d.h. der aktuelle Schlusskurs ist größer als der Schlusskurs der vorherigen Bar, wenn die Funktion ta.barssince aufgerufen wird, deren Bedingung close < close ist[1] wurde nicht gegründet, und es gab auch keine letzte gegründete Stelle.ta.barssince: Wenn die Funktion aufgerufen wird und diese Bedingung noch nie vor der aktuellen K-Zeile erfüllt wurde, wird na。 zurückgegeben.
Wie in der Abbildung gezeigt:
Also, wenn wir die Grafik malen, dann zeichnen wir nur die Daten, wenn die Res-Variable ((-1) }} hat.
Um dieses Problem zu vermeiden, benutzen wir nur
ta.barssince(close < close[1])Der Funktionsaufruf wird aus dem Trinitären Operator herausgenommen und an jede mögliche Bedingungsabteilung externe geschrieben. Damit wird die Berechnung auf jeder K-Zeile Bar durchgeführt.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)
Zeitfolge
Das Konzept der Zeitreihen ist sehr wichtig in der Sprache Pine und ist ein Konzept, das wir verstehen müssen, wenn wir die Sprache Pine lernen. Die Zeitreihen sind keine Art, sondern die grundlegende Struktur für die Speicherung von Variablen mit der Zeit. Wir wissen, dass die Schrift von Pine auf Diagrammen basiert, und das grundlegendste, was in den Diagrammen angezeigt wird, ist die K-Linien-Diagramme.openist eine eingebaute Variable der Sprache Pine, die als Zeitreihen für die Speicherung der Eröffnungspreise für jeden K-Line-Bar aufgebaut ist.openDiese Zeitreihenstruktur repräsentiert den Eröffnungswert aller K-Linienbars, wenn die aktuelle K-Linienkarte von der ersten Bar am Anfang bis zur Bar, die das aktuelle Skript ausführt. Wenn die aktuelle K-Linienkarte eine 5-Minuten-Periode ist, dann zitieren wir in der Pine-Strategie den Code ((oder verwenden)openDer Startpreis der K-Line-Bar bei der aktuellen Ausführung des Strategiecodes.[]Operator <unk> wird verwendet, wenn die Pine-Strategie auf einer K-String-Bar ausgeführt wirdopen[1]Angabe von ReferenzenopenDer Anfangspreis des vorherigen K-Linienbars dieser K-Linienbar, der von der aktuellen Schrift ausgeführt wird (d.h. der Anfangspreis des vorherigen K-Linienzyklus).
-
Variablen auf Zeitreihen sind sehr einfach zu berechnen
Wir benutzen die eingebaute Funktion.ta.cumEin 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.sumTestcode:
pinev1 = 1 v2 = ta.cum(v1) plot(v1, title="v1") plot(v2, title="v2") plot(bar_index+1, title="bar_index")Es gibt viele ähnliche
ta.cumEine solche integrierte Funktion kann Daten in einer Zeitreihenfolge direkt bearbeiten, z. B.ta.cumDas Ergebnis ist, dass wir die eingegebenen Variablen auf jeder K-Linie auf die entsprechenden Werte addieren, und wir verwenden eine Grafik, um es zu verstehen.Die Strategie läuft mit der Variablen bar_index und v1 und v2.
| - | - | - | - |
Die Strategie funktioniert auf der ersten K-Linie Bar ≠ 0 ≠ 1 ≠ 1.
Die Strategie funktioniert auf der zweiten K-Linie Bar
Die Strategie funktioniert auf der dritten K-Linie Bar ≠ 2 ≠ 1 ≠ 3 ≠
|...|...|...|...|
Die Strategie läuft auf der ersten N+1 K-LinieWie man sehen kann, sind v1, v2 und sogar bar_index tatsächlich Zeitreihenstrukturen, die auf jeder Bar mit entsprechenden Daten versehen sind. Dieser Testcode unterscheidet sich unabhängig davon, ob ein "Echtzeit-Preismodell" oder ein "Abschlusskursmodell" verwendet wird. Der Unterschied besteht nur darin, ob die reale Bar auf der Grafik angezeigt wird.
Da die Variable v1 auf jeder Bar 1 ist,
ta.cum(v1)Da die Funktion auf der ersten K-Zeile Bar ausgeführt wird und nur die erste Bar vorhanden ist, erhält die Funktion 1 und wird der Variablen v2 gegeben.
Wennta.cum(v1)Bei der Ausführung auf der zweiten K-Linie Bar gibt es bereits 2 K-Linien Bar ((das erste entspricht der eingebauten Variablen bar_index ist 0, das zweite entspricht der eingebauten Variablen bar_index ist 1), so dass das Ergebnis 2 berechnet wird, der Wert wird der Variablen v2 zugeteilt, und so weiter. Es kann tatsächlich beobachtet werden, dass v2 die Anzahl der K-Linien Bar in der Grafik ist, da die K-Linienbar_indexEs ist also 0 und es wird immer größer.bar_index + 1Das ist eigentlich die Anzahl der K-Linien.v2Undbar_indexDas ist eine echte Überschneidung.Ich kann das auch.
ta.cumDie eingebaute Funktion berechnet die Summe der Schlusskosten aller Bars auf dem aktuellen Diagramm und kann so geschrieben werden:ta.cum(close), wenn die Strategie auf die rechte Echtzeit-Bar läuftta.cum(close)Das Ergebnis ist die Summe der Schlusskosten für alle Bars in der Tabelle (ohne die rechte Seite zu berechnen, wird nur der aktuelle Bar addiert).Variablen auf Zeitreihen können auch mit Operatoren berechnet werden, z. B. mit dem Code:
ta.sma(high - low, 14)Die Variablen sind inhigh(Höchstpreis der K-Linie Bar) abzüglichlow(K-Line-Bar-Mindestpreise), Endverbrauchta.smaDie Funktion verlangt den Mittelwert. -
Die Funktionsaufrufe hinterlassen auch ihre Spuren in der Zeitreihenfolge.
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 beim Testlauf zurückgemessen und kann beobachtet werden
v1Undv2Die Werte der Funktion sind identisch, und die auf der Grafik gezeichneten Linien überschneiden sich vollständig. Die Ergebnisse der Funktionsaufrufe hinterlassen eine Spur von Werten in der Zeitreihenfolge, z. B. Codeta.highest(high, 10)[1]Einer davonta.highest(high, 10)Die Ergebnisse der Funktionsaufrufe können auch verwendet werden.[1] um den historischen Wert zu zitieren.ta.highest(high, 10)Das Ergebnis istta.highest(high[1], 10)Das ist es.ta.highest(high[1], 10)Undta.highest(high, 10)[1]Genau das gleiche.Die Ausgabe wird mit einer anderen Diagrammfunktion verifiziert:
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)Die Werte der Variablen a und b in der Zeitreihenfolge werden über und unter den entsprechenden Bars angezeigt. Der Zeichnungscode kann während des Lernens beibehalten werden, da bei Tests und Experimenten häufig Informationen zur Beobachtung auf der Grafik ausgegeben werden müssen.
Schriftstruktur
Allgemeine Struktur
Im Anfang des Tutorials haben wir einige Unterschiede zwischen der Verwendung von Pine auf der FMZ und der Verwendung von Pine in Trading View zusammengefasst.indicator()、strategy()Und, vorläufig nicht unterstützt.library()Um mit früheren Versionen von Pine kompatibel zu sein, wurde natürlich die Strategie geschrieben://@version=5,indicator(),strategy()Es ist auch möglich. Einige Einstellungen können instrategy()In der Funktion werden die Übertragungsparameter festgelegt.
<version>
<declaration_statement>
<code>
<version>Versionskontrollinformationen können weggelassen werden.
Anmerkungen
Pine-Sprache//Als Einzelzeilenkommentare wurde die Kommentare von FMZ erweitert, da es in der Sprache Pine keine Mehrzeilenkommentare gibt/**/Für mehrsprachige Anmerkungen.
Der Code
Eine Zeile in einem Skript, die keine Kommentare oder Kompilierer-Anweisungen enthält, ist ein Statement, das die Algorithmen des Skripts umsetzt. Ein Statement kann eines dieser Inhalte sein.
- Variablenerklärung
- Variablen neu zuordnen
- Funktionserklärung
- Eingebettete Funktionsaufrufe, benutzerdefinierte Funktionsaufrufe
if,for,whileoderswitchGleichgewichtsstruktur
Sätze können auf verschiedene Arten angeordnet werden.
- Einige Sätze können in einer Zeile ausgedrückt werden, wie z. B. die meisten Variablenerklärungen, die nur eine Zeile mit einem Funktionsaufruf oder eine Einzelarbeitserklärung enthalten. Andere, wie Strukturen, benötigen immer mehrere Zeilen, da sie einen lokalen Block benötigen.
- Die globalen Aussagen des Skripts (d. h. die Teile, die nicht zu den lokalen Blöcken gehören) können nicht als
空格oder制表符(Tab-Taste) beginnen. Ihr erster Buchstabe muss auch der erste Buchstabe der Zeile sein. Zeilen, die mit der ersten Position in der Zeile beginnen, sind per Definition Teil des globalen Umfangs des Skripts. - Eine Struktur- oder Mehrzeilenfunktionsanweisung erfordert immer eine
local block。 Ein lokaler Block muss in ein Kennzeichen oder vier Leerzeichen geschrumpft werden (andernfalls wird er als die fortlaufende Inhalte der vorherigen Codezeile analysiert), wobei jeder lokale Block einen anderen lokalen Bereich definiert。 - Mehrere einzelne Sätze können in einer Zeile durch die Verwendung des Kommas ((,) als Trennzeichen in einer Reihe zusammengefügt werden.
- Eine Zeile kann Kommentare enthalten oder nur Kommentare sein.
- Die Zeilen können auch eingewickelt werden (weiter auf mehreren Zeilen).
Zum Beispiel umfasst es drei lokale Blöcke, eine in einer benutzerdefinierten Funktionsanweisung und zwei, die die if-Struktur in einer Variablenanweisung verwenden, wie folgt:
pine
indicator("", "", true) // 声明语句(全局范围),可以省略不写
barIsUp() => // 函数声明(全局范围)
close > open // 本地块(本地范围)
plotColor = if barIsUp() // 变量声明 (全局范围)
color.green // 本地块 (本地范围)
else
color.red // 本地块 (本地范围)
runtime.log("color", color = plotColor) // 调用一个内置函数输出日志 (全局范围)
Code-Wechsel
Längere Zeilen können in mehrere Zeilen aufgeteilt oder "eingepflanzt" werden. Die eingepflanzte Zeile muss in eine beliebige Anzahl von Leerstellen geschrumpft werden, sofern sie nicht ein Vielfaches von 4 ist (diese Grenzen dienen dazu, in lokale Blöcke zu schrumpfen).
pine
a = open + high + low + close
Es kann in folgenden Formularen verpackt werden (beachten Sie, dass die Anzahl der Zeilen, die pro Zeile eingekrümmt werden, kein Vielfaches von 4 ist):
pine
a = open +
high +
low +
close
Ein langer Plot ((() -Aufruf kann in eine Packe packt werden.
pine
close1 = request.security(syminfo.tickerid, "D", close) // syminfo.tickerid 当前交易对的日线级别收盘价数据系列
close2 = request.security(syminfo.tickerid, "240", close) // syminfo.tickerid 当前交易对的240分钟级别收盘价数据系列
plot(ta.correlation(close, open, 100), // 一行长的plot()调用可以被包装
color = color.new(color.purple, 40),
style = plot.style_area,
trackprice = true)
Sätze in einer benutzerdefinierten Funktionsanweisung können auch verpackt werden. Da jedoch die lokalen Blöcke grammatisch mit einem Verkürzungszeichen beginnen müssen (z. B. 4 Felder oder 1 Schreibzeichen), müssen die Fortsetzungssätze der Sätze, wenn sie in die nächste Zeile aufgeteilt werden, mit einem oder mehr Verkürzungen beginnen (z. B. nicht gleich dem Vielfachen von 4 Feldern).
pine
test(c, o) =>
ret = c > o ?
(c > o+5000 ?
1 :
0):
(c < o-5000 ?
-1 :
0)
a = test(close, open)
plot(a, title="a")
Identifikator und Operator
Kennzeichen
Bevor wir uns mit Variablen befassen, müssen wir zunächst die Konzepte von Antennen-Identifikatoren verstehen.FunktionUndVariableDie Namen der Variablen und Funktionen.FunktionWie wir im nächsten Tutorial erfahren werden, lernen wir zuerst den Zitronen-Kennzeichen <unk>。
-
- Die Kennzeichen müssen in Großbuchstaben stehen
(A-Z)oder klein(a-z)Buchstaben oder Unterstriche(_)Der Beginn, als erster Zeichen der Kennung ▽.
- Die Kennzeichen müssen in Großbuchstaben stehen
-
- Das nächste Zeichen nach dem ersten Zeichen des Identifikators kannDie Buchstaben、UnterstreichungoderZahlen。
-
- Die Namen der Kennzeichen sind in Groß- und Kleinbuchstaben geschrieben.
Ein Beispiel dafür sind folgende Namen:
pine
fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown // 错误的命名!使用了数字字符作为标识符的开头字符
Wie in den meisten Programmiersprachen gibt es auch in der Sprache Pine Schreibempfehlungen.
-
- Alle Buchstaben werden in Großbuchstaben geschrieben, um Konstanten zu benennen.
-
- VerwendungDie Kamelspitze-RegelBenannt nach anderen Kennungen.
pine
// 命名变量、常量
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7
// 命名函数
zeroOne(boolValue) => boolValue ? 1 : 0
Operator
Operatoren sind in Programmiersprachen einige Operator-Zeichen, die zum Erstellen von Ausdrücken verwendet werden, während Ausdrücke Berechnungsregeln sind, die für einen bestimmten Berechnungszweck entwickelt wurden, wenn wir eine Strategie schreiben. Die Operatoren in der Sprache Pine werden nach Funktion als:
Es gibt auch andere Operatoren, wie z.B. den Verwertungsoperator, den Algorithmusoperator, den Vergleichsoperator, den Logikoperator, den Logikoperator, den Algorithmusoperator, den Algorithmusoperator, den Algorithmusoperator.? : Das ist ein Triple-Operator.[]Der Operator für historische Verweise.
Mit der Arithmetikoperator*Zum Beispiel gibt es die folgenden Testcodes, um die Art von Problemen zu unterscheiden, die durch die Ergebnisse des Pine-Sprachoperators in Trading View verursacht werden:
pine
//@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)
Wenn Sie das Skript in der Trading View ausführen, wird ein Kompilierungsfehler auftreten, weil:adjustedLength = lenInput * factorDas Ergebnis nach der Multiplikationseries intTyp (Serie), jedochta.emaDer zweite Parameter der Funktion unterstützt diesen Typ nicht. Auf FMZ gibt es jedoch keine solchen strengen Einschränkungen.
Im Folgenden sehen wir uns die verschiedenen Operatoren an.
Zuweisungsoperator
Es gibt zwei Arten von Verwertungsoperatoren:=、:=Wir haben einige Beispiele im Anfang des Tutorials gesehen.
=Der Operator wird verwendet, um eine Variable zu initialisieren oder zu deklarieren.=Variablen, die nach der Initiialisierung und der Angabe eines Wertes zugewiesen werden, beginnen mit diesem Wert auf jeder Bar danach. Diese sind gültige Variablenerklärungen:
a = close // 使用内置变量赋值给a
b = 10000 // 使用数值赋值
c = "test" // 使用字符串赋值
d = color.green // 使用颜色值赋值
plot(a, title="a")
plot(b, title="b")
plotchar(true, title="c", char=str.tostring(c), color=d, overlay=true)
Beachtena = closeDie Variablen a auf jeder Bar sind die aktuellen Schlusskosten für diese Bar. Die anderen Variablenb、c、dDas ist unveränderlich und kann in einem Rückmeldesystem auf der FMZ getestet werden.
:=Die Variablen, die zur Wiedergabe von Werten in vorhandene Variablen verwendet werden, können einfach so verstanden werden::=Die Operatoren werden verwendet, um die Werte von Variablen zu ändern, die bereits deklariert und initialisiert wurden.
Wenn verwendet:=Die Zuteilung eines Operators an eine Variable, die nicht initialisiert oder deklariert wurde, führt zu Fehlern, z. B.:
pine
a := 0
Das ist es.:=Zuweisungsoperatoren werden im Allgemeinen für die Neubewertung bereits vorhandener Variablen verwendet, z. B.:
pine
a = close > open
b = 0
if a
b := b + 1
plot(b)
Beurteilen, obclose > open(d.h. der aktuelle BAR ist die Sonnenlinie) und a ist der wahre Wert ((true) <unk>) und führt den Code in der lokalen Block der if-Anweisung ausb := b + 1Verwenden Sie den Assignment-Operator:=Geben Sie b einen neuen Wert, addieren Sie 1 ◦ und zeichnen Sie dann mit der Plot-Funktion die Werte der Variablen b auf den BARs der Zeitreihen auf der Tabelle, verbinden Sie sie in eine Linie ◦.
Sind wir der Meinung, dass, wenn wir eine Sonnenstrahl BAR haben, b immer 1 addiert? Natürlich nicht, hier haben wir keine Schlüsselwörter verwendet, um die Variable b zu deklarieren und mit 0 zu initialisieren.b=0Wir können also sehen, dass das Ergebnis dieses Codes ist, dass die Variable b jedes Mal wieder auf 0 gesetzt wird, wenn die Variable a wahr ist.close > openIn dieser Ausführung wird b mit 1 addiert, in der Plot-Funktion wird b mit 1 dargestellt, aber in der nächsten Ausführungsrunde wird b mit 0 neu bewertet. Dies ist auch der Punkt, an dem Pine-Anfänger leicht in die Irre gehen können.
In Bezug auf die Zuteilung von Operatoren müssen wir zwei Schlüsselwörter erweitern:var、varip
-
var
Wir haben dieses Schlüsselwort bereits in den vorherigen Tutorials gesehen, aber es wurde nicht detailliert diskutiert.
var ist ein Schlüsselwort für die Verteilung und einmalige Initialisierung von Variablen. In der Regel führt die Variablen-Bewertungssymbolik ohne das Schlüsselwort var dazu, dass die Werte der Variablen bei jeder Datenaktualisierung überschrieben werden. Im Gegensatz dazu, wenn das Schlüsselwort var verwendet wird, können die Variablen verteilt werden, obwohl die Daten aktualisiert werden.
Wir benutzen dieses Beispiel, aber wir benutzen es, wenn wir b etwas geben.
varSchlüsselwort:pinea = close > open var b = 0 if a b := b + 1 plot(b)varDie Schlüsselwörter lassen die Variable b nur die ursprüngliche erste Zuweisung ausführen, sodass bei jeder weiteren Ausführung der Strategie-Logik b nicht mehr auf 0 zurückgesetzt wird, so dass man aus der Laufzeit gezogenen Linie b beobachten kann, d. h. die Anzahl der Y-Linien BAR, die bei der aktuellen K-LinienBAR aufgetreten sind, als Rückmessung des aktuellen K-LinienBAR.Variablen in einer var-Erklärung können nicht nur global geschrieben werden, sondern auch in Code-Blöcken, wie in diesem Beispiel:
pinestrategy(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' behält den Schlusskurs der ersten Säule in der Reihe.
Die Variable 'b' hält den Schlusskurs der ersten in der Reihe, der grünen Zitronen-Preisschwange.
Die Variable 'c' hält den Schlusskurs für die zehnte Kartoffel in der Reihe. -
varip
varipWir haben dieses Schlüsselwort zum ersten Mal gesehen, und wir können die Beschreibung dieses Schlüsselworts sehen:varip ((var intrabar persist) ist ein Schlüsselwort für die Verteilung und einmalige Initialisierung von Variablen. Es ist ähnlich wie das Schlüsselwort var, aber die Variablen mit der Varip-Erklärung behalten ihren Wert zwischen den K-Linien-Aktualisierungen in Echtzeit.
Ist es schwierig zu verstehen? Es ist okay, wir werden es mit Beispielen erklären, es ist leicht zu verstehen.
strategy(overlay=true) // 测试 var varip var i = 0 varip ii = 0 // 将策略逻辑每轮改变的i、ii打印在图上 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) // 每轮逻辑执行都给i、ii递增1 i := i + 1 ii := ii + 1Der Testcode wirkt unterschiedlich auf die Schlusskursmodelle und die Echtzeit-Kursmodelle:
Das sind die Faktoren, die uns helfen.
Erinnern Sie sich an die Strategie, die wir zuvor beschrieben haben, die in historische BAR-Phasen und in Echtzeit-BAR-Phasen ausgeführt wird?var、varipVariablen in der Erklärungi、iiBei jeder Ausführung des Strategie-Codes wird die Erhöhung durchgeführt. Die Zahlen, die in der Rückmessung auf der KBAR-Zeile angezeigt werden, werden also jeweils um 1 erhöht. Wenn die historische K-Zeile endet und die Echtzeit-K-Zeile beginnt, ändern sich die Variablen der Var-Varip-Aussagen.i := i + 1Undii := ii + 1Der Unterschied ist, dass ii jedes Mal geändert wird. Obwohl i jedes Mal geändert wird, wird der vorherige Wert bei der nächsten Ausführung der Strategie-Logik wiederhergestellt (Erinnern Sie sich an den Rücklaufmechanismus, den wir im vorherigen Kapitel "Modelldurchführung" erläutert haben?), bis die aktuelle KBAR-Linie abgeschlossen ist, um den Wert von i zu aktualisieren (d. h. die vorherige Wert wird bei der nächsten Ausführung der Strategie-Logik nicht mehr wiederhergestellt).Die Schlusskursmodelle:
Da das Schlusskursmodell eine Strategie-Logik ausführt, wenn jeder K-Line BAR abgelaufen ist. In dem Schlusskursmodell sind die Variablen der historischen K-Line-Phase und der Echtzeit-K-Line-Phase, die Variablen der Var-Varip-Erklärungen, in den obigen Beispielen exakt identisch und pro K-Line BAR 1 erhöht.
Arithmetik-Operator
| Operator | veranschaulichen |
|---|---|
| + | Zusatz |
| - | Abzug |
| * | Multiplikation |
| / | Verbot |
| % | Ich suche nach Vorbildern. |
+、-Die Operatoren können als binäre Operatoren oder als unitarische Operatoren verwendet werden. Andere Operatoren können nur als binäre Operatoren verwendet werden, wenn sie als unitarische Operatoren verwendet werden.
- Die beiden Seiten des Operators sind Zahlenarten, was zu Zahlenarten, Ganzenarten oder Floating-Point-Zahlen führt.
- Wenn eine der Operationen ein String ist, ist der Operator
+, wird als String berechnet, die Werte werden in Stringform umgewandelt und dann zusammengefügt. Wenn es sich um einen anderen Algorithmus-Operator handelt, wird versucht, die Strings in Werte umzuwandeln und dann zu berechnen. - Wenn eine der Operationszahlen na ist, ist die Berechnung null und NaN wird beim Drucken auf dem FMZ angezeigt.
pine
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 hier ein wenig von der Pine-Sprache auf Trading View. Die Pine-Sprache auf FMZ ist nicht sehr anspruchsvoll und streng in Bezug auf die Variablen-Typen. Zum Beispiel:
pine
a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A"
plot(a)
plot(b)
plot(c)
Auf der FMZ ist dies möglich, aber in der Trading View wird ein Typfehler gemeldet. Wenn die operativen Zahlen auf beiden Seiten des Operators Strings sind, wird das System die Strings in Zahlen umgewandelt. Wenn nicht-numerische Strings nicht berechnet werden können, wird das Ergebnis der Systemoperation null.
Vergleichen der Operatoren
Vergleiche sind binäre Operatoren.
| Operator | veranschaulichen |
|---|---|
| < | Weniger als |
| > | Mehr als |
| <= | Weniger als gleich |
| >= | Größer ist gleich |
| == | Gleichwertig |
| != | Ungleichheit |
Testbeispiel:
pine
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 verwenden, aber es ist der Operator, den wir am häufigsten verwenden, wenn wir Strategien schreiben. Sie können sowohl Werte als auch eingebaute Variablen vergleichen, z. B.close、openWarten.
Wie bei den operativen Operatoren unterscheidet sich Pine von Trading View in der FMZ, die keine besonders strengen Anforderungstypen hat, so dass solche Aussagend = "1" >= 2 Auf FMZ wird kein Fehler gemeldet, die String wird erst in Zahlen umgewandelt und dann verglichen. Auf Trading View wird ein Fehler gemeldet.
Logische Operatoren
| Operator | Codezeichen | veranschaulichen |
|---|---|---|
| Nein | not | Einzeloperator, nicht operativ |
| Und | and | Binäre Operatoren, mit (und) |
| oder | or | Binäre Operatoren, oder Operationen |
Wenn wir über Logik-Operatoren sprechen, dann müssen wir auch über Wahrheitszahlen sprechen. Genau wie wir es in der Highschool gelernt haben, nur dass wir es hier im Feedback-System getestet und gelernt haben:
pine
a = 1 == 1 // 使用比较运算符构成的表达式,结果为布尔值
b = 1 != 1
c = not b // 逻辑非操作符
d = not a // 逻辑非操作符
runtime.log("测试逻辑操作符: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("测试逻辑操作符: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 nicht zu beobachten, dass das System ständig Druckinformationen druckt, verwenden wirruntime.error("stop")Die Aussage: Nach dem Ausdrucken wird ein Ausnahmefehler ausgelöst, der die Rückmessung beendet, und die Ausgabe wird beobachtet, um festzustellen, dass der Inhalt des Drucks und die Tabelle der wahren Werte identisch sind.
Trinitäre Operatoren
Verwendung von dreifachen Operatoren? : Dreifache Ausdrücke mit einer Kombination von Operationencondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseWir haben es bereits in den vorherigen Kursen gelernt. Die sogenannten Dreier-Ausdrücke und Dreier-Operatoren bedeuten, dass es insgesamt drei Operationen gibt.
condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseIn derconditionDas sind die Beurteilungsbedingungen, wenn die Werte für die Wahrheitsformel:valueWhenConditionIsTrueWennconditionDer Wert für den Fall-Ausdruck istvalueWhenConditionIsFalse。
Es ist zwar nicht sehr praktisch, aber es sind Beispiele, die es Ihnen erleichtern, dies zu demonstrieren:
pine
a = close > open
b = a ? "阳线" : "阴线"
c = not a ? "阴线" : "阳线"
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)
Wenn Sie eine Kreuzung finden, ist es egal, was Sie tun. Die Triad-Ausdrücke können auch eingebettet werden, wie wir es bereits in den vorherigen Tutorials getan haben.
pine
a = close > open
b = a ? math.abs(close-open) > 30 ? "阳线" : "十字星" : math.abs(close-open) > 30 ? "阴线" : "十字星"
c = not a ? math.abs(close-open) > 30 ? "阴线" : "十字星" : math.abs(close-open) > 30 ? "阳线" : "十字星"
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)
Das ist so, als würde mancondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseInvalueWhenConditionIsTrue、valueWhenConditionIsFalseEs wird auch eine andere trinitäre Formulierung verwendet.
Historischer Operator
Verwenden Sie den Historiker[], beziehen sich auf die Historik der Zeitschiene. Diese Historikwerte sind die Werte der Variablen auf der K-Linie vor der aktuellen K-Linie BAR, als das Skript ausgeführt wurde.[]Operatoren werden nach Variablen, Ausdrücken und Funktionen aufgerufen.[]Der Wert in dieser Eckklammer ist die Abweichung der historischen Daten von der aktuellen K-Linie BAR. Wenn ich beispielsweise den Schlusskurs der letzten K-Linie BAR anzeige, schreibt man:close[1]。
Wir haben in früheren Kursen ähnliche Schreibweisen gesehen:
pine
high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)
[]Der Operator kann nur einmal auf demselben Wert verwendet werden, so dass dies falsch geschrieben wird und fehlerhaft ist:
pine
a = close[1][2] // 错误
Vielleicht sehen Sie hier, dass einige Ihrer Kommilitonen sagen, Operatoren[]Es ist eine Reihe von Strukturen, die ähnlich wie Arrays aussehen.
Im Folgenden zeigen wir anhand eines Beispiels, dass es zwischen einer Reihe (series) und einer Array in der Sprache Pine nichts zu unterscheiden gibt.
pine
strategy("test", overlay=true)
a = close
b = close[1]
c = b[1]
plot(a, title="a")
plot(b, title="b")
plot(c, title="c")
Obwohla = close[1][2]Das ist ein Fehler, aber:
pine
b = close[1]
c = b[1]
Es ist nicht falsch, wenn man es in Form eines gewöhnlichen Arrays interpretiert.b = close[1]Nach der Zuordnung sollte b ein Wert sein, aberc = b[1], b kann noch einmal mit dem historischen Operator auf die historische Wert bezogen werden. Das Konzept der Reihe in der Sprache von Pine ist nicht so einfach wie das der Arrays. Es kann als die historische Wert auf der letzten Bar von close verstanden werden, b ist auch eine Zeitreihenstruktur, die ihre historische Wert weiter bezieht. So sehen wir in den drei gezeichneten Linien a, b, c, b ist langsamer als a eine BAR, b langsamer als b eine BAR.
Wir können das Diagramm ganz links nach unten ziehen und sehen, dass die Werte b und c auf der ersten K-Zeile null sind. Das liegt daran, dass es keine historischen Werte gibt, wenn die Schrift auf der ersten K-Zeile BAR ausgeführt wird.na、nzWir haben es in der Vergangenheit auch schon mal mit der Funktion in der Input-Funktion zu tun.nz、naFunktionen, erinnern Sie sich, in welchem Kapitel?) die Null-Werte behandeln, z. B.:
pine
close > nz(close[1], open) // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量
Das ist eine Behandlung für den Nullwert ((na) ≠ 0).
Betreiberpriorität
Wir haben schon viele Operatoren in der Sprache Pine gelernt, die durch verschiedene Kombinationen von Operatoren und Zahlen zum Ausdruck kommen. Was ist die Priorität dieser Operationen, wenn sie in Ausdrücken berechnet werden? Wie die Vier-Regel-Operationen, die wir in der Schule gelernt haben, gibt es die Multiplikation und die Subtraktion, die die Multiplikation und die Subtraktion berücksichtigen.
| Prioritäten | Operator |
|---|---|
| 9 | [] |
| 8 | Ein Operator mit den Elementen + 、- und ```not`` |
| 7 | *、/、% |
| 6 | Wenn der binäre Operator +, - |
| 5 | >、<、>=、<= |
| 4 | ==、!= |
| 3 | and |
| 2 | or |
| 1 | ?: |
Der Teil des Ausdrucks, der eine hohe Priorität hat, wird zuerst berechnet, wenn die Priorität gleich ist, wird von links nach rechts berechnet.()Die Ausdrucksform wird mit der Phrase "Beschränkt" versehen, die zwangsläufig zuvor berechnet wurde.
Variable
Variablenerklärung
Wir haben bereits das Konzept der Variablen-Identifikatoren gelernt, die Variablen als Variablen-Namen benannt werden. Also: Variablen sind Kennzeichen für die Speicherung von Werten. Wie kann man eine Variable deklarieren?
-
Anmeldungsmodus:
Die Variablen werden in drei Arten deklariert:- Schlüsselwörter verwenden
var。 - Schlüsselwörter verwenden
varip。 - Nichts schreiben.
var、varipDie Schlüsselwörter haben wir im vorherigen Kapitel "Ermächtigungsoperator" gelernt und werden hier nicht erwähnt. Wenn die Variablen-Erklärungsmodell nichts schreibt, z. B. die Aussage:i = 1In der Tat, wie wir bereits erwähnt haben, werden Variablen, die so deklariert werden und denen Werte zugeteilt werden, auf jeder K-Linie BAR ausgeführt. - Schlüsselwörter verwenden
-
Typ
Die Pine-Sprache auf FMZ ist nicht so streng in Bezug auf die Typenanforderungen und kann in der Regel weggelassen werden. Die Variablen können jedoch auch mit Typen deklariert werden, um die Skriptstrategie auf Trading View zu unterstützen. Zum Beispiel:int i = 0 float f = 1.1Die Typen in der Trading View sind sehr anspruchsvoll, wenn man die folgenden Codes in der Trading View verwendet, wird ein Fehler angezeigt:
baseLine0 = na // compile time error! -
Kennzeichen
Der Identifikator ist ein Variablenname, dessen Bezeichnung im vorherigen Kapitel erwähnt wurde, siehe: https://www.fmz.com/bbs-topic/9390#标识符
Zusammenfassend kann man sagen, dass eine Variablenerklärung wie folgt geschrieben werden kann:
// [<declaration_mode>] [<type>] <identifier> = value
声明模式 类型 标识符 = 值
Hier wird der Assignment-Operator verwendet:=Wenn eine Variable einer Variablenerklärung zugewiesen wird, können die Werte Strings, Werte, Ausdrücke, Funktionsaufrufe und so weiter sein.if、 for、whileoderswitchDie Strukturen werden in den folgenden Kursen näher erläutert. In den vorherigen Kursen haben wir die einfache Bezeichnung von if-Sätzen gelernt, die wir uns noch einmal ansehen können.)
Hier geht es um die Input-Funktion, eine Funktion, die wir sehr häufig verwenden, wenn wir Strategien entwickeln und schreiben.
Input-Funktion:
input函数,参数defval、title、tooltip、inline、group
Die Input-Funktion auf der FMZ unterscheidet sich etwas von der in Trading View, aber sie dient als Wert-Eingabe für Strategieparameter. Hier ist ein Beispiel, um die Verwendung der Input-Funktion auf der FMZ zu beschreiben:
pine
param1 = input(10, title="参数1名称", tooltip="参数1的描述信息", group="分组名称A")
param2 = input("close", title="参数2名称", tooltip="参数2的描述信息", group="分组名称A")
param3 = input(color.red, title="参数3名称", tooltip="参数3的描述信息", group="分组名称B")
param4 = input(close, title="参数4名称", tooltip="参数4的描述信息", group="分组名称B")
param5 = input(true, title="参数5名称", tooltip="参数5的描述信息", group="分组名称C")
ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)
Bei der Deklaration von Variablen werden häufig die Input-Funktionen verwendet, die in der FMZ-Strategie-Oberfläche automatisch Steuerelemente für die Einstellung von Strategieparametern zeichnen. Die auf der FMZ unterstützten Steuerelemente umfassen derzeit Zahlen-Eingabefelder, Text-Eingabefelder, Abziehfelder und die Markierung von Bohrwerten. Es können auch Funktionen wie die Einstellung von Strategieparameter-Gruppen und Hinweise zur Einstellung von Parametern angezeigt werden.
Wir haben einige der wichtigsten Parameter der Input-Funktion beschrieben:
- defval: Default-Wert für die Option "Strategy Parameter" als Inputfunktion, unterstützt die integrierten Variablen, Werte und Strings der Sprache Pine
- title: Name der Parameter, die die Strategie auf der Festplatte/der Rückmessung anzeigt.
- tooltip: Hinweis auf die Einstellung der Strategieparameter, wenn die Maus über die Strategieparameter hängt.
- group: Name der Politik-Argumentengruppe, der die Argumentengruppe gegeben werden kann.
Zusätzlich zu den einzelnen Variablen-Erklärungen und -Werte gibt es in der Sprache Pine eine Schreibweise, in der eine Gruppe von Variablen deklariert und Werte zugeteilt werden:
[变量A,变量B,变量C] = 函数 或者 ```if```、 ```for```、```while```或```switch```等结构
Die häufigste ist die, die wir benutzen.ta.macdDa der MACD-Indikator ein mehrlinearer Indikator ist, berechnet die Funktion drei Datensätze.
pine
[dif,dea,column] = ta.macd(close, 12, 26, 9)
plot(dif, title="dif")
plot(dea, title="dea")
plot(column, title="column", style=plot.style_histogram)
Es ist sehr einfach, MACD-Diagramme zu erstellen, wenn man den obigen Code benutzt. Eine integrierte Funktion kann mehrere Variablen zurückgeben, aber auch eine benutzerdefinierte Funktion kann mehrere Daten zurückgeben.
pine
twoEMA(data, fastPeriod, slowPeriod) =>
fast = ta.ema(data, fastPeriod)
slow = ta.ema(data, slowPeriod)
[fast, slow]
[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)
Die Verwendung von Strukturen wie "if" als mehrere Variablen ist ähnlich wie bei den oben beschriebenen benutzerdefinierten Funktionen.
[ema10, ema20] = if true
fast = ta.ema(close, 10)
slow = ta.ema(close, 20)
[fast, slow]
plot(ema10, title="ema10", color=color.fuchsia, overlay=true)
plot(ema20, title="ema20", color=color.aqua, overlay=true)
Bedingte Struktur
Einige Funktionen können nicht in einem lokalen Codeblock geschrieben werden, der in einer bedingten Abgrenzung liegt.
barcolor(), fill(), hline(), indicator(), plot(), plotcandle(), plotchar(), plotshape()
Auf der Trading View werden Fehlermeldungen erstellt. Auf der FMZ sind die Einschränkungen nicht so streng, aber es wird empfohlen, die Spezifikationen auf der Trading View zu befolgen. So wird beispielsweise auf der FMZ keine Fehlermeldung erstellt, aber nicht empfohlen.
pine
strategy("test", overlay=true)
if close > open
plot(close, title="close")
else
plot(open, title="open")
Die if-Anweisung
Das ist ein Beispiel:
pine
var lineColor = na
n = if bar_index > 10 and bar_index <= 20
lineColor := color.green
else if bar_index > 20 and bar_index <= 30
lineColor := color.blue
else if bar_index > 30 and bar_index <= 40
lineColor := color.orange
else if bar_index > 40
lineColor := color.black
else
lineColor := color.red
plot(close, title="close", color=n, linewidth=5, overlay=true)
plotchar(true, title="bar_index", char=str.tostring(bar_index), location=location.abovebar, color=color.red, overlay=true)
Hinweis: Die Ausdrucksformel gibt einen Bohr-Wert zurück. Bitte beachten Sie, dass es nur eine andere Ausdrucksformel geben kann. Alle Ausdrucksformeln sind falsch, und wenn keine andere Ausdrucksformel vorliegt, wird na zurückgegeben.
pine
x = if close > open
close
plot(x, title="x")
Da der lokale Codeblock für if nicht ausgeführt wird, wenn die K-Linie BAR negative ist, also wenn close < open, also wenn die Expression nach dem if-Statement false ist. Es gibt auch keine andere Abgrenzung, so dass der if-Statement na zurückgibt. x wird als na bewertet.
Switch-Aussagen
Eine Switch-Anweisung ist auch eine Abzweigung, die verwendet wird, um verschiedene Wege zu entwerfen, die unter bestimmten Bedingungen ausgeführt werden können.
- Die switch-Anweisung kann wie die if-Anweisung einen Wert zurückgeben.
- Im Gegensatz zu anderen Sprachen wird die Switch-Anweisung nur für einen lokalen Block in ihrem Code ausgeführt, so dass eine Break-Erklärung nicht notwendig ist (d.h. keine Schlüsselwörter wie "break") [2].
- Jeder Ableger des Switches kann einen lokalen Codeblock schreiben, dessen letzte Zeile als Rückgabewert verwendet wird (was eine Subgruppe von Werten sein kann). Wenn kein Ableger ausgeführt wird, wird na zurückgegeben.
- Ausdrücke in der Switch-Struktur können als Zeichenfolgen, Variablen, Ausdrücke oder Funktionen bezeichnet werden.
- switch erlaubt die Angabe eines Rückgabewertes, der als Standardwert verwendet wird, wenn keine anderen Bedingungen in der Struktur ausgeführt werden.
Wir haben zwei Arten von Switches, die wir als Beispiele betrachten, um zu verstehen, wie sie verwendet werden können.
- mit einem Ausdruck
switchEin Beispiel:
pine
// input.string: defval, title, options, tooltip
func = input.string("EMA", title="指标名称", tooltip="选择要使用的指标函数名称", options=["EMA", "SMA", "RMA", "WMA"])
// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="周期参数")
fastPeriod = input.int(10, title="快线周期参数", options=[5, 10, 20])
slowPeriod = input.int(20, title="慢线周期参数", options=[20, 25, 30])
data = input(close, title="数据", tooltip="选择使用收盘价、开盘价、最高价...")
fastColor = color.red
slowColor = color.red
[fast, slow] = switch func
"EMA" =>
fastLine = ta.ema(data, fastPeriod)
slowLine = ta.ema(data, slowPeriod)
fastColor := color.red
slowColor := color.red
[fastLine, slowLine]
"SMA" =>
fastLine = ta.sma(data, fastPeriod)
slowLine = ta.sma(data, slowPeriod)
fastColor := color.green
slowColor := color.green
[fastLine, slowLine]
"RMA" =>
fastLine = ta.rma(data, fastPeriod)
slowLine = ta.rma(data, slowPeriod)
fastColor := color.blue
slowColor := color.blue
[fastLine, slowLine]
=>
runtime.error("error")
plot(fast, title="fast" + fastPeriod, color=fastColor, overlay=true)
plot(slow, title="slow" + slowPeriod, color=slowColor, overlay=true)
Wir haben zuvor die Input-Funktion gelernt, und hier kommen wir zu zwei Funktionen, die ähnlich wie Input sind:input.string、input.intFunktion.
input.stringDas ist eine Funktion, mit der man Strings zurückgibt.input.intFunktionen, die eine ganze Zahl zurückgeben. In diesem Beispiel wurde eine neue Funktion hinzugefügt.optionsDie Verwendung von ParameternoptionsDie Parameter können in ein Array mit wählbaren Werten übertragen werden.options=["EMA", "SMA", "RMA", "WMA"]Undoptions=[5, 10, 20](Beachten Sie, dass einer der String-Typen und der andere der Zahlen-Typen ist). So müssen die Steuerelemente in der Strategie-Oberfläche keine spezifischen Zahlen eingeben, sondern die Steuerelemente werden zu einem Abziehfeld, das die Optionen auswählt, die im Options-Parameter zur Verfügung gestellt werden.
Der Wert der Variablen func wird als eine String ausgeführt, wobei die Variablenfunc als Ausdruck des Switches (möglicherweise als Variable, Funktionsanruf oder Ausdruck) verwendet wird, um zu bestimmen, welcher Zweig der Switch ausgeführt wird. Wenn die Variablenfunc nicht mit den Ausdrücken auf einem Zweig des Switches übereinstimmen kann (d.h. gleich sind), wird der Standard-Branchcode-Block ausgeführt, der ausgeführt wirdruntime.error("error")Die Funktion führt dazu, dass die Strategie die Ausnahme ausgibt und stoppt.
Wir haben in unserem Testcode nicht die letzte Zeile von runtime.error in der Standard-Branch-Code-Block des Switches hinzugefügt.[Na, na] ist ein Kompatibilitätscode, der in der Trading View berücksichtigt werden muss, wenn der Typ nicht übereinstimmt. Auf der FMZ kann dieser Kompatibilitätscode jedoch übersehen werden, da keine strengen Typen erforderlich sind. Auf der FMZ müssen die Kompatibilitätsprobleme mit den Typen, für die die if, switch oder branch zurückgegeben wird, nicht berücksichtigt werden.
pine
strategy("test", overlay=true)
x = if close > open
close
else
"open"
plotchar(true, title="x", char=str.tostring(x), location=location.abovebar, color=color.red)
Auf FMZ wird kein Fehler gemeldet, auf der Trading View wird ein Fehler gemeldet.
- Nicht ausgedrückt
switch
Wir werden sehen.switchEine andere Verwendung ist die Schreibweise ohne Ausdruck.
pine
up = close > open // up = close < open
down = close < open
var upOfCount = 0
var downOfCount = 0
msgColor = switch
up =>
upOfCount += 1
color.green
down =>
downOfCount += 1
color.red
plotchar(up, title="up", char=str.tostring(upOfCount), location=location.abovebar, color=msgColor, overlay=true)
plotchar(down, title="down", char=str.tostring(downOfCount), location=location.belowbar, color=msgColor, overlay=true)
Aus dem Testcode-Beispiel geht hervor, dass die Ausführung von switches mit den Branchbedingungen für den echten lokalen Codeblock übereinstimmt. Im Allgemeinen müssen die Branchbedingungen, die nach der Ausführung von switch-Aussagen folgen, gegenseitig ablehnend sein. Das heißt, in diesem Beispiel können up und down nicht gleichzeitig wahr sein.up = close > open // up = close < open Es ist außerdem zu beachten, dass Funktionsaufrufe möglichst nicht in den Zweigen des Switches geschrieben werden müssen, da die Funktion nicht auf jeder BAR aufgerufen werden kann, was zu Problemen bei der Berechnung von Daten führen kann. Es sei denn, dass die Funktion "mit einem Ausdruck"switch"In diesem Beispiel ist die Ausführungsbranche festgelegt und wird im Laufe der Strategie nicht geändert".)
Kreislaufstruktur
For-Aussagen
返回值 = for 计数 = 起始计数 to 最终计数 by 步长
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Die for-Anweisung ist sehr einfach zu verwenden, da der for-Loop letztendlich einen Wert (() oder mehrere Werte zurückgibt, um[a, b, c]). Die Variablen, die den "Return Value"-Standort bezeichnen, wie in den oben genannten Pseudo-Codes. Nach dem For-Ausspruch folgt eine "Count"-Variable, um die Anzahl der Zyklen zu steuern, andere Werte zu zitieren usw. Die "Count"-Variable wird vor Beginn des Zyklus als "Initial Count" bezeichnet und dann in der Schritt-Einstellung als "Initial Count" erweitert. Der Zyklus wird gestoppt, wenn die "Count"-Variable größer als "End Count" ist.
Verwendet im for-KreisbreakSchlüsselwort: Wenn ausgeführtbreakDer Kreislauf endet mit dem Satz:
Verwendet im for-KreiscontinueSchlüsselwort: Wenn ausgeführtcontinueDer Kreislauf ignoriert die Aussage.continueDer folgende Code führt direkt die nächste Runde durch. Die for-Anweisung gibt den Wert zurück, der bei der letzten Laufdurchführung zurückgegeben wurde. Wenn kein Code ausgeführt wurde, wird null zurückgegeben.
Im Folgenden zeigen wir es mit einem einfachen Beispiel:
pine
ret = for i = 0 to 10 // 可以增加by关键字修改步长,暂时FMZ不支持 i = 10 to 0 这样的反向循环
// 可以增加条件设置,使用continue跳过,break跳出
runtime.log("i:", i)
i // 如果这行不写,就返回空值,因为没有可返回的变量
runtime.log("ret:", ret)
runtime.error("stop")
Für ... in Sätze
for ... inEs gibt zwei Formen von Sätzen, die durch folgende Pseudo-Codes gekennzeichnet sind:
返回值 = for 数组元素 in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Der Hauptunterschied zwischen den beiden Formen besteht darin, dass der For-Keyword in den Formen, die eine Variable als Referenz auf ein Array-Element verwenden, verfolgt wird. Einer der Formen verwendet eine Struktur, die eine Subgruppe der Array-Element-Variablen enthält, um sie zu referenzieren.
pine
testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray // 修改成 [i, ele]的形式:for [i, ele] in testArray , runtime.log("ele:", ele, ", i:", i)
runtime.log("ele:", ele)
runtime.error("stop")
Verwenden Sie Indizes, wenn Sie es brauchenfor [i, ele] in testArrayDie Schreibweise von
Für eine Kreislauf-Anwendung
Wenn man mit den integrierten Funktionen der Pine-Sprache einige Kreislauflogik-Berechnungen durchführen kann, kann man sie direkt mit der Kreislaufstruktur schreiben oder mit den integrierten Funktionen bearbeiten. Hier sind zwei Beispiele.
- Berechnung des Mittelwerts
Wenn Sie eine Kreislaufstruktur verwenden:
pine
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
sum = 0
for ele in a
sum += ele
avg = sum / length
plot(avg, title="avg", overlay=true)
In diesem Beispiel wird die For-Kreislaufsummierung verwendet, um den Mittelwert zu berechnen.
Berechnen Sie die Mittellinie direkt mit der eingebauten Funktion:
pine
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Benutzung von integrierten Funktionenta.smaEs ist offensichtlich, dass es einfacher ist, die eingebaute Funktion zu verwenden, um die Durchschnittslinie zu berechnen. In der Grafik kann der Vergleich gesehen werden, dass die berechneten Ergebnisse vollständig übereinstimmen.
- Zählung
Oder nutzen Sie das oben genannte Beispiel.
Wenn Sie eine Kreislaufstruktur verwenden:
pine
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
sum = 0
for ele in a
sum += ele
avg = sum / length
plot(avg, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Für die Berechnung der Summe aller Elemente eines Arrays kann man Loops verwenden oder eine eingebaute Funktion.array.sumEs gibt keine Zahlen.
Die Summe wird direkt mit der eingebauten Funktion berechnet:
pine
length = 5
var a = array.new(length)
array.push(a, close)
if array.size(a) >= length
array.remove(a, 0)
plot(array.sum(a) / length, title="avg", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Die Berechnungsdaten werden in der Grafik mit Hilfe eines Plot-Drahmens vollständig übereinstimmend dargestellt.
Wenn man es mit einer eingebauten Funktion machen kann, warum sollte man dann einen Kreislauf entwerfen?
- Für einige Operationen mit Arrays.
- Zurück in die Vergangenheit, z. B. um herauszufinden, wie viele alte Höhen der Vergangenheit höher waren als die Höhen des aktuellen BAR. Da die Höhen des aktuellen BAR nur auf den BARs bekannt sind, die die Skripte ausführen, ist eine Schleife erforderlich, um rechtzeitig zurückzukehren und die alten BARs zu analysieren.
- Die integrierte Funktion in der Sprache Pine kann die Berechnung der letzten BAR nicht abschließen.
Während-Sätze
whileDie Sätze lassen den Code des Loop-Teils so lange ausführen, bis die Urteilsbedingung in der While-Struktur false () ist.
返回值 = while 判断条件
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Die anderen Regeln von while sind ähnlich wie bei der For-Loop, wobei die letzte Zeile des Loop-Local-Code-Blocks der Rückgabewert ist und mehrere Werte zurückgeben kann. Der Loop wird ausgeführt, wenn die "Loop-Bedingung" wahr ist, und der Loop wird beendet, wenn die Bedingung falsch ist.
Ich werde es mit einem Beispiel für die Berechnung der Gleichung zeigen:
pine
length = 10
sma(data, length) =>
i = 0
sum = 0
while i < 10
sum += data[i]
i += 1
sum / length
plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Es ist auch möglich, Berechnungslogiken zu entwerfen, die nicht durch eine eingebaute Funktion ersetzt werden können, z. B. die Berechnung von Stufenmultiplikationen:
pine
counter = 5
fact = 1
ret = while counter > 0
fact := fact * counter
counter := counter - 1
fact
plot(ret, title="ret") // ret = 5 * 4 * 3 * 2 * 1
Gruppe
Die Array-Definition in Pine ist ähnlich wie in anderen Programmiersprachen. Eine Array ist eine vierdimensionale Array. Arrays, in denen einzelne Daten gespeichert werden, werden als Array-Elemente bezeichnet. Die Typen dieser Elemente können sein: Integer, Float-Typ, String, Farbwert, Bull-Wert.[]Wir müssen sie nutzen.array.get()undarray.set()Funktion 。 Die Elementindex-Reihenfolge der Elemente in einer Array ist so, dass der Index des ersten Elements der Array 0 ist und der Index des nächsten Elements 1 erhöht wird.
Wir zeigen das mit einem einfachen Code:
pine
var a = array.from(0)
if bar_index == 0
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 1
array.push(a, bar_index)
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1])
else if bar_index == 2
array.push(a, bar_index)
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2])
else if bar_index == 3
array.push(a, bar_index)
runtime.log("当前BAR上的a值:", a, ", 上1根BAR上的a,即a[1]值:", a[1], ", 向前数2根BAR上的a,即a[2]值:", a[2], ", 向前数3根BAR上的a,即a[3]值:", a[3])
else if bar_index == 4
// 使用array.get 按索引获取元素,使用array.set按索引修改元素
runtime.log("数组修改前:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
array.set(a, 1, 999)
runtime.log("数组修改后:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
Arrays deklarieren
verwendenarray<int> a、float[] bArrays, die Arrays deklarieren oder nur eine Variable deklarieren, können Arrays zugeordnet werden, z. B.:
pine
array<int> a = array.new(3, bar_index)
float[] b = array.new(3, close)
c = array.from("hello", "fmz", "!")
runtime.log("a:", a)
runtime.log("b:", b)
runtime.log("c:", c)
runtime.error("stop")
Allgemeine Verwendung für die Initialisierung von Array-Variablenarray.newUndarray.fromFunktion <unk> Es gibt viele andere Funktionen in der Sprache Pine, die Array.new ähnlich sind und Typen betreffen:array.new_int()、array.new_bool()、array.new_color()、array.new_string()Warten.
Das var-Keyword kann auch mit Array-Erklärungen verbunden werden, wobei die Arrays mit der var-Keyword-Erklärung nur auf der ersten BAR-Ebene initialisiert werden.
pine
var a = array.from(0)
b = array.from(0)
if bar_index == 1
array.push(a, bar_index)
array.push(b, bar_index)
else if bar_index == 2
array.push(a, bar_index)
array.push(b, bar_index)
else if barstate.islast
runtime.log("a:", a)
runtime.log("b:", b)
runtime.error("stop")
Man kann sehen, dass die Änderungen an der Array a kontinuierlich festgestellt werden, ohne dass sie umgesetzt werden. Die Array b wird auf jedem BAR initialisiert.barstate.islastFür den Echtzeit-Druck gibt es immer noch nur ein Element, der Wert 0。
Lesen und Schreiben von Elementen in einem Array
Mit array.get erhält man die Elemente, die in der Array indexiert sind, und mit array.set ändert man die Elemente, die in der Array indexiert sind.
Das erste Parameter von array.get ist das zu behandelnde Array, das zweite Parameter ist der angegebene Index.
Das erste Parameter von array.set ist das zu behandelnde Array, das zweite Parameter ist der angegebene Index, das dritte Parameter ist das zu schreibende Element.
Ein einfaches Beispiel zeigt das:
pine
lookbackInput = input.int(100)
FILL_COLOR = color.green
var fillColors = array.new(5)
if barstate.isfirst
array.set(fillColors, 0, color.new(FILL_COLOR, 70))
array.set(fillColors, 1, color.new(FILL_COLOR, 75))
array.set(fillColors, 2, color.new(FILL_COLOR, 80))
array.set(fillColors, 3, color.new(FILL_COLOR, 85))
array.set(fillColors, 4, color.new(FILL_COLOR, 90))
lastHiBar = - ta.highestbars(high, lookbackInput)
fillNo = math.min(lastHiBar / (lookbackInput / 5), 4)
bgcolor(array.get(fillColors, int(fillNo)), overlay=true)
plot(lastHiBar, title="lastHiBar")
plot(fillNo, title="fillNo")
Dieses Beispiel initialisiert die Grundfarbe Grün, deklariert und initialisiert ein Array, um die Farbe zu speichern, und verleiht den Farbwerten dann eine unterschiedliche Transparenz (mit der Funktion color.new). Die Farbstufe wird berechnet, indem man die Entfernung zwischen dem aktuellen BAR und dem maximalen High innerhalb von 100 Rückblickzyklen berechnet. Je näher der maximale High innerhalb der letzten 100 Rückblickzyklen ist, desto höher ist die Stufe und desto tiefer ist der entsprechende Farbwert (niedrig).
Array-Elemente durchlaufen
Wie können wir ein Array durchlaufen, indem wir die For/For in/While-Sätze verwenden, die wir zuvor gelernt haben?
pine
a = array.from(1, 2, 3, 4, 5, 6)
for i = 0 to (array.size(a) == 0 ? na : array.size(a) - 1)
array.set(a, i, i)
runtime.log(a)
runtime.error("stop")
pine
a = array.from(1, 2, 3, 4, 5, 6)
i = 0
while i < array.size(a)
array.set(a, i, i)
i += 1
runtime.log(a)
runtime.error("stop")
pine
a = array.from(1, 2, 3, 4, 5, 6)
for [i, ele] in a
array.set(a, i, i)
runtime.log(a)
runtime.error("stop")
Die Ergebnisse der drei Durchfahrten sind gleich.
Arrays können sowohl im globalen Rahmen eines Skripts als auch im lokalen Rahmen einer Funktion oder eines if-Branches erklärt werden.
Historische Daten zitiert
Für die Verwendung von Elementen in Arrays ist die folgende Methode gleichwertig, wir können durch das folgende Beispiel sehen, dass wir zwei Gruppen von Linien in der Tabelle zeichnen, zwei Linien in jeder Gruppe, und die beiden Linien in jeder Gruppe haben die gleichen Werte.
pine
a = array.new_float(1)
array.set(a, 0, close)
closeA1 = array.get(a, 0)[1]
closeB1 = close[1]
plot(closeA1, "closeA1", color.red, 6)
plot(closeB1, "closeB1", color.black, 2)
ma1 = ta.sma(array.get(a, 0), 20)
ma2 = ta.sma(close, 20)
plot(ma1, "ma1", color.aqua, 6)
plot(ma2, "ma2", color.black, 2)
Funktionen zum Hinzufügen und Entfernen von Arrays
- Funktionen, die mit der Addition von Arrays zusammenhängen:
array.unshift()、array.insert()、array.push()。
- Funktionen, die mit dem Entfernen von Arrays zusammenhängen:
array.remove()、array.shift()、array.pop()、array.clear()。
Wir testen die Additions- und Subtractions-Funktionen dieser Arrays mit dem folgenden Beispiel:
pine
a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("数组a:", a, ", ret:", ret)
ret := array.insert(a, 1, "Y")
runtime.log("数组a:", a, ", ret:", ret)
ret := array.push(a, "D")
runtime.log("数组a:", a, ", ret:", ret)
ret := array.remove(a, 2)
runtime.log("数组a:", a, ", ret:", ret)
ret := array.shift(a)
runtime.log("数组a:", a, ", ret:", ret)
ret := array.pop(a)
runtime.log("数组a:", a, ", ret:", ret)
ret := array.clear(a)
runtime.log("数组a:", a, ", ret:", ret)
runtime.error("stop")
Hinzufügen und Entfernen von Anwendungen: Arrays als Queue
Mit Arrays und einigen Add- und Delete-Funktionen aus Arrays können wir eine "Queue"-Datenstruktur erstellen. Die Queue kann als Moving Average für Tick-Preise verwendet werden. Einige Schüler werden vielleicht fragen: "Warum soll ich eine Queue-Struktur erstellen?
Eine Queue ist eine Struktur, die häufig in der Programmierung verwendet wird.
Die Elemente, die zuerst in die Queue eingehen, werden zuerst aus der Queue herauskommen.
Auf diese Weise kann sichergestellt werden, dass die Daten, die in der Queue vorhanden sind, die aktuellsten Daten sind und dass die Queue nicht unendlich lang wird (Code, der unendlich lang wird, kann nur mittags geschrieben werden, da es Probleme mit Frühstück und Abend gibt).
Im folgenden Beispiel werden die Preise pro Tick mit einer Queue aufgezeichnet, der Moving Average für die Tick-Ebene berechnet und dann mit dem Moving Average für die 1-Minuten-K-Line-Ebene verglichen.
pine
strategy("test", overlay=true)
varip a = array.new_float(0)
var length = 10
if not barstate.ishistory
array.push(a, close)
if array.size(a) > length
array.shift(a)
sum = 0.0
for [index, ele] in a
sum += ele
avgPrice = array.size(a) == length ? sum / length : na
plot(avgPrice, title="avgPrice")
plot(ta.sma(close, length), title="ta.sma")
Beachten Sie, dass wir bei der Angabe von Array a die Angabe-Methode mit dem SchlüsselwortvaripSo wird jede Preisänderung in einem Array von a aufgezeichnet.
Funktionen zur Array-Berechnung und -Betrieb
Berechnen Sie die entsprechenden Funktionen:
array.avg()Finden Sie den Mittelwert aller Elemente im Array.array.min()Finde das kleinste Element der Array.array.max()Finden Sie das größte Element in der Array.array.stdev()Die Standarddifferenz aller Elemente in der Arrayarray.sum()Finde die Summe aller Elemente des Arrays.
Funktionen, die mit der Operation verbunden sind:
array.concat()Zusammenfügen oder Verbinden zweier Arrays.
array.copy()Replizieren der Arrays.
array.joinVerbindet alle Elemente des Arrays zu einer String.
array.sort()In der Reihenfolge von Aufstieg und Abstieg.
array.reverse()Umkehrschaltung der Arrays.
array.slice()Schnitt der Arrays.
array.includes()Das Urteilsmoment
array.indexof()Gibt den Index zurück, in dem der eingegebene Wert zum ersten Mal erschien. Wenn dieser Wert nicht gefunden wird, wird -1 zurückgegeben.
array.lastindexof()Finden Sie den Wert, der zuletzt erschien.
Testbeispiele für Array-Computing-bezogene Funktionen:
pine
a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)
runtime.log("数组a的算数平均:", array.avg(a))
runtime.log("数组a中的最小元素:", array.min(a))
runtime.log("数组a中的最大元素:", array.max(a))
runtime.log("数组a中的标准差:", array.stdev(a))
runtime.log("数组a的所有元素总和:", array.sum(a))
runtime.error("stop")
Das sind die am häufigsten verwendeten Array-Computing-Funktionen.
Beispiele für Funktionen, die mit der Operation verbunden sind:
pine
a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)
runtime.log("数组a:", a, ", 数组b:", b)
runtime.log("数组a,数组b连接在一起:", array.concat(a, b))
c = array.copy(b)
runtime.log("复制一个数组b,赋值给变量c,变量c:", c)
runtime.log("使用array.join处理数组c,给每个元素中间增加符号+,连接所有元素结果为字符串:", array.join(c, "+"))
runtime.log("排序数组b,按从小到大顺序,使用参数order.ascending:", array.sort(b, order.ascending)) // array.sort函数修改原数组
runtime.log("排序数组b,按从大到小顺序,使用参数order.descending:", array.sort(b, order.descending)) // array.sort函数修改原数组
runtime.log("数组a:", a, ", 数组b:", b)
array.reverse(a) // 此函数修改原数组
runtime.log("反转数组a中的所有元素顺序,反转之后数组a为:", a)
runtime.log("截取数组a,索引0 ~ 索引3,遵循左闭右开区间规则:", array.slice(a, 0, 3))
runtime.log("在数组b中搜索元素11:", array.includes(b, 11))
runtime.log("在数组a中搜索元素100:", array.includes(a, 100))
runtime.log("将数组a和数组b连接,搜索其中第一次出现元素2的索引位置:", array.indexof(array.concat(a, b), 2), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.log("将数组a和数组b连接,搜索其中最后一次出现元素6的索引位置:", array.lastindexof(array.concat(a, b), 6), " , 参考观察 array.concat(a, b):", array.concat(a, b))
runtime.error("stop")
Funktion
Benutzerdefinierte Funktionen
Die Pine-Sprache kann benutzerdefinierte Funktionen entwerfen. In der Regel haben die benutzerdefinierten Funktionen der Pine-Sprache folgende Regeln:
- Alle Funktionen sind im globalen Umfang des Skripts definiert. Eine Funktion kann nicht in einer anderen Funktion deklariert werden.
- Die Funktion darf sich nicht in ihrem eigenen Code selbst () aufrufen.
- Die Graphik-Funktion ist in Prinzip in allen PINE-Sprachen integriert.
barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) kann nicht in einer benutzerdefinierten Funktion aufgerufen werden. - Funktionen können als einzelne Zeile oder mehrere Zeilen geschrieben werden. Die Rückgabe des letzten Satzes ist die Rückgabe der aktuellen Funktion. Die Rückgabe kann in Form von Elementen zurückgegeben werden.
In den vorherigen Tutorials haben wir auch oft benutzte Custom-Funktionen verwendet, zum Beispiel die in einer einzigen Zeile entworfenen Custom-Funktionen:
pine
barIsUp() => close > open
Die Funktion gibt zurück, ob der aktuelle BAR der Sonnenstrahl ist.
Entworfen als mehrsprachige benutzerdefinierte Funktion:
pine
sma(data, length) =>
i = 0
sum = 0
while i < 10
sum += data[i]
i += 1
sum / length
plot(sma(close, length), title="sma", overlay=true)
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Eine SMA-Linienrechnung, die wir selbst mit einer benutzerdefinierten Funktion implementiert haben.
Ein Beispiel für eine benutzerdefinierte Funktion für zwei Variablen:
pine
twoEMA(data, fastPeriod, slowPeriod) =>
fast = ta.ema(data, fastPeriod)
slow = ta.ema(data, slowPeriod)
[fast, slow]
[ema10, ema20] = twoEMA(close, 10, 20)
plot(ema10, title="ema10", overlay=true)
plot(ema20, title="ema20", overlay=true)
Eine Funktion berechnet eine Schnelllinie, eine Langlinie und zwei EMA-Gleichlinien.
Eingebettete Funktionen
Die eingebaute Funktion kann bequem inFMZ PINE Script DokumentationNachfragen
Die Funktionen der Pine-Sprache sind so klassifiziert:
- Funktionen zur String-Verarbeitung
str.Die Serie - Funktion zur Farbwertverarbeitung
color.Die Serie - Funktion zur Eingabe von Parametern
input.Die Serie - Funktion zur Berechnung der Indikatoren
ta.Die Serie - Graphische Funktion
plot.Die Serie - Array-Funktionen
array.Die Serie - Transaktionsbezogene Funktionen
strategy.Die Serie - Funktionen für mathematische Operationen
math.Die Serie
9), andere Funktionen (z.B. Zeitverarbeitung, nicht-plotreiche Zeichnungsfunktionen,request.Serienfunktionen, Typbearbeitungsfunktionen usw.)
Transaktionsfunktionen
strategy.Serienfunktionen sind Funktionen, die wir häufig in der Gestaltung von Strategien verwenden, die mit der Strategie verbunden sind, um Transaktionsoperationen auszuführen, wenn diese ausgeführt werden.
1、strategy.entry
strategy.entryEine Funktion ist eine Auftragsfunktion, die bei der Erstellung von Strategien von großer Bedeutung ist. Die wichtigsten Parameter der Funktion sind:id, direction, qty, whenWarten.
Parameter:
id: kann verstanden werden als ein Name, der einer bestimmten Handelsposition zugewiesen wird. Diese ID kann verwendet werden, um einen Auftrag zu widerrufen, zu ändern oder zu platzieren.directionDie Parameter werden übertragen, wenn die Bestellrichtung "Mehr machen (... kaufen) " ist.strategy.longDiese eingebaute Variable wird übertragen, wenn man sich auszahlt.strategy.shortDiese Variable:qty: Geben Sie die Anzahl der Bestellungen an, wenn Sie diese Parameter nicht übermitteln, wird die Anzahl der Bestellungen als Standard verwendet.when: Ausführungsbedingung, kann als Parameter verwendet werden, um zu kontrollieren, ob der aktuelle Auftrag ausgelöst wird oder nicht.limitDie Preise für Bestellungen sind begrenzt.stopDer Stop Loss.
strategy.entryDetails zur FunktionsdurchführungstrategyDie Parameter-Einstellungssteuerung beim Aufruf einer Funktion kann auch über"Pine-Parameter für die Modellversion der Exchange-Class-Bibliothek"Weitere Details zu den Parameterkontrollen für die Einstellungssteuerung und die Modellversion der Pine-Language-Transaction-Klasse finden Sie in der Dokumentation unter dem Link.
Hier ist ein kurzer Überblick.strategyIn der Funktionpyramiding、default_qty_valueParameter ◦ Test mit folgenden Codes:
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
ema10 = ta.ema(close, 10)
findOrderIdx(idx) =>
if strategy.opentrades == 0
false
else
ret = false
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := true
break
ret
if not findOrderIdx("long1")
strategy.entry("long1", strategy.long)
if not findOrderIdx("long2")
strategy.entry("long2", strategy.long, 0.2, when = close > ema10)
if not findOrderIdx("long3")
strategy.entry("long3", strategy.long, 0.2, limit = low[1])
strategy.entry("long3", strategy.long, 0.3, limit = low[1])
if not findOrderIdx("long4")
strategy.entry("long4", strategy.long, 0.2)
plot(ema10, title="ema10", color=color.red)
Anfang des Codes/*backtest ... */Das Paket ist teilweise als Rückmess-Einstellung gedacht, um Informationen wie die Zeit der Rückmess-Einstellung zu speichern, um die Debugging zu erleichtern, und nicht als Strategiecode.
Der Code:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)Wenn wir diepyramidingWenn der Parameter 3 ist, haben wir maximal 3 Transaktionen in die gleiche Richtung eingestellt.strategy.entryDer folgende Befehl wurde nicht ausgeführt.default_qty_valueDer Parameter ist 0.1, also ist die ID-Kennzeichnung <unk>long1<unk>strategy.entryDie Anzahl der Schritte, die mit der nächsten Schritt-Operation durchgeführt werden, ist als Standard 0,1 festgelegt.strategy.entryWenn wir die Funktion aufrufen, dann geben wirdirectionDurchschnittstrategy.longEs gibt keine Kosten für die Tests, es gibt keine Kosten für die Tests.
Vorsicht im Codestrategy.entry("long3", ...Der folgende Befehl wurde zweimal aufgerufen, für die gleiche ID: <unk>long3<unk>.strategy.entryNachfolgende Operation erfolglos, zweiter Aufrufstrategy.entryDie Funktion ändert den Auftrag dieser ID: ((Die Daten, die bei der Rückmessung des Tests angezeigt werden, zeigen auch, dass der Auftrag unter diesem Limit-Auftrag geändert wurde, um 0.3)). In einem anderen Fall, beispielsweise wenn der erste Auftrag der ID für 3 Tonnen lang gekauft wurde, wird die Verwendung der gekauften ID weiter fortgesetzt.strategy.entryWenn eine Funktion bestellt wird, dann werden die Bestellpositionen auf der ID-Taste long3 aufgestockt.
2、strategy.close
strategy.closeDie Funktion wird verwendet, um die Eintrittsposition zu identifizieren, die den ID für die Platzierung angibt. Die wichtigsten Parameter sind:id,when,qty,qty_percent。
Parameter:
idDas ist die Eintrittskarte, die wir verwenden, um die Einzahlung zu erledigen.strategy.entryDie Eintritts- und Eintrittsordnungsfunktion wird mit der angegebenen ID geöffnet.whenBedingungen für die Durchführung:qtyAnzahl der Flachlager.qty_percentDer Anteil der Flächen.
Ein Beispiel für die Verwendung dieser Funktion:
Im Code/*backtest ... */Es handelt sich um die Konfigurationsinformationen der FMZ.COM International Station zum Zeitpunkt der Rückmessung. Sie können die Informationen löschen und den Markt, die Sorte und den Zeitrahmen einstellen, die Sie testen möchten.
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("close Demo", pyramiding=3)
var enableStop = false
if enableStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.2)
if strategy.opentrades >= 3
strategy.close("long1") // 多个入场订单,不指定qty参数,全部平仓
// strategy.close() // 不指定id参数,会平掉当前的持仓
// strategy.close("long2") // 如果指定一个不存在的id则什么都不操作
// strategy.close("long1", qty=0.15) // 指定qty参数平仓
// strategy.close("long1", qty_percent=50) // qty_percent设置50即为平掉long1标识仓位的50%持仓
// strategy.close("long1", qty_percent=80, when=close<open) // 指定when参数,修改为close>open就不触发了
enableStop := true
Die Teststrategie zeigte, dass man mit drei aufeinanderfolgenden Eintritts mit den Eintrittskennzeichen <unk>long1<unk> beginnt und dannstrategy.closeUnterschiedliche Ergebnisse bei der Rückmessung der verschiedenen Parameter der Funktion können gefunden werden.strategy.closeDiese Funktion hat keine Parameter, um den Auftragspreis für eine Ausgleichsstellung zu bestimmen. Diese Funktion wird hauptsächlich für die sofortige Ausgleichsstellung zum aktuellen Marktpreis verwendet.
3、strategy.close_all
strategy.close_allDie Funktion wird verwendet, um alle aktuellen Positionen auszugleichen, da die Pineskripte nur eine Richtung haben können, d.h. wenn ein Signal ausgelöst wird, das der entgegengesetzten Richtung entspricht, wird die aktuelle Position ausgeglichen und die Position wird entsprechend ausgelöst.strategy.close_allWenn der Anruf erfolgt, werden alle Positionen in der aktuellen Richtung abgewickelt.strategy.close_allDie Hauptparameter der Funktion sind:when。
Parameter:
whenBedingungen für die Durchführung:
Wir verwenden ein Beispiel:
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("closeAll Demo")
var enableStop = false
if enableStop
runtime.error("stop")
strategy.entry("long", strategy.long, 0.2, when=strategy.position_size==0 and close>open)
strategy.entry("short", strategy.short, 0.3, when=strategy.position_size>0 and close<open)
if strategy.position_size < 0
strategy.close_all()
enableStop := true
Der Testcode beginnt mit einer Positionsgröße von 0 (d.h.strategy.position_size==0ist wahr), so dass nur die Ausführung von ID als <unk>long<unk> ausgeführt wird, wenn die Bedingung des when-Parameters erfüllt wirdstrategy.entryEintrittsfunktion ≠ nach mehreren Positionenstrategy.position_sizeWenn die Eintrittsfunktion für die ID-Shortspan größer als 0 ist, kann die Eintrittsfunktion für die ID-Shortspan nur ausgeführt werden, da die derzeitige Positionsbeteiligung besteht. Dieses kurzfristige Rückwärtssignal führt dazu, dass die Positionsbeteiligung nach dem Ausgleich wieder rückwärts freigegeben wird.strategy.position_size < 0Wenn Sie eine Position mit leeren Händen halten, platzieren Sie alle Positionen in der Richtung, in der Sie die Position halten. Und markieren SieenableStop := true│ die Strategie zum Beobachten des Logs auslaufen lassen │
Es gibtstrategy.close_allDiese Funktion hat keine Parameter, um den Auftragspreis für eine Ausgleichsstellung zu bestimmen. Diese Funktion wird hauptsächlich für die sofortige Ausgleichsstellung zum aktuellen Marktpreis verwendet.
4、strategy.exit
strategy.exitDie Funktion wird für die Eintritts- und Haltungs-Platzoperation verwendet, anders als die Funktionstrategy.closeUndstrategy.close_allDie Funktion ist die sofortige Ausgleichung der Position zum aktuellen Marktpreis.strategy.exitDie Funktion wird nach den Parameter-Einstellungen planmäßig ausgeglichen.
Parameter:
idDie Order-ID des aktuellen Ausgleichspapiers lautet:from_entry: Eintritts-ID, die verwendet wird, um einen Ausgleich zu bestimmen.qtyAnzahl der Flachlager.qty_percentDer Wert der Aktien liegt in der Größenordnung von 0 bis 100%.profitDas Ergebnis wird in Punkten angegeben.lossDas Ziel ist die Verringerung der Verletzungsrate, in Punkten ausgedrückt.limitDas Ergebnis wird als Preis angegeben.stopDas Ziel ist ein Stop-Loss-Ziel, bei dem der Preis angegeben wird.whenBedingungen für die Durchführung:
Verwenden Sie eine Teststrategie, um die Verwendung der einzelnen Parameter zu verstehen.
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
strategy("strategy.exit Demo", pyramiding=3)
varip isExit = false
findOrderIdx(idx) =>
ret = -1
if strategy.opentrades == 0
ret
else
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := i
break
ret
strategy.entry("long1", strategy.long, 0.1, limit=1, when=findOrderIdx("long1") < 0)
strategy.entry("long2", strategy.long, 0.2, when=findOrderIdx("long2") < 0)
strategy.entry("long3", strategy.long, 0.3, when=findOrderIdx("long3") < 0)
if not isExit and strategy.opentrades > 0
// strategy.exit("exitAll") // 如果仅仅指定一个id参数,则该退场订单无效,参数profit, limit, loss, stop等出场条件也至少需要设置一个,否则也无效
strategy.exit("exit1", "long1", profit=50) // 由于long1入场订单没有成交,因此ID为exit1的出场订单也处于暂待状态,直到对应的入场订单成交才会放置exit1
strategy.exit("exit2", "long2", qty=0.1, profit=100) // 指定参数qty,平掉ID为long2的持仓中0.1个持仓
strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000) // 指定参数qty_percent,平掉ID为long3的持仓中50%的持仓
isExit := true
if bar_index == 0
runtime.log("每点价格为:", syminfo.mintick) // 每点价格和Pine语言模板参数上「定价货币精度」参数设置有关
Die Teststrategie beginnt mit der Durchführung von 3 Einstiegsoperationen (z.B.strategy.entryFunktion), die von long1 absichtlich eingestellt wurdelimitParameter, der Angebotspreis ist 1, so dass er nicht verkauft werden kann. Dann testen Sie die Ausgangskondition.strategy.exitEs wurden Punkte-Stopps, Preisstopps, Platzierungen mit festen Positionen und Prozentsatz-Stopps verwendet. In Anbetracht des Umfangs des Beispiels werden nur Stopps dargestellt. Die Stop-Loss-Operation ist ebenfalls vergleichbar.strategy.exitDie Funktion hat auch noch kompliziertere Tracking-Stop-Parameter:trail_price、trail_points、trail_offsetIn diesem Beispiel können Sie auch testen, wie man sie benutzt.
5、strategy.cancel
strategy.cancelFunktionen, die alle Befehle für die Annullierung/Stilllegung von vorgefertigten Listen verwenden.strategy.order, strategy.entry , strategy.exitDie Hauptparameter der Funktion sind:id、when。
Parameter:
idDie Eintrittskarte muss gekündigt werden.whenBedingungen für die Durchführung:
Diese Funktion ist sehr gut zu verstehen und wird verwendet, um unerledigte Eintrittsbefehle zu stornieren.
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("strategy.cancel Demo", pyramiding=3)
var isStop = false
if isStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0.3, limit=3)
if not barstate.ishistory and close < open
strategy.cancel("long1")
strategy.cancel("long2")
strategy.cancel("long3")
isStop := true
6、strategy.cancel_all
strategy.cancel_allFunktionen undstrategy.cancelDie Funktion ist ähnlich wie die . Annullieren/Deaktivieren aller Vorhängen-Befehle . Es kann angegeben werdenwhenParameter
Parameter:
whenBedingungen für die Durchführung:
pine
/*backtest
start: 2022-07-03 00:00:00
end: 2022-07-09 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"BTC_USDT"}]
*/
strategy("strategy.cancel Demo", pyramiding=3)
var isStop = false
if isStop
runtime.error("stop")
strategy.entry("long1", strategy.long, 0.1, limit=1)
strategy.entry("long2", strategy.long, 0.2, limit=2)
strategy.entry("long3", strategy.long, 0.3, limit=3)
if not barstate.ishistory and close < open
strategy.cancel_all()
isStop := true
7、strategy.order
strategy.orderFunktionen, Parameter-Einstellungen usw. sind fast identisch mitstrategy.entryEinheitlichkeit, Unterscheidungstrategy.orderFunktionen sind nicht geschützt.strategyFunktionpyramidingEinfluss der Parameter-Einstellungen, keine Einschränkung der Anzahl der Abrufe.
Parameter:
id: kann verstanden werden als ein Name, der einer bestimmten Handelsposition zugewiesen wird. Diese ID kann verwendet werden, um einen Auftrag zu widerrufen, zu ändern oder zu platzieren.directionDie Parameter werden übertragen, wenn die Bestellrichtung "Mehr machen (... kaufen) " ist.strategy.longDiese eingebaute Variable wird übertragen, wenn man sich auszahlt.strategy.shortDiese Variable:qty: Geben Sie die Anzahl der Bestellungen an, wenn Sie diese Parameter nicht übermitteln, wird die Anzahl der Bestellungen als Standard verwendet.when: Ausführungsbedingung, kann als Parameter verwendet werden, um zu kontrollieren, ob der aktuelle Auftrag ausgelöst wird oder nicht.limitDie Preise für Bestellungen sind begrenzt.stopDer Stop Loss.
Wir benutzen es.strategy.orderEs gibt keine Einschränkung für die Anzahl der Folgen, die mit der Kombinationstrategy.exitDie Bedingungsabschlussfunktion ◦ Konstruieren eines Skripts, das einem Gitter-ähnlichen Handel entspricht ◦ Die Beispiele sind sehr einfach und nur zum Lernen geeignet:
pine
/*backtest
start: 2021-03-01 00:00:00
end: 2022-08-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/
varip beginPrice = -1
if not barstate.ishistory
if beginPrice == -1 or (math.abs(close - beginPrice) > 1000 and strategy.opentrades == 0)
beginPrice := close
for i = 0 to 20
strategy.order("buy"+i, strategy.long, 0.01, limit=beginPrice-i*200, when=(beginPrice-i*200)<close)
strategy.exit("coverBuy"+i, "buy"+i, qty=0.01, profit=200)
strategy.order("sell"+i, strategy.short, 0.01, limit=beginPrice+i*200, when=(beginPrice+i*200)>close)
strategy.exit("coverSell"+i, "sell"+i, qty=0.01, profit=200)
Strategiebeispiel
Die Strategiebeispiele in diesem Tutorial dienen ausschließlich als Lehrstrategien, Anleitungen zur Gestaltung von Strategien und nicht als Anleitung oder Empfehlung für Transaktionen.
Strategie für Supertrendindikatoren
pine
strategy("supertrend", overlay=true)
[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))
plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)
if direction < 0
if supertrend > supertrend[2]
strategy.entry("entry long", strategy.long)
else if strategy.position_size < 0
strategy.close_all()
else if direction > 0
if supertrend < supertrend[3]
strategy.entry("entry short", strategy.short)
else if strategy.position_size > 0
strategy.close_all()
Die Entwicklung von Trendstrategien in der Sprache Pine ist sehr einfach. Hier haben wir eine einfache Trendverfolgungsstrategie mit einem Supertrend-Indikator entwickelt. Lassen Sie uns gemeinsam den Quellcode dieser Strategie analysieren.
Zuerst wurde der Strategiecode verwendet.strategyDie Funktion hat einige einfache Einstellungen vorgenommen:strategy("supertrend", overlay=true)Ich habe nur eine Strategie eingerichtet, die den Titel "Supertrend" trägt.overlayDie Parameter sindtrueWenn wir eine Pine-Strategie entwerfen oder eine Pine-Strategie-Skript erlernen, müssen wir uns zunächst die Parameter-Design der Strategie-Schnittstelle ansehen. Wir schauen uns den Quellcode von "Supertrend-Indikator-Strategie" an, in dem wir etwas gelernt haben, das wir in früheren Kursen gelernt haben.inputFunktion
[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))
inputFunktionsaufrufe werden direkt alsta.supertrendDie Parameter der Indikator-Funktion werden verwendet, um die Supertrend-Indikatoren zu berechnen.
- input(5, "factor")
- input.int(10, "atrPeriod")
Die Funktion setzt zwei Parameter-Controls in der Pine-Language-Strategie-Schnittstelle, wie in der Abbildung:
Wie Sie sehen können, ist der Standardwert auf der SteuerunginputFunktionen undinputDie Serienfunktion ((input.intDie ersten Parameter für die Funktion "Streaming" und die Funktion "Streaming" werden in den vorherigen Kapiteln erläutert.ta.supertrendDie Parameter für die Funktion ≠ ∞ berechnen eine Preisdaten.supertrendund eine Richtung Datendirection◦ Dann benutzen Sie esplotFunktionsdiagramm, achten Sie darauf, dass Sie nur die aktuelle Richtung nach dem Supertrend-Indikator zeichnen.directionWenn der aktuelle Trend nach oben ist, dann ist der aktuelle Trend nach unten.directionWir können also sehen, dass der Trend in den letzten zwei Stunden in Richtung unten ist.plotFunktionsdiagramm zu beurteilendirectionGrößer als, kleiner als 0
Die nächsteif ... else ifLogik ist die Beurteilung von Handelssignalen, wenn der Ausdruckdirection < 0Der Supertrend-Indikator ist eine Echtzeit-Anzeige der aktuellen Situation in der Aufwärtsphase, in der die Preisdaten in einem Supertrend-IndikatorsupertrendDer Supertrend-Indexpreis ist höher als der auf den 2 BARs vorn liegende Preis (d.h.supertrend[2],还记得历史操作符引用某个变量历史数据吧Erinnern Sie sich noch? Wenn Sie eine aktuelle Position haben, wird die Rückwärts-Auftragsfunktion zu diesem Zeitpunkt aufgerufen, um die vorherige Position auszugleichen und dann die Position gemäß der aktuellen Handelsrichtung zu eröffnen.supertrend > supertrend[2]Die Bedingungen sind nicht erfüllt, solangestrategy.position_size < 0Das bedeutet, dass die Position des Leerstandes auch einen Auslöser hat.strategy.close_all()Funktionsdurchführung, bei der alle Positionen ausgeglichen werden.
direction > 0Das gilt auch für die Phase des Abwärtstrends, wenn mehrere Positionen platziert werden und dann die Bedingungen erfüllt werden.supertrend < supertrend[3]Das ist der Grund, warum die Einstellung auf "Aus" gesetzt wird, wenn das Vakuumsignal ausgelöst wird.[3]Wie wäre es mit dem Bezug auf die Supertrend-Preisindikator-Daten auf der vorwärts gerichteten dritten BAR? Das könnte von den Strategie-Autoren beabsichtigt sein, denn in manchen Märkten, wie z. B. dem Vertragshandel, ist das Risiko eines Verlusts etwas größer als das Risiko eines Überrisikos.
fürta.supertrendDer Indikator, sind einige meiner Kollegen interessiert, wie man erkennt, ob ein aktueller Trend nach oben oder nach unten geht?
Der Indikator kann auch in Form einer benutzerdefinierten Funktion in der Sprache Pine realisiert werden:
pine
pine_supertrend(factor, atrPeriod) =>
src = hl2
atr = ta.atr(atrPeriod)
upperBand = src + factor * atr
lowerBand = src - factor * atr
prevLowerBand = nz(lowerBand[1])
prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
int direction = na
float superTrend = na
prevSuperTrend = superTrend[1]
if na(atr[1])
direction := 1
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
Diese benutzerdefinierte Funktion ist die integrierte Funktionta.supertrendDie Algorithmen sind identisch, und natürlich sind auch die Kennzahlen identisch.
Aus diesem benutzerdefinierten Funktionsalgorithmus können wir sehen, dass der integrierte Supertrendindikator von Pine berechnet wird mithl2Die eingebaute Variable ((höchste und niedrigste Preise addiert und dividiert durch 2, d.h. durchschnittlich die höchsten und niedrigsten Preise), berechnet dann den ATR-Wert für eine bestimmte Periode nach dem ParameteratrPeriod ((Wellenlänge)). Dann wird mithilfe von hl2 und ATR ein Auf- und Abgleis erstellt.
Aktualisiert nach Triad-Ausdrücken im CodelowerBandUndupperBand。
pine
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
lowerBand: Die untere Bahn, um zu bestimmen, ob sich der Aufwärtstrend geändert hat. upperBand: Die obere Bahn, um zu bestimmen, ob sich der Abwärtstrend geändert hat.
pine
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
Hier wird beurteilt, ob der Preiswert der letzten Supertendenz auf der BARprevUpperBand, also die Aufwärtslinie, zeigt den aktuellen Abwärtstrend an.closeÜberschreitenupperBandDer Preis bricht durch und wird als Trendwechsel betrachtet, der sich in einen Aufwärtstrend umwandelt.directionDie Richtungsvariablen sind auf -1 (= Aufwärts) eingestellt. Andernfalls sind sie auf 1 (= Abwärts) eingestellt.if direction < 0Wenn die Signalbedingungen ausgelöst werden, wird mehr getan.direction > 0Wenn die Signalbedingung ausgelöst wird, wird die Position frei gemacht.
pine
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
Schließlich werden die spezifischen Supertrend-Indikatorpreis- und -Richtungsdaten zurückgegeben, die je nach Richtung ausgewählt werden.
Strategie für dynamische Balance
pine
/*backtest
start: 2021-03-01 00:00:00
end: 2022-09-08 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["v_input_1",4374],["v_input_2",3],["v_input_3",300],["ZPrecision",0,358374]]
*/
varip balance = input(50000, "balance")
varip stocks = input(0, "stocks")
maxDiffValue = input(1000, "maxDiffValue")
if balance - close * stocks > maxDiffValue and not barstate.ishistory
// more balance , open long
tradeAmount = (balance - close * stocks) / 2 / close
strategy.order("long", strategy.long, tradeAmount)
balance := balance - tradeAmount * close
stocks := stocks + tradeAmount
runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)
else if close * stocks - balance > maxDiffValue and not barstate.ishistory
// more stocks , open short
tradeAmount = (close * stocks - balance) / 2 / close
strategy.order("short", strategy.short, tradeAmount)
balance := balance + tradeAmount * close
stocks := stocks - tradeAmount
runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)
plot(balance, title="balance value(quoteCurrency)", color=color.red)
plot(stocks*close, title="stocks value(quoteCurrency)", color=color.blue)
Wir haben uns einige Beispiele für die Entwicklung von Pine-Strategien angeschaut. Diesmal geht es um eine Strategie zur dynamischen Ausgewogenheit.BaseCurrency(Variante des Handels) undQuoteCurrencyDer Betrag der Währung wird immer ausgeglichen behandelt. Welche Vermögenswerte werden verkauft, wenn der relative Preis eines Vermögenswerts steigt und der Wert des Kontobesitzes steigt. Wenn der relative Preis eines Vermögenswerts sinkt und der Wert des Kontobesitzes sinkt, dann wird dieser Vermögenswert gekauft. Dies ist die sogenannte dynamische Ausgleichsstrategie.
Der Nachteil ist, wie die Rückmessung dieser Strategie auf der Grafik zeigt, dass die Strategie in den Phasen, in denen die Preise in der großen Tendenz steigen (oder fallen), eine größere Fluktuation und Verlust verursacht. Daher ist diese Strategie gut für die Bargeldstrategie, aber bei der Verwendung von Futures muss das Risiko gut kontrolliert werden.
Ein Beispiel für die Strategie-Code-Design:
Wir benutzen ein vereinfachtes Design, um eine Strategie zu simulieren.balance(d.h. die Anzahl der QuoteCurrency-Vermögenswerte) undstocks(d.h. die Anzahl der BaseCurrency-Assets) Balance-Informationen. Wir lesen nicht die tatsächliche Anzahl der Assets in den Konten, wir berechnen nur die angemessene Kauf- und Verkaufsmenge mit simulierten Beträgen.maxDiffValueDas Parameter ist der Maßstab für die Ausgleichung.BaseCurrencyUndQuoteCurrencyDie Abweichung übersteigtmaxDiffValueEs ist Zeit, das Gleichgewicht herzustellen, die hohen Vermögenswerte zu verkaufen, die niedrigen zu kaufen und die Vermögenswerte wieder ins Gleichgewicht zu bringen.
Die Auslösung des Strategie-Trading-Signals muss in der Echtzeit-BAR-Phase sinnvoll sein, so dass die Strategie-Trading-Bedingungen in der If-Beurteilung festgelegt sind.not barstate.ishistory◦ Bei aktuellen Preisen sind es etwa 20 bis 30 Euro.balanceMehr als das.stocksKaufen bei Wert. Umgekehrt verkaufen. Aktualisieren nach Ausführung der Transaktion.balanceUndstocksDie Variablen werden dann mit dem nächsten Gleichgewichtsschalter ausgelöst.
Die Informationen über die Strategie-Retrospektive enthalten den Preis der Sorte zum Zeitpunkt des Beginns der Strategie-Retrospektive, der Preis ist 1458, also habe ich die Parameter speziell festgelegtbalanceDas ist 47741458.*3), Einstellungsparameterstocks3. Das Vermögen zu Beginn im Gleichgewicht zu halten.
Supertrend-Strategien mit Verlust-Stopp-Tracking
In den vorherigen Lektionen haben wir gelernt,strategy.exitDie Positionsausgang-Funktion, deren Tracking-Stopp-Loss-Stopp-Funktion wir nicht mit Beispielen erläutern.strategy.exitDie Funktion verfolgt die Stop-Loss-Stopp-Funktion, um eine Supertrendstrategie zu optimieren.
Zuerst wollen wir sehen,strategy.exitDie Funktion verfolgt die Stop-Loss-Stop-Parameter:
1、trail_priceParameter: Auslöser der Position der Tracking-Stopp-Stopp-Loss-Plating-Position (die Position, an der der Preis angegeben ist).
2、trail_offsetParameter: Die Entfernung zwischen dem Höchstwert (bei der Aufnahme) und dem Tiefstwert (bei der Ausgabe) nach der Ausführung des Stop-Loss-Stopp-Vorgehens.
3、trail_pointsParameter: wie folgttrail_priceDie Parameter werden nur mit der Anzahl der Vorteile als Position angegeben.
Es ist nicht so einfach, das zu verstehen, aber es ist okay, wir verstehen das Lernen durch eine Strategie der Rückmeldungsszenarien, die einfach ist.
pine
/*backtest
start: 2022-09-23 00:00:00
end: 2022-09-23 08:00:00
period: 1m
basePeriod: 1m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
strategy("test", overlay = true)
varip a = na
varip highPrice = na
varip isTrade = false
varip offset = 30
if not barstate.ishistory and not isTrade
strategy.entry("test 1", strategy.long, 1)
strategy.exit("exit 1", "test 1", 1, trail_price=close+offset, trail_offset=offset)
a := close + offset
runtime.log("每点价格为:", syminfo.mintick, ",当前close:", close)
isTrade := true
if close > a and not barstate.ishistory
highPrice := na(highPrice) ? close : highPrice
highPrice := close > highPrice ? close : highPrice
plot(a, "trail_price 触发线")
plot(strategy.position_size>0 ? highPrice : na, "当前最高价")
plot(strategy.position_size>0 ? highPrice-syminfo.mintick*offset : na, "移动止损触发线")
Die Strategie beginnt mit der Ausführung des sofortigen Einstiegs in die Mehrspitze, und dann sofort nach dem nächstenstrategy.exitDer Ausgangsauftrag ((bezeichnet die Tracking Stop Stop-Parameter), beginnt mit der Ausführung der Tracking Stop Stop-Logik, wenn der Kurswechsel über die Trail_price-Triggerlinie steigt, der Stop Stop Stop-Triggerlinie ((blau) beginnt mit der höchsten Preisdynamik, die Position des blauen Linien ist der Preis, an dem der Stop Stop-Trigger die Plazierung auslöst, und schließlich wird die Plazierung ausgelöst, wenn der Kurswechsel unter die blaue Linie fällt.
Also benutzen wir diese Funktion, um eine Supertrend-Strategie zu optimieren, indem wir nur eine Eintritts-Order für die Strategie angeben.strategy.exitAuf der Ausflugsplanung kann diese Tracking-Stop-Loss-Stop-Funktion hinzugefügt werden.
pine
if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
trail_price := strategy.position_size > 0 ? close + offset : close - offset
strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
runtime.log("每点价格为:", syminfo.mintick, ",当前close:", close, ",trail_price:", trail_price)
state := 2
tradeBarIndex := bar_index
Der vollständige Strategiecode:
pine
/*backtest
start: 2022-05-01 00:00:00
end: 2022-09-27 00:00:00
period: 1d
basePeriod: 5m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["RunMode",1,358374],["ZPrecision",0,358374]]
*/
varip trail_price = na
varip offset = input(50, "offset")
varip tradeBarIndex = 0
// 0 : idle , 1 current_open , 2 current_close
varip state = 0
findOrderIdx(idx) =>
ret = -1
if strategy.opentrades == 0
ret
else
for i = 0 to strategy.opentrades - 1
if strategy.opentrades.entry_id(i) == idx
ret := i
break
ret
if strategy.position_size == 0
trail_price := na
state := 0
[superTrendPrice, dir] = ta.supertrend(input(2, "atr系数"), input(20, "atr周期"))
if ((dir[1] < 0 and dir[2] > 0) or (superTrendPrice[1] > superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
strategy.entry("open", strategy.long, 1)
state := 1
else if ((dir[1] > 0 and dir[2] < 0) or (superTrendPrice[1] < superTrendPrice[2])) and state == 0 and tradeBarIndex != bar_index
strategy.entry("open", strategy.short, 1)
state := 1
// 反向信号,全平
if strategy.position_size > 0 and dir[2] < 0 and dir[1] > 0
strategy.cancel_all()
strategy.close_all()
runtime.log("趋势反转,多头全平")
else if strategy.position_size < 0 and dir[2] > 0 and dir[1] < 0
strategy.cancel_all()
strategy.close_all()
runtime.log("趋势反转,空头全平")
if not barstate.ishistory and findOrderIdx("open") >= 0 and state == 1
trail_price := strategy.position_size > 0 ? close + offset : close - offset
strategy.exit("exit", "open", 1, trail_price=trail_price, trail_offset=offset)
runtime.log("每点价格为:", syminfo.mintick, ",当前close:", close, ",trail_price:", trail_price)
state := 2
tradeBarIndex := bar_index
plot(superTrendPrice, "superTrendPrice", color=dir>0 ? color.red : color.green, overlay=true)
- 1




















