En la carga de los recursos... Cargando...

Inventor de la introducción al lenguaje PINE cuantificado

El autor:Los inventores cuantifican - sueños pequeños, Creado: 2022-05-30 16:23:43, Actualizado: 2022-09-28 17:10:21

Los ejemplos:

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: Expresiones para juzgar, que devuelven valores de Boole. Nota de reducción. Sólo puede haber un máximo de una rama deelse. Todas las expresiones de rama no son verdaderas y no tienen una rama deelse, que devuelven na.

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

Dado que cuando la K-línea BAR es una línea cintil, es decir, cuando close < open, la expresión después de la frase if es falsa, no se ejecuta el bloque de código local de si. En este caso tampoco hay una ramaelse, la frase if devuelve na. x se asigna a na.

La frase de cambio

Las declaraciones de switch también son una estructura de ramificación para diseñar diferentes rutas de ejecución según ciertas condiciones. Las declaraciones de switch generalmente tienen los siguientes puntos clave de conocimiento.

1, como la expresión switch y la expresión if, puede devolver valores. 2, a diferencia de las declaraciones de switch en otros lenguajes, cuando se ejecuta la estructura de switch, solo se ejecuta un bloque local de su código, por lo que la declaración de break no es necesaria (es decir, no se necesita escribir palabras clave como break). Cada rama del switch puede escribir un bloque de código local, y la última línea de este bloque de código local es el valor de retorno (puede ser un conjunto de valores). Si no se ejecuta ninguno de los bloques de código local ramificados, se devuelve na. 4, la determinación de la posición de las expresiones en la estructura del switch, que puede escribirse como una cadena, una variable, una expresión o una llamada de función. 5. El switch permite especificar un valor de retorno que se usa como valor predeterminado cuando no se ejecuta ninguna otra situación en la estructura.

Los switches se dividen en dos formas, y vamos a ver ejemplos para entender cómo se usan.

1 con la expresiónswitchEn la página web del blog, se puede leer:

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

En este caso, la función de entrada es la función de entrada y la función de entrada es la función de entrada.input.stringinput.intLa función.input.stringEn el caso de los usuarios de Twitter, el número de mensajes que envían es el siguiente:input.intLa función se utiliza para devolver valores enteros. En este ejemplo, se añade un nuevo valor.options¿Cómo se usan los parámetros?optionsLos parámetros se pueden pasar a una matriz de valores seleccionables; por ejemplo, en el ejemplo anterior.options=["EMA", "SMA", "RMA", "WMA"]yoptions=[5, 10, 20](Nota que uno es de tipo de cadena y el otro de tipo de número). Así, los controles en la interfaz de la política no necesitan ingresar valores específicos, sino que se convierten en un cuadro desplegable para seleccionar las opciones que se ofrecen en el parámetro de opciones.

El valor de la variable func es una cadena, la variable func es la expresión del switch (puede ser una variable, una llamada de función, una expresión) para determinar qué rama del switch se ejecuta. Si la variable func no puede coincidir con la expresión en cualquiera de las ramas del switch (es decir, es igual), se ejecuta el bloque de código de rama predeterminado, que se ejecutará.runtime.error("error")La función hace que la política deje de lanzar excepciones.

En nuestro código de prueba anterior, después de la última línea de runtime.error del bloque de código de rama por defecto de Switch, no agregamos código como [na, na] para devolver el valor de compatibilidad, en el punto de vista comercial se necesita considerar el problema, si el tipo no es coherente, se reportará un error. Pero en FMZ se puede omitir este código de compatibilidad debido a que no hay requisitos estrictos de tipo.

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 reportan errores, en trading view se reportan errores; porque el tipo de la rama que se devuelve no es el mismo.

2 no tiene una expresiónswitch

Ahora vamos a ver.switchLa otra forma de usar la palabra es escribirla sin una 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, el switch coincide con el bloque de código local verdadero en las condiciones de ejecución de la rama. En general, las condiciones de rama después de la declaración del switch deben ser mutuamente contradictorias. Es decir, en el ejemplo, el up y el down no pueden ser simultáneamente verdaderos.up = close > open // up = close < openReemplazar el contenido de los comentarios, volver a evaluar los resultados observados. Se encontrará que la rama de switch sólo puede ejecutar la primera rama. Además, se debe tener cuidado de no escribir las llamadas de funciones en la rama de switch, las funciones no pueden ser llamadas en cada BAR, lo que puede causar algunos problemas de cálculo de datos.switchEn el ejemplo de "la rama de ejecución está definida y no se cambiará durante la ejecución de la estrategia").

