Die Ressourcen sind geladen. Beförderung...

Erfinder quantifizieren PINE-Einführung in die Sprache

Schriftsteller:Die Erfinder quantifizieren - Kleine Träume, Erstellt: 2022-05-30 16:23:43, Aktualisiert: 2022-09-28 17:10:21

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)

Wichtig: Ausdrücke, die für die Beurteilung verwendet werden, die einen Boole-Wert zurückgeben. Bitte beachten Sie die Verkleinerung. Es kann maximal nur eine Else-Abteilung geben. Alle Branch-Expressionen sind nicht wahr und keine Else-Abteilung gibt es, die na zurückgibt.

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

Da der if-Ausdruck nach dem if-Satz false ist, wenn die K-Linie BAR die Centauri ist, also close < open, wird der lokale Codeblock für if nicht ausgeführt. Auch in diesem Fall gibt es keinen Else-Branch. Der if-Ausdruck gibt na zurück.

Schaltzeintrag

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

1, wie auch die Switch-Sprache und die if-Sprache, kann einen Wert zurückgeben. 2. Im Gegensatz zu anderen Sprachen, in denen die Switch-Sprache nur einen lokalen Block in ihrem Code ausführt, ist eine Break-Ankündigung unnötig (d. h. es ist kein Schlüsselwort wie break erforderlich). 3. Jeder Branch des Switches kann einen lokalen Codeblock schreiben, dessen letzte Zeile den zurückgegebenen Wert ist. 4. Beurteilen Sie die Position der Ausdrücke in der Switch-Struktur und schreiben Sie Strings, Variablen, Ausdrücke oder Funktionsanrufe. 5. Switch erlaubt die Angabe eines Rückgabewerts, der als Default verwendet wird, wenn keine andere Situation in der Struktur ausgeführt wird.

Die Schalter sind in zwei Formen unterteilt, und wir werden ein Beispiel für ein Beispiel betrachten, um zu verstehen, wie sie verwendet werden.

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 die Input-Funktion gelernt, und wir lernen hier zwei ähnliche Funktionen:input.stringinput.intDie Funktion.input.stringDas ist ein sehr schwieriges Problem, aber es gibt viele Möglichkeiten.input.intDie Funktion wird verwendet, um einen ganzen Wert zurückzugeben.optionsDie Verwendung von ParameternoptionsDie Parameter können in eine Array von Optionswerten ü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 Kontrollen in der Schaltfläche keine spezifischen Werte mehr eingegeben werden, sondern werden zu einem Dropdown-Box, in dem die in den Options-Parametern bereitgestellten Optionen ausgewählt werden.

Der Wert der Variable func ist eine String, die als Ausdruck der Variable func verwendet wird, um zu bestimmen, welcher Branch in der ausgeführten Switch ausgeführt wird. Wenn die Variable func nicht mit den Ausdrücken auf einem der Branchen in der Switch übereinstimmt, wird der Standard-Branch-Block ausgeführt, der ausgeführt wird.runtime.error("error")Die Funktion führt dazu, dass die Strategie abweichend stoppt.

In unserem Testcode oben haben wir nach der letzten Zeile des Runtime.error des Standard-Branch-Code-Blocks von Switch keinen Code wie [na, na] hinzugefügt, um einen kompatiblen Wert zurückzugeben, der in der Handelsansicht berücksichtigt werden muss, wenn der Typ nicht übereinstimmt.

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)

In der FMZ werden keine Fehler gemeldet, in der Trading View werden Fehler gemeldet.

2 gibt es nicht.switch

Wir werden sehen.switchEine andere Art der Verwendung ist, dass sie nicht mit einer expressiven Schrift geschrieben wird.

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)

In den Test-Code-Beispielen kann man sehen, dass Switch den lokalen Codeblock mit der Ausführungsbedingung für den Branch als wahr anpasst. Im Allgemeinen müssen sich die Branchbedingungen nach den Switch-Statements gegenseitig widersprechen. Das heißt, in diesem Beispiel können up und down nicht gleichzeitig wahr sein.up = close > open // up = close < openStatt der in den Anmerkungen enthaltenen Inhalte, überprüfen Sie die Ergebnisse. Sie werden feststellen, dass der Switch-Branch nur den ersten Branch ausführen kann. Sie sollten außerdem darauf achten, dass Funktionsanrufe nicht in den Branchen des Switches geschrieben werden, da Funktionen nicht an jeder BAR aufgerufen werden können, was zu Datenrechenproblemen führen kann.switchIn diesem Fall ist der Exekutivzweig festgelegt und wird nicht geändert, während die Strategie ausgeführt wird.)

Kreislaufstruktur

For-Sätze

返回值 = for 计数 = 起始计数 to 最终计数 by 步长
    语句                                            // 注释:语句里可以有break,continue
    语句                                            // 注释:最后一条语句为返回值

Die Verwendung der For-Sätze ist sehr einfach. Die For-Lippe kann einen Wert (oder mehrere Werte in der Form von [a, b, c]) zurückgeben. Wie in der Pseudo-Code oben, werden Variablen an die Position "Rückgabewert" zugewiesen. Nach der For-Sprache folgt eine "Zählung" -Variable, die zur Steuerung der Anzahl der Zyklen verwendet wird, andere Werte zitiert, usw. Die "Zählung" -Variable wird vor Beginn des Zyklus als "Anfängliche Zählung" bewertet und dann nach der "Zunahme" -Einstellung weitergegeben.

