Inventor Quantitative PINE Language Einführungs-Tutorial

Erstellt in: 2022-05-30 16:23:43, aktualisiert am: 2022-09-28 17:10:21
comments   0
hits   8860

rioritä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:
    1. Schlüsselwörter verwendenvar
    2. Schlüsselwörter verwendenvarip
    3. Nichts schreiben.

varvaripDie 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.

  • 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.1

Die 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!

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.ifforwhileoderswitchDie 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:

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.

Inventor Quantitative PINE Language Einführungs-Tutorial

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.

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

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.

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

Die if-Anweisung

Das ist ein Beispiel:

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.

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.

  1. Die switch-Anweisung kann wie die if-Anweisung einen Wert zurückgeben.
  2. 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].
  3. 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.
  4. Ausdrücke in der Switch-Struktur können als Zeichenfolgen, Variablen, Ausdrücke oder Funktionen bezeichnet werden.
  5. 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.

  1. mit einem AusdruckswitchEin Beispiel:
// 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.stringinput.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.

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.

  1. Nicht ausgedrücktswitch

Wir werden sehen.switchEine andere Verwendung ist die Schreibweise ohne Ausdruck.

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 < openEs 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:

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.

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.

  1. Berechnung des Mittelwerts

Wenn Sie eine Kreislaufstruktur verwenden:

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:

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.

  1. Zählung

Oder nutzen Sie das oben genannte Beispiel.

Wenn Sie eine Kreislaufstruktur verwenden:

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:

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? 1. Für einige Operationen mit Arrays. 2. 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. 3. 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:

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:

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:

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> afloat[] bArrays, die Arrays deklarieren oder nur eine Variable deklarieren, können Arrays zugeordnet werden, z. B.:

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 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.

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:

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?

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

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.

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

  1. Funktionen, die mit der Addition von Arrays zusammenhängen:

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

  1. 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:

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.

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:

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:

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:

  1. Alle Funktionen sind im globalen Umfang des Skripts definiert. Eine Funktion kann nicht in einer anderen Funktion deklariert werden.
  2. Die Funktion darf sich nicht in ihrem eigenen Code selbst () aufrufen.
  3. 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.
  4. 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:

barIsUp() => close > open

Die Funktion gibt zurück, ob der aktuelle BAR der Sonnenstrahl ist.

Entworfen als mehrsprachige benutzerdefinierte Funktion:

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:

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:

  1. Funktionen zur String-Verarbeitungstr.Die Serie
  2. Funktion zur Farbwertverarbeitungcolor.Die Serie
  3. Funktion zur Eingabe von Parameterninput.Die Serie
  4. Funktion zur Berechnung der Indikatorenta.Die Serie
  5. Graphische Funktionplot.Die Serie
  6. Array-Funktionenarray.Die Serie
  7. Transaktionsbezogene Funktionenstrategy.Die Serie
  8. Funktionen für mathematische Operationenmath.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 Funktionpyramidingdefault_qty_valueParameter ◦ Test mit folgenden Codes:

/*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 long1strategy.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: long3.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:idwhenqtyqty_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.

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

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

/*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_pricetrail_pointstrail_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:idwhen

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.

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