do el operador histórico[]
Los valores históricos en la secuencia de tiempo de referencia. Estos valores históricos son los valores de la variable en la línea K BAR anterior a la línea K BAR actual cuando se ejecuta el script.[]
El operador se utiliza después de las llamadas de variables, expresiones y funciones.[]
El valor en este paréntesis cuadrado es el desplazamiento de la data histórica a la que queremos referir desde la línea BAR de la línea K actual. Por ejemplo, si quisiera citar el precio de cierre de la línea BAR de la línea K anterior, escribiría:close[1]
。
En las lecciones anteriores hemos visto una forma similar de escribir:
high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)
[]
El operador solo puede ser usado una vez en el mismo valor, por lo que esto es incorrecto y se equivocará:
a = close[1][2] // 错误
Tal vez vean aquí, algunos de sus compañeros de clase dirán que el operador[]
Es para la estructura de series, que parece ser muy parecida a la estructura de series (series) y a la de arrays.
A continuación, vamos a usar un ejemplo para mostrar la diferencia entre series y arrays en el lenguaje 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")
Aunque se dicea = close[1][2]
Es una forma equivocada de escribir esto, pero:
b = close[1]
c = b[1]
En este caso, el valor de la matriz es el valor de la matriz, y el valor de la matriz es el valor de la matriz, y la matriz es el valor de la matriz.b = close[1]
Después de la asignación, b debería ser un valor, sin embargoc = b[1]
, b todavía puede ser usado de nuevo por el operador histórico para citar el valor histórico. Se puede ver que el concepto de serie en el lenguaje de Pine no es tan simple como el de un conjunto. Se puede entender como el valor histórico de la barra anterior cercana, b es también una estructura de secuencia de tiempo, y se puede seguir citando su valor histórico.
Podemos mover el gráfico hacia abajo a la izquierda y ver que en la primera línea K, los valores de b y c son valores nulos ((na)). Esto se debe a que cuando el script se ejecuta en la primera línea K BAR, los valores históricos de referencia de uno o dos ciclos hacia adelante no existen. Por lo tanto, debemos tener en cuenta a menudo cuando escribimos estrategias si se hace referencia a valores nulos cuando se hace referencia a datos históricos.na
、nz
La función interna es la que juzga si la función es correcta o no, y la función interna es la que juzga si la función es correcta o no.nz
、na
Funciones, ¿recuerdas en qué capítulo?) que tratan específicamente los casos de valores vacíos, por ejemplo:
close > nz(close[1], open) // 当引用close内置变量前一个BAR的历史值时,如果不存在,则使用open内置变量
Esto es un tratamiento para el que se puede citar el valor nulo ((na)).
Hemos aprendido muchos de los operadores de la lengua Pine, que forman expresiones a través de varias combinaciones de números y operaciones. Entonces, ¿cuál es la prioridad de estas operaciones cuando se calcula en expresiones?
Las prioridades | El operador |
---|---|
9 | [] |
8 | El operador de unidad + 、 - y `not |
7 | * 、/ 、% |
6 | El operador binario + 、 - |
5 | > 、< 、>= 、<= |
4 | == 、!= |
3 | and |
2 | or |
1 | ?: |
Las partes de la expresión que tienen una alta prioridad se operan primero, y si tienen la misma prioridad se operan de izquierda a derecha. Si se quiere forzar la primera operación de una parte, se puede usar()
Envuelve una expresión que requiere una operación de esta parte primero.
Ya hemos aprendido el concepto de la etiqueta de la variable, la etiqueta de la variable es el nombre que se le da a la variable. Por lo tanto, también se dice: la variable es el identificador del valor guardado. Entonces, ¿cómo se declara una variable?
var
。varip
。var
、varip
La palabra clave es algo que ya hemos aprendido en el capítulo anterior “Operadores de asignación” y que no vamos a mencionar aquí. Si el modelo de declaración de la variable no escribe nada, por ejemplo, la frase:i = 1
En realidad, como hemos dicho antes, las variables que se declaran y se asignan se ejecutan en cada línea KBAR.
int i = 0
float f = 1.1
Los tipos en Trading View son más exigentes, y se producen errores si se usa el siguiente código en Trading View:
baseLine0 = na // compile time error!
En resumen, la declaración de una variable puede escribirse así:
// [<declaration_mode>] [<type>] <identifier> = value
声明模式 类型 标识符 = 值
Aquí se usa el operador de asignación:=
Asignar un valor a una variable en una declaración de variables. Cuando se asigna un valor, el valor puede ser una cadena, un valor, una expresión, una llamada de función, o un número.if
、 for
、while
oswitch
Estas estructuras de palabras clave, sentencias y usos se explicarán en detalle en los siguientes cursos, de hecho, hemos aprendido la asignación de sentencias if simples en los cursos anteriores, y podemos repasarlos).
Aquí nos centramos en la función de entrada, una función que usamos con mucha frecuencia cuando diseñamos y escribimos estrategias. Es una función muy importante en la estrategia de diseño.
Funciones de entrada:
input函数,参数defval、title、tooltip、inline、group
La función de entrada en FMZ es un poco diferente a la de Trading View, pero se utiliza como entrada asignada a los parámetros de la estrategia. A continuación, detallamos el uso de la función de entrada en FMZ con un ejemplo:
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)
Los controles soportados en FMZ actualmente incluyen entradas de valores, entradas de texto, tiradores y selección de valores. También se puede configurar el grupo de parámetros de la política, así como información de texto de sugerencia para configurar los parámetros.
A continuación se presentan algunos de los principales parámetros de la función de entrada:
Además de las declaraciones y asignaciones de variables individuales, el lenguaje Pine también declara un conjunto de variables y asigna un valor:
[变量A,变量B,变量C] = 函数 或者 ```if```、 ```for```、```while```或```switch```等结构
La más común es la que usamosta.macd
Cuando la función calcula el MACD, como el MACD es un indicador multilineal, calcula tres conjuntos de datos. Por lo tanto, se puede escribir como:
[dif,dea,column] = ta.macd(close, 12, 26, 9)
plot(dif, title="dif")
plot(dea, title="dea")
plot(column, title="column", style=plot.style_histogram)
Es muy sencillo dibujar un gráfico MACD con el código anterior, ya que las funciones incorporadas pueden devolver varias variables y las funciones personalizadas pueden devolver varios datos.
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)
El uso de estructuras como if como asignación de valores a varias variables también es similar a la forma de funciones personalizadas anterior, y los interesados pueden intentarlo.
[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)
Algunas funciones no se pueden escribir en bloques de código local de ramificaciones condicionales, principalmente las siguientes:
barcolor(), fill(), hline(), indicator(), plot(), plotcandle(), plotchar(), plotshape()
En Trading View se compilarán los informes de errores. En FMZ, las restricciones no son tan estrictas, pero también se recomienda seguir las normas de Trading View. Por ejemplo, aunque no se informan errores en FMZ, no se recomienda escribir así.
strategy("test", overlay=true)
if close > open
plot(close, title="close")
else
plot(open, title="open")
Un ejemplo:
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)
Nota: la expresión para juzgar, devuelve un valor de burr. Tenga en cuenta que no puede haber más de una sucursal de else. Todas las expresiones de la sucursal no son verdaderas, y sin la sucursal de else, devuelve na.
x = if close > open
close
plot(x, title="x")
Debido a que el bloque local de if no se ejecuta cuando la línea K BAR es negativa, es decir, cuando close < open, la expresión después de la frase if es falsa. En este caso tampoco hay una rama else, y la frase if devuelve na… … … … … . .
Una declaración de switch también es una declaración de estructura ramificada que se utiliza para diseñar diferentes vías de ejecución según ciertas condiciones. Las declaraciones de switch generalmente tienen los siguientes puntos clave de conocimiento:
1, la sentencia switch puede devolver un valor igual que la sentencia if 2. A diferencia de las declaraciones de cambio en otros lenguajes, la ejecución de la estructura de cambio solo ejecuta un bloque local en su código, por lo que la declaración de ruptura no es necesaria (es decir, no se necesita escribir palabras clave como ruptura). 3. cada rama de switch puede escribir un bloque de código local, y la última línea de este bloque de código local es el valor que se devuelve (que puede ser un subgrupo de un valor). Si no se ejecuta ningún bloque de código local de la rama, se devuelve na. 4. La ubicación de la expresión en la estructura de switches, donde se pueden escribir cadenas, variables, expresiones o llamadas de funciones. 5. switch permite especificar un valor de retorno que se utiliza como valor predeterminado cuando no hay otras condiciones en la estructura.
Los switches se dividen en dos formas, y vamos a ver ejemplos de cada una para entender cómo se usan.
1, con una expresiónswitch
Un ejemplo:
// 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)
Antes habíamos aprendido las funciones de entrada, y aquí continuamos con dos funciones similares a la entrada:input.string
、input.int
función.
input.string
El nombre de la secuencia de comandos es el siguiente:input.int
Función que devuelve un valor entero. En el ejemplo se añade una nueva función.options
El uso de los parámetros,options
Los parámetros se pueden pasar a un conjunto de valores seleccionables. Por ejemplo, en el ejemplooptions=["EMA", "SMA", "RMA", "WMA"]
yoptions=[5, 10, 20]
(Tenga en cuenta que uno es un tipo de cadena y el otro es un tipo de valor numérico). Así, los controles en la interfaz de la política no necesitan ingresar valores específicos, sino que se convierten en cajones para seleccionar las opciones que se proporcionan en el parámetro de opciones.
El valor de la variable func es una cadena de caracteres, la variable func como una expresión de la conmutación ((puede ser una variable, una llamada de función, una expresión), para determinar qué rama de la conmutación se ejecuta. Si la variable func no puede coincidir con la expresión en cualquier rama de la conmutación (es decir, es equivalente), se ejecuta el bloque de código de la rama predeterminada, que se ejecutaruntime.error("error")
La función hace que la política de lanzamiento de excepciones se detenga.
En nuestro código de prueba de arriba, después de la última línea de runtime.error de la rama de código por defecto de switch, no hemos añadido[Na, na] para compatibilizar el valor de devolución, en la vista de trading es necesario considerar el problema, si el tipo no es consistente, el error será compensado. Pero en FMZ, ya que no hay un tipo de requisito estricto, se puede omitir este código de compatibilidad.
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)
En FMZ no se producen errores, pero en trading view sí. Porque los tipos de las ramas de if son inconsistentes.
switch
Ahora lo vemos.switch
Otra forma de usar el término es escribirlo sin la expresión.
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)
Como se puede ver en el ejemplo de código de prueba, switch coincide con la ejecución de un bloque de código local que es verdadero en términos de ramificación. En general, las condiciones de ramificación después de la sentencia de switch deben ser mutuamente rechazadas. Es decir, en el ejemplo, up y down no pueden ser verdaderos al mismo tiempo.up = close > open // up = close < open
Cambiar el contenido de la nota, y volver a medir el resultado que se observa. Encontrará que la rama de switch solo puede ejecutar la primera rama. Además, se debe tener en cuenta que no se debe escribir la llamada de la función en la rama de switch, ya que la función no puede ser llamada en cada BAR, lo que puede causar problemas de cálculo de datos.switch
En el ejemplo, la rama de ejecución está definida y no se cambia en el funcionamiento de la estrategia.)
返回值 = for 计数 = 起始计数 to 最终计数 by 步长
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Las sentencias for son muy sencillas de usar, ya que el ciclo for puede finalmente devolver un valor (en inglés) o devolver varios valores para[a, b, c] como forma de a, b, c) ❚ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦ ◦
Utilizado en el ciclo forbreak
Palabras clave: Cuando se ejecutabreak
Después de la frase, el ciclo se detiene.
Utilizado en el ciclo forcontinue
Palabras clave: Cuando se ejecutacontinue
Después de la frase, el ciclo lo ignora.continue
El código siguiente ejecuta directamente la siguiente ronda de ciclo. La declaración for devuelve el valor devuelto en la última ejecución de ciclo. Si no se ejecuta ningún código, devuelve un valor nulo.
A continuación, mostramos un ejemplo sencillo:
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
Hay dos formas de sentencias, las que se explican con los siguientes códigos falsos:
返回值 = for 数组元素 in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
返回值 = for [索引变量, 索引变量对应的数组元素] in 数组
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Se puede ver que la principal diferencia entre las dos formas radica en el contenido que sigue a la palabra clave for, una de las cuales utiliza una variable como referencia a un elemento de la matriz. Una de ellas utiliza una estructura de referencia que contiene una variable de índice, un subconjunto de variables de un elemento de la matriz.
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")
Cuando se necesita un índice.for [i, ele] in testArray
¿Cómo se escribe?
Aplicaciones para el ciclo
Cuando se puede usar una función incorporada proporcionada por el lenguaje Pine para realizar algunos cálculos lógicos circulares, se puede escribir directamente con una estructura circular, o se puede procesar con una función incorporada. Tomemos dos ejemplos.
1 Calcular el promedio
Cuando se usa un diseño de estructura circular:
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)
En el ejemplo se utiliza la suma de for y se calcula el promedio.
La línea media se calcula directamente con la función incorporada:
plot(ta.sma(close, length), title="ta.sma", overlay=true)
Utiliza funciones integradas directamenteta.sma
Para calcular el indicador de la línea media, es obvio que es más sencillo usar la función integrada para calcular la línea media. En el gráfico de comparación se puede ver que los resultados calculados son completamente idénticos.
2 La suma
¿Utilizas el ejemplo anterior para ilustrarlo?
Cuando se usa un diseño de estructura circular:
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)
Para calcular la suma de todos los elementos de la matriz, se puede usar el ciclo, o se puede usar una función interna.array.sum
¿Qué es lo que está pasando?
La suma se calcula directamente con la función incorporada:
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)
Se puede ver que los datos calculados se muestran perfectamente en el gráfico usando un gráfico.
Entonces, ¿por qué diseñar un ciclo si se puede hacer todo esto con una función incorporada? 1 . Para algunas operaciones de la matriz, cálculo . 2. Revisar la historia, por ejemplo, para averiguar cuántos puntos altos del pasado fueron más altos que los del BAR actual. Dado que los puntos altos del BAR actual solo se conocen en el BAR en el que se ejecuta el script, se requiere un ciclo para regresar a tiempo y analizar los BAR anteriores. 3. Cuando la función interna en el lenguaje Pine no puede completar el cálculo del BAR pasado.
while
La sentencia permite que el código de la parte del ciclo se ejecute hasta que la condición de juicio de la estructura while sea falsa.
返回值 = while 判断条件
语句 // 注释:语句里可以有break,continue
语句 // 注释:最后一条语句为返回值
Las otras reglas de while son similares a las del ciclo for, donde la última línea del bloque de código local del cuerpo circular es el valor de retorno, que puede devolver varios valores. Cuando la “condición del ciclo” ejecuta el ciclo en tiempo real, el ciclo se detiene cuando la condición es falsa. También se puede usar la frase break, continue en el cuerpo circular.
También puedo mostrar el ejemplo de la línea de medición:
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)
Se puede ver que el uso de while en ciclo también es muy simple, y también se pueden diseñar algunas lógicas de cálculo que no pueden ser reemplazadas por funciones integradas, por ejemplo, la multiplicación por escalas:
counter = 5
fact = 1
ret = while counter > 0
fact := fact * counter
counter := counter - 1
fact
plot(ret, title="ret") // ret = 5 * 4 * 3 * 2 * 1
Arrays en el lenguaje de programación Pine y otras definiciones de arrays en lenguajes de programación similares, Arrays de Pine es un conjunto de dimensiones. Se suele utilizar para almacenar una serie continua de datos. Arrays en los que los datos individuales almacenados se llaman elementos del conjunto, los tipos de estos elementos pueden ser: enteros, flotantes, cadenas, valores de color, valores de burr.[]
Es necesario usararray.get()
yarray.set()
La función ◦ es la secuencia de índices de los elementos de la matriz, es decir, el índice del primer elemento de la matriz es 0, y el índice del siguiente elemento es incrementado por 1。
En un código muy simple, explicamos:
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))
usararray<int> a
、float[] b
Un conjunto de declaraciones o una sola variable puede ser asignado a un conjunto, por ejemplo:
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")
Utilizado generalmente para la inicialización de variables de la matrizarray.new
yarray.from
Función 。 Hay muchas otras funciones similares a array.new relacionadas con el tipo en el lenguaje Pine:array.new_int()
、array.new_bool()
、array.new_color()
、array.new_string()
esperar.
La palabra clave var también puede funcionar con el modo de declaración de la matriz, donde la matriz declarada con la palabra clave var sólo se inicializa en la primera línea BAR. Observemos con un ejemplo:
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")
Se puede ver que los cambios de la matriz a se determinan continuamente y no se restablecen. La matriz b se inicializa en cada BAR.barstate.islast
Por lo tanto, la impresión en tiempo real sigue teniendo un solo elemento, el valor 0。
Utiliza array.get para obtener los elementos que se indican en la posición de índice en el array, y utiliza array.set para modificar los elementos que se indican en la posición de índice en el array.
El primer parámetro de array.get es el array a procesar y el segundo es el índice especificado. El primer parámetro de array.set es el conjunto a tratar, el segundo es el índice especificado, y el tercero es el elemento a escribir.
Para ilustrarlo, utilicemos el siguiente ejemplo:
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")
Este ejemplo inicializa el color base verde, declara e inicializa un array para conservar el color y luego otorga una transparencia diferente a los valores de color (utilizando la función color.new) [2]. Calcula el grado de color calculando la distancia entre el BAR actual y el máximo de 100 ciclos de revisión. Cuanto más cerca del máximo de 100 ciclos de revisión más recientes, más alto es el grado y más profundo es el color correspondiente (baja transparencia).
¿Cómo se puede hacer un recorrido por una matriz usando las expresiones for/for in/while que hemos aprendido anteriormente?
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")
Los resultados son los mismos en las tres formas de recorrido.
Los arrays pueden ser declarados en el ámbito global del script, o en el ámbito local de la función o de la rama if.
Para el uso de elementos en una matriz, la siguiente manera es equivalente, podemos ver en el siguiente ejemplo que dibujamos dos grupos de líneas en la tabla, dos en cada grupo, y los valores de las dos líneas de cada grupo son exactamente los mismos.
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)
array.unshift()
、array.insert()
、array.push()
。
array.remove()
、array.shift()
、array.pop()
、array.clear()
。
Utilizamos el siguiente ejemplo para probar las operaciones de adición y eliminación de estas 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")
Aplicaciones para agregar y eliminar: Arrays como colas
Usando una matriz, y algunas de las funciones de adición y eliminación de la matriz, podemos construir una estructura de datos llamada “cuadrilla”. La cuadrilla se puede usar para calcular el promedio móvil del precio de tick, y algunos estudiantes pueden preguntar: ¿Por qué construir una estructura de cuadrilla? ¿No podríamos calcular el promedio con una matriz antes?
Una secuencia es una estructura que se utiliza a menudo en la programación. Las características de la secuencia son:
Los elementos que entran primero en la cola salen primero.
Esto asegura que los datos que existen en la cola son los más recientes y que la cola no se expande indefinidamente (el código que se expande indefinidamente solo se puede escribir al mediodía, ya que los problemas se producen entre la mañana y la tarde).
En el siguiente ejemplo, utilizamos una estructura de cola para registrar el precio de cada tick, calcular el promedio móvil a nivel de tick y luego compararlo con el promedio móvil a nivel de línea K de 1 minuto.
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")
Nótese que cuando declaramos una matriz a, especificamos el modo de declaración y usamos la palabra clavevarip
Así, cada cambio de precio se registra en una matriz a.
Calcular las funciones correspondientes:
array.avg()
Busquemos el promedio de todos los elementos de la matriz.array.min()
Busquemos el elemento más pequeño de la matriz.array.max()
Busque el elemento más grande de la matriz.array.stdev()
Busque la diferencia estándar de todos los elementos en la matriz.array.sum()
Busque la suma de todos los elementos del conjunto.
Funciones relacionadas con la operación:
array.concat()
Combinación o conexión de dos series.
array.copy()
Copiar una matriz.
array.join
Conecta todos los elementos de la matriz en una cadena.
array.sort()
En orden ascendente o descendente.
array.reverse()
Un conjunto invertido.
array.slice()
Se cortan las matrices.
array.includes()
El elemento de juicio.
array.indexof()
Devuelve el índice en el que apareció por primera vez el valor introducido por el parámetro. Si no encuentra ese valor, devuelve -1.
array.lastindexof()
Encuentra el último valor que apareció.
Ejemplos de prueba de funciones relacionadas con el cálculo de matrices:
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")
Estas son las funciones de cálculo de array más usadas.
Ejemplos de funciones operativas:
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")
El lenguaje Pine puede diseñar funciones personalizadas, y en general las funciones personalizadas del lenguaje Pine tienen las siguientes reglas:
barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()
) no puede ser invocado dentro de una función personalizada.También hemos usado funciones personalizadas en tutoriales anteriores, por ejemplo, las funciones personalizadas diseñadas en una sola línea:
barIsUp() => close > open
Esta función devuelve si el BAR actual es el rayo de sol.
Diseño de funciones personalizadas en varias líneas:
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)
Una función de la línea media de sma que nosotros mismos hemos implementado con una función personalizada.
También, se puede devolver un ejemplo de una función de configuración de dos 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)
Una función puede calcular una línea rápida, una línea lenta, dos indicadores de línea media EMA.
Las funciones integradas pueden ser fácilmenteFMZ PINE Script DocumentaciónEncuestas en línea
Las funciones integradas en el lenguaje Pine se clasifican:
Funciones de procesamiento de cadenasstr.
La serie.
2 Funciones de procesamiento de valores de colorcolor.
La serie.
3 , la función de entrada de parámetrosinput.
La serie.
4 . Función de cálculo del índiceta.
La serie.
5o, las funciones de dibujoplot.
La serie.
6 Funciones de procesamiento de arraysarray.
La serie.
Funciones relacionadas con la transacciónstrategy.
La serie.
Funciones relacionadas con las operaciones matemáticasmath.
La serie.
9, otras funciones ((procesamiento de tiempo, serie de dibujo de gráficos no-plot,request.
Funciones de serie, funciones de procesamiento de tipos, etc.)
strategy.
Las funciones de serie son las funciones que usamos a menudo en el diseño de estrategias, y están relacionadas con la ejecución de operaciones de transacción cuando la estrategia se ejecuta.
1、strategy.entry
strategy.entry
La función es una función de orden que es muy importante cuando se escribe una estrategia. Algunos de los parámetros más importantes de la función son:id
, direction
, qty
, when
esperar.
parámetro:
id
: puede entenderse como un nombre que se utiliza para referirse a una posición de negociación. Puede referirse a este id para revocar, modificar órdenes, cerrar posiciones.direction
Si la dirección de la orden es hacer más (comprar) este parámetro se transmitestrategy.long
Esta variable interna se transmite si se va a hacer un descuento.strategy.short
Esta variable es:qty
: Especifica la cantidad de pedidos, si no se transmite este parámetro, se usa la cantidad de pedidos por defecto.when
: condición de ejecución, se puede especificar este parámetro para controlar si se activa la operación de la orden actual.limit
Especificar el precio de la orden.stop
El precio de parada es:strategy.entry
Detalles de ejecución de la funciónstrategy
El control de la configuración de los parámetros en la llamada de la función también se puede realizar mediante“Parámetros de modelado de la biblioteca de clases de intercambio de lenguaje Pine”.Para más detalles sobre los controles de configuración, los controles de parámetros de la versión de la biblioteca de clases de transacciones en el lenguaje Pine, consulte el documento en el enlace.
¿Qué es lo más importante aquí?strategy
En la función,pyramiding
、default_qty_value
Parámetros. Prueba con el siguiente código:
/*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)
Inicio del código/*backtest ... */
La parte del paquete es para la configuración de retroalimentación, es para registrar información como la hora de configuración de retroalimentación en ese momento, para facilitar la desinstalación, no el código de la política.
En el código:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)
Cuando lo designamos,pyramiding
Si el parámetro es 3, entonces estamos configurando el máximo de tres operaciones en la misma dirección.strategy.entry
La siguiente operación no se ejecutó una vez.default_qty_value
El parámetro es 0.1, por lo que la identificación de la barra de ID es 1longstrategy.entry
El número de ordenes por debajo de la operación es el 0.1 que se establece por defecto.strategy.entry
Cuando la función se llamadirection
Es igual astrategy.long
En la actualidad, el costo de la prueba es de US$1,5 millones, por lo que los pedidos son pagados en la prueba de respuesta.
Nota en el códigostrategy.entry("long3", ...
La siguiente operación se llama dos veces, la primera para el mismo ID: long3strategy.entry
La siguiente operación no tuvo éxito, segunda llamadastrategy.entry
La función es para modificar el pedido de este ID ((los datos mostrados en la prueba de retroalimentación también pueden mostrar que el pedido de este pedido de precio límite se modificó para 0.3)). En otro caso, por ejemplo, si el primer pedido de ID se transactó con el ID de long3, continúe usando el ID de long3 que se transactóstrategy.entry
Si una función es ordenada, entonces la posición de la orden se acumula en IDlong3.
2、strategy.close
strategy.close
La función se utiliza para la posición de salida de la posición de entrada que identifica el ID de la posición de salida. Los parámetros principales son:id
,when
,qty
,qty_percent
。
parámetro:
id
La identificación de entrada que se requiere para la liquidación es la que usamos.strategy.entry
El ID que se indica al abrir la posición de la función de pedido de entrada.when
Condiciones de ejecución:qty
La cantidad de liquidaciones.qty_percent
Porcentaje de liquidez.Para familiarizarse con el uso de esta función, un ejemplo:
En el código/*backtest ... */
Es la información de configuración de FMZ.COM en la estación internacional de retrospectiva, puede eliminar, configurar el mercado, la variedad, el rango de tiempo que necesita para la prueba, etc.
/*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 estrategia de prueba mostró que se comenzó con tres entradas múltiples consecutivas, con ID de entrada de 1 long, y luego se usóstrategy.close
Los diferentes resultados de las respuestas de los diferentes parámetros de la función se pueden encontrar.strategy.close
Esta función no tiene parámetros para especificar el precio de salida de la posición de liquidación. Esta función se utiliza principalmente para la liquidación inmediata a los precios actuales del mercado.
3、strategy.close_all
strategy.close_all
La función se utiliza para despejar todas las posiciones actuales, ya que los guiones del lenguaje Pine solo pueden tener posiciones en una dirección, es decir, si se activa una señal en la dirección opuesta a la de la posición actual, se despejará la posición actual y se abrirá la posición según la señal.strategy.close_all
Cuando se llama, se borran todas las posiciones en la dirección actual.strategy.close_all
Los principales parámetros de la función son:when
。
parámetro:
when
Condiciones de ejecución:En este caso, el uso de un ejemplo para observar:
/*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
El código de prueba comienza con una tenencia de 0…strategy.position_size==0
es verdadero), por lo que sólo se ejecuta el ID de columna de longitud columna cuando cumple con las condiciones de la configuración del parámetro whenstrategy.entry
Función de entrada: después de tener varias posicionesstrategy.position_size
Más grande que 0, entonces la función de entrada de ID para la barra de short se puede ejecutar, debido a la posición de los titulares en ese momento, esta señal de inversión de la baja en la bolsa que se produce en este momento puede causar que la posición de los titulares se apague y luego se vuelva a abrir. Luego escribimos en la condición if cuandostrategy.position_size < 0
Cuando se mantiene una posición en blanco, se elimina toda la posición en la dirección de la posición actual. Y se marcaenableStop := true
│ dejar que la estrategia deje de ejecutarse para poder ver el registro │
Se puede encontrarstrategy.close_all
Esta función no tiene parámetros para especificar el precio de salida de la posición de liquidación. Esta función se utiliza principalmente para la liquidación inmediata a los precios actuales del mercado.
4、strategy.exit
strategy.exit
La función se utiliza para la operación de posición cerrada de entrada en la posición, a diferencia de la funciónstrategy.close
ystrategy.close_all
La función es la liquidación inmediata al precio de mercado actual.strategy.exit
La función planea la liquidación de acuerdo con la configuración de los parámetros.
parámetro:
id
: ID de pedido para la lista de condiciones de esta posición.from_entry
: ID de entrada que se utiliza para especificar la operación de liquidación que se realizará.qty
La cantidad de liquidaciones.qty_percent
Porcentaje de liquidez, rango: 0 ~ 100 ◦profit
El objetivo de ganancias, expresado en puntos.loss
El objetivo de la suspensión de daños, expresado en puntos.limit
Los objetivos de ganancias se determinan por el precio.stop
El objetivo es detener el daño y fijar el precio.when
Condiciones de ejecución:Utiliza una estrategia de prueba para comprender el uso de los parámetros.
”`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参数,则该退场订单无效,参数prof