für den Kreislauf verwendetbreakSchlüsselwort: Wenn ausgeführtbreakNach dem Satz stoppt der Kreislauf. für den Kreislauf verwendetcontinueSchlüsselwort: Wenn ausgeführtcontinueNach dem Satz ignoriert der Kreislauf.continueNachfolgender Code, der direkt die nächste Runde ausführt. Der For-Satz gibt den Wert zurück, der bei der letzten Runde ausgeführt wurde. Wenn kein Code ausgeführt wurde, gibt er einen Nullwert zurück.

Hier ist ein einfaches 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")

For... in Sätze

for ... inEs gibt zwei Arten von Aussagen, die mit folgenden Pseudo-Codes beschrieben werden können:

返回值 = for 数组元素 in 数组 
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
    语句                        // 注释:语句里可以有break,continue
    语句                        // 注释:最后一条语句为返回值 

Der Hauptunterschied zwischen den beiden Formen ist der Inhalt, der nach dem Schlüsselwort "for" folgt. Die eine ist die Verwendung einer Variable als Referenz für ein Arrayelement. Die andere ist die Verwendung einer Struktur, die eine Array von Variablen enthält, die eine Index-Variable, ein Arrayelement enthält.

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

Wenn Sie ein Index benötigen, verwenden Sie es.for [i, ele] in testArrayIch bin ein guter Mann.

für Kreislaufanwendungen

Wenn man einige Kreislauf-Logik-Rechnungen mit den eingebauten Funktionen der Sprache Pine durchführen kann, kann man sie direkt mit Kreislaufstrukturen schreiben oder sie mit eingebauten Funktionen bearbeiten. Hier sind zwei Beispiele.

1 ist der berechnete Mittelwert.

Bei der Entwicklung von Kreislaufstrukturen:

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-Rundsummierung verwendet, um dann den Durchschnittswert zu berechnen.

Gleichlinien direkt mit der eingebauten Funktion berechnen:

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

Benutzen Sie die eingebauten Funktionen direktta.smaDie Berechnung der Gleichlinienindikatoren ist offensichtlich einfacher als die Berechnung der Gleichlinien mit Hilfe der eingebauten Funktion.

Zwei, zwei und drei.

Das kann man mit dem obigen Beispiel verdeutlichen.

Bei der Entwicklung von Kreislaufstrukturen:

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 aller Elemente einer Array kann ein Loop verwendet werden, der auch mit einer eingebauten Funktion verarbeitet werden kannarray.sumIch bin nicht derjenige. 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)

Sie können sehen, dass die berechneten Daten vollständig übereinstimmen.

Wenn man diese Aufgaben mit eingebauten Funktionen erledigen kann, warum sollte man dann eine Schleife entwerfen? 1. Einige Operationen für Arrays, Berechnung. 2. Rückblick auf die Geschichte, z. B. um herauszufinden, wie viel früherer Höhepunkte höher sind als die Höhepunkte der aktuellen BAR. Da die Höhepunkte der aktuellen BAR nur auf der BAR bekannt sind, auf der das Skript ausgeführt wird, ist eine Schleife erforderlich, um rechtzeitig zurückzukehren und die vergangenen BAR zu analysieren. 3. Eine eingebaute Funktion mit der Sprache Pine kann die Berechnung der Vergangenheit BAR nicht abschließen.

while-Sätze

whileDie Aussage lässt den Code für den Loop-Teil laufen, bis die Beurteilungsvoraussetzung in der while-Struktur falsch ist.

返回值 = while 判断条件
    语句                    // 注释:语句里可以有break,continue
    语句                    // 注释:最后一条语句为返回值

Die anderen Regeln von while sind ähnlich wie bei der For-Schleife. Die letzte Zeile des lokalen Codeblocks des Schleiers ist ein Rückgabewert, der mehrere Werte zurückgeben kann.

Ich möchte Ihnen noch ein Beispiel von einer Gleichlinie 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)

Man kann sehen, dass die Verwendung von while Loops auch sehr einfach ist, und man kann auch einige Rechenlogiken entwerfen, die nicht durch eine eingebaute Funktion ersetzt werden können, wie z.B. die Berechnung von Schritten:

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

Arithmetische Gruppen

Die Definition von Arrays in der Pine-Sprache ist ähnlich wie in anderen Programmiersprachen. Die Arrays in der Pine-Sprache sind eindimensionale Arrays. Sie werden häufig verwendet, um eine Reihe von Daten zu speichern. Arrays, in denen einzelne Daten gespeichert werden, werden als Elemente der Array bezeichnet. Diese Elemente können von folgenden Typen sein: ganzt, floppy, String, Farbwert, Booleinhalt.[]Es ist notwendig, sie zu nutzen.array.get()undarray.set()Die Indexfolge der Elemente in einer Array ist 0 für das erste Element und 1 für das nächste Element.

Wir zeigen es 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))

Erklärung von Arrays

Nutzungarray<int> afloat[] bEine erklärte Array oder nur eine erklärte Variable kann eine Assignierung von Arrays sein, 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 Initiierung von Arrayvariablenarray.newundarray.from函数。Pine语言中还有很多和类型相关的与array.new类似的函数:array.new_int()array.new_bool()array.new_color()array.new_string()Und so weiter.