La estructura circular

Las frases for

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

El uso de la declaración for es muy simple, ya que el ciclo for puede devolver finalmente un valor (o devolver varios valores, en forma de [a, b, c]); como en el pseudo código anterior, la variable asignada a la posición de "valor de retorno" es seguida por una variable de "cuento" para controlar el número de vueltas, citar otros valores, etc. La variable "cuento" se asigna como "cuento inicial" antes de que comience el ciclo, y luego se pasa según la configuración de "crecimiento", y el ciclo se detiene cuando el número de "cuento" es mayor que el de "variable final".

para el ciclobreakPalabras clave: Cuando se ejecutabreakDespués de una frase, el ciclo se detiene. para el ciclocontinuePalabras clave: Cuando se ejecutacontinueDespués de una frase, el ciclo se desvanece.continueEl código posterior, ejecuta directamente el siguiente ciclo. La frase for devuelve el valor de la última vez que se ejecutó el ciclo. Si no se ejecuta ningún código, devuelve el valor en blanco.

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

Las frases para... en

for ... inLas frases tienen dos formas, las cuales se explican con el siguiente código falso:

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

Se puede ver que la principal diferencia entre las dos formas está en lo que sigue después de la palabra clave for, una es usar una variable como referencia a los elementos de la matriz. La otra es usar una estructura que contiene una variable de índice, un elemento de matriz y una matriz de variables para hacer referencia. La otra es usar reglas de valor de retorno, reglas como break, continuue y for. También mostramos el uso con un ejemplo simple.

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, se usa.for [i, ele] in testArrayEl nombre de la ciudad es el siguiente:

para aplicaciones circulares

Cuando se pueden realizar algunos cálculos de lógica circular con funciones integradas proporcionadas por el lenguaje Pine, se pueden escribir directamente con estructuras circulares, o se puede procesar con funciones integradas. Demos dos ejemplos.

1 es la media calculada.

Cuando se utiliza el diseño de estructuras circulares:

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 el for para la suma circular, y luego se calcula la igualdad.

Calcular la línea media directamente con la función integrada:

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

Utilice directamente las funciones integradasta.smaEl cálculo de los indicadores de la línea uniforme es, evidentemente, más sencillo que el cálculo de la línea uniforme mediante funciones integradas. En el gráfico, el contraste puede ver que los resultados calculados son perfectamente coincidentes.

2 y suma

También puede utilizar el ejemplo anterior para ilustrarlo.

Cuando se utiliza el diseño de estructuras circulares:

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 todos los elementos de la matriz y que se pueden procesar con el ciclo, también se pueden usar funciones integradas.array.sum¿Qué es lo que está sucediendo? Calcular la suma directamente con las funciones integradas:

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 coherentes en el gráfico usando el gráfico de la trama.

¿Por qué diseñar ciclos si se puede hacer todo esto con funciones integradas? 1, algunas operaciones para el conjunto de matrices, cálculo. 2, Revisando el historial, por ejemplo, para averiguar cuántos picos pasados son más altos que los picos del BAR actual. Como el pico del BAR actual solo se conoce en el BAR en el que se ejecuta el script, se necesita un ciclo para regresar a tiempo y analizar el BAR pasado. 3, en el caso de que las funciones integradas que utilizan el lenguaje Pine no puedan completar el cálculo de BAR en el pasado.

Mientras

whileLas instrucciones permiten que el código de la parte circular se ejecute hasta que la condición de juicio en la estructura while sea falsa.

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

Las otras reglas de while son similares a las de los ciclos for, donde la última línea del bloque de código local del ciclista es el valor de retorno, y puede devolver varios valores. Cuando la "condición del ciclo" es real, se ejecuta el ciclo, y cuando la condición es falsa, se detiene el ciclo. También se pueden usar las declaraciones break, continue en el cuerpo del ciclo.

En la actualidad, la mayoría de los usuarios de Twitter están usando el teléfono móvil como una herramienta de comunicació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 del ciclo de whilst también es muy sencillo, y también se puede diseñar algunas lógicas de cálculo que no pueden ser reemplazadas por funciones integradas, por ejemplo, el cálculo de la multiplicación:

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

