Einführung in die PINE-Sprache FMZ Quant

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

Also sehen wir, dass in den gezeichneten drei Linien a, b und c, Linie b ist ein BAR langsamer als Linie a, und Linie c ist ein BAR langsamer als Linie b. Linie c ist 2-BAR langsamer als Linie a.

Wir können das Diagramm nach links ziehen und beobachten, dass auf der ersten K-Linie beide Werte von b und c null (na) sind. Dies liegt daran, dass das Skript, wenn es auf der ersten K-Linie BAR ausgeführt wird, nicht existiert, wenn man sich auf den historischen Wert von ein oder zwei Perioden nach vorne bezieht, der nicht existiert. Daher müssen wir beim Schreiben von Strategien vorsichtig sein, um zu überprüfen, ob das Verweisen auf historische Daten zu Nullwerten führt. Wenn der Nullwert unvorsichtig verwendet wird, verursacht dies eine Reihe von Berechnungsunterschieden und kann sogar den Echtzeit-BAR beeinflussen. Normalerweise verwenden wir integrierte Funktionenna, nzDas ist eine sehr schwierige Frage, die wir uns stellen müssen.nz, ```na`` in unseren vorherigen Videos, erinnern Sie sich, welches Kapitel es ist?) beschäftigen sich mit dem Fall von Nullwerten, zum Beispiel:

close > nz(close[1], open)    // When referencing the historical value of the previous BAR of the close built-in variable, if it does not exist, the open built-in variable is used

Dies ist eine Möglichkeit, mögliche Verweise auf Nullwerte (na) zu behandeln.

Priorität des Betreibers

Wir haben viele Operatoren in der Pine-Sprache gelernt. Diese Operatoren bilden Ausdrücke durch verschiedene Kombinationen mit Operanden. Was ist also die Priorität dieser Operationen bei der Auswertung in Ausdrücken? Genau wie die Arithmetik, die wir in der Schule gelernt haben, werden Multiplikation und Division zuerst berechnet, gefolgt von Addition und Subtraktion. Das gleiche gilt für Ausdrücke in der Pine-Sprache.

Priorität Betreiber
9 []
8 +-undnotin der unarischen Operator
7 */%
6 +-im Binäroperator
5 ><>=<=
4 ==!=
3 and
2 or
1 ?:

Wenn Sie ein bestimmtes Teil zuerst bewerten wollen, können Sie()um den Ausdruck zu wickeln, um den Teil zu zwingen, der zuerst ausgewertet werden soll.

Variablen

Variable Erklärung

Wir haben bereits das Konzept von marker untersucht, das als Name einer Variablen verwendet wird, dh eine Variable ist ein Marker, der einen Wert enthält.

  • Anmeldemodus: Das erste, was beim Deklarieren einer Variable geschrieben wird, ist der Declaration-Modus.

    1. Verwenden Sie das Schlüsselwortvar.
    2. Verwenden Sie das Schlüsselwortvarip.
    3. Schreib nichts.

    DievarundvaripSchlüsselwörter wurden in unserem vorherigen KapitelAssignment OperatorsWenn nichts für den Variablendeklarationsmodus geschrieben wird, wie z.B. die Anweisung:i = 1, wie bereits erwähnt, wird eine solche Variable, die deklariert und zugewiesen wird, auf jeder K-Line BAR ausgeführt.

  • Typ Die Pine-Sprache auf FMZ ist nicht streng hinsichtlich der Typen und kann im Allgemeinen weggelassen werden.

    int i = 0 
    float f = 1.1
    

    Die Typanforderungen für die Trading-Ansicht sind recht streng, und ein Fehler wird gemeldet, wenn der folgende Code in der Trading-Ansicht verwendet wird:

    baseLine0 = na          // compile time error!
    
  • Markierung Marker sind Variablennamen. Die Benennung von Markern wurde in früheren Kapiteln erwähnt, so dass Sie es hier überprüfen können:https://www.fmz.com/bbs-topic/9637#markers

Zusammenfassend lässt sich die Erklärung einer Variablen wie folgt schreiben:

// [<declaration_mode>] [<type>] <marker> = value 
   declaration mode             type     marker      = value

Der Zuweisungsoperator wird hier verwendet:=Beim Zuordnen kann der Wert eine Zeichenfolge, eine Zahl, ein Ausdruck, ein Funktionsanruf sein,if, for, while, oderswitchund andere Strukturen (diese strukturellen Schlüsselwörter und Statement-Nutzung werden in den folgenden Kursen ausführlich erläutert.

Hier konzentrieren wir uns auf die Eingabefunktion, die wir häufig bei der Gestaltung und Erstellung von Strategien verwenden.

Eingabefunktion:

input function, parameters: defval、title、tooltip、inline、group

Die Eingabefunktion auf FMZ unterscheidet sich etwas von der auf Trading View, aber diese Funktion wird als Zuweisungseingabe von Strategieparametern verwendet.

param1 = input(10, title="name of param1", tooltip="description for param1", group="group name A")
param2 = input("close", title="name of param2", tooltip="description for param2", group="group name A")
param3 = input(color.red, title="name of param3", tooltip="description for param3", group="group name B")
param4 = input(close, title="name of param4", tooltip="description for param4", group="group name B")
param5 = input(true, title="name of param5", tooltip="description for param5", group="group name C")

ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)

Die Eingabefunktion wird häufig verwendet, um Variablen beim Deklarieren von Werten zuzuweisen. Die Eingabefunktion auf FMZ zieht Steuerelemente für die automatische Einstellung von Strategieparametern in der FMZ-Strategieoberfläche. Die auf FMZ unterstützten Steuerelemente umfassen derzeit numerische Eingabefelder, Text-Eingabefelder, Dropdown-Boxen und booleanische Kontrollkästchen. Und Sie können die Gruppierung von Strategieparametern, die Einstellung der Parameter-Aufforderungsschrift und andere Funktionen festlegen.

img

Wir stellen einige Hauptparameter der Eingabefunktion vor:

  • defval: Der Standardwert für die Strategieparameteroptionen, die von der Eingabefunktion festgelegt werden und die integrierte Variablen, numerische Werte und Zeichenfolgen der Sprache Pine unterstützen.
  • Titel: Der Parametername der Strategie, der während des Live-Handels/Backtests auf der Strategieoberfläche angezeigt wird.
  • Tooltip: Die Tooltip-Informationen für Strategieparameter, wenn die Maus über den Strategieparameter bewegt wird, werden die Textinformationen der Parameter-Einstellung angezeigt.
  • Gruppe: Name der Strategieparametergruppe, die für Strategieparameter verwendet werden kann.

Zusätzlich zur Erklärung und Zuordnung einzelner Variablen gibt es auch eine Möglichkeit, eine Gruppe von Variablen zu deklarieren und in der Pine-Sprache zuzuweisen:

[Variable A, Variable B, Variable C] = function or structure, such as ```if```, ```for```, ```while``` or ```switch```

Die häufigste ist, wenn wir dieta.macdDa der MACD-Indikator ein Multi-Line-Indikator ist, werden drei Datensätze berechnet.

[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)

Wir können das MACD-Chart mit dem obigen Code leicht zeichnen. Nicht nur die eingebauten Funktionen können mehrere Variablen zurückgeben, sondern auch die geschriebenen benutzerdefinierten Funktionen können mehrere Daten zurückgeben.

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 Schreibmethode zur Verwendung von if und anderen Strukturen als Multiple Variable-Zuteilungen ähnelt ebenfalls der obigen benutzerdefinierten Funktion, und Sie können sie ausprobieren, wenn Sie interessiert sind.

[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)

Zustandsstruktur

Einige Funktionen können nicht im lokalen Code-Block des bedingten Zweigs geschrieben werden, hauptsächlich die folgenden Funktionen:

Barfarbe (), Füllfarbe (), Linie (), Indikator (), Grafik (), Grafikleuchten (), Grafikbild (), Grafikbild (), Grafikbild ().

Trading View wird mit Fehlern kompiliert, FMZ ist nicht so restriktiv, aber es wird empfohlen, die Spezifikationen von Trading View zu befolgen.

strategy("test", overlay=true)
if close > open 
    plot(close, title="close")
else 
    plot(open, title="open")

wenn Erklärung

Beispiel für Erläuterungen:

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)

Schlüsselpunkt: Ausdrücke, die für Beurteilungen verwendet werden, die Boolean-Werte zurückgeben. Beachten Sie die Einzug. Es kann höchstens noch eine Zweigstelle geben. Wenn alle Zweigstellen nicht wahr sind und es keine andere Zweigstelle gibt, geben Sie na zurück.

x = if close > open
    close
plot(x, title="x")

Übergangsanweisung

Die Switch-Anweisung ist auch eine verzweigte strukturierte Anweisung, die verwendet wird, um verschiedene Pfade zu entwerfen, die unter bestimmten Bedingungen ausgeführt werden sollen.

  1. Die Switch-Anweisung, wie die if-Anweisung, kann auch einen Wert zurückgeben.
  2. Im Gegensatz zu Switch-Anweisungen in anderen Sprachen wird bei der Ausführung eines Switch-Konstrukts nur ein lokaler Block seines Codes ausgeführt, so dass die Break-Anweisung unnötig ist (d. h. es ist nicht notwendig, Schlüsselwörter wie break zu schreiben).
  3. Jeder Branch des Switches kann einen lokalen Codeblock schreiben, die letzte Zeile dieses lokalen Codeblocks ist der Rückgabewert (es kann ein Tupel von Werten sein).
  4. Der Ausdruck in der Schaltstruktur bestimmt die Position, kann eine Zeichenfolge, eine Variable, einen Ausdruck oder einen Funktionsanruf schreiben.
  5. switch ermöglicht die Angabe eines Rückgabewerts, der als Standardwert dient, wenn kein anderer Fall in der Struktur ausgeführt werden muss.

Es gibt zwei Arten von Schalter, schauen wir uns die Beispiele einzeln an, um ihre Verwendung zu verstehen.

  1. Eineswitchmit Ausdrücken - Beispiel Erklärung:
// input.string: defval, title, options, tooltip
func = input.string("EMA", title="indicator name", tooltip="select the name of the indicator function to be used", options=["EMA", "SMA", "RMA", "WMA"])

// input.int: defval, title, options, tooltip
// param1 = input.int(10, title="period parameter")
fastPeriod = input.int(10, title="fastPeriod parameter", options=[5, 10, 20])
slowPeriod = input.int(20, title="slowPeriod parameter", options=[20, 25, 30])

data = input(close, title="data", tooltip="select the closing price, opening price, highest price...")
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 die Eingabefunktion schon früher gelernt, hier lernen wir zwei Funktionen weiter, die der Eingabe ähneln:input.string, input.int functions. input.stringwird verwendet, um eine Zeichenfolge zurückzugeben, und dieinput.intFunktion verwendet wird, um einen ganzen Wert zurückzugeben.optionsDieoptionsParameter kann ein Array von optionalen Werten übergeben werden, wieoptions=["EMA", "SMA", "RMA", "WMA"]undoptions=[5, 10, 20]In diesem Fall müssen die Steuerelemente der Strategieoberfläche keine spezifischen Werte eingeben, sondern werden zu Dropdown-Boxen, um diese Optionen auszuwählen, die im Optionsparameter angegeben sind.

Der Wert der Variablen func ist eine Zeichenkette, und die Variable func wird als Ausdruck für switch verwendet (der eine Variable, Funktionsaufruf oder Ausdruck sein kann), um zu bestimmen, welcher Zweig im Switch ausgeführt wird.runtime.error("error")Funktion ausgeführt wird, wodurch die Strategie eine Ausnahme wirft und stoppt.

In unserem obigen Testcode haben wir nach der letzten Zeile von runtime.error im standardmäßigen Branchcode-Block von switch keinen Code wie [na, na] hinzugefügt, um mit dem Rückgabewert kompatibel zu sein. Dieses Problem muss in der Trading View berücksichtigt werden. Wenn der Typ inkonsistent ist, wird ein Fehler gemeldet. Aber in FMZ, da der Typ nicht streng erforderlich ist, kann dieser Kompatibilitätscode weggelassen werden. Daher ist es nicht notwendig, die Typkompatibilität des Rückgabewerts von if und Switch Branches in FMZ zu berücksichtigen.

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, aber auf der Handelsansicht wird ein Fehler gemeldet, da der vom if-Zweig zurückgegebene Typ inkonsistent ist.

  1. switchohne Ausdruck

Als nächstes schauen wir uns eine andere Möglichkeit an,switchDas heißt, ohne Ausdrücke.

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)

Wie wir aus dem Testcode-Beispiel sehen können, wird der Switch mit der Ausführung des lokalen Codeblocks übereinstimmen, der auf der Branch-Bedingung wahr ist. Im Allgemeinen müssen sich die Branch-Bedingungen nach einer Switch-Anweisung gegenseitig ausschließen. Das heißt, oben und unten im Beispiel können nicht gleichzeitig wahr sein. Da der Switch nur den lokalen Codeblock eines Branches ausführen kann, können Sie, wenn Sie interessiert sind, diese Zeile im Code ersetzen:up = close > open // up = close < openSie werden feststellen, dass der Switch-Branch nur den ersten Branch ausführen kann. Darüber hinaus ist es notwendig, darauf zu achten, keine Funktionsanrufe in den Branch des Switches so weit wie möglich zu schreiben, da die Funktion nicht auf jeder BAR aufgerufen werden kann, was einige Datenberechnungsprobleme verursachen kann (es sei denn, wie im Beispiel "switchmit den Ausdrücken "der Ausführungszweig ist deterministisch und wird während des Strategiebetriebs nicht geändert).

Schleifstruktur

für eine Erklärung

return value = for count = start count to final count by step length
    statement                                            // Note: There can be break and continue in the statement
    statement                                            // Note: The last statement is the return value

Die for-Anweisung ist sehr einfach zu bedienen, die for-Schleife kann schließlich einen Wert (oder mehrere Werte in Form von [a, b, c]) zurückgeben. Wie die Variable, die der Position return value im Pseudocode oben zugewiesen wird. Der for-Anweisung folgt eine count Variable, die zur Steuerung der Anzahl der Schleifen, Bezug auf andere Werte usw. verwendet wird. Der count Variablen wird die initial count zugewiesen, bevor die Schleife beginnt, dann steigt sie entsprechend der step length-Einstellung, und die Schleife stoppt, wenn die count Variable größer ist als die final count.

DiebreakSchlüsselwort in der For-Schleife verwendet: die Schleife stoppt, wenn diebreakAnweisung ausgeführt. DiecontinueSchlüsselwort in der For-Schleife verwendet:continueWenn die Anweisung ausgeführt wird, ignoriert die Schleife den Code nachcontinueDie For-Anweisung gibt den Rückgabewert der letzten Ausführung der Schleife zurück und gibt null zurück, wenn kein Code ausgeführt wird.

Dann demonstrieren wir mit einem einfachen Beispiel:

ret = for i = 0 to 10       // We can increase the keyword by to modify the step length, FMZ does not support reverse loops such as i = 10 to 0 for now
    // We can add condition settings, use continue to skip, use break to jump out
    runtime.log("i:", i)
    i                       // If this line is not written, it will return null because there is no variable to return
    
runtime.log("ret:", ret)
runtime.error("stop")

für... in der Erklärung

Diefor ... inDie Aussage hat zwei Formen, die wir im folgenden Pseudocode illustrieren.

return value = for array element in array 
    statement                        // Note: There can be break and continue in the statement
    statement                        // Note: The last statement is the return value
Return value = for [index variable, array element corresponding to index variable] in array
    statement                        // Note: There can be break and continue in the statement
    statement                        // Note: The last statement is the return value 

Wir können sehen, dass der Hauptunterschied zwischen den beiden Formen der Inhalt ist, der dem Schlüsselwort for folgt, einer ist die Verwendung einer Variable als Variable, die sich auf die Elemente des Arrays bezieht, der andere ist die Verwendung einer Struktur, die Indexvariablen, Tupel von Array-Elementvariablen als Referenzen enthält.

testArray = array.from(10, 20, 30, 40, 50, 60, 70, 80, 90, 100)
for ele in testArray            // Modify it to the form of [i, ele]: for [i, ele] in testArray, runtime.log("ele:", ele, ", i:", i)
    runtime.log("ele:", ele)

runtime.error("stop")

Wenn Sie den Index verwenden müssen, verwenden Sie die Grammatikfor [i, ele] in testArray.

Anwendungsbereich der für Schleifen

Wir können die in der Pine-Sprache bereitgestellten eingebauten Funktionen verwenden, um einige der Loop-Logikberechnungen abzuschließen, die entweder direkt mit der Loop-Struktur geschrieben oder mit den eingebauten Funktionen verarbeitet werden.

  1. Berechnen Sie den Mittelwert

Bei der Konstruktion mit einer Schleifstruktur:

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)

Das Beispiel verwendet eine For-Schleife, um die Summe zu berechnen und dann den Mittelwert zu berechnen.

Berechnen Sie den gleitenden Durchschnitt direkt mit der eingebauten Funktion:

plot(ta.sma(close, length), title="ta.sma", overlay=true)

Verwenden Sie die eingebaute Funktionta.smaEs ist offensichtlich einfacher, die eingebaute Funktion zur Berechnung des gleitenden Durchschnitts zu verwenden.

  1. Zusammenfassung

Wir verwenden immer noch das obige Beispiel zum Veranschaulichen.

Bei der Konstruktion mit einer Schleifstruktur:

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 in einem Array können wir eine Schleife verwenden, um es zu verarbeiten, oder verwenden Sie die eingebaute Funktionarray.sumIch habe eine Frage an Sie. Berechnen Sie die Summe direkt mit der eingebauten Funktion:

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)

Wir können sehen, dass die berechneten Daten genau die gleichen sind wie die, die auf der Grafik mit Grafiken angezeigt werden.

Warum also Schleifen entwerfen, wenn wir all das mit eingebauten Funktionen tun können?

  1. Für einige Operationen und Berechnungen für Arrays.
  2. Da der Höhepunkt des aktuellen BAR nur an der BAR bekannt ist, in der das Skript ausgeführt wird, ist eine Schleife erforderlich, um die vergangenen BARs rechtzeitig zurückzugeben und zu analysieren.
  3. Wenn Pine-Sprache eingebaute Funktionen können keine Berechnungen für vergangene BARs abschließen.

während statemnet

DiewhileDie Anweisung hält den Code in der Schleife auszuführen, bis die Beurteilungsbedingung in der while-Struktur falsch ist.

return value = while judgment condition
    statement                    // Note: There can be break and continue in the statement
    statement                    // Note: The last statement is the return value

Andere Regeln von while ähneln denen der for-Schleife. Die letzte Zeile des lokalen Code-Blocks des Loop-Körpers ist der Rückgabewert, der mehrere Werte zurückgeben kann. Die Schleife wird ausgeführt, wenn die loop-Bedingung wahr ist, und die Schleife wird gestoppt, wenn die Bedingung falsch ist. Die Break- und Continue-Anweisungen können auch im Loop-Körper verwendet werden.

Wir verwenden weiterhin das Beispiel der Berechnung gleitender Durchschnitte zur Demonstration:

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)

Wir können sehen, dass die while-Schleife auch sehr einfach zu bedienen ist, und es ist auch möglich, einige Berechnungslogik zu entwerfen, die nicht durch die eingebauten Funktionen ersetzt werden kann, wie die Berechnung von Faktoren:

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

Arrays

Die Definition von Arrays in der Pine-Sprache ist ähnlich wie in anderen Programmiersprachen. Pines Arrays sind eindimensionale Arrays. Normalerweise werden sie verwendet, um eine kontinuierliche Datenreihe zu speichern. Die einzelnen in der Array gespeicherten Daten werden als Element des Arrays bezeichnet, und die Arten dieser Elemente können sein: ganzzahlend, Schwimmballpunkt, Zeichenfolge, Farbwert, Booleanwert. Die Pine-Sprache auf FMZ ist nicht sehr streng hinsichtlich der Typen und kann sogar Zeichenfolgen und Zahlen gleichzeitig in einem Array speichern. Da die zugrunde liegende Struktur des Arrays auch eine Reihenstruktur ist, wird der historische Operator verwendet, um sich auf den Arrayzustand auf der vorherigen BAR zu beziehen.[]Um auf ein Element im Array zu verweisen, müssen wir die Funktionen verwendenarray.get()undarray.set()Die Indexreihenfolge der Elemente im Array ist, dass der Index des ersten Elements des Arrays 0 beträgt und der Index des nächsten Elements um 1 erhöht wird.

Wir veranschaulichen es mit einem einfachen Code:

var a = array.from(0)
if bar_index == 0 
    runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1])
else if bar_index == 1 
    array.push(a, bar_index)
    runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1])
else if bar_index == 2
    array.push(a, bar_index)
    runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1], ", a on the last second BAR, i.e. the value of a[2]:", a[2])
else if bar_index == 3 
    array.push(a, bar_index)
    runtime.log("current value a on BAR:", a, ", a on the last BAR, i.e. the value of a[1]:", a[1], ", a on the last second BAR, i.e. the value of a[2]:", a[2], ", a on the last third BAR, i.e. the value of a[3]:", a[3])
else if bar_index == 4 
    // Obtain elements by index using array.get, modify elements by index using array.set
    runtime.log("Before array modification:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))
    array.set(a, 1, 999)
    runtime.log("After array modification:", array.get(a, 0), array.get(a, 1), array.get(a, 2), array.get(a, 3))

Ein Array deklarieren

Verwendungarray<int> a, float[] bum ein Array zu deklarieren oder einfach eine Variable zu deklarieren, die einem Array zugewiesen werden kann, zum Beispiel:

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")

Die Array-Variablen werden mit derarray.newundarray.fromEs gibt auch viele typenbezogene Funktionen ähnlich wiearray.newin der Kiefersprache:array.new_int(), array.new_bool(), array.new_color(), array.new_string(), usw.

Das Schlüsselwort var funktioniert auch mit dem Array-Deklarationsmodus. Arrays, die mit dem Schlüsselwort var deklariert werden, werden nur auf der ersten BAR initialisiert.

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")

Es kann gesehen werden, dass die Änderungen des Arrays a kontinuierlich bestimmt und nicht zurückgesetzt wurden. Das Array b wird auf jeder BAR initialisiert.barstate.islastist wahr, gibt es immer noch nur ein Element mit einem Wert von 0.

Lesen und Schreiben von Elementen in einem Array

Verwenden Sie array.get, um das Element an der angegebenen Indexposition im Array zu erhalten, und verwenden Sie array.set, um das Element an der angegebenen Indexposition im Array zu ändern.

Der erste Parameter von array.get ist das zu verarbeitende Array, und der zweite Parameter ist der angegebene Index. Der erste Parameter von array.set ist das zu verarbeitende Array, der zweite Parameter ist der angegebene Index und der dritte Parameter ist das zu schreibende Element.

Wir verwenden das folgende einfache Beispiel:

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")

Das Beispiel initialisiert die Grundfarbe grün, deklariert und initialisiert ein Array, um Farben zu speichern, und weist dann den Farben unterschiedliche Transparenzwerte zu (mit Hilfe dercolor.newDer Farbwert wird berechnet, indem man den Abstand des aktuellen BARs vom maximalen Wert von HIGH in 100 Lookback-Perioden berechnet. Je näher der Abstand zum maximalen Wert von HIGH in den letzten 100 Lookback-Zyklen ist, desto höher ist der Rang und desto dunkler (niedriger Transparenz) der entsprechende Farbwert. Viele ähnliche Strategien verwenden diese Methode, um den aktuellen Preisniveau innerhalb von N Lookback-Perioden darzustellen.

Iteration durch Array-Elemente

Wie man durch ein Array iteriert, können wir die for/for in/while Anweisungen verwenden, die wir zuvor gelernt haben.

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")
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")
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")

Diese drei Durchlaufmethoden haben die gleichen Ausführungsergebnisse.

Arrays können im globalen Bereich eines Skripts oder im lokalen Bereich einer Funktion oder eines If-Branches deklariert werden.

Referenzen zu historischen Daten

Für die Verwendung von Elementen in Arrays sind die folgenden Möglichkeiten gleichwertig. Wir können durch das folgende Beispiel sehen, dass zwei Liniensätze auf dem Diagramm gezogen werden, zwei in jedem Satz, und die beiden Linien in jedem Satz haben genau den gleichen Wert.

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 Löschen von Arrays

  1. Funktionen im Zusammenhang mit der Addition von Arrays:

array.unshift(), array.insert(), array.push().

  1. Funktionen im Zusammenhang mit dem Löschen von Arrays:

array.remove(), array.shift(), array.pop(), array.clear().

Wir verwenden das folgende Beispiel, um diese Array-Zusatz- und Löschoperationsfunktionen zu testen.

a = array.from("A", "B", "C")
ret = array.unshift(a, "X")
runtime.log("array a:", a, ", ret:", ret)

ret := array.insert(a, 1, "Y")
runtime.log("array a:", a, ", ret:", ret)

ret := array.push(a, "D")
runtime.log("array a:", a, ", ret:", ret)

ret := array.remove(a, 2)
runtime.log("array a:", a, ", ret:", ret)

ret := array.shift(a)
runtime.log("array a:", a, ", ret:", ret)

ret := array.pop(a)
runtime.log("array a:", a, ", ret:", ret)

ret := array.clear(a)
runtime.log("array a:", a, ", ret:", ret)

runtime.error("stop")

Anwendung von Ergänzungen, Löschungen: Arrays als Warteschlangen

Wir können eine Warteschlange Datenstruktur konstruieren, indem wir Arrays und einige Funktionen zum Hinzufügen und Löschen von Arrays verwenden. Warteschlange können verwendet werden, um den gleitenden Durchschnitt der Tick-Preise zu berechnen. Jemand mag fragen, Warum sollten wir eine Warteschlange-Struktur konstruieren? Haben wir nicht zuvor Arrays verwendet, um den Durchschnitt zu berechnen?

Eine Warteschlange ist eine Struktur, die häufig im Bereich der Programmierung verwendet wird. Die Merkmale einer Warteschlange sind:

Das Element, das zuerst in die Warteschlange kommt, verlässt die Warteschlange zuerst.

Auf diese Weise wird sichergestellt, dass die Daten in der Warteschlange die neuesten Daten sind und dass sich die Warteschlange nicht unbegrenzt erweitert.

In dem folgenden Beispiel verwenden wir eine Warteschlange, um den Preis jedes Ticks aufzuzeichnen, den mobilen Durchschnittspreis auf dem Tickspiegel zu berechnen und ihn dann mit dem gleitenden Durchschnitt auf der 1-minütigen K-Line-Ebene zu vergleichen.

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 beim Deklarieren von Array a den Deklarierungsmodus angeben und das SchlüsselwortvariantAuf diese Weise wird jede Preisänderung in der Matrix a erfasst.

Häufig verwendete Funktionen für die Berechnung und Bedienung von Arrays

Berechnung der Korrelationsfunktionen:

array.avg()berechnet den Durchschnittswert aller Elemente in einem Array,array.min()berechnet das kleinste Element in einem Array,array.max()berechnet das kleinste Element in einem Array,array.stdev()berechnet die Standardabweichung aller Elemente in einem Array,array.sum()berechnet die Standardabweichung aller Elemente in einem Array.

Betriebsbezogene Funktionen:array.concat()Um zwei Arrays zu verschmelzen oder zu verketten.array.copy()um das Array zu kopieren.array.jointo verknüpft alle Elemente eines Arrays in eine Zeichenfolge.array.sort()nach Aufstiegs- oder Abstiegsreihenfolge sortieren.array.reverse()Um die Anordnung umzukehren.array.slice()um die Matrix zu schneiden.array.includes()Das Element zu beurteilen.array.indexof()Wenn der Wert nicht gefunden wird, wird -1 zurückgegeben.array.lastindexof()um das letzte Auftreten des Wertes zu finden.

Prüfbeispiele für Arrayberechnungsfunktionen:

a = array.from(3, 2, 1, 4, 5, 6, 7, 8, 9)

runtime.log("Arithmetic average of the array a:", array.avg(a))
runtime.log("The minimum element in the array a:", array.min(a))
runtime.log("The maximum element in the array a:", array.max(a))
runtime.log("Standard deviation in array a:", array.stdev(a))
runtime.log("Sum of all elements of the array a:", array.sum(a))
runtime.error("stop")

Dies sind häufig verwendete Array-Rechenfunktionen.

Beispiele für betriebliche Funktionen:

a = array.from(1, 2, 3, 4, 5, 6)
b = array.from(11, 2, 13, 4, 15, 6)

runtime.log("array a: ", a, ", array b: ", b)
runtime.log("array a, array b is concatenated with:", array.concat(a, b))
c = array.copy(b)

runtime.log("Copy an array b and assign it to the variable c, variable c:", c)

runtime.log("use array.join to process the array c, add the symbol + to the middle of each element, concatenating all elements results in a string:", array.join(c, "+"))
runtime.log("Sort the array b, in order from smallest to largest, using the parameter order.ascending:", array.sort(b, order.ascending))     // array.sort function modifies the original array
runtime.log("Sort the array b, in order from largest to smallest, using the parameter order.descending:", array.sort(b, order.descending))   // array.sort function modifies the original array

runtime.log("array a:", a, ", array b:", b)
array.reverse(a)   // This function modifies the original array
runtime.log("reverse the order of all elements in the array a, after reversing, the array a is:", a)    

runtime.log("Intercept array a, index 0~index 3, and follow the rule of left-closed and right-open interval:", array.slice(a, 0, 3))
runtime.log("Search for element 11 in array b:", array.includes(b, 11))
runtime.log("Search for element 100 in array a:", array.includes(a, 100))
runtime.log("Connect array a and array b, and search the index position of the first occurrence of element 2:", array.indexof(array.concat(a, b), 2), " , observe array.concat(a, b):", array.concat(a, b))
runtime.log("Connect array a and array b, and search the index position of the last occurrence of element 6:", array.lastindexof(array.concat(a, b), 6), " , observe array.concat(a, b):", array.concat(a, b))

runtime.error("stop")

Funktionen

Benutzerdefinierte Funktionen

Die Pine-Sprache kann mit benutzerdefinierten Funktionen gestaltet werden.

  1. Alle Funktionen werden im globalen Bereich des Skripts definiert. Eine Funktion kann nicht innerhalb einer anderen Funktion deklariert werden.
  2. Funktionen dürfen sich nicht selbst in ihrem eigenen Code aufrufen (Rekursion).
  3. Grundsätzlich werden alle in PINE-Sprache integrierten Zeichnungsfunktionen (barcolor(), fill(), hline(), plot(), plotbar(), plotcandle()) kann nicht in benutzerdefinierten Funktionen aufgerufen werden.
  4. Funktionen können als einzelne Zeile oder mehrere Zeilen geschrieben werden. Der Rückgabewert der letzten Anweisung ist der Rückgabewert der aktuellen Funktion, die in Tupelform zurückgegeben wird.

Wir haben die benutzerdefinierten Funktionen auch in unseren früheren Tutorials viele Male verwendet, wie zum Beispiel die, die als eine einzige Zeile entworfen wurden:

barIsUp() => close > open

Ob die aktuelle BAR eine positive Linie ist, wenn die Funktion zurückkehrt.

Benutzerdefinierte Funktionen, die für mehrere Zeilen ausgelegt sind:

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)

Wir verwenden eine benutzerdefinierte Funktion, um eine Funktion der SMA-Durchschnittsberechnung zu realisieren.

Darüber hinaus gibt es zwei Beispiele für benutzerdefinierte Funktionen, die wir zurückgeben können:

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 kann die schnelle Linie, die langsame Linie und zwei EMA-Durchschnitte berechnen.

Einbaufunktionen

Die integriertenFMZ PINE Skriptdokument.

Klassifizierung der eingebauten Funktionen in der Pine-Sprache:

  1. Stringverarbeitungsfunktionstr. series.
  2. Die Farbwertverarbeitungsfunktioncolor. series.
  3. Parameter-Eingabefunktioninput. series.
  4. Indikatorberechnungsfunktionta. series.
  5. Zeichnungsfunktionplot. series.
  6. Array-Handling-Funktionarray. series.
  7. Handelsbezogene Funktionen derstrategy. series.
  8. Funktionen im Zusammenhang mit mathematischen Operationenmath. series.
  9. Sonstige Funktionen (Zeitverarbeitung, Nicht-Grafikreihe-Zeichnungsfunktionen,request.Serienfunktionen, Typbehandlungsfunktionen usw.)

Handelsfunktionen

Diestrategy.Funktionsreihen sind Funktionen, die wir häufig bei der Gestaltung von Strategien verwenden, und diese Funktionen sind eng mit der Ausführung von Handelsoperationen verbunden, wenn die Strategie speziell ausgeführt wird.


  1. strategy.entry

strategy.entryFunktion ist eine wichtigere Funktion, wenn wir eine Strategie schreiben, um eine Bestellung zu platzieren, sind mehrere wichtige Parameter für die Funktion:id, direction, qty, when, usw.

Parameter:

  • id: Dies kann verstanden werden als die Angabe eines Namens für eine Handelsposition zur Referenz.
  • direction: Wenn die Bestellrichtung lang ist (kaufen), geben Sie die eingebaute Variable einstrategy.long, und wenn Sie kurz gehen wollen (verkaufen), geben Sie die Variablestrategy.short.
  • qty: Geben Sie den zu platzierenden Auftragsbetrag an, wenn dieser Parameter nicht übergeben wird, wird der Standardbetrag der Aufträge verwendet.
  • when: Ausführungsbedingung, Sie können diesen Parameter angeben, um zu kontrollieren, ob diese aktuelle Auftragsoperation ausgelöst wird oder nicht.
  • limit: Geben Sie den Auftragsbegrenzungspreis an.
  • stopStop-Loss-Preis.

Die spezifischen Einzelheiten der Ausführung desstrategy.entryFunktion durch die Parameter-Einstellungen gesteuert werden, wenn diestrategyFunktion aufgerufen wird, und es kann auch durch die gesteuert werden [Pine Language Trade-Class Library Template Argumente](https://www.fmz.com/bbs-topic/9293#template-- arguments-of-pine-language-trade-class-library) Einstellung Steuerung, Pine-Language Trade-Class Bibliotheksvorlage Argumente mehr Details der Transaktion steuern, Sie können die verknüpfte Dokumentation für Details überprüfen.

Wir konzentrieren unspyramiding, default_qty_valueParameter in derstrategyWir verwenden den folgenden Code zum Testen:

/*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)

Der Teil am Anfang des Codes/* backtest... */ist eine Backtest-Einstellung, die verwendet wird, um die Backtest-Einstellungszeit und andere Informationen zu diesem Zeitpunkt für das Debugging zu erfassen, nicht den Startcode.

Der Code lautet:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true), wenn wir diepyramidingParameter als 3, setzen wir die maximale Anzahl der Trades in der gleichen Richtung auf 3. Also eine der vierstrategy.entryDa wir auch angegeben haben, diedefault_qty_valueParameter 0,1, dasstrategy.entryBetrieb mit IDlong1hat eine Standardordergröße von 0,1strategy.entryFunktion aufrufen, wenn wir diedirectionalsstrategy.long, also sind die Test-Backtest-Bestellungen alle Kaufbestellungen.

Beachten Sie, dass die Bestelloperationstrategy.entry("long3", ...in dem Code zweimal für die gleiche ID aufgerufen wird:long3, die erstestrategy.entryDie zweite Aufforderung an diestrategy.entryEine andere Möglichkeit ist, wenn z. B. die erste Reihenfolge mit ID long3 ausgefüllt ist, diestrategy.entryFunktion, um Aufträge gemäß der ID long3 zu platzieren, dann werden die Orderpositionen auf der ID long3 angesammelt.


  1. strategy.close

Diestrategy.closeDie Funktion wird verwendet, um die Eingangsposition mit der angegebenen Identifikationskennung zu schließen.id, when, qty, qty_percent.

Parameter:

  • id: Die zu schließende Eintritts-ID ist die ID, die wir angeben, wenn wir eine Position mit einer Eintritts-Orderfunktion eröffnen, z. B.strategy.entry.
  • when: Durchführungsbedingungen.
  • qty: Anzahl der geschlossenen Positionen.
  • qty_percent: Prozentsatz der geschlossenen Positionen

Lassen Sie uns mit einem Beispiel die Einzelheiten der Verwendung dieser Funktion kennenlernen: Die/*backtest ... */in dem Code sind die Konfigurationsinformationen fürFMZ.COMInternational Website Backtest, Sie können es löschen und setzen Sie den Markt, Sorte, Zeitrahmen und andere Informationen, die Sie testen müssen.

/*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")                   // Multiple entry orders, no qty parameters specified, close all
    // strategy.close()                          // Without specifying the id parameter, the current position will be closed
    // strategy.close("long2")                   // If a non-existent id is specified then nothing is done
    // strategy.close("long1", qty=0.15)         // Specify qty parameters to close a position
    // strategy.close("long1", qty_percent=50)   // qty_percent is set to 50 to close 50% of the positions marked by long1
    // strategy.close("long1", qty_percent=80, when=close<open)  // Specify the parameter when, change it to close>open and it won't trigger
    enableStop := true

Die Teststrategie zeigt drei aufeinanderfolgende lange Eingaben mit der Eingabe-ID long1 und verwendet dann verschiedene Parameter derstrategy.closeDie Funktion zur Einstellung der verschiedenen Ergebnisse des Backtests beim Schließen einer Position.strategy.closeFunktion hat keine Parameter, um den Preis der Bestellung zum Schließen der Position anzugeben, diese Funktion wird hauptsächlich verwendet, um die Position sofort zum aktuellen Marktpreis zu schließen.


  1. strategy.close_all

Die Funktionstrategy.close_allwird verwendet, um alle aktuellen Positionen zu schließen, weil die Pine-Skript-Sprache Positionen nur eine Richtung haben kann, das heißt, wenn es ein Signal in der entgegengesetzten Richtung der aktuellen Position ausgelöst wird die aktuelle Position schließen und dann öffnen Sie es nach dem Signal auslösen.strategy.close_allDer Hauptparameter derstrategy.close_allFunktion ist:when.

Parameter:

  • when: Durchführungsbedingungen.

Lassen Sie uns ein Beispiel verwenden:

/*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 Prüfcode beginnt mit einer Positionsnummer 0 (d. h.strategy.position_size==0ist wahr), so dass, wenn die Bedingungen, die durch die wenn Parameter erfüllt sind, nur diestrategy.entryEintrittsfunktion mit ID long wird ausgeführt.strategy.position_sizeist größer als 0, dann kann die Eingabefunktion mit ID short ausgeführt werden, da die aktuelle Long-Position gehalten wird, wird dieses Shorting-Umkehrsignal zu diesem Zeitpunkt dazu führen, dass die Long-Position geschlossen und dann die Short-Position in entgegengesetzte Richtung geöffnet wird.strategy.position_size < 0, d. h. wenn eine Short-Position gehalten wird, werden alle Positionen in der aktuellen Halterichtung geschlossen.enableStop := true. Stoppt die Strategieausführung, damit das Protokoll beobachtet werden kann.

Es kann festgestellt werden, dass die Funktionstrategy.close_allDie Funktion "Lösung der Position" ist eine Funktion, bei der der Bestellpreis nicht angegeben wird.


  1. strategy.exit

Diestrategy.exitDiese Funktion wird verwendet, um eine Eingangsposition zu schließen.strategy.closeundstrategy.close_allDie Funktionen schließen eine Position sofort zum aktuellen Marktpreis ab.strategy.exitDie Funktion schließt die Position nach den Parameter-Einstellungen.

Parameter:

  • id: Die Auftragsidentifikator-ID der aktuellen Auftragsverbindung.
  • from_entry: Verwendet zur Angabe der Eingabe-ID der zu schließenden Position.
  • qty: Anzahl der geschlossenen Positionen.
  • qty_percent: Prozentsatz der geschlossenen Positionen, Bereich: 0 ~ 100.
  • profit: Gewinnziel in Punkten.
  • loss: Stop-Loss-Ziel, ausgedrückt in Punkten.
  • limit: Gewinnziel, durch Preis angegeben.
  • stop: Stop-Loss-Ziel, angegeben durch den Preis.
  • when: Durchführungsbedingungen.

Verwenden Sie eine Teststrategie, um die Parameterverwendung zu verstehen.

/*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")          // If only one id parameter is specified, the exit order is invalid, and the parameters profit, limit, loss, stop and other exit conditions also need to be set at least one, otherwise it is also invalid
    strategy.exit("exit1", "long1", profit=50)                    // Since the long1 entry order is not filled, the exit order with ID exit1 is also on hold until the corresponding entry order is filled before exit1 is placed
    strategy.exit("exit2", "long2", qty=0.1, profit=100)          // Specify the parameter qty to close 0.1 positions in the position with ID long2
    strategy.exit("exit3", "long3", qty_percent=50, limit=strategy.opentrades.entry_price(findOrderIdx("long3")) + 1000)   // Specify the parameter qty_percent to close 50% of the positions in the position with ID long3
    isExit := true 

if bar_index == 0 
    runtime.log("The price per point:", syminfo.mintick)    // The price per point is related to the "Pricing Currency Precision" parameter setting on the Pine language template parameters

Wir verwenden das Echtzeit-Preismodell für Backtest, die Teststrategie beginnt mit 3 Eingabeoperationen (strategy.entryFunktion) undlong1wird absichtlich mitlimitParameter mit einem ausstehenden Auftragspreis von 1, so dass es nicht ausgefüllt werden kann.strategy.exitWir haben die take profit by point und take profit by price, den Schluß einer festen Anzahl von Positionen und die Schlußpositionen in Prozent verwendet.strategy.exitFunktion hat auch komplexere Trailing Stop-Parameter:trail_price, trail_points, trail_offsetkann auch in diesem Beispiel getestet werden, um ihre Verwendung zu lernen.


  1. strategy.cancel

Diestrategy.cancelFunktionen werden verwendet, um alle ausstehenden Aufträge zu stornieren/stoppen.strategy.order, strategy.entry , strategy.exitDie wichtigsten Parameter dieser Funktion sind:id, when.

Parameter:

  • id: Die Eintrittskarte wird gestrichen.
  • when: Durchführungsbedingungen.

Diese Funktion ist leicht zu verstehen und wird verwendet, um nicht ausgefüllte Eintrittsbestellungen zu stornieren.

/*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

Mehr