Das Schlüsselwort var kann auch mit dem Deklarationsmodell der Array funktionieren, wobei die Array mit der Erklärung des Schlüsselworts var nur an der ersten BAR initialiert wird.

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 Veränderungen der a-Array kontinuierlich festgelegt werden und nicht neu platziert werden. Die b-Array wird an jedem BAR initialiert.barstate.islastFür die Echtzeit-Drucke bleibt nur noch ein Element, der Wert 0//.

Lesen und Schreiben von Elementen in Arrays

Mit array.get erhalten Sie Elemente, für die eine bestimmte Indexposition in einer Array festgelegt wurde, und mit array.set ändern Sie Elemente, für die eine bestimmte Indexposition in einer Array festgelegt wurde.

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

Das kann man anhand eines einfachen Beispiels erklären:

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 initialiert die Grundfarbe Grün, erklärt und initialiert eine Array, die verwendet wird, um Farben zu speichern, und gibt dann den Farbwerten eine andere Transparenz an (die Funktion color.new verwendet). Die Farbstufe wird berechnet, indem man den maximalen Abstand des aktuellen BAR-Highs in 100 Sichtzyklen berechnet. Je näher der Maximalwert des Highs in den letzten 100 Sichtzyklen ist, desto höher ist der entsprechende Farbwert (die Transparenz ist niedriger). Viele ähnliche Strategien geben in dieser Weise die Stufe des Preises in den aktuellen N Sichtzyklen an.

Überschreiten von Elementen

Wie man eine Array durchläuft, kann man mit den For/for in/while-Sätzen machen, die wir vorher 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 drei Wege führen zu den gleichen Ergebnissen.

Arrays können sowohl im globalen Bereich des Skripts als auch im lokalen Bereich der Funktion oder der if-Branche deklariert werden

Historische Daten

Für die Verwendung von Elementen in einer Array ist die folgende Methode gleichwertig. Wir können anhand des folgenden Beispiels sehen, dass zwei Gruppen von Linien auf einem Diagramm gezeichnet werden, in denen jede Gruppe zwei Linien hat und die beiden Linien in jeder Gruppe genau die gleichen Werte haben.

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)

Ergänzung der Arrays, Löschung der Funktionen

1. Die Funktion, die mit der Erhöhung der Arrays verbunden ist:

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

2. Funktionen für die Löschung von Arrays:

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

Wir testen die Ergänzungs- und Entfernungselementen dieser Arrays mit den folgenden Beispielen.

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 Schlange

Mit Arrays und einigen Array-Ergänzungs- und Entfernungsfunktionen können wir eine Datenstruktur erstellen, die als "Strecke" bezeichnet wird.

Eine Warteschlange ist eine Struktur, die häufig im Programmiersektor verwendet wird.

Ein Element, das zuerst in die Warteschlange kommt, kommt zuerst aus der Warteschlange.

Dies stellt sicher, dass die Daten, die in der Warteschlange vorhanden sind, die neuesten Daten sind und dass die Warteschlange nicht unendlich lang ist (Kode mit unendlicher Warteschlange kann nur um Mittag geschrieben werden, da Frühstück und Nachmittag Probleme verursachen).

In dem folgenden Beispiel verwenden wir eine Queue-Struktur, um den Preis pro Ticks zu erfassen, den gleitenden Durchschnitt der Ticks zu berechnen und dann mit dem gleitenden Durchschnitt der K-Linien-Ebenen in 1 Minute 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 der Array a den Deklarierungsmodus angegeben haben, mit dem SchlüsselwortvaripHierbei wird jede Preisänderung in einer Matrix aufgezeichnet.

Häufig verwendete Arithmetische Berechnungen, Operationsfunktionen

Berechnen Sie die Funktionen:

array.avg()Die durchschnittlichen Werte aller Elemente in einer Array.array.min()Das kleinste Element in einer Array.array.max()Das ist das größte Element in der Array.array.stdev()Die Standarddifferenz aller Elemente in einer Arithmetie.array.sum()Die Summe aller Elemente in einer Array.

Funktionen, die mit der Bedienung verbunden sind:array.concat()Zwei Arrays zu kombinieren oder zu verbinden.array.copy()Das ist ein sehr schwieriges Problem.array.joinAlle Elemente in einer Array werden zu einer String verbunden.array.sort()Sie werden in Aufstiegs- oder Abstiegsreihenfolge sortiert.array.reverse()Die Umkehrung der Matrix.array.slice()Die Array wird zerschnitten.array.includes()Das Urteil über die Elemente.array.indexof()Geben Sie den Index, in dem der eingegebene Wert zuerst erschien. Wenn dieser nicht gefunden wird, gibt er -1 zurück.array.lastindexof()Finden Sie den Wert, der zuletzt erschienen ist.

Testbeispiele für die Berechnung der relevanten Funktionen in Arithmetik:

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

Dies sind die am häufigsten verwendeten Arithmetik-Funktionen.

Beispiele für die Handhabung der entsprechenden Funktionen:

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

Funktionen

Funktionen definieren