Los conjuntos

Similar a la definición de las matrices en el lenguaje Pine y en otros lenguajes de programación, las matrices de Pine son matrices en una dimensión. Generalmente se utilizan para almacenar una serie continua de datos. Las matrices en las que se almacenan datos individuales se llaman elementos de la matriz, y los tipos de estos elementos pueden ser: entero, tipo de punto flotante, cadena, valor de color, valor de Boole. El lenguaje Pine en FMZ no requiere un tipo muy estricto, incluso puede almacenar cadenas y valores al mismo tiempo en una matriz.[]Es necesario usarlo.array.get()yarray.set()Función. La secuencia de índices de los elementos en el conjunto es 0 para el primer elemento y 1 para el siguiente elemento.

En el caso de los bloggers, el código es muy simple:

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

Declarado

Usoarray<int> afloat[] bLas matrices declaradas o las que declaran solo una variable pueden ser asignadas a matrices, 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")

Utilización general para la inicialización de variables de matrizarray.newyarray.from函数。Pine语言中还有很多和类型相关的与array.new类似的函数:array.new_int()array.new_bool()array.new_color()array.new_string()Y luego.

La palabra clave var también puede funcionar con el modo de declaración de la matriz, donde la matriz con la palabra clave var se inicializa solo en la primera barra.

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 en el conjunto a se determinan continuamente y no se vuelven a colocar; el conjunto b se inicializa en cada BAR; y finalmente en elbarstate.islastEn el caso de la impresión en tiempo real, solo queda un elemento, el valor 0♦.

Leer y escribir elementos en una matriz

Obtener elementos que especifican la posición del índice en una matriz con array.get y modificar elementos que especifican la posición del índice en una matriz con array.set.

El primer parámetro de array.get es el parámetro a tratar, y el segundo parámetro es el índice indicado. El primer parámetro de array.set es el parámetro a procesar, el segundo parámetro es el índice a especificar y el tercero es el elemento a escribir.

Para ilustrarlo, utilice el siguiente ejemplo 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")

Este ejemplo inicializa el color base verde, declara e inicializa una matriz para guardar el color, y luego asigna una transparencia diferente al valor del color (utilizando la función color.new). El rango del color se calcula calculando la distancia máxima del valor high en 100 ciclos de visualización del BAR actual. La distancia más cercana al máximo de high en los ciclos de visualización más recientes es el rango más alto y el valor de color correspondiente es más profundo (baja transparencia). Muchas estrategias similares se usan de esta manera para representar el nivel del precio en N ciclos de visualización actuales.

Acceso a los elementos de la matriz

¿Cómo se puede recorrer una matriz, podemos hacerlo con la oración 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 tres métodos de exploración tienen el mismo resultado.

Las matrices pueden declararse en el ámbito global del guión, o en el ámbito local de la función o de la rama if.

Referencias históricas

Para el uso de los elementos de la matriz, la siguiente forma es equivalente, podemos ver en el siguiente ejemplo que se dibujan dos grupos de líneas en el gráfico, dos líneas por grupo, y el número de líneas de cada grupo es exactamente el mismo.

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)

Añadir y eliminar las funciones de operación

1, Función relacionada con el aumento de la operación del conjunto:

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

Función relacionada con la operación de eliminación de la matriz 2:

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

Utilizamos los siguientes ejemplos para probar las funciones de adición, eliminación y operació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: matriz como columna

Usando las matrices, y algunas funciones de adición y eliminación de matrices, podemos construir estructuras de datos de "columnas". Las columnas se pueden usar para calcular las medias móviles de los precios de los ticks. Algunos estudiantes pueden preguntar: ¿Por qué construir estructuras de columnas?

Una cola es una estructura que se utiliza a menudo en el campo de la programación.

Primero entra el elemento de la cola, primero sale de la cola.

Esto garantiza que los datos que existen en la cola son los más recientes y que la longitud de la cola no se expande infinitamente (el código de inflación infinita solo se puede escribir a mediodía, ya que los días tempranos o tardíos pueden ser problemáticos).

En el ejemplo siguiente, utilizamos una estructura de cola para registrar el precio de cada tick, calcular el precio promedio móvil a nivel de tick y luego compararlo con el promedio de observación de la línea 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")

