cours précédents:
high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)
[]
L’opérateur ne peut être utilisé qu’une seule fois sur la même valeur, donc cette écriture est erronée:
a = close[1][2] // 错误
Vous pouvez voir ici, certains de mes camarades disent que l’opérateur[]
C’est pour les structures de séries, qui ressemblent beaucoup à des structures de séries et à des ensembles !
Voici un exemple pour illustrer la différence entre une série et un tableau dans le langage Pine.
strategy("test", overlay=true)
a = close
b = close[1]
c = b[1]
plot(a, title="a")
plot(b, title="b")
plot(c, title="c")
Bien quea = close[1][2]
Je ne sais pas si j’ai bien compris, mais:
b = close[1]
c = b[1]
Il n’y a pas d’erreur à le décomposer, si l’on le prend comme un tableau ordinaire.b = close[1]
Après avoir attribué une valeur, b devrait être un nombre, maisc = b[1]
, b peut toujours être réutilisé par l’opérateur historique pour faire référence à la valeur historique. Comme on peut le voir dans le langage de Pine, le concept de série n’est pas aussi simple qu’un tableau. On peut l’interpréter comme la valeur historique sur la barre précédente de close, b est aussi une structure de séquence temporelle, et on peut continuer à faire référence à sa valeur historique.
Nous pouvons faire glisser le graphique vers l’extrême gauche et observer que les valeurs de b et c sont nulles sur la première ligne K ((na) ). C’est parce que lorsque le script est exécuté sur la première ligne K BAR, aucune valeur historique n’est citée pour les cycles un ou deux en avant, elle n’existe pas.na
、nz
En fait, nous avons déjà abordé cela dans notre étude précédente.nz
、na
Les fonctions, vous vous souvenez de quel chapitre?) traitent spécifiquement des valeurs vides, par exemple:
close > nz(close[1], open) // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量
C’est un traitement qui peut se référer à une valeur nulle (null).
Nous avons déjà appris beaucoup d’opérateurs du langage Pine, qui forment des expressions en utilisant diverses combinaisons d’opérateurs et de nombres. Alors, quelle est la priorité de ces opérations lors du calcul dans les expressions?
Les priorités | Outil de calcul |
---|---|
9 | [] |
8 | Les opérateurs unitaires sont `+ 、 - et non |
7 | * 、/ 、% |
6 | Les opérateurs binaires sont + , - |
5 | > 、< 、>= 、<= |
4 | == 、!= |
3 | and |
2 | or |
1 | ?: |
Les parties de l’expression qui ont la priorité la plus élevée sont traitées en premier, et si elles ont la même priorité, elles sont traitées de gauche à droite. Si vous voulez forcer une partie à être traité en premier, vous pouvez utiliser()
Emballez une expression qui impose d’opérer cette partie d’abord.
Nous avons déjà étudié la notion d’identifiant de variable, qui est le nom donné à une variable en tant que nom de la variable. On peut donc dire que la variable est l’identifiant de la valeur conservée. Alors, comment déclarer une variable? Quelles sont les règles pour déclarer une variable?
var
。
2/ Utilisez des mots clésvarip
。
3/ Ne rien écrire.var
、varip
Le mot-clé a été étudié dans la section précédente sur les opérateurs d’attribution et n’est plus abordé ici. Si le mode de déclaration de la variable n’est pas écrit, par exemple:i = 1
En fait, comme nous l’avons déjà dit, les variables déclarées et attribuées sont exécutées sur chaque ligne KBAR.
int i = 0
float f = 1.1
Les types sont plus exigeants dans la vue de trading, et l’utilisation du code suivant dans la vue de trading entraînera des erreurs:
baseLine0 = na // compile time error!
En résumé, la déclaration d’une variable peut s’écrire:
// [<declaration_mode>] [<type>] <identifier> = value
声明模式 类型 标识符 = 值
L’opérateur d’attribution est utilisé ici:=
Les valeurs peuvent être des chaînes de caractères, des valeurs, des expressions, des appels de fonctions, ou encore des variables.if
、 for
、while
ouswitch
Les structures sont des mots-clés et des expressions structurées dont nous parlerons plus en détail dans les cours suivants. En fait, nous avons déjà appris l’attribution d’une simple expression if dans les cours précédents, nous pouvons revenir en arrière.
Nous allons nous concentrer sur la fonction d’entrée, une fonction que nous utilisons fréquemment dans la conception et l’écriture de stratégies. C’est aussi une fonction très importante dans la conception de stratégies.
Fonction d’entrée:
input函数,参数defval、title、tooltip、inline、group
La fonction d’entrée sur FMZ est un peu différente de celle de Trading View, mais elle est utilisée comme entrée de valeur attribuée pour les paramètres de stratégie. Voici un exemple détaillé de l’utilisation de la fonction d’entrée sur FMZ:
param1 = input(10, title="参数1名称", tooltip="参数1的描述信息", group="分组名称A")
param2 = input("close", title="参数2名称", tooltip="参数2的描述信息", group="分组名称A")
param3 = input(color.red, title="参数3名称", tooltip="参数3的描述信息", group="分组名称B")
param4 = input(close, title="参数4名称", tooltip="参数4的描述信息", group="分组名称B")
param5 = input(true, title="参数5名称", tooltip="参数5的描述信息", group="分组名称C")
ma = ta.ema(param4, param1)
plot(ma, title=param2, color=param3, overlay=param5)
La fonction d’entrée est souvent utilisée pour attribuer une valeur à une variable lors de la déclaration d’une variable. La fonction d’entrée sur FMZ dessine automatiquement les contrôles utilisés pour définir les paramètres de la stratégie sur l’interface de la stratégie FMZ. Les contrôles pris en charge sur FMZ incluent actuellement les cases de saisie de valeurs, les cases de saisie de texte, les cases déroulantes et la sélection de valeurs.
Nous vous présentons quelques paramètres principaux d’une fonction d’entrée:
En plus de la déclaration et de l’attribution de variables individuelles, le langage Pine déclare un ensemble de variables et d’attributions:
[变量A,变量B,变量C] = 函数 或者 ```if```、 ```for```、```while```或```switch```等结构
Le plus courant est celui que nous utilisons.ta.macd
Comme l’indicateur MACD est un indicateur multilinéaire, la fonction calcule trois ensembles de données. On peut donc écrire:
[dif,dea,column] = ta.macd(close, 12, 26, 9)
plot(dif, title="dif")
plot(dea, title="dea")
plot(column, title="column", style=plot.style_histogram)
Il est facile de dessiner un diagramme MACD avec le code ci-dessus. Non seulement les fonctions intégrées peuvent renvoyer plusieurs variables, mais les fonctions personnalisées peuvent également renvoyer plusieurs données.
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)
L’utilisation de structures telles que if comme attribution de valeurs à plusieurs variables est similaire à celle de la fonction personnalisée ci-dessus.
[ema10, ema20] = if true
fast = ta.ema(close, 10)
slow = ta.ema(close, 20)
[fast, slow]
plot(ema10, title="ema10", color=color.fuchsia, overlay=true)
plot(ema20, title="ema20", color=color.aqua, overlay=true)
Certaines fonctions ne peuvent pas être écrites dans un bloc de code local de branche conditionnelle, principalement les fonctions suivantes:
barcolor(), fill(), hline(), indicator(), plot(), plotcandle(), plotchar(), plotshape()
Le Trading View compile des rapports d’erreurs. Les restrictions sur FMZ ne sont pas aussi strictes, mais il est recommandé de suivre les spécifications de Trading View. Par exemple, bien que cela ne soit pas rapporté sur FMZ, il n’est pas recommandé de le faire.
strategy("test", overlay=true)
if close > open
plot(close, title="close")
else
plot(open, title="open")
Voici un exemple:
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 marquants: l’expression utilisée pour le jugement renvoie une valeur de Boole. Attention à la contraction. Il ne peut y avoir qu’une seule branche de la branche.
x = if close > open
close
plot(x, title="x")
Puisque le bloc local de if n’est pas exécuté lorsque la ligne KBAR est négative, c’est-à-dire lorsque close < open, l’expression suivante de la phrase if est false. Il n’y a pas non plus de branche else à ce moment-là. La phrase if renvoie na.
Les déclarations de commutation sont également des déclarations branchées qui sont utilisées pour concevoir différents chemins d’exécution selon certaines conditions. Les déclarations de commutation ont généralement les points clés suivants:
1, comme pour les expressions if et switch, il est possible de renvoyer une valeur. 2. Contrairement aux expressions de commutation dans d’autres langages, la commutation n’exécute qu’un seul bloc local de son code, de sorte qu’il n’est pas nécessaire d’écrire une déclaration de rupture (c’est-à-dire qu’il n’est pas nécessaire d’écrire des mots-clés tels que break). 3, chaque branche de switch peut écrire un bloc de code local, dont la dernière ligne est la valeur de retour ((il peut s’agir d’un sous-groupe de valeurs). Si aucune des branches n’a été exécutée, le bloc de code local est renvoyé. 4/ Déterminer l’emplacement d’une expression dans une structure de commutation, écrire une chaîne de caractères, une variable, une expression ou un appel de fonction. 5. switch permet de spécifier une valeur de retour qui est la valeur par défaut utilisée lorsqu’il n’y a pas d’autres conditions dans la structure.
On peut distinguer deux types de commutateurs, et nous allons voir un exemple à la fois pour comprendre comment ils sont utilisés.
1 avec une expressionswitch
L’exemple suivant:
// 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 déjà étudié les fonctions d’entrée, et nous allons maintenant étudier deux fonctions similaires à l’entrée:input.string
、input.int
fonction.
input.string
Le mot “script” est utilisé dans le texte de la requête.input.int
La fonction est utilisée pour renvoyer des valeurs entières.options
L’utilisation des paramètresoptions
Les paramètres peuvent être transférés dans un ensemble composé de valeurs sélectives. Par exemple, dans l’exempleoptions=["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 numérique). Ainsi, les contrôles de l’interface de stratégie n’ont pas besoin de saisir des valeurs spécifiques, mais deviennent des cases déroulantes pour sélectionner les options fournies dans le paramètre options.
La valeur de la variable func est une chaîne de caractères, avec la variable func comme expression de la commutation (en tant que variable, appel de fonction, expression), pour déterminer quelle branche de la commutation est exécutée. Si la variable func ne peut pas correspondre à l’expression sur n’importe quelle branche de la commutation (c’est-à-dire égale), l’exécution du bloc de code de la branche par défaut s’exécute.runtime.error("error")
La fonction a provoqué l’arrêt de l’exception de la stratégie.
Dans notre code de test ci-dessus, nous n’avons pas ajouté de runtime.error après la dernière ligne du bloc de code de la branche par défaut de switch[Un code tel que na, na] est nécessaire pour la compatibilité des valeurs de retour, mais il est possible d’ignorer ce code de compatibilité car il n’y a pas de type strictement requis sur FMZ. Il n’est donc pas nécessaire de prendre en compte la compatibilité des types des valeurs de retour des branches if, switch sur FMZ.
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 sur la FMZ, mais il y a une erreur sur la vue de trading.
2/ Non expriméswitch
Nous verrons plus loin.switch
Une autre façon d’écrire le mot “sans” est de l’é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)
Comme on peut le voir dans l’exemple de code de test, switch va faire correspondre le bloc de code local qui exécute la branche comme étant le vrai bloc de code local. En général, les conditions de la branche après la déclaration de switch doivent être mutuellement récusatives.up = close > open // up = close < open
En remplaçant le contenu de la note par le résultat de l’observation, on constate que la branche switch ne peut exécuter que la première branche. En outre, il faut veiller à ne pas écrire l’appel de la fonction dans la branche switch, car l’appel de la fonction sur chaque BAR peut causer des problèmes de calcul de données.switch
Dans l’exemple, la branche d’exécution est définie et ne peut pas être modifiée pendant le fonctionnement de la stratégie.)
返回值 = for 计数 = 起始计数 to 最终计数 by 步长
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
L’instruction for est très simple à utiliser, car la boucle for peut retourner une valeur finale ((), ou retourner plusieurs valeurs, pour[a, b, c]). Comme dans le pseudo-code ci-dessus, les variables attribuées à la position de “valeur de retour” sont suivies d’une variable “compte” utilisée pour contrôler le nombre de cycles, la référence à d’autres valeurs, etc. La variable “compte” est attribuée comme “compte initial” avant le début du cycle, puis progressivement selon le paramètre “pace”, et le cycle s’arrête lorsque la variable “compte” est supérieure au “compte final”.
Utilisé dans la boucle forbreak
Mots-clés: Quand cela est faitbreak
Le cycle s’arrête après la phrase.
Utilisé dans la boucle forcontinue
Mots-clés: Quand cela est faitcontinue
La phrase suivante est ignorée.continue
Le code suivant exécute directement le prochain cycle. L’instruction for renvoie la valeur de la dernière exécution du cycle. Si aucun code n’a été exécuté, elle renvoie une valeur nulle.
Voici un exemple simple pour le dé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 y a deux formes de phrases, et le pseudo-code ci-dessous en est une illustration.
返回值 = 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, soit en utilisant une variable comme référence d’un élément de l’arrayon. L’une est en utilisant une structure de référence qui contient un sous-ensemble de variables d’index, d’éléments de l’arrayon.
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’indexation lorsque cela est nécessaire.for [i, ele] in testArray
L’orthographe de l’anglais
Applications pour le cycle
Il est possible d’utiliser des fonctions intégrées fournies par le langage Pine pour effectuer des calculs de logique circulaire, d’écrire directement avec une structure circulaire ou de traiter avec des fonctions intégrées. Nous donnons deux exemples.
1, calculer la moyenne
Utilisez la conception de la structure circulaire:
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 for cyclique, puis on calcule la moyenne.
Calculez la moyenne en utilisant directement la fonction intégrée:
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Utilisation directe de fonctions intégréesta.sma
Il est évidemment plus simple d’utiliser une fonction intégrée pour calculer l’indicateur de la ligne moyenne. On peut voir une parfaite concordance des résultats calculés dans la comparaison du graphique.
2 - La somme
Vous pouvez aussi utiliser l’exemple ci-dessus.
Utilisez la conception de la structure circulaire:
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 la somme de tous les éléments d’une matrice, on peut utiliser un cycle ou une fonction intégrée.array.sum
Pour calculer.
Pour calculer l’addition 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)
On peut voir que les données calculées sont parfaitement cohérentes sur le graphique.
Alors, si on peut faire tout cela avec des fonctions intégrées, pourquoi concevoir des cycles ? 1 Pour certaines opérations sur un tableau, calculer: 2. Revenir en arrière dans l’histoire, par exemple, pour savoir combien de points élevés dans le passé sont supérieurs aux points élevés du BAR actuel. Comme le point élevé du BAR actuel n’est connu que sur le BAR du script en cours d’exécution, un cycle est nécessaire pour revenir en arrière et analyser les points élevés du BAR passé. 3 Les fonctions intégrées du langage Pine ne peuvent pas compléter le calcul du BAR passé.
while
L’instruction permet au code de la partie de la boucle d’être exécuté jusqu’à ce que la condition de jugement de la structure while soit false (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 corps de la boucle est une valeur de retour, qui peut renvoyer plusieurs valeurs. L’exécution de la boucle s’effectue lorsque la condition de la boucle est vraie et s’arrête lorsque la condition est fausse.
Je vais vous montrer l’exemple d’un calcul de l’équation:
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 de while en boucle est également très simple, mais on peut aussi concevoir des logiques de calcul qui ne peuvent pas être remplacées par des fonctions intégrées, par exemple pour calculer la multiplication par degrés:
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
L’array de Pine est une matrice qui est une matrice en trois dimensions. Elle est généralement utilisée pour stocker une série de données en continu. L’array dans lequel les données individuelles sont stockées s’appelle l’array d’éléments. Les types d’éléments peuvent être: entiers, floats, chaînes, valeurs de couleur, valeurs de boule.[]
Il faut utiliserarray.get()
etarray.set()
La fonction 。 est une fonction d’indexation de l’ordre des éléments dans l’arrêté si l’indexation du premier élément de l’arrêté est égale à 0 et celle du suivant est augmentée de 1。
Nous utilisons 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))
utiliserarray<int> a
、float[] b
Les ensembles de valeurs peuvent être attribués à des ensembles de valeurs qui déclarent des ensembles de valeurs ou qui déclarent une seule variable, 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’initialization de variables d’une matricearray.new
etarray.from
Il existe d’autres fonctions dans le langage Pine qui sont similaires à celles de array.new:array.new_int()
、array.new_bool()
、array.new_color()
、array.new_string()
attendez.
Le mot-clé var peut aussi s’appliquer au mode de déclaration d’un tableau. Un tableau déclaré avec le mot-clé var n’est initialisé que sur la première ligne BAR.
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 de l’arrayon a sont déterminées de façon continue, sans être réinitialisées. L’arrayon b est initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement initialement inbarstate.islast
Pour l’impression en temps réel, il n’y a qu’un seul élément, la valeur 0。
Utilisez array.get pour obtenir les éléments dont l’index est spécifié dans l’array et utilisez array.set pour modifier les éléments dont l’index est spécifié dans l’array.
Le premier paramètre de array.get est l’array à traiter, le second l’index spécifié. Le premier paramètre de array.set est l’array à traiter, le second l’index désigné, et le troisième l’élément à écrire.
L’exemple suivant est simple:
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 le vert comme couleur de base, déclare et initie un tableau pour préserver la couleur, puis confère une transparence différente à la valeur de la couleur (en utilisant la fonction color.new). Le niveau de couleur est calculé en calculant la distance de la valeur maximale de BAR actuelle de high sur 100 cycles de revue. Plus la distance est proche de la valeur maximale de high sur les 100 derniers cycles de revue, plus le niveau est élevé, et plus la valeur de couleur correspondante est profonde.
Comment parcourir un tableau, nous pouvons le faire avec les expressions 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 traversée donnent le même résultat.
Les ensembles peuvent être déclarés au niveau global du script, ou au niveau local de la fonction ou de la branche if.
Pour l’utilisation d’éléments dans un tableau, la méthode suivante est équivalente, nous pouvons voir par l’exemple suivant que deux groupes de lignes sont dessinés sur le graphique, deux lignes dans chaque groupe, et que les deux lignes de chaque groupe sont exactement les mêmes.
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)
1, les fonctions associées aux opérations d’addition d’un tableau:
array.unshift()
、array.insert()
、array.push()
。
2 Les fonctions associées à la suppression d’un tableau:
array.remove()
、array.shift()
、array.pop()
、array.clear()
。
Nous utilisons l’exemple suivant pour tester les opérations d’ajout et de retrait de ces ensembles.
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")
Ajout et suppression d’applications: Arrays en tant que queue
On peut construire une structure de données appelée “cohorte” en utilisant des matrices et des fonctions d’addition et de suppression de matrices. Les matrices peuvent être utilisées pour calculer les moyennes mobiles des prix de tick. Certains de vos camarades se demanderont peut-être: pourquoi construire une structure de cohorte ?
Une queue est une structure couramment utilisée dans le domaine de la programmation, caractérisée par:
Les éléments qui entrent en premier dans la queue sortent en premier.
Cela permet de s’assurer que les données présentes dans la queue sont les dernières et que la longueur de la queue ne s’agrandit pas à l’infini (le code qui s’agrandit à l’infini ne peut être écrit qu’à midi, car il y a des problèmes entre le matin et le soir).
Dans l’exemple suivant, nous utilisons une structure de queue pour enregistrer le prix à chaque tick, calculer une moyenne mobile au niveau du tick, puis la comparer avec une moyenne mobile au niveau de la ligne K à 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")
Notez que nous avons spécifié le mode de déclaration de l’arrayon a en utilisant le mot clévarip
Ainsi, chaque variation de prix est enregistrée dans un tableau a.
Calculer les fonctions suivantes:
array.avg()
Trouvez la moyenne de tous les éléments de l’array.array.min()
Trouvez le plus petit élément de l’array.array.max()
Trouvez le plus grand élément de l’array.array.stdev()
Trouvez la différence standard de tous les éléments de l’array.array.sum()
Trouver la somme de tous les éléments de l’array.
Fonctions liées à l’opération:
array.concat()
Fusion ou connexion de deux ensembles.
array.copy()
Copier une matrice
array.join
Connectez tous les éléments de l’array en une seule chaîne de caractères.
array.sort()
Par ordre décroissant ou décroissant.
array.reverse()
Arrayes inversées
array.slice()
Découper un tableau.
array.includes()
Éléments de jugement
array.indexof()
Retourne l’index de la première occurrence de la valeur de l’entrée de paramètre. Si cette valeur n’est pas trouvée, retourne -1.
array.lastindexof()
Trouver la dernière valeur qui apparaît.
Exemples de tests de fonctionnalités liées au calcul des ensembles:
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 de l’arrayon les plus couramment utilisées.
Exemple de fonctionnalités d’exploitation:
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 permet de concevoir des fonctions personnalisées, généralement avec les règles suivantes:
barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()
) ne peut pas être appelé dans une fonction personnalisée.
Les fonctions peuvent être écrites en une seule ligne ou en plusieurs lignes. La dernière phrase renvoie la valeur de la fonction actuelle, qui peut être renvoyée sous forme d’éléments.Nous avons utilisé plusieurs fois des fonctions personnalisées dans des tutoriels précédents, par exemple des fonctions personnalisées conçues en une seule ligne:
barIsUp() => close > open
Cette fonction renvoie si le BAR actuel est un rayonnement solaire.
Fonctions personnalisées en 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)
La fonction que nous avons nous-mêmes réalisée avec une fonction personnalisée de calcul de la moyenne de sma.
On peut également retourner des exemples de fonctions personnalisées pour 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 la ligne moyenne EMA.
Les fonctions intégrées peuvent facilement êtreNom de fichier:Les résultats de la recherche.
Les fonctions intégrées du langage Pine sont classées:
1 , fonction de traitement de chaînestr.
Série
2/ Fonction de traitement des valeurs de couleurcolor.
Série
3 - Fonction de saisie de paramètresinput.
Série
4/ La fonction de calcul des indicesta.
Série
5 - Fonction de dessinplot.
Série
Fonctions de traitement d’arrayarray.
Série
Fonctions liées aux transactionsstrategy.
Série
Fonctions mathématiquesmath.
Série
9), d’autres fonctions (traitement du temps, dessin de séries non-plot),request.
Fonctions de séries, fonctions de traitement de types, etc.)
strategy.
Les fonctions de séries sont des fonctions que nous utilisons souvent dans la conception de stratégies et qui sont liées à la stratégie pour exécuter des opérations de transaction lors de leur exécution.
1、strategy.entry
strategy.entry
Une fonction est une fonction de commande qui est importante pour nous quand nous écrivons des stratégies. Les paramètres qui sont importants pour cette fonction sont:id
, direction
, qty
, when
attendez.
paramètre:
id
: peut être interprété comme un nom donné à une position de négociation pour être utilisé comme référence. Il peut être utilisé comme référence pour l’annulation, la modification de l’ordre, la clôture de position.direction
: le paramètre est transmis si la direction de commande est faire plus (acheter)strategy.long
Cette variable interne est transmise si vous voulez faire une vente à découvert.strategy.short
Cette variable:qty
: indique le montant de la commande, si ce paramètre n’est pas transmis, le montant de la commande par défaut est utilisé.when
: Condition d’exécution, vous pouvez spécifier ce paramètre pour contrôler si l’opération suivante est déclenchée ou non.limit
Le prix limite de la commande est indiqué.stop
Le prix d’arrêt:strategy.entry
Détails de l’exécutionstrategy
Le contrôle des paramètres lors de l’appel d’une fonction peut également être effectué parParamètres de modélisation de la classe de transaction de langue PinePour plus de détails sur les paramètres de configuration et de contrôle de la modélisation de la bibliothèque de classes de transactions en langage Pine, consultez le document ci-dessous.
Je vais vous expliquer pourquoi.strategy
Dans la fonction,pyramiding
、default_qty_value
Paramètres ◦ Test avec 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)
Début du code/*backtest ... */
La partie du paquet est un réglage de la rétro-mesure, qui est destiné à enregistrer des informations telles que le temps de réglage de la rétro-mesure à ce moment-là, pour faciliter le débogage, et non le code de stratégie.
Dans le code:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
Quand nous avons désignépyramiding
Si le paramètre est de 3, nous pouvons régler le maximum de 3 transactions dans la même direction. Donc dans l’exemple, 4 fois.strategy.entry
L’opération suivante n’a pas été exécutée une fois.default_qty_value
Le paramètre est 0.1, donc l’identifiant de l’ID est long1strategy.entry
La valeur par défaut de la commande suivante est 0.1.strategy.entry
Et nous avons appelé la fonction.direction
est égal àstrategy.long
Les tests de retour sont payants.
Attention au codestrategy.entry("long3", ...
L’opération suivante est appelée deux fois, pour le même ID: long3.strategy.entry
La commande suivante n’a pas été exécutée, deuxième appelstrategy.entry
La fonction modifie l’ordre de l’ID ((les données affichées lors du test de retour peuvent également montrer que le montant de l’ordre de plafonnement a été modifié pour 0.3)). Dans un autre cas, par exemple, si l’ordre d’ID a été négocié pour la première fois pour 3 piles de longueur, continuez à utiliser l’ID négocié pour 3 piles de longueur.strategy.entry
Si la fonction commande, alors la position de commande s’accumule sur IDlong3.
2、strategy.close
strategy.close
La fonction est utilisée pour désigner les positions de placement pour les positions d’entrée identifiées par l’ID. Les principaux paramètres sont:id
,when
,qty
,qty_percent
。
paramètre:
id
Nous avons besoin d’un identifiant d’accès pour faire un dépôt, et nous l’utilisons.strategy.entry
L’ID indiqué lors de l’ouverture de la fonction de commande d’entrée.when
Conditions de mise en œuvre:qty
Nombre de placements en bourse.qty_percent
Le taux d’équilibre est de:Pour en savoir plus sur l’utilisation de cette fonction, voici un exemple:
Dans le code/*backtest ... */
Il s’agit de l’information de configuration de la station internationale FMZ.COM lors du test de retour, qui peut être supprimée, et de l’information sur le marché, la variété, la période de test et d’autres informations dont vous avez besoin.
/*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 a montré qu’il fallait commencer par faire trois entrées consécutives avec un ID d’entrée de longueur 1 et ensuite utiliserstrategy.close
On peut trouver les différents résultats de la régression des paramètres de la fonction.strategy.close
Cette fonction n’a pas de paramètre pour spécifier le prix de la commande de placement, cette fonction est principalement utilisée pour le placement immédiat au prix du marché actuel.
3、strategy.close_all
strategy.close_all
La fonction est utilisée pour effacer toutes les positions actuelles, car les scripts de langage Pine ne peuvent tenir que dans un seul sens, c’est-à-dire si un signal opposé à la direction de la position actuelle est déclenché, la position actuelle est effacée et la position est déclenchée en fonction du signal.strategy.close_all
La position de l’indicateur est appelée et évacue toutes les positions dans la direction actuelle.strategy.close_all
Les principaux paramètres de la fonction sont:when
。
paramètre:
when
Conditions de mise en œuvre:Nous utilisons 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
Le code de test débute avec un portefeuille de 0…strategy.position_size==0
est vraie), donc l’exécution de l’ID est à l’emplacement de la colonne de longueur de la colonne de longueur de la colonne de longueur de la colonne de longueurstrategy.entry
Fonction d’entrée:strategy.position_size
Plus grand que 0, c’est à ce moment-là que la fonction d’entrée ID pour la colonne short peut être exécutée, car il y a actuellement des positions multiples, ce signal de dépréciation inversé qui apparaît à ce moment-là entraînera le dépréciation de la position multiples et la reprise de la vacance. Ensuite, nous écrivons dans la condition if lorsquestrategy.position_size < 0
Lorsque le détenteur détient une position à vide, il élimine la totalité de la position détenue dans la direction de la position actuelle.enableStop := true
◦ Arrêter l’exécution de la stratégie afin d’observer le journal ◦
On peut trouverstrategy.close_all
Cette fonction n’a pas de paramètre pour spécifier le prix de la commande de placement, cette fonction est principalement utilisée pour le placement immédiat au prix du marché actuel.
4、strategy.exit
strategy.exit
La fonction est utilisée pour les opérations de placement d’entrée de position. Elle diffère de la fonctionstrategy.close
etstrategy.close_all
La fonction est la liquidation immédiate au prix du marché actuel.strategy.exit
La fonction planifie la compensation en fonction des paramètres.
paramètre:
id
: L’identifiant de commande de ce bon de placement actuel est l’ID。from_entry
: est l’identifiant d’entrée utilisé pour spécifier l’opération de placement.qty
Nombre de placements en bourse.qty_percent
Pourcentage de plafonnement, gamme: 0 ~ 100 ◦profit
Les objectifs de profit sont exprimés en points.loss
: Objectif d’arrêt des dégâts, exprimé en points.limit
Les objectifs de rentabilité sont définis par le prix.stop
: cessez-le-feu, indiquez le prix.when
Conditions de mise en œuvre:Utilisez une stratégie de test pour comprendre l’utilisation des paramètres.
”`pine /*backtest start: 2022-07-03 00:00:00 end: 2022-07-09 00:00:00 period: 1d basePeriod: 1h exchanges: [{“eid”:“Binance”,“currency”:“BTC_USDT”}] args: [[“RunMode”,1,358374],[“ZPrecision”,0,358374]] */
strategy(“strategy.exit Demo”, pyramiding=3)
varip isExit = false
findOrderIdx(idx) => ret = -1 if strategy.opentrades == 0 ret else for i = 0 to strategy.opentrades - 1 if strategy.opentrades.entry_id(i) == idx ret := i break ret
strategy.entry(“long1”, strategy.long, 0.1, limit=1, when=findOrderIdx(“long1”) < 0) strategy.entry(“long2”, strategy.long, 0.2, when=findOrderIdx(“long2”) < 0) strategy.entry(“long3”, strategy.long, 0.3, when=findOrderIdx(“long3”) < 0)
if not isExit and strategy.opentrades > 0 // strategy.exit(“exitAll”) // 如果仅仅指定一个id参数,则该退场订单无