Die Pine-Sprache kann benutzerdefinierte Funktionen entwerfen, die im Allgemeinen folgende Regeln haben:

1. Alle Funktionen sind im globalen Rahmen des Skripts definiert. Eine Funktion kann nicht in einer anderen Funktion deklariert werden. 2. Die Funktion darf sich nicht in ihrem Code selbst aufrufen. 3, grundsätzlich alle PINE-Sprachen haben eine eingebaute Grafikfunktionbarcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) kann nicht in einer benutzerdefinierten Funktion aufgerufen werden. 4. Die Funktion kann als Einzelzeile oder mehrere Zeilen geschrieben werden. Der Rückgabewert des letzten Satzes ist der Rückgabewert der aktuellen Funktion, die die Form eines Elements zurückgibt.

In früheren Tutorials haben wir auch mehrmals benutzt, wie z.B. die Einzeilinie:

barIsUp() => close > open

Die Funktion gibt an, ob die aktuelle BAR die Sonnenstrahlung ist.

Es wurde als mehrstrichige benutzerdefinierte Funktionen konzipiert:

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 Funktion, die wir selbst mit einer benutzerdefinierten Funktion realisiert haben.

Außerdem kann man ein Beispiel für eine benutzerdefinierte Funktion mit zwei Variablen 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)

Eine Funktion kann eine schnelle Linie, eine langsame Linie und zwei EMA-Gleichlinien berechnen.

Eingebaute Funktionen

Die eingebauten Funktionen können sehr einfach inFMZ PINE Script DokumentationIch habe eine Frage gestellt.

Die Pine-Funktion ist hier aufgeführt:

1, eine String-Verarbeitung.str.Die Serie. 2, die Farbwertverarbeitungcolor.Die Serie. 3. Die Parameter-Eingabefunktioninput.Die Serie. 4. Indikatorberechnungsfunktionta.Die Serie. 5. Die Grafikfunktionplot.Die Serie. 6. Arithmetikverarbeitungsfunktionarray.Die Serie. 7. Transaktionsfunktionenstrategy.Die Serie. 8. Mathematische Funktionenmath.Die Serie. 9, andere Funktionen ((Zeitverarbeitung, Non-Plot-Serien-Grafikfunktionen,request.Sie werden von der Funktion "Typ-Processing" (Typ-Verarbeitung) abgerufen.

Transaktionsfunktionen

strategy.Serie-Funktionen sind Funktionen, die wir häufig in unserer Design-Strategie verwenden, und sie sind eng mit der Strategie verbunden, um Transaktionen auszuführen, wenn sie ausgeführt werden.


1、strategy.entry

strategy.entryDie Funktion ist eine untergeordnete Funktion, die bei der Erstellung von Strategien wichtiger ist.id, direction, qty, whenUnd so weiter.

Parameter:

  • id: kann verstanden werden, um einen Namen für eine Handelsposition zu verwenden.
  • direction: wenn die Bestellrichtung mehr (kaufen) ist, wird die Parameter übertragenstrategy.longDiese eingebaute Variable wird übertragen, wenn man sie leert.strategy.shortDiese Variable.
  • qty: Bestimmt die Anzahl der Bestellungen, wenn dieser Parameter nicht übermittelt wird, wird die Anzahl der Bestellungen standardmäßig verwendet.
  • when: Ausführungsbedingungen, die angegeben werden können, um zu steuern, ob die aktuelle Unterordnungsoperation ausgelöst wird.
  • limitEs gibt eine Reihe von Möglichkeiten, wie Sie Ihre Bestellung anbieten können.
  • stopDas ist ein großes Problem.

strategy.entrySpezifische FunktionsdetailsstrategyDie Parameter-Einstellungen bei Funktionsaufrufen können auch durch"Pine-Language Exchange-Library-Modellparameter"Für weitere Details zu den Transaktionen, die durch die Einstellung von Kontrollen und die Parameter der Template der Transaktionslibrary in der Sprache Pine gesteuert werden, siehe Dokumentation unter dem Link.

Hier ist der Schwerpunkt.strategyWir haben eine Funktion.pyramidingdefault_qty_valueParameter. Test mit folgendem Code:

/*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 Code beginnt/*backtest ... */Der Paketanteil ist für die Wiederholung eingestellt, um Informationen wie den Zeitpunkt der Wiederholung zu erfassen, um Debugging zu erleichtern, nicht um Strategiecode zu erstellen.

Der Code:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)Wenn wir diepyramidingWenn die Parameter 3 sind, dann haben wir die Möglichkeit, dass wir in der gleichen Richtung bis zu drei Mal handeln.strategy.entryEine der folgenden Operationen wurde nicht ausgeführt.default_qty_valueDie Parameter sind 0.1, also ist die ID-Kennzeichnung für das Dinglong 1 Ding.strategy.entryDie Unterordnungszahl für die Unterordnungsoperation ist standardmäßig auf 0.1 festgelegt.strategy.entryDie Funktion, auf die wir zugeschrieben haben, wenn wir sie aufrufen.directionGleichstrategy.longDas bedeutet, dass man bei der Nachprüfung bezahlt wird.

Achten Sie auf den Code.strategy.entry("long3", ...Die folgende Operation wird zweimal aufgerufen, für die gleiche ID: long3.strategy.entryDer Nachbestellvorgang wurde nicht abgewickelt, zweiter Aufrufstrategy.entryDie Funktion ändert die ID der Bestellung (die Daten, die bei der Rückprüfung angezeigt werden, zeigen auch, dass die Bestellmenge für diese Limit-Bestellung für 0.3 geändert wurde).strategy.entryWenn die Funktion eine Bestellung aufgibt, werden alle Bestellpositionen auf der ID-Length-3-Length angesammelt.


2、strategy.close

strategy.closeDie Funktion wird verwendet, um die Eintrittspositionen für die Identifikations-ID der Eintrittspositionen zu bestimmen. Die Hauptparameter sind:idwhenqtyqty_percent

Parameter:

  • idWir verwenden das Login-ID, das für die Abrechnung benötigt wird.strategy.entryDie ID, die bei Eintritt der Einzelfunktion angegeben wird.
  • whenDie Bedingungen für die Umsetzung.
  • qtyDie Zahl der Anleihen.
  • qty_percentDer Anteil an der Ausgleichsquote.

Hier ist ein Beispiel, wie man diese Funktion verwenden kann: In der Code/*backtest ... */是FMZ.COM国际站回测时的配置信息,可以删掉,设置自己需要测试的市场、品种、时间范围等信息。

/*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 zeigt, dass Sie drei Mal in Folge mehrere Einträge machen, die Eintrittskennzeichen sind jeweils 1 long, und dann verwendenstrategy.closeVerschiedene Ergebnisse, die bei der Einstellung verschiedener Parameter der Funktion wiedergefunden werden.strategy.closeDiese Funktion hat keine Parameter, um den Preis für die Auflösung zu bestimmen. Die Funktion wird hauptsächlich für die sofortige Auflösung zum aktuellen Marktpreis verwendet.


3、strategy.close_all

strategy.close_allDie Funktion wird verwendet, um alle aktuellen Positionen auszugleichen, da die Pine-Skripte nur in einer Richtung positionieren können, d. h. wenn ein Signal ausgelöst wird, der der gegenwärtigen Positionsrichtung entgegengesetzt ist, wird der aktuelle Positionswert ausgeglichen und die Position entsprechend ausgelöst.strategy.close_allWenn sie aufgerufen werden, werden alle Haltungen in der aktuellen Richtung ausgeglichen.strategy.close_allDie Hauptparameter der Funktion sind:when

Parameter:

  • whenDie Bedingungen für die Umsetzung.

Wir haben ein Beispiel verwendet, um zu beobachten:

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

Wenn wir den Testcode anfangen, ist die Lagermenge 0 (d.h.strategy.position_size==0Wenn die Definition von When erfüllt ist, wird die Definition von When nur dann ausgeführt, wenn die Definition von When erfüllt ist.strategy.entryEintrittsfunktion.strategy.position_sizeDie Eintrittsfunktion für die "ID" ist größer als 0 und kann nur dann ausgeführt werden, wenn die "ID" für die "ID" für die "ID" ist. Da die Position derzeit mehrfach gehalten wird, wird das "STOP"-Rückwärtssignal angezeigt, was dazu führt, dass die Position mehrfach gehalten wird.strategy.position_size < 0Wenn Sie eine Position halten, die sich in der Richtung der aktuellen Position befindet, werden alle Positionen ausgeglichen.enableStop := true◦ Die Aktivierung der Aktion unterbrechen, damit die Logs besser beobachtet werden können.

Sie können es finden.strategy.close_allDiese Funktion hat keine Parameter, um den Preis für die Auflösung zu bestimmen. Die Funktion wird hauptsächlich für die sofortige Auflösung zum aktuellen Marktpreis verwendet.


4、strategy.exit

strategy.exitDie Funktion wird für die Eintritts-Platzierung verwendet.strategy.closeundstrategy.close_allDie Funktion wird sofort zum aktuellen Marktpreis ausgeglichen.strategy.exitDie Funktion schlägt nach den Parameter-Einstellungen aus.

Parameter:

  • id: Order-ID für die aktuelle Bilanzierungsbedingungen.
  • from_entry: wird verwendet, um die Login-ID für die Ausgleichsoperation anzugeben.
  • qtyDie Zahl der Anleihen.
  • qty_percent: Flachgewichtsprozentsatz, Bereich: 0 ~ 100.
  • profitDas Ziel ist: Gewinnziele, in Punkten angegeben.
  • lossDas Ziel des Stopps wird in Punkten angegeben.
  • limitDer Profitziel wird mit einem Preis angegeben.
  • stopDas Ziel ist: Stopp-Loss, Preis angegeben.
  • whenDie Bedingungen für die Umsetzung.

Verwenden Sie eine Teststrategie, um die Verwendung der 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 Ausführung von 3 Eintrittsvorgängen, die mit einem Echtzeit-Preismodell-Rücktest durchgeführt werden.strategy.entryFunktion), die auf "long1" eingestellt istlimitParameter, der Preis für die Auflage 1 macht sie nicht möglich; dann testen Sie die Bedingungen für den Ausgang der Funktionstrategy.exitHierbei wird ein Stopp durch Punktzahl, ein Stopp durch Preis, ein Steigerung der Anzahl der Positionen und ein Steigerung des Prozentsatzes verwendet.strategy.exitDie Funktion hat auch noch kompliziertere Tracking-Stopp-Parameter:trail_pricetrail_pointstrail_offsetSie können auch in diesem Beispiel testen, um zu lernen, wie sie verwendet werden.


5、strategy.cancel

strategy.cancelFunktionen, die verwendet werden, um alle Vorhang-Befehle zu löschen.strategy.order, strategy.entry , strategy.exitSie können eine Anmeldedatenbank erstellen. Die Hauptparameter der Funktion sind:idwhen

Parameter:

  • idSie müssen sich nicht an die Anmeldung beteiligen.
  • whenDie Bedingungen für die Umsetzung.

Diese Funktion ist sehr verständlich, weil sie für die Abschaffung von nicht-transformierten Login-Befehlen verwendet wird.

/*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.cancelFunktionen ähnlich wie ‹ab/abschalten aller Vorhangbefehle› können angegeben werdenwhenParameter.

Parameter:

  • whenDie Bedingungen für die Umsetzung.
/*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 und so weiter sind fast identisch.strategy.entryEinheitlich, unterscheidet sichstrategy.orderDie Funktion ist nichtstrategyDie FunktionpyramidingEinfluss auf die Einstellung von Parametern, ohne Einsatzbegrenzung.

Parameter:

  • id: kann verstanden werden, um einen Namen für eine Handelsposition zu verwenden.
  • direction: wenn die Bestellrichtung mehr (kaufen) ist, wird die Parameter übertragenstrategy.longDiese eingebaute Variable wird übertragen, wenn man sie leert.strategy.shortDiese Variable.
  • qty: Bestimmt die Anzahl der Bestellungen, wenn dieser Parameter nicht übermittelt wird, wird die Anzahl der Bestellungen standardmäßig verwendet.
  • when: Ausführungsbedingungen, die angegeben werden können, um zu steuern, ob die aktuelle Unterordnungsoperation ausgelöst wird.
  • limitEs gibt eine Reihe von Möglichkeiten, wie Sie Ihre Bestellung anbieten können.
  • stopDas ist ein großes Problem.

Wir benutzenstrategy.orderEs gibt keine Begrenzung für diese Eigenschaft.strategy.exitDie bedingte Ausstiegsfunktion ─ Konstruieren eines Skripts, das wie eine Gittertransaktion aussieht ─ ist ein sehr einfaches Beispiel, das nur für das Lernen verwendet wird:

/*backtest
start: 2021-03-01 00:00:00
end: 2022-08-30 00:00:00
period: 1d
basePeriod: 1h
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["ZPrecision",0,358374]]
*/

varip beginPrice = -1

if not barstate.ishistory
    if beginPrice == -1 or (math.abs(close - beginPrice) > 1000 and strategy.opentrades == 0) 
        beginPrice := close
    
    for i = 0 to 20
        strategy.order("buy"+i, strategy.long, 0.01, limit=beginPrice-i*200, when=(beginPrice-i*200)<close)
        strategy.exit("coverBuy"+i, "buy"+i, qty=0.01, profit=200)
        
        strategy.order("sell"+i, strategy.short, 0.01, limit=beginPrice+i*200, when=(beginPrice+i*200)>close)
        strategy.exit("coverSell"+i, "sell"+i, qty=0.01, profit=200)

Strategische Vorbilder

Die Strategien in diesem Tutorial dienen ausschließlich der Lehre von Strategien und der Konzeption von Strategien, nicht als Handlungshilfe oder Empfehlung.

Die Supertrend-Indikatoren-Strategie

strategy("supertrend", overlay=true)

[supertrend, direction] = ta.supertrend(input(5, "factor"), input.int(10, "atrPeriod"))

plot(direction < 0 ? supertrend : na, "Up direction", color = color.green, style=plot.style_linebr)
plot(direction > 0 ? supertrend : na, "Down direction", color = color.red, style=plot.style_linebr)

if direction < 0
    if supertrend > supertrend[2]
        strategy.entry("entry long", strategy.long)
    else if strategy.position_size < 0
        strategy.close_all()
else if direction > 0
    if supertrend < supertrend[3]
        strategy.entry("entry short", strategy.short)
    else if strategy.position_size > 0
        strategy.close_all()

Es ist sehr einfach, eine Trendstrategie in der Sprache Pine zu schreiben. Hier entwerfen wir eine einfache Trend-Tracking-Strategie mit einem Super-Trend-Indikator.

Das ist der erste Schritt, um den Strategic Code zu verwenden.strategyDie Funktion macht einige einfache Einstellungen:strategy("supertrend", overlay=true), einfach eine Strategie mit der Überschrift "Supertrend"-Tastatur eingestellt.overlayDie Parameter sind:trueWenn wir eine Pine-Strategie entwerfen oder ein Pine-Skript lernen, müssen wir uns zunächst die Parameter für die Strategieinterface entwerfen, und wir schauen uns die Quellen für die Supertrend-Indikator-Strategie an, die wir in früheren Kursen gelernt haben.inputFunktionen

[Supertrend, Richtung] = ta.Supertrend ((Eingabe ((5, Faktor),input.int(10, atPeriode))

inputFunktionsanrufe werden direkt verwendet.ta.supertrendDie Parameter der Indikatorfunktion werden für die Berechnung der Supertendenzindikatoren verwendet.

  • Input ((5, factor)
  • input.int(10, atPeriode)

Die Funktion setzt standardmäßig zwei Parameter-Kontrollen in der Pine-Politik-Schnittstelle ein, wie folgt:

img

Sie können sehen, dass der Standardwert für die SteuerunginputFunktionen undinputHier ist eine Reihe von Funktionen.input.intDiese beiden Funktionen können wir in der Strategie-Schnittstelle einstellen.ta.supertrendDie Parameter der Funktion. Die Supertrend-Indikator-Funktion berechnet eine Preisdaten.supertrendund eine Richtung DatendirectionUnd dann benutzt man sie.plotFunktionsdiagramme, beachten Sie, dass die Diagramme nur in der aktuellen Richtung gezeichnet werden, wenn sie in der Richtung des Supertrend-Indikators gezeichnet werden.directionDie aktuelle Marktentwicklung ist aufwärts bei -1 Uhr.directionDer Markt ist um 1 Uhr auf dem Abwärtstrend.plotBeurteilen Sie, wenn Sie ein Diagramm zeichnendirectionGrößer als, kleiner als 0.

Die nächsteif ... else ifLogik ist die Beurteilung der Transaktionssignale, wenn diedirection < 0In Echtzeit zeigt, dass die aktuelle Marktlage in der oberen Phase ist, wenn die Preisdaten im Supertrend-IndikatorsupertrendDer Preis des Supertrend-Indikators auf den ersten 2 BARs ist höher als der Preis des Supertrend-Indikators (d.h.supertrend[2],还记得历史操作符引用某个变量历史数据吧Erinnern Sie sich daran? Wenn Sie gerade eine Position haben, werden Sie mit einem umgekehrten Einzelfunktionsanruf die vorherige Position ausgleichen und dann entsprechend der aktuellen Handelsrichtung eröffnen.supertrend > supertrend[2]Die Bedingungen sind nicht erfüllt.strategy.position_size < 0Das bedeutet, dass die Position des Leerstandes auch ausgelöst wird.strategy.close_all()Die Funktion wird ausgeführt und alle Ausgleichswerte ausgeführt.

direction > 0Das gleiche gilt für die Abwärtstrendphase, wenn mehrere Positionen ausgeglichen werden und die Bedingungen erfüllt sind.supertrend < supertrend[3]Wenn Sie ein Blackout-Signal auslösen, warum ist das hier so eingestellt?[3]Was ist mit den Supertrend-Index-Preisdaten auf der dritten Bar? Vielleicht ist das die Absicht des Strategisten, denn in einigen Märkten, wie z. B. im Contract-Trading-Markt, ist das Null-Risiko etwas größer als das Mehr-Risiko.

Fürta.supertrendDer Indikator, den einige Schüler interessieren, ist, wie man den aktuellen Trend aufwärts oder abwärts beurteilt.

In der Tat kann dieser Indikator auch in Form einer benutzerdefinierten Funktion in der Sprache Pine realisiert werden:

pine_supertrend(factor, atrPeriod) =>
	src = hl2
	atr = ta.atr(atrPeriod)
	upperBand = src + factor * atr
	lowerBand = src - factor * atr
	prevLowerBand = nz(lowerBand[1])
	prevUpperBand = nz(upperBand[1])

	lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
	upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
	int direction = na
	float superTrend = na
	prevSuperTrend = superTrend[1]
	if na(atr[1])
		direction := 1
	else if prevSuperTrend == prevUpperBand
		direction := close > upperBand ? -1 : 1
	else
		direction := close < lowerBand ? 1 : -1
	superTrend := direction == -1 ? lowerBand : upperBand
	[superTrend, direction]

Diese benutzerdefinierte Funktion ist eine eingebaute Funktionta.supertrendDie gleiche Algorithmus, natürlich auch die gleichen Indikatordaten. Aus diesem Algorithmus der Custom Function können wir sehen, dass die Supertrend-Anzeige, die Pine eingebaut hat, mithl2Die Variablen (höchste, niedrigste, addierte und durch 2 geteilte Höchst- und niedrigste Preise) werden dann mit dem Parameter atrPeriod berechnet.

Aktualisiert nach den dreifachen Ausdrücken im CodelowerBandundupperBand

    lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
    upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand

lowerBand: Unterstrecke, um zu bestimmen, ob sich der Aufwärtstrend geändert hat. upperBand: Oberstrecke, um zu bestimmen, ob sich der Abwärtstrend geändert hat. lowerBand und upperBand werden immer berechnet, nur um die aktuelle Trendrichtung zu bestimmen.

    else if prevSuperTrend == prevUpperBand
        direction := close > upperBand ? -1 : 1
    else
        direction := close < lowerBand ? 1 : -1

Hier wird festgestellt, ob der Preiswert des Supertrendens auf der letzten BARprevUpperBandWenn Sie sich in der Nähe von einem anderen Ort befinden, können Sie sich in der Nähe von einem anderen Ort befinden.closeMehr alsupperBandDer Preis wird durchbrochen, weil man glaubt, dass sich die Tendenz in diesem Moment verändert hat und sich in einen Aufwärtstrend verwandelt.directionDie Richtungsvariablen sind auf -1 ((Obertrend)); ansonsten bleiben sie auf 1 ((Abwärtstrend)); also sehen Sie es in der Supertrend-Strategie.if direction < 0Wenn die Signalbedingungen ausgelöst werden, dann tun Sie mehr.direction > 0Wenn die Signalbedingungen ausgelöst werden, ist die Auslösung möglich.

    superTrend := direction == -1 ? lowerBand : upperBand
    [superTrend, direction]

Schließlich werden die spezifischen Supertrend-Indikatoren für die Preisdaten und die Richtungsdaten nach Richtung ausgewählt.

Dynamische Ausgleichsstrategien

/*backtest
start: 2021-03-01 00:00:00
end: 2022-09-08 00:00:00
period: 1h
basePeriod: 15m
exchanges: [{"eid":"Binance","currency":"ETH_USDT"}]
args: [["v_input_1",4374],["v_input_2",3],["v_input_3",300],["ZPrecision",0,358374]]
*/

varip balance = input(50000, "balance")
varip stocks = input(0, "stocks")

maxDiffValue = input(1000, "maxDiffValue")


if balance - close * stocks > maxDiffValue and not barstate.ishistory
    // more balance , open long 
    tradeAmount = (balance - close * stocks) / 2 / close
    strategy.order("long", strategy.long, tradeAmount)
    balance := balance - tradeAmount * close
    stocks := stocks + tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

else if close * stocks - balance > maxDiffValue and not barstate.ishistory
    // more stocks , open short 
    tradeAmount = (close * stocks - balance) / 2 / close
    strategy.order("short", strategy.short, tradeAmount)
    balance := balance + tradeAmount * close
    stocks := stocks - tradeAmount
    runtime.log("balance:", balance, ", stocks:", stocks, ", tradeAmount:", tradeAmount)

plot(balance, title="balance value(quoteCurrency)", color=color.red)
plot(stocks*close, title="stocks value(quoteCurrency)", color=color.blue)

img

img

Wir lernen weiter einige Strategien-Design-Probleme in der Pine-Sprache, und diesmal sehen wir eine dynamische Balance-Strategie.BaseCurrency(Transaktionsart) undQuoteCurrencyDie Summe wird stets ausgeglichen. Der relative Preis eines Vermögenswerts steigt und der Wert des im Konto gehaltenen Vermögens steigt, und der Vermögenswert wird verkauft. Wenn der relative Preis eines Vermögenswerts sinkt und der Wert des im Konto gehaltenen Vermögenswert sinkt, kauft man diesen Vermögenswert. Dies ist die sogenannte dynamische Ausgleichsstrategie.

Der Nachteil dieser Strategie ist, dass sie, wie in den Rücksichtsdiagrammen zu sehen ist, in der Phase eines hohen (oder niedrigeren) Kurstrends eine größere Gewinne erzielt.

Wir haben eine Reihe von Programmen entwickelt, die in der Lage sind, unsere Kunden zu unterstützen.

Wir haben ein vereinfachtes Design verwendet, um eine Strategie zu simulieren, in der wir einebalance(d.h. Anzahl der Quoten-Währungs-Assets) undstocksDie Balance-Informationen. Wir lesen nicht die tatsächliche Anzahl der Vermögenswerte in den Konten, sondern verwenden nur simulierte Beträge, um die richtigen Käufe und Verkäufe zu berechnen.maxDiffValueDer Parameter ist der Maßstab für die Ausgewogenheit.BaseCurrencyundQuoteCurrencyDie Abweichungen übersteigenmaxDiffValueEs ist Zeit, sich auszugleichen, hochpreisige Vermögenswerte zu verkaufen, niedrige zu kaufen und die Vermögenswerte wieder auszugleichen.

Strategie-Trading-Signale müssen erst in der Echtzeit-BAR-Phase sinnvoll ausgelöst werden, so dass die strategischen Trading-Bedingungen im If-Urteil gesetzt werden.not barstate.ishistoryUnd wenn man die Preise anhand der aktuellen Preise berechnet, dann sind es die Preise, die man verdient.balanceDer Wert ist überschrittenstocksKauf bei Wert; Verkauf umgekehrt; Aktualisierung nach der Ausführung des TransaktionssatzesbalanceundstocksSie werden dann auf die nächste Balance-Trigger warten.

Die oben angegebene Strategie-Rücklauf-Nachricht enthält den Preis für die Sorte, bei der die Strategie-Rücklauf-Nachricht begann, und der Preis ist 1458, also habe ich die Parameter absichtlich eingestellt.balanceParameter für: 4374 ((1458*3)stocks3. Das Vermögen am Anfang im Gleichgewicht zu halten.

Supertrend-Strategien mit Stop-Loss-Tracking

Wir haben in früheren Kursen gelernt,strategy.exitDie Positionsaustritt-Funktion, bei der die Tracking-Stopp-Loss-Stopp-Funktion nicht beschrieben wird.strategy.exitDie Tracking-Stopp-Loss-Stopp-Funktion der Funktion optimiert eine Supertrend-Strategie.

Erst mal sehen wir:strategy.exitDie Tracking-Stopp-Loss-Stopp-Parameter der Funktion:

1、trail_priceParameter: Auslöser, der die logische Position des Tracking Stop-Loss-Bilanzordens auslöst (z.B. Preis angegeben)


Mehr