Voici quelques exemples:
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)
Points importants: l'expression utilisée pour le jugement retourne une valeur de Boole. Attention à la contraction. Il ne peut y avoir qu'une brancheelse au maximum. Toutes les expressions branchées ne sont pas vraies et aucune brancheelse ne retourne na.
x = if close > open
close
plot(x, title="x")
Puisque lorsque la ligne K BAR est une ligne cintrée, c'est-à-dire lorsque close < open, l'expression après la phrase if est false, le bloc de code local de if n'est pas exécuté. Cette fois non plus, il n'y a pas de brancheelse, la phrase if renvoie na. x est attribué à na.
Les statements switch sont également des statements à structure branchée, conçus pour exécuter différents chemins en fonction de certaines conditions. Les statements switch ont généralement les points de connaissances suivants:
Les expressions 1, switch et if renvoient des valeurs. 2) Contrairement aux expressions de commutation dans d'autres langages, l'exécution de la structure de commutation n'exécute qu'un seul bloc local de son code, de sorte qu'une déclaration de break n'est pas nécessaire (c'est-à-dire qu'il n'est pas nécessaire d'écrire des mots clés tels que break). Chaque branche de Switch peut écrire un bloc de code local, dont la dernière ligne est la valeur de retour (elle peut être un élément de valeur). Si aucun bloc de code local branché n'est exécuté, il renvoie na. 4. Déterminer la position d'une expression dans une structure de commutation, écrire des strings, des variables, des expressions ou des appels de fonction. 5. switch permet de spécifier une valeur de retour qui est utilisée comme valeur par défaut lorsqu'aucune autre situation dans la structure n'est exécutée.
Les commutateurs sont divisés en deux types, et nous allons voir un exemple après l'autre pour comprendre comment ils sont utilisés.
1 avec une expressionswitch
Il y a aussi des exemples:
// 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)
Nous avons étudié les fonctions d'entrée plus tôt, et nous avons continué à étudier deux fonctions similaires à celles d'entrée:input.string
、input.int
Les fonctions.input.string
Il y a un autre moyen de retourner les chaînes.input.int
La fonction est utilisée pour renvoyer une valeur entière.options
Les paramètres sont utilisés.options
Les paramètres peuvent être passés dans une matrice composée de valeurs sélectionnables.options=["EMA", "SMA", "RMA", "WMA"]
etoptions=[5, 10, 20]
(Notez que l'un est un type de chaîne et l'autre un type de valeur). Ainsi, les contrôles de l'interface de stratégie n'ont pas besoin d'entrer de valeur spécifique, mais deviennent un menu déroulant pour sélectionner les options fournies dans le paramètre options.
La valeur de la variable func est une chaîne, la variable func est utilisée comme expression de la commutation (peut être une variable, un appel à une fonction, une expression) pour déterminer quelle branche de la commutation est exécutée. Si la variable func ne correspond pas à l'expression de n'importe quelle branche de la commutation (c'est-à-dire est égale), la branche par défaut est exécutée.runtime.error("error")
Les fonctions provoquent l'arrêt exceptionnel de la stratégie.
Dans notre code de test ci-dessus, nous n'avons pas ajouté de code tel que [na, na] après la dernière ligne du bloc de code de branche par défaut de Switch pour rendre la valeur de compatibilité, ce qui nécessite de considérer le problème en vue du trading, si le type n'est pas cohérent. Mais dans FMZ, il est possible d'ignorer ce code de compatibilité car il n'y a pas de type strictement requis.
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)
Il n'y a pas d'erreur dans FMZ, mais il y en a dans Trading View.
Il n'y a pas d'expressionswitch
Nous allons voir.switch
L'autre façon d'utiliser le terme est d'écrire sans expression.
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)
On peut voir dans l'exemple de code de test que le switch correspond à un bloc de code local vrai sur la condition d'exécution d'une branche. En général, les conditions de branche après la déclaration du switch doivent être réciproques. C'est-à-dire que dans l'exemple, up et down ne peuvent pas être vrais à la fois.up = close > open // up = close < open
Au lieu de remplacer le contenu dans les notes, réessayez d'observer le résultat. Vous constaterez que la branche de switch ne peut exécuter que la première branche.switch
Dans l'exemple "Executive branch" la branche d'exécution est définie et n'est pas modifiée au cours de l'exécution de la stratégie).
返回值 = for 计数 = 起始计数 to 最终计数 by 步长
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
L'utilisation de l'instruction for est très simple, car le cycle for peut finalement renvoyer une valeur ((ou plusieurs valeurs, sous la forme de [a, b, c])); comme dans le pseudo ci-dessus, l'attribution d'une variable à la position de "valeur de retour". Une variable de "compte" est suivie d'une instruction for pour contrôler le nombre de cycles, citer d'autres valeurs, etc. La variable "compte" est attribuée au "compte initial" avant le début du cycle, puis est passée en fonction de la configuration "croissance", le cycle s'arrête lorsque le nombre de "compte" est supérieur à "variable final".
Pour la circulationbreak
Mots clés: Quand cela est faitbreak
Après une phrase, le cycle s'arrête.
Pour la circulationcontinue
Mots clés: Quand cela est faitcontinue
Après une phrase, le cycle est ignoré.continue
Le code suivant, exécute directement le prochain cycle. La déclaration for renvoie la valeur de retour lors de l'exécution du dernier cycle. Si aucun code n'est exécuté, elle renvoie une valeur vide.
Voici un exemple simple pour le montrer:
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
Il existe deux formes de phrases, illustrées par le pseudo-code ci-dessous.
返回值 = for 数组元素 in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
On peut voir que la principale différence entre les deux formes réside dans le contenu qui suit le mot-clé for, l'une étant l'utilisation d'une variable comme référence à un élément d'une matrice. L'autre est l'utilisation d'une structure contenant une variable d'index, un élément d'une matrice.
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")
Utilisez l'index quand vous en avez besoin.for [i, ele] in testArray
Il est écrit comme ça:
pour les applications cyclables
Lorsque des calculs de logique circulaire peuvent être effectués à l'aide des fonctions intégrées fournies par le langage Pine, il est possible d'écrire directement à l'aide de structures circulaires ou de traiter les fonctions intégrées. Nous en donnons deux exemples.
1 est la moyenne.
Pour la conception de structures circulaires:
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)
Dans l'exemple, on utilise la somme circulaire for, puis on calcule l'égalité.
Comptez directement l'équation en utilisant la fonction intégrée:
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Utilisez directement les fonctions intégréesta.sma
Le calcul de l'indicateur homogène est évidemment plus simple pour le calcul de l'homogénéité en utilisant des fonctions intégrées.
2 et plus
L'exemple ci-dessus peut être utilisé comme exemple.
Pour la conception de structures circulaires:
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)
Pour calculer tous les éléments d'une matrice et qui peuvent être traités en utilisant le cycle, on peut également utiliser des fonctions intégrées.array.sum
Il y a des gens qui sont en train de calculer.
Calculer la somme directement à l'aide des fonctions intégrées:
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)
Les données calculées peuvent être vues comme étant parfaitement cohérentes sur le graphique à l'aide d'un diagramme.
Alors, si ces tâches peuvent être accomplies avec des fonctions intégrées, pourquoi concevoir des cycles? 1, quelques opérations pour les arithmétiques, calculer. 2° Revenir sur l'histoire, par exemple, pour savoir combien de pics passés sont supérieurs à ceux du BAR actuel. Puisque les pics du BAR actuel ne sont connus que dans le BAR où le script est exécuté, un cycle est nécessaire pour revenir en temps opportun et analyser le BAR passé. 3, lorsque les fonctions intégrées utilisant le langage Pine ne peuvent pas compléter le calcul du passé BAR.
while
Les statements permettent au code de la partie circulaire d'être exécuté jusqu'à ce que la condition de jugement dans la structure while soit false.
返回值 = while 判断条件
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Les autres règles de while sont similaires à celles de la boucle for, la dernière ligne du bloc de code local du boucle est une valeur de retour, qui peut renvoyer plusieurs valeurs.
Je vais vous montrer l'exemple d'une ligne horizontale:
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)
On peut voir que l'utilisation du while loop est également très simple, mais il est possible de concevoir des logiques de calcul qui ne peuvent pas être remplacées par des fonctions intégrées, telles que calculer des multiples:
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
Les définitions d'une matrice dans le langage Pine sont similaires à celles des autres langages de programmation. Une matrice dans le langage Pine est une matrice en une dimension. Elle est généralement utilisée pour stocker une série de données en continu. Une matrice dans laquelle des données individuelles sont stockées est appelée élément d'une matrice.[]
Nous avons besoin d'utiliserarray.get()
etarray.set()
Fonction. L'ordre d'indexation des éléments d'une matrice est tel que l'indexation du premier élément est 0, l'indexation du prochain élément augmente de 1.
Nous avons utilisé un code simple pour expliquer:
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))
Utilisationarray<int> a
、float[] b
Une grille déclarée ou une variable déclarée peut être attribuée à une grille, par exemple:
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")
Généralement utilisé pour l'initialisation des variables d'une matricearray.new
etarray.from
函数。Pine语言中还有很多和类型相关的与array.new类似的函数:array.new_int()
、array.new_bool()
、array.new_color()
、array.new_string()
Je ne sais pas.
Le mot-clé var peut également fonctionner avec le mode de déclaration de l'array, l'array qui utilise le mot-clé var n'est initialement initialisé que sur le premier BAR. Nous observons ceci par un exemple:
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")
On peut voir que les modifications d'une matrice a sont constamment fixées et ne sont pas réinstallées. Les matrices b sont initiales à chaque BAR.barstate.islast
Il n'y a toujours qu'un seul élément à imprimer en temps réel, une valeur de 0.
Utilisez array.get pour obtenir un élément dans une matrice dont la position est indiquée par l'index, et modifiez l'élément dans une matrice dont la position est indiquée par l'index avec array.set.
Le premier paramètre d'array.get est l'array à traiter et le second paramètre est l'index désigné. Le premier paramètre d'array.set est l'array à traiter, le deuxième paramètre est l'index spécifié et le troisième paramètre est l'élément à écrire.
Pour illustrer cela, on peut utiliser l'exemple suivant:
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")
L'exemple initie la couleur de base vert, déclare et initie une matrice pour conserver la couleur, puis attribue une transparence différente à la valeur de couleur (en utilisant la fonction color.new). Le rangement de couleur est calculé en calculant la distance maximale de la valeur high au cours des 100 cycles de revue actuels BAR. Plus la distance est proche de la valeur maximale high au cours des 100 cycles de revue récents, plus le rangement est élevé, plus la valeur de couleur correspondante est profonde (la transparence est faible).
Comment traverser une arithmétique peut être réalisé avec les phrases for/for in/while que nous avons apprises précédemment.
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")
Les trois méthodes de navigation donnent les mêmes résultats.
L'arithmétique peut être déclarée à l'échelle globale du script, ou à l'échelle locale de la fonction ou de la branche if.
Pour l'utilisation d'un élément dans une matrice, la méthode suivante est équivalente, nous pouvons voir par l'exemple suivant que deux groupes de lignes sont tracés sur le graphique, deux lignes par groupe, et que les deux lignes de chaque groupe ont exactement les mêmes valeurs.
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)
Les fonctions liées à l'augmentation des opérations de l'arithmétique 1.
array.unshift()
、array.insert()
、array.push()
。
Les fonctions liées à l'opération de suppression de l'arithmétique 2.
array.remove()
、array.shift()
、array.pop()
、array.clear()
。
Nous avons utilisé l'exemple suivant pour tester les fonctions d'ajout et de suppression d'opérations de ces matrices.
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")
Applications d'ajout et de suppression: Arrays comme queue
Nous pouvons construire une structure de données "queue" à l'aide d'une matrice, ainsi que des fonctions d'ajout et de suppression d'une matrice. Les queues peuvent être utilisées pour calculer les moyennes mobiles des prix des ticks.
Une file d'attente est une structure couramment utilisée dans le domaine de la programmation.
Le premier élément à entrer dans la file d'attente, le premier à sortir de la file d'attente.
Cela permet de s'assurer que les données présentes dans la file d'attente sont les plus récentes et que la longueur de la file d'attente ne s'élargit pas à l'infini.
Dans l'exemple ci-dessous, nous utilisons une structure de file d'attente pour enregistrer le prix de chaque tick, calculer la moyenne mobile au niveau du tick, puis la comparer à la moyenne mobile observée au niveau de la ligne K en 1 minute.
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")
Remarquez que nous avons spécifié le mode de déclaration en utilisant le mot-clévarip
Ainsi, chaque variation de prix est enregistrée dans une matrice a.
Calculer les fonctions:
array.avg()
La moyenne de tous les éléments de l'arithmétique.array.min()
Le plus petit élément de l'arithmétiquearray.max()
L'élément le plus grand de l'arithmétique.array.stdev()
L'erreur de référence de tous les éléments d'une matrice est la différence de référence de tous les autres éléments.array.sum()
La somme de tous les éléments de l'ensemble des nombres.
Fonctions liées à l'opération:array.concat()
Combinez ou connectez deux matrices.array.copy()
Répliquer une matrice.array.join
Connectez tous les éléments de l'array en une seule chaîne.array.sort()
L'ordre de l'article est classé par ordre d'ascension ou de descente.array.reverse()
L'inverse de l'arithmétique.array.slice()
On coupe les matrices.array.includes()
Il est important de savoir ce qui se passe.array.indexof()
Retourne l'index dans lequel la valeur d'un paramètre est apparue pour la première fois. Si la valeur n'est pas trouvée, renvoie −1.array.lastindexof()
Trouvez la valeur qui est apparue la dernière fois.
Exemples de tests de calcul arithmétique des fonctions connexes:
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")
Ce sont les fonctions de calcul arithmétiques les plus couramment utilisées.
Exemples d'opérations avec des fonctions:
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")
Le langage Pine peut concevoir des fonctions personnalisées. En général, les fonctions personnalisées du langage Pine ont les règles suivantes:
1, toutes les fonctions sont définies dans l'échelle globale du script. Une fonction ne peut pas être déclarée dans une autre fonction.
2° Ne pas autoriser les fonctions à s'appeler elles-mêmes dans leur propre code.
3, en principe, toutes les langues PINE ont une fonction graphique intégréebarcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()
) ne peut pas être appelé dans une fonction personnalisée.
4, les fonctions peuvent être écrites en une seule ligne, plusieurs lignes. La valeur de retour de la dernière phrase est la valeur de retour de la fonction actuelle, qui peut être retournée sous forme d'éléments.
Nous avons utilisé des fonctions personnalisées plusieurs fois dans les tutoriels précédents, par exemple en créant des fonctions personnalisées en une seule ligne:
barIsUp() => close > open
Cette fonction renvoie si le BAR actuel est le rayon solaire.
Il est conçu comme une fonction personnalisée à plusieurs lignes:
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)
Une fonction calculée par une moyenne SMA que nous avons réalisée nous-mêmes avec des fonctions personnalisées.
Il est également possible de retourner l'exemple d'une fonction personnalisée avec deux variables:
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)
Une fonction peut calculer une ligne rapide, une ligne lente, deux indicateurs de l'EMA.
Les fonctions intégrées sont faciles à utiliser.FMZ PINE Script est un fichierJe ne suis pas d'accord avec toi.
Les fonctions intégrées dans le langage Pine:
1, fonction de traitement de chaînestr.
La série.
2, fonction de traitement des valeurs de couleurcolor.
La série.
3, fonction d'entrée de paramètresinput.
La série.
4, fonction de calcul des indicateursta.
La série.
5, fonction de dessinplot.
La série.
6, fonction de traitement d'arithmétiquearray.
La série.
7. Fonctions liées aux transactionsstrategy.
La série.
8. Fonctions mathématiquesmath.
Une série.
9, autres fonctions (traitement du temps, fonctions de dessin de séries non-plots,request.
Les fonctions de série, les fonctions de traitement de type, etc.)
strategy.
Les fonctions de série sont des fonctions que nous utilisons souvent dans les stratégies de conception, qui sont étroitement liées à l'exécution des opérations de transaction lorsque la stratégie est spécifiquement exécutée.
1、strategy.entry
strategy.entry
La fonction est une fonction sous-jacente qui est plus importante lorsque nous écrivons des stratégies, et qui a plusieurs paramètres plus importants:id
, direction
, qty
, when
Je ne sais pas.
Paramètres:
id
: peut être compris comme une référence au nom d'une position de négociation.direction
: si la direction de la commande est plus (acheter) le paramètre est transmisstrategy.long
Cette variable intégrée est transmise si vous voulez faire un sale.strategy.short
Cette variable.qty
: spécifier la quantité à commander, si ce paramètre n'est pas transmis, la quantité à commander par défaut est utilisée.when
: Conditions d'exécution, vous pouvez spécifier ce paramètre pour contrôler si cette opération est déclenchée.limit
Le prix de la commande est fixé par le site: WEBstop
Le prix de vente est le même.strategy.entry
Les détails d'exécution spécifiques de la fonctionstrategy
Les paramètres de contrôle lors de l'appel de la fonction peuvent également être contrôlés par"Paramètres du modèle de la bibliothèque de langues Pine"Pour plus de détails sur la configuration des contrôles, voir la documentation ci-jointe.
Je vais vous expliquer les points principaux.strategy
Dans la fonction,pyramiding
、default_qty_value
Paramètres. Testez en utilisant le code suivant:
/*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)
Le début du code/*backtest ... */
La partie du paquet est réglée pour la réévaluation, afin de documenter des informations telles que l'heure de la réévaluation à ce moment-là, pour faciliter le débogage, et non le code de stratégie.
Le code est:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
Et quand on désignepyramiding
Si le paramètre est 3, nous avons un maximum de trois transactions dans la même direction. Donc quatre fois dans l'exemple.strategy.entry
Une des opérations ci-dessous n'a pas été exécutée.default_qty_value
Le paramètre est 0.1, donc l'identifiant ID est le long de 1 tonne cette fois.strategy.entry
La valeur de la sous-liste de l'opération est définie par défaut à 0.1 ∞.strategy.entry
C'est la fonction que nous avons désignée pour appeler.direction
Ils sont tous égaux.strategy.long
Les tests de réévaluation sont payants.
Attention au code.strategy.entry("long3", ...
L'opération suivante est appelée deux fois, pour le même ID: strategy.entry
L'opération suivante n'a pas été effectuée, appelée une deuxième foisstrategy.entry
Les données affichées lors du retest peuvent également indiquer que la quantité de commande sous cette commande limitée a été modifiée pour 0.3). Dans un autre cas, par exemple, si la première commande pour l'ID de 3 tonnes a été passée, continuez à l'utiliser selon cette commande.strategy.entry
Si la fonction passe une commande, toutes les positions seront cumulées sur l'ID de la longueur de 3 bits.
2、strategy.close
strategy.close
La fonction est utilisée pour spécifier l'ID de l'entrée de placement. Les principaux paramètres sont:id
,when
,qty
,qty_percent
。
Paramètres:
id
Nous utilisons des identifiants de connexion qui nécessitent un identifiant de mise sur le marché.strategy.entry
L'ID indiqué lors de l'ouverture d'une fonction unique.when
Les conditions de mise en œuvre:qty
Le nombre d'offres.qty_percent
Le résultat de cette enquête est le suivant:Pour vous familiariser avec le fonctionnement de cette fonction, voici un exemple:
Dans le 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
La stratégie de test montre qu'il est possible de commencer à effectuer plusieurs entrées trois fois de suite avec un ID d'entrée de 1 tonne, puis d'utiliserstrategy.close
Différents résultats sont obtenus lorsque les différents paramètres de la fonction sont réglés en équilibre.strategy.close
Cette fonction n'a pas de paramètre permettant de spécifier le prix de l'ordre de mise en liquidation. Elle est principalement utilisée pour la mise en liquidation immédiate au prix du marché actuel.
3、strategy.close_all
strategy.close_all
La fonction est utilisée pour aplanir toutes les positions actuelles, car le script de la langue Pine ne peut aplanir que dans une seule direction, c'est-à-dire qu'il aplanit la position actuelle en fonction du déclenchement d'un signal contraire à la direction actuelle de la position.strategy.close_all
Les positions en direction de l'aéroport sont appelées à égaler toutes les positions dans la direction actuelle.strategy.close_all
Les principaux paramètres de la fonction sont:when
。
Paramètres:
when
Les conditions de mise en œuvre:Nous avons utilisé un exemple pour observer:
/*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
Au début du code de test, le stock est de 0 (c'est à direstrategy.position_size==0
Si le paramètre when est correct, alors le paramètre when est correct, mais si le paramètre when est correct, alors le paramètre when est correct.strategy.entry
Fonction d'entrée. Après avoir détenu plusieurs positionsstrategy.position_size
Si l'ID est supérieur à 0, la fonction d'entrée de l'étalon de short peut être exécutée. En raison de l'existence de plusieurs positions, le signal de revers d'emplacement qui apparaît à ce moment-là entraînera une élimination des positions multiples.strategy.position_size < 0
Lorsque vous avez une position vide, la position totale de la direction actuelle est égalée; et marquezenableStop := true
◦ Arrêter l'exécution de la politique pour faciliter l'observation des journaux.
Vous pouvez trouverstrategy.close_all
Cette fonction n'a pas de paramètre permettant de spécifier le prix de l'ordre de mise en liquidation. Elle est principalement utilisée pour la mise en liquidation immédiate au prix du marché actuel.
4、strategy.exit
strategy.exit
La fonction est utilisée pour les opérations de mise en place des positions d'entrée, mais elle est différente de la fonctionstrategy.close
etstrategy.close_all
Les fonctions sont immédiatement liquidées au prix du marché actuel.strategy.exit
La fonction planifie l'équilibrage en fonction des paramètres.
Paramètres:
id
: l'identifiant d'ordre de la liste de conditions de mise en liquidation actuelle.from_entry
: est utilisé pour spécifier l'ID de connexion pour effectuer une opération de mise en place.qty
Le nombre d'offres.qty_percent
: pourcentage de l'équilibre, plage: 0 à 100.profit
Les objectifs de profit sont indiqués par un nombre de points.loss
Le nombre de points indiqué est celui de l'objectif de stop-loss.limit
Les objectifs de profit sont indiqués par le prix.stop
Les prix sont indiqués par le prix de vente.when
Les conditions de mise en œuvre:Utilisez une stratégie de test pour comprendre l'utilisation des différents paramètres.
/*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语言模板参数上「定价货币精度」参数设置有关
Cette stratégie de test a commencé par exécuter trois opérations d'entrée en utilisant le test de rétrospection du modèle de prix en temps réel.strategy.entry
fonction), le long de 1 est délibérément définilimit
Paramètres, prix de l'ordre de vente est de 1 pour empêcher la transaction. Ensuite, tester la condition de sortie de la fonctionstrategy.exit
⇒ On utilise le stop par point, le stop par prix, on utilise le nombre fixe de positions, on utilise le stop par pourcentage. D'autant que l'exemple ci-dessus ne démontre que le stop.strategy.exit
La fonction comporte également des paramètres de suivi plus complexes:trail_price
、trail_points
、trail_offset
Vous pouvez également essayer d'apprendre à l'utiliser dans cet exemple.
5、strategy.cancel
strategy.cancel
Les fonctions sont utilisées pour annuler / désactiver toutes les commandes des listes en attente.strategy.order
, strategy.entry
, strategy.exit
Il est possible de générer un identifiant de connexion.id
、when
。
Paramètres:
id
Il y a aussi une autre version de la vidéo:when
Les conditions de mise en œuvre:Cette fonction est bien comprise, car elle est utilisée pour annuler les commandes de connexion sans transaction.
/*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_all
Les fonctions etstrategy.cancel
Fonction similaire: ʽannuler/désactiver toutes les commandes prépayées‛when
Paramètres.
Paramètres:
when
Les conditions de mise en œuvre:/*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.order
Les fonctions, les paramètres, etc. sont presque identiques.strategy.entry
Le problème est que les gens ne comprennent pas.strategy.order
Les fonctions ne sont passtrategy
La fonctionpyramiding
Les paramètres affectent les paramètres, il n'y a pas de limite au nombre de fois suivantes.
Paramètres:
id
: peut être compris comme une référence au nom d'une position de négociation.direction
: si la direction de la commande est plus (acheter) le paramètre est transmisstrategy.long
Cette variable intégrée est transmise si vous voulez faire un sale.strategy.short
Cette variable.qty
: spécifier la quantité à commander, si ce paramètre n'est pas transmis, la quantité à commander par défaut est utilisée.when
: Conditions d'exécution, vous pouvez spécifier ce paramètre pour contrôler si cette opération est déclenchée.limit
Le prix de la commande est fixé par le site: WEBstop
Le prix de vente est le même.Nous utilisonsstrategy.order
Il n'y a pas de limite à cette propriété.strategy.exit
Fonction de sortie conditionnelle ─ construire un script similaire à une transaction de grille ─ exemple très simple, uniquement pour apprendre:
/*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)
Les exemples de stratégies dans ce tutoriel sont uniquement utilisés pour les stratégies pédagogiques, les idées de conception de stratégies de guidage, et ne font aucun type de conseils, de conseils et de conseils commerciaux.
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()
Il est très simple d'écrire une stratégie de tendance en utilisant le langage Pine, ici nous avons conçu une stratégie de suivi de tendance simple avec un indicateur de tendance super.
La première chose à faire est d'utiliser le code stratégique.strategy
La fonction fait quelques réglages simples:strategy("supertrend", overlay=true)
, il suffit de définir une stratégie intitulée Supertrend.overlay
Le paramètre esttrue
La première chose que nous faisons pour concevoir une stratégie Pine ou pour apprendre un script de stratégie Pine est de regarder la conception des paramètres de l'interface de stratégie. Nous regardons le code source de la stratégie de l'indicateur de super-tendance, qui contient des choses que nous avons apprises dans des cours précédents.input
Les fonctions
[supertrend, direction] = ta.supertrend ((input ((5,
facteur input.int(Période de référence)),
input
L'appel à la fonction est utilisé directement pourta.supertrend
Les paramètres de la fonction indicateur sont utilisés pour calculer les indicateurs de supertrend. Parmi eux:
Par défaut, la fonction définit deux contrôles de paramètres dans l'interface de stratégie de la langue Pine, comme suit:
Vous pouvez voir que la valeur par défaut de la commande estinput
Les fonctions etinput
Les fonctions de série ((ici) sontinput.int
Ces deux fonctions nous permettent de définir sur l'interface stratégique.ta.supertrend
Paramètres de la fonction. La fonction d'indicateur de super-tendance calcule une donnée de prix.supertrend
et les données dans une direction.direction
Je ne sais pas comment faire.plot
Graphique de fonction, notez que lorsque le graphique est dessiné, il est dessiné en fonction de la direction de l'indicateur de supertrend et ne dessine que la direction actuelle; lorsquedirection
La tendance actuelle du marché est à la hausse à -1 heure, alors que la tendance actuelle du marché est à la hausse à 1 heure.direction
La tendance actuelle du marché est à la baisse à 1 heure.plot
Déterminez quand une fonction est dessinée.direction
Plus ou moins que 0.
Le prochainif ... else if
La logique est le jugement du signal de transaction, quand l'expressiondirection < 0
L'indicateur de tendance est un indicateur en temps réel indiquant que le marché est en hausse et que si les données de prix dans l'indicateur de tendance supérieure sont supérieures à celles de l'indicateur de tendance supérieure, les prix seront supérieurs à ceux de l'indicateur de tendance supérieure.supertrend
Plus élevé que le prix de l'indicateur de la super-tendance sur les 2 premières barres (c'est-à-diresupertrend[2],还记得历史操作符引用某个变量历史数据吧
Vous vous souvenez? Si vous avez une position en cours, un appel à la fonction descendante inverse vous permettra d'aplanir la position précédente et d'ouvrir la position en fonction de la direction de la transaction en cours.supertrend > supertrend[2]
Les conditions ne sont pas réunies, à condition que ce soit pour le moment.strategy.position_size < 0
Il y a aussi la possibilité d'utiliser des appareils de surveillance pour contrôler les mouvements de l'air.strategy.close_all()
L'exécution de la fonction, effectuant toutes les opérations d'équilibrage.
direction > 0
C'est la même chose lorsque vous êtes dans la phase de tendance à la baisse, si vous avez plusieurs titres qui sont tous en équilibre, alors vous remplissez les conditions.supertrend < supertrend[3]
Si vous utilisez le bouton de déclenchement de l'alarme, pourquoi le configurer comme ceci?[3]
Qu'en est-il des données sur les prix de l'indicateur de supertrend sur la troisième barre avant? Peut-être que c'est intentionnel pour le stratège, car certains marchés, comme le marché des contrats, sont légèrement plus à risque que les marchés à risque.
Pourta.supertrend
L'indicateur, si certains de vos camarades sont intéressés, c'est de savoir comment vous pouvez déterminer si la tendance actuelle est à la hausse ou à la baisse.
En fait, ce paramètre peut également être réalisé sous la forme d'une fonction personnalisée dans le langage Pine:
pine_supertrend(factor, atrPeriod) =>
src = hl2
atr = ta.atr(atrPeriod)
upperBand = src + factor * atr
lowerBand = src - factor * atr
prevLowerBand = nz(lowerBand[1])
prevUpperBand = nz(upperBand[1])
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
int direction = na
float superTrend = na
prevSuperTrend = superTrend[1]
if na(atr[1])
direction := 1
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
C'est une fonction personnalisée.ta.supertrend
L'algorithme est identique, bien sûr, les données d'indicateurs sont les mêmes.
On peut voir à partir de cet algorithme de fonctionnalités personnalisées que le calcul des indicateurs de super-tendance intégrés de Pine est utilisé parhl2
La variable intégrée (le prix le plus élevé, le prix le plus bas, le prix le plus élevé, le prix le plus bas, le prix le plus élevé, le prix le plus bas, le prix le plus élevé, le prix le plus bas, le prix le plus élevé, le prix le plus bas, le prix le plus élevé, le prix le plus bas, le prix le plus élevé, le prix le plus bas, la valeur moyenne du prix le plus élevé, le prix le plus bas) est calculée en fonction du paramètre atPeriod.
Mise à jour en fonction des expressions triangulaires dans le codelowerBand
etupperBand
。
lowerBand := lowerBand > prevLowerBand or close[1] < prevLowerBand ? lowerBand : prevLowerBand
upperBand := upperBand < prevUpperBand or close[1] > prevUpperBand ? upperBand : prevUpperBand
lowerBand: ligne descendante, pour déterminer si la tendance ascendante a changé; upperBand: ligne descendante, pour déterminer si la tendance descendante a changé; lowerBand et upperBand sont toujours en cours de calcul, mais cette fonction personnalisée détermine finalement la direction de la tendance actuelle.
else if prevSuperTrend == prevUpperBand
direction := close > upperBand ? -1 : 1
else
direction := close < lowerBand ? 1 : -1
On peut voir ici si la valeur de la super tendance sur la dernière barre estprevUpperBand
La tendance à la baisse est indiquée par la ligne ascendante.close
Plus queupperBand
Les prix ont évolué et ont été transformés en tendance haussière.direction
La variable de direction est définie sur - (Tendance haussière) ; sinon elle reste définie sur 1 (Tendance baissière).if direction < 0
Les conditions du signal ont été déclenchées.direction > 0
Les conditions du signal ont été déclenchées et le signal est resté vide.
superTrend := direction == -1 ? lowerBand : upperBand
[superTrend, direction]
Enfin, les données relatives aux prix et aux orientations des indicateurs de supertrend spécifiques sont retournées selon la direction choisie.
/*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)
Nous avons continué à étudier quelques exemples de conception de stratégies dans le langage Pine, mais cette fois nous avons vu une stratégie de balancement dynamique.BaseCurrency
Le montant et la variété de la transactionQuoteCurrency
Le montant de la monnaie est toujours traité en équilibre. Le prix relatif d'un actif augmente et la valeur du compte augmente. Si le prix relatif d'un actif diminue et la valeur du compte diminue, l'actif est acheté. C'est ce qu'on appelle la stratégie d'équilibrage dynamique.
Les inconvénients de cette stratégie sont que, comme le montre le graphique de retrospective, la stratégie de flottaison est plus importante lors de la phase de forte hausse (ou forte baisse) des prix.
Nous allons voir la stratégie de conception du code:
Nous avons utilisé une conception simplifiée pour simuler dans la stratégie unebalance
(c'est-à-dire le nombre d'actifs en devises) etstocks
Nous n'allons pas lire le nombre réel d'actifs dans le compte, nous utilisons simplement des montants simulés pour calculer les achats et les ventes appropriés.maxDiffValue
Ce paramètre est le critère de jugement d'équilibre.BaseCurrency
etQuoteCurrency
La déviation est plus grandemaxDiffValue
Il est temps d'équilibrer, de vendre des actifs plus chers, d'acheter des actifs moins chers et de rééquilibrer les actifs.
Le déclenchement du signal de trading stratégique doit avoir un sens à la phase BAR en temps réel, donc les conditions de trading stratégique sont mises en place dans le jugement if.not barstate.ishistory
Les prix actuels ne sont pas très élevés.balance
La valeur dépassestocks
Opération d'achat lors de la valeur. Opération de vente à l'inverse. Mise à jour après l'exécution de la transaction.balance
etstocks
Il y a une différence entre les deux types d'équilibre.
L'information ci-dessus contient le prix de la variété au début de l'analyse stratégique, qui est de 1458, donc j'ai délibérément défini le paramètrebalance
Paramètres définis pour: 4374 ((1458*3)stocks
Pour: 3° maintenir l'actif en équilibre au début.
Dans les cours précédents, nous avons apprisstrategy.exit
Nous n'avons pas d'exemples pour les fonctions de sortie de position, dont la fonction de suivi de l'arrêt de la perte. Nous utilisons les exemples de conception de stratégie dans cette section.strategy.exit
La fonction de suivi stop-loss stop-loss fonctionne pour optimiser une stratégie de super-trend.
Tout d'abord, voyons.strategy.exit
Les paramètres de la fonction Tracking Stop Loss Stop:
1、trail_price
Paramètres: déclencheur pour placer le suivi de l'ordre de mise en place logique de l'ordre de mise en place (à un prix spécifié)