Nota, cuando declaramos una matriz, hemos especificado el modelo de declaración, usando la palabra clave.varipAsí, cada cambio de precio se registra en una matriz a.

Computación aritmética de uso común, funciones operativas

Calcular las funciones:

array.avg()El valor medio de todos los elementos de la matriz.array.min()Es el elemento más pequeño de la matriz.array.max()El elemento más grande de la matriz.array.stdev()El valor de los elementos de la matriz es el valor de los valores de los elementos de la matriz.array.sum()La suma de todos los elementos de la matriz.

Funciones relacionadas con la operación:array.concat()Combinar o conectar dos matrices.array.copy()Replicación de las matrices.array.joinConecta todos los elementos de la matriz en una sola cadena.array.sort()En la lista de las personas que han sido seleccionadas, el nombre de la persona que ha sido seleccionada debe estar en el orden ascendente o descendente.array.reverse()El conjunto invertido.array.slice()Se hace un corte en el conjunto.array.includes()Los elementos de juicio.array.indexof()Devuelve el índice en el que apareció por primera vez el valor del parámetro enviado. Si no se encuentra, devuelve −1.array.lastindexof()Encuentra el valor que apareció por última vez.

Ejemplos de pruebas de funciones relacionadas con el cálculo aritmético:

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 computación de arítmetos más usadas.

Ejemplos de funciones relacionadas:

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

Función

Funciones personalizadas

El lenguaje Pine puede diseñar funciones personalizadas, y en general, las funciones personalizadas del lenguaje Pine tienen las siguientes reglas:

1, todas las funciones están definidas en el ámbito global del script. No se puede declarar una función en otra función. 2, no permite que las funciones se llamen a sí mismas en su propio código. 3. En principio, todas las lenguas PINE tienen funciones gráficas incorporadas.barcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) no puede ser llamado dentro de funciones personalizadas. 4, la función puede ser escrita como una sola línea, varias líneas. El valor de retorno de la última frase es el valor de retorno de la función actual, el valor de retorno puede ser de forma de grupo.

En tutoriales anteriores también hemos usado varias veces funciones personalizadas, como diseñar funciones personalizadas en una sola línea:

barIsUp() => close > open

Esta función devuelve si el BAR actual es el rayo solar.

Se ha diseñado como una función personalizada de 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 cálculo de la línea media de SMA que hemos implementado nosotros mismos con funciones personalizadas.

También, podemos devolver ejemplos de funciones personalizadas con 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 EMA equilíneos.

Funciones integradas

Las funciones integradas se pueden usar fácilmenteFMZ PINE Script documentaciónEncuesta en el centro.

Las funciones integradas en el lenguaje Pine:

1, la función de procesamiento de la cadenastr.La serie también incluye: 2, función de procesamiento de valor de colorcolor.La serie también incluye: 3, función de entrada de parámetrosinput.La serie también incluye: Función de cálculo de indicadoresta.La serie también incluye: 5, la función de dibujoplot.La serie también incluye: Función de procesamiento de matrices 6.array.La serie también incluye: 7 Funciones relacionadas con transaccionesstrategy.La serie también incluye: Funciones relacionadas con las operaciones matemáticasmath.La serie también incluye: 9, otras funciones (procesamiento de tiempo, funciones de gráficos de series no plot, etc.)request.Las funciones de serie, las funciones de procesamiento de tipos, etc.)

Función de transacción

strategy.Las funciones de serie son funciones que usamos a menudo en las estrategias de diseño, que están estrechamente relacionadas con la ejecución de operaciones cuando se ejecutan específicamente.


1、strategy.entry

strategy.entryLa función es una función de subordinación que es más importante cuando escribimos la política, que es más importante en varios parámetros:id, direction, qty, whenY luego.

Parámetros:

  • idSe puede entender que: se usa para referirse a un nombre para una posición comercial. Se puede referirse a este id para cancelar, modificar la orden, liquidar.
  • direction: si la dirección de la orden es hacer más (comprar) el parámetro se transmitestrategy.longEsta variable está hecha para pasar si se quiere hacer un espacio libre (venda).strategy.shortEsta es una variable.
  • qty: especifica la cantidad a ordenar, si no se transmite este parámetro se usa la cantidad de unidad por defecto.
  • when: Condición de ejecución, se puede especificar este parámetro para controlar si se activa o no la operación de la orden actual.
  • limitEl precio límite para el pedido es:
  • stopEl precio de la suspensión de pérdida.

strategy.entryLos detalles específicos de ejecución de la funciónstrategyLos parámetros de configuración del control cuando se llama una función también se pueden controlar mediante"Parámetros para el modelo de la librería de transacciones de lenguaje Pine"Para más detalles sobre el control de transacciones, consulte la documentación en el enlace.

¿Qué es lo que está sucediendo?strategyEn el caso de las funciones,pyramidingdefault_qty_valuePará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 está configurada para la revisión, es para registrar información como el tiempo de la revisión en ese momento, para facilitar el desactivació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 especificamos,pyramidingCuando el parámetro es 3, tenemos un máximo de tres transacciones en la misma dirección.strategy.entryUna de las siguientes operaciones no se ejecutó.default_qty_valueEl parámetro es 0.1, por lo que el ID es el 1 por tonelado.strategy.entryLa cantidad de menús de la operación de menús está configurada por defecto como 0.1′.strategy.entryLa función que llamamos.directionEs el mismostrategy.longEn la actualidad, la mayoría de los usuarios de Twitter no tienen acceso a la red social, por lo que los usuarios deben pagar para volver a probar.

En el código.strategy.entry("long3", ...La siguiente operación se llama dos veces, para el mismo ID: long3.strategy.entryNo se ha completado la siguiente operación, se llama por segunda vez.strategy.entryFunción para modificar el ID de la orden (los datos que se muestran en la prueba de retrospección también pueden ver que el volumen de la orden de este pedido de precio límite se ha modificado para 0.3); en otro caso, por ejemplo, si la primera orden de ID se realiza con el ID de la transacción, continúa con el ID de la transacción.strategy.entrySi la función pone un pedido, las posiciones de pedido se acumulan en el ID de la pieza de 3 piezas.


2、strategy.close

strategy.closeLa función se utiliza para especificar el ID de identificación de la posición de entrada de la posición de liquidación. Los parámetros principales son:idwhenqtyqty_percent

Parámetros:

  • idEn la actualidad, la mayoría de los usuarios de Facebook están usando el nombre de usuario de Facebook.strategy.entryEl ID que se indica cuando se abre la función de entrada.
  • whenLas condiciones de ejecución:
  • qtyEl número de operaciones de liquidación.
  • qty_percentPorcentaje de liquidación.

Para familiarizarse con los detalles de uso de esta función, veamos un ejemplo: En el código/*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 estrategia de prueba muestra que se comienza a hacer múltiples entradas tres veces consecutivas, con un ID de entrada de 1 long, y luego se usastrategy.closeLos diferentes resultados obtenidos cuando los diferentes parámetros de la función se ponen en equilibrio pueden encontrarse.strategy.closeEsta función no tiene parámetros para especificar el precio de un pedido de liquidación, y se utiliza principalmente para liquidar de inmediato el precio actual del mercado.


3、strategy.close_all

strategy.close_allLa función se utiliza para nivelar todas las posiciones actuales, ya que el script de Pine solo puede tener una dirección de posicionamiento, es decir, si hay una señal en contra de la dirección de la posición actual, el gatillo se aplanará y abrirá la posición según la señal.strategy.close_allCuando se le llama, estabiliza todas las posiciones en la dirección actual.strategy.close_allLos parámetros principales de la función son:when

Parámetros:

  • whenLas condiciones de ejecución:

En el caso de los que no tienen acceso a la red, la información es más fácil de obtener.

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

Cuando el código de prueba comienza, el volumen de almacenamiento es 0 (es decir,strategy.position_size==0Para ver), por lo que cumple con las condiciones del parámetro de cuando sólo se ejecuta el ID para el parámetro de when.strategy.entryFunción de entrada. Después de mantener varias posicionesstrategy.position_sizeLa función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de entrada de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida de la función de salida destrategy.position_size < 0Cuando se mantiene una posición vacía, se estabiliza toda la posición en la dirección de la posición actual; y se marcaenableStop := truePor ejemplo, en el caso de los registros de seguridad, la política de bloqueo de la aplicación puede ser más fácil de observar.

¿Cómo se puede encontrar?strategy.close_allEsta función no tiene parámetros para especificar el precio de un pedido de liquidación, y se utiliza principalmente para liquidar de inmediato el precio actual del mercado.


4、strategy.exit

strategy.exitLa función se utiliza para operaciones de liquidación de entradas de tenencia, que difiere de la funciónstrategy.closeystrategy.close_allLa función se estabiliza inmediatamente en el precio actual del mercado.strategy.exitLa función planea el equilibrio de acuerdo con los parámetros.

Parámetros:

  • id: el identificador de pedido de la lista de condiciones de liquidación actual.
  • from_entry: se utiliza para especificar el ID de entrada para realizar operaciones de liquidación.
  • qtyEl número de operaciones de liquidación.
  • qty_percentPorcentaje de liquidación, rango: 0 ~ 100.
  • profitEl objetivo de la ganancia, expresado en puntos.
  • lossEl objetivo es detener los daños, indicado en puntos.
  • limitLos objetivos de ganancias se determinan por el precio.
  • stopEl objetivo es detener los daños, y el precio es el indicado.
  • whenLas condiciones de ejecución:

Utilice una estrategia de prueba para entender el uso de los parámetros.

/*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语言模板参数上「定价货币精度」参数设置有关

Utilizando la prueba de retrospección del modelo de precios en tiempo real, esta estrategia de prueba comienza con la ejecución de 3 operaciones de entrada.strategy.entryFunción), conlong1 tiene una configuración intencionallimitParámetros, el precio del pedido de suspensión es 1 lo que hace que sea imposible de negociar. Luego prueba la condición de salida de la funciónstrategy.exit; se utilizan paradas por número de puntos, paradas por precio, paradas por número de posiciones fijas, paradas por porcentaje. Dado que en el ejemplo de este artículo solo se demuestra el paradas. Las operaciones de paradas y pérdidas también son simétricas.strategy.exitLa función también tiene parámetros de seguimiento más complejos:trail_pricetrail_pointstrail_offsetTambién se puede probar en este ejemplo para aprender cómo usarlo.


5、strategy.cancel

strategy.cancelFunciones para cancelar/desactivar todos los comandos de las listas de espera. Estas funcionesstrategy.order, strategy.entry , strategy.exitSe puede generar un ID de entrada. El parámetro principal de esta función es:idwhen

Parámetros:

  • idEn la página web de la organización, se puede leer:
  • whenLas condiciones de ejecución:

Esta función se entiende bien porque se utiliza para cancelar órdenes de acceso sin transacción.

/*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_allFunción ystrategy.cancelFunción similar a: ⇒ cancelar/desactivar todos los comandos de lista de espera. ⇒ puede especificarwhenLos parámetros.

Parámetros:

  • whenLas condiciones de ejecución:
/*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.orderLas funciones, los parámetros, etc. son casi iguales.strategy.entryEn la actualidad, la mayoría de los blogs están en línea.strategy.orderLa función no puedestrategyLa funciónpyramidingLos parámetros afectan a la configuración, no hay límite de número de veces.

Parámetros:

  • idSe puede entender que: se usa para referirse a un nombre para una posición comercial. Se puede referirse a este id para cancelar, modificar la orden, liquidar.
  • direction: si la dirección de la orden es hacer más (comprar) el parámetro se transmitestrategy.longEsta variable está hecha para pasar si se quiere hacer un espacio libre (venda).strategy.shortEsta es una variable.
  • qty: especifica la cantidad a ordenar, si no se transmite este parámetro se usa la cantidad de unidad por defecto.
  • when: Condición de ejecución, se puede especificar este parámetro para controlar si se activa o no la operación de la orden actual.
  • limitEl precio límite para el pedido es:
  • stopEl precio de la suspensión de pérdida.

Así que usamosstrategy.orderNo hay limitación en el número de unidades siguientes, la combinaciónstrategy.exitFunción de salida condicional. Construye un script similar a una transacción de red. El ejemplo es muy simple, sólo para aprender:

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

Ejemplos estratégicos

Los ejemplos de estrategias en este tutorial se utilizan solo para la enseñanza de estrategias y ideas de diseño de estrategias de orientación, y no son ninguna guía de transacciones, sugerencias o consejos.

Las estrategias de los indicadores de súper tendencia

strategy("supertrend", overlay=true)

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

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

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

Es muy sencillo escribir estrategias de tendencia en el lenguaje Pine, aquí diseñamos una estrategia de seguimiento de tendencias simple con un indicador de tendencia súper. Vamos a analizar el código fuente de esta estrategia juntos.

Primero, el código estratégico comienza a utilizarse.strategyLa función hace algunos ajustes simples:strategy("supertrend", overlay=true), sólo tiene que establecer una política titulada Supertrend.overlayEl parámetro estrueCuando diseñamos una estrategia Pine o aprendemos un guión de la estrategia Pine, lo primero que debemos ver es el diseño de parámetros de la interfaz de la estrategia.inputFunción

[supertendencia, dirección] = ta.supertendencia ((entrada ((5, factor),input.int(por ejemplo, en el caso de las empresas de servicios de telecomunicaciones, en el caso de las empresas de telecomunicaciones)

inputLas llamadas a funciones se utilizan directamente comota.supertrendLos parámetros de las funciones de indicadores se utilizan para calcular los indicadores de supertrend; entre ellos:

  • entrada ((5, factor)
  • input.int(Periodo de 10 años)

Por defecto, la función establece dos controles de parámetros en la interfaz de la política del lenguaje Pine:

img

Como se puede ver, el valor predeterminado en el control esinputFunción yinputLa función de serie (() aquí esinput.intLos dos primeros parámetros se explican en los capítulos anteriores. Con estas dos funciones podemos configurar en la interfaz estratégicata.supertrendLos parámetros de la función. La función del indicador de tendencia súper calcula un dato de precio.supertrendy datos de una dirección.directionY luego se usa.plotDiagrama de función, tenga en cuenta que cuando se dibuja el diagrama se dibuja en función de la dirección del indicador de supertrend, y se dibuja solo la dirección actual; cuandodirectionLa tendencia actual del mercado es al alza a las -1 horas, cuandodirectionLa tendencia actual es a la baja a la hora 1:00, así que podemos ver que el mercado está bajando.plotDecidir cuando dibujar una funcióndirectionEs mayor o menor que 0.

El siguiente:if ... else ifLa lógica es el juicio de la señal de transacción, cuando la expresióndirection < 0En tiempo real indica que el mercado está en la fase de subida, cuando los datos de precios en el indicador de supertrend están en la fase de subida.supertrendMás alto que el precio del indicador de supertrend en los dos primeros BAR (es decir,supertrend[2],还记得历史操作符引用某个变量历史数据吧Si hay una posición en ese momento, una llamada a la función inversa a la baja de una sola función se despejará primero la posición anterior y luego abrirá la posición según la dirección actual de la operación.supertrend > supertrend[2]Las condiciones no se han cumplido, por lo tanto, por ahora.strategy.position_size < 0El hecho de tener una posición de cabeza vacía también puede desencadenar el problema.strategy.close_all()La función se ejecuta, se realiza todo el equilibrio.

direction > 0Cuando se encuentra en la fase de tendencia a la baja, también es lo mismo, si hay varias tenencias, todas se estabilizan, entonces cumple con las condiciones.supertrend < supertrend[3]¿Por qué se ha configurado esto? ¿Por qué se ha configurado esto?[3]¿Qué pasa con la referencia a los datos de precios del indicador de súper tendencia en la tercera barra anterior? Puede que sea intencional para el estratega, después de todo, en algunos mercados, como el mercado de operaciones de contratos, el riesgo de hacer nada es ligeramente mayor que el riesgo de hacer más.

En cuanto ata.supertrendEl indicador, si algunos de sus compañeros están interesados, es cómo se determina si la tendencia actual es alcista o descendente.

En realidad, este indicador también se puede implementar en forma de funciones personalizadas en el lenguaje 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]

Esta función es una función de configuraciónta.supertrendEl algoritmo es el mismo y, por supuesto, los datos de los indicadores que se calculan son los mismos. De este algoritmo de funciones personalizadas podemos ver que el cálculo de los indicadores de supertrend que Pine tiene incorporados se usa para calcular el valor de las tendencias.hl2Las variables de configuración (el precio más alto, el precio más bajo sumado y dividido por 2, es decir, el promedio del precio más alto y el precio más bajo) se calculan según el parámetro trPeriod.

Actualizaciones basadas en expresiones tridimensionales en el códigolowerBandyupperBand

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

LowerBand: línea descendente, para determinar si la tendencia ascendente ha cambiado. UpperBand: línea descendente, para determinar si la tendencia descendente ha cambiado. LowerBand y upperBand están siempre siendo calculados, sólo que en esta función de configuración final se determina la dirección de la tendencia actual.

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

Aquí se determina si el valor de la súper tendencia en la última barra esprevUpperBandLa línea ascendente es la que indica la tendencia descendente.closeMás deupperBandEl precio se rompe, creyendo que en ese momento la tendencia cambia y se convierte en una tendencia al alza.directionLa variable de dirección se establece en -1 (trend ascendente); de lo contrario, se mantiene en 1 (trend descendente); por lo que se verá en la estrategia de supertrend.if direction < 0Cuando la señal se dispara, haz más.direction > 0Cuando se dispara la señal, las condiciones son inactivas.

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

Por último, los datos de precios y de dirección de los indicadores de súper tendencia específicos se devuelven según la dirección seleccionada.

Las estrategias de equilibrio dinámico

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

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

maxDiffValue = input(1000, "maxDiffValue")


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

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

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

img

img

Continuamos aprendiendo algunos ejemplos de diseño de estrategias en el lenguaje Pine, y esta vez vamos a ver una estrategia de equilibrio dinámico.BaseCurrency(variedad negociada) yQuoteCurrencyLa cantidad de (moneda de cuentas) siempre se trata de un equilibrio. El aumento del precio relativo de un activo, el aumento del valor de lo que se tiene en la cuenta, el aumento del valor de lo que se vende en la cuenta. Si el precio relativo de un activo disminuye, el valor de lo que se tiene en la cuenta disminuye, se compra el activo.

La desventaja de esta estrategia es que, como se puede ver en el gráfico de retrospectiva, la estrategia de flotación es más grande en la fase de la tendencia al alza (o a la baja) de los precios. Por lo tanto, esta estrategia es buena para la estrategia de contado, y su uso en futuros requiere controlar el riesgo.

En este caso, la estrategia de diseño de código es la siguiente:

Usamos un diseño simplificado para simular una estrategia en la que se usa un sistema de control de velocidad.balance(es decir, el número de activos de la moneda cotizada)stocks(es decir, el número de activos BaseCurrency) información de equilibrio. No vamos a leer el número de activos reales en la cuenta, sólo usamos la cantidad simulada para calcular la compra y venta adecuadas.maxDiffValueEste parámetro es el criterio de equilibrio.BaseCurrencyyQuoteCurrencyLa desviación excedemaxDiffValueEn el caso de los bancos, el precio de los activos es el mismo que el de los bancos, y el precio de los activos es el mismo que el de los bancos.

La activación de la señal de negociación estratégica debe tener sentido en la etapa BAR en tiempo real, por lo que las condiciones de negociación estratégica se establecen en el juicio sinot barstate.ishistoryLos precios de los productos de la industria se han incrementado en los últimos años.balanceEl valor es superiorstocksComprar cuando el valor es; vender al revés; actualizar después de ejecutar la declaración de transacción.balanceystocksEl resultado es que el número de personas que se encuentran en la misma situación de equilibrio es igual al número de personas que se encuentran en la misma situación.

La información de la estrategia de recuperación anterior contiene el precio de la variedad en la que la estrategia de recuperación comenzó, el precio es 1458, así que he configurado el parámetro a propósito.balancePara: 4374 ((1458*3), el parámetro de configuraciónstocksPor ejemplo: 3: mantener el activo en equilibrio al principio.

Las estrategias de supertrends con seguimiento de pérdidas y pérdidas

En las clases anteriores hemos aprendidostrategy.exitFunción de salida de posición, en la que no tenemos un ejemplo de la función de stop loss tracking. En el ejemplo de diseño de estrategias de esta sección, usamosstrategy.exitLa función de seguimiento de stop-loss para optimizar una estrategia de supertrend.

Primero vamos a ver.strategy.exitParámetros de parálisis de parálisis de parálisis de parálisis de parálisis de parálisis de parálisis de parálisis de parálisis de parálisis:

1、trail_priceParámetros: activar la ubicación del comportamiento lógico de la orden de liquidación de seguimiento de pérdidas y pérdidas (especificado en el precio)


Más.