O recurso está a ser carregado... Carregamento...

Inventor de Tutoriais de Introdução à Língua PINE

Autora:Inventor quantificado - sonho pequeno, Criado: 2022-05-30 16:23:43, Atualizado: 2022-09-28 17:10:21

Exemplos:

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: Expresso para julgamento, que retorna o valor de Boole. Observação: encolher. Só pode haver um ramo deelse no máximo. Todas as expressões de branches não são verdadeiras e não têm um ramo deelse e retornam na.

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

Uma vez que quando a linha K BAR é um quadrado, ou seja, quando close < open, a expressão após a sentença if é falsa, não se executa o bloco de código local de if. Neste caso também não há uma ramificaçãoelse, e a sentença if retorna na. x é atribuído como na.

A expressão switch

A expressão switch também é uma expressão de estrutura ramificada, usada para projetar diferentes caminhos de execução de acordo com certas condições.

A expressão 1, como a expressão switch e a expressão if, pode retornar valores. 2, ao contrário das expressões de switch em outras linguagens, quando executamos a estrutura do switch, apenas um bloco local de seu código é executado, então a declaração break é desnecessária (ou seja, não é necessário escrever palavras-chave como break). 3, cada ramo do switch pode escrever um bloco de código local, e a última linha do bloco de código local é o valor de retorno (pode ser um conjunto de valores); se nenhum bloco de código local que foi ramificado for executado, retorna na. 4, O comando expressivo na estrutura do switch pode ser usado para escrever uma string, uma variável, uma expressão ou uma chamada de função. O switch permite especificar um valor de retorno que é usado como o valor padrão quando nenhuma outra situação na estrutura é executada.

O switch é dividido em duas formas, e vamos ver um exemplo de cada uma delas para entender como é usado.

1, com uma expressãoswitchO que é o que você está fazendo?

// 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 aprendemos sobre funções de entrada, e aqui continuamos a aprender duas funções semelhantes às de entrada:input.stringinput.intFunção.input.stringO que é que é isso?input.intA função é usada para retornar valores inteiros.optionsO uso dos parâmetros.optionsOs parâmetros podem ser transmitidos para um conjunto de valores opcionais; por exemplo, no exemplooptions=["EMA", "SMA", "RMA", "WMA"]eoptions=[5, 10, 20](Nota: um é de tipo de strings e outro é de tipo de números) ; assim, os controles da interface da política não precisam ser inseridos em números específicos, mas se tornam uma caixa deslizante para selecionar as opções fornecidas no parâmetro de opções.

O valor da variável func é uma string, e func serve como uma expressão do switch (podendo ser uma variável, uma chamada de função, uma expressão) para determinar qual o ramo do switch executado. Se a variável func não pode corresponder com a expressão em qualquer dos ramos do switch (ou seja, é igual), o bloco de código do ramo por defeito é executado.runtime.error("error")A função faz com que a política pare de lançar anomalias.

Em nosso código de teste acima, após a última linha do bloco de código de ramificação padrão do switch runtime.error, não adicionamos código como [na, na] para retornar o valor compatível, o que é necessário para considerar o problema no trading view, se o tipo não for consistente. Mas no FMZ, esse código compatível pode ser ignorado, pois não há requisitos rigorosos 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)

Não há erros no FMZ, mas no trading view; porque o tipo de retorno do ramo if não é o mesmo.

2, sem expressão.switch

Vamos ver.switchA outra forma de usar o termo é escrever sem expressão.

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)

O exemplo do código de teste mostra que o switch irá corresponder a um bloco de código local verdadeiro em termos de execução de um ramo. Em geral, os termos de ramificação após a declaração do switch devem ser recíprocos. Ou seja, no exemplo, o up e o down não podem ser verdadeiros ao mesmo tempo. Como o switch só executa um bloco de código local de um ramo, é interessante colocar a seguinte frase no código:up = close > open // up = close < openEm vez do conteúdo nos comentários, reexamine os resultados observados. Descobrirá que o ramo do switch só executa o primeiro ramo. Além disso, é necessário tomar cuidado para não escrever chamadas de funções no ramo do switch, as funções não podem ser chamadas em cada BAR, o que pode causar alguns problemas de computação de dados.switchNo exemplo "Executar a ramificação é definido e não é alterado durante a execução da estratégia").

Estrutura circular

Palavras para

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

O uso da expressão for é muito simples, pois o ciclo for pode retornar um valor final (ou retornar vários valores, como [a, b, c]); como no pseudônimo acima, as variações atribuídas ao "valor de retorno" são colocadas em uma posição. A expressão for é seguida de uma variável "contado" para controlar o número de ciclos, referir outros valores, etc. A variável "contado" é atribuída como "contado inicial" antes do início do ciclo, e depois é passada de acordo com a configuração "crescente", e o ciclo pára quando o número de "contados" é maior que a "variável final".

For usado no ciclobreakPalavras-chave: Quando executadobreakDepois de uma frase, o ciclo pára. For usado no ciclocontinuePalavras-chave: Quando executadocontinueDepois de uma frase, o ciclo é ignorado.continueO código posterior, para executar diretamente o próximo ciclo. A expressão for retorna o valor retornado na última execução do ciclo. Se nenhum código for executado, retorna o valor em branco.

A seguir, mostramos um exemplo simples:

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... em sentenças

for ... inA frase tem duas formas, e o pseudônimo abaixo mostra isso.

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

A principal diferença entre as duas formas é o conteúdo que se segue após a palavra-chave for, uma é a utilização de uma variável como referência para um elemento de matriz. A outra é a utilização de uma estrutura que contém uma variável de índice, um elemento de matriz e um conjunto de variáveis.

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

Usamos o índice quando é necessário.for [i, ele] in testArrayA tradução é:

para aplicações circulares

Quando é possível realizar alguns cálculos de lógica de ciclo com funções embutidas fornecidas pela linguagem Pine, pode-se escrever diretamente com estruturas de ciclo ou pode-se processar com funções embutidas.

1 é a média calculada.

Quando se usa o design de estruturas 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)

No exemplo, o for é usado para a soma circular, e depois o valor médio é calculado.

Calcule a linha média diretamente usando a função embutida:

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

Utilize diretamente funções embutidasta.smaO cálculo do indicador da linha uniforme, obviamente, é mais simples para o cálculo da linha uniforme usando funções embutidas. No gráfico, o contraste pode ser visto como o resultado do cálculo é totalmente consistente.

2, soma

Ou use o exemplo acima para demonstrar isso.

Quando se usa o design de estruturas 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 os elementos da matriz e que podem ser tratados com o ciclo, também pode ser usado um função embutida.array.sumA partir daí, o mundo começou a mudar. Calcule a soma diretamente usando a função embutida:

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)

Os dados calculados podem ser vistos, usando gráficos de plot para mostrar a concordância completa no gráfico.

A função de usar um ciclo é baseada principalmente em três aplicações: 1, algumas operações para matrizes, cálculo. 2, rever a história, por exemplo, para descobrir quantos pontos altos do passado são maiores que os pontos altos do BAR atual. Como os pontos altos do BAR atual são conhecidos apenas no BAR em que o script está sendo executado, é necessário um ciclo para voltar a tempo e analisar o BAR passado. 3, quando a função embutida que usa a linguagem Pine não consegue completar o cálculo do passado BAR.

Sentença while

whileA instrução permite que o código da parte circular continue sendo executado até que a condição de julgamento na estrutura while seja falsa.

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

Outras regras do while são semelhantes às do loop for, onde a última linha do bloco local do loop é um valor de retorno, e pode retornar vários valores. Quando a condição do loop é executada em tempo real, o loop é interrompido quando a condição é falsa.

O que eu quero demonstrar é que, usando um exemplo de linha recta:

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)

Pode-se ver que o uso do ciclo de whil é muito simples, mas também é possível projetar algumas lógicas de computação que não podem ser substituídas por funções embutidas, como o cálculo de multiplicações:

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

Arquivos

A definição de arrays na linguagem Pine é semelhante à de outras linguagens de programação, onde o array de Pine é um conjunto de matrizes em uma dimensão. Geralmente, ele é usado para armazenar uma série de dados contínuos. Os matrizes em que os dados individuais são armazenados são chamados de elementos de arrays, e esses elementos podem ser de tipos como: inteiro, ponto flutuante, strings, valores de cor, valores de Boole.[]É preciso usar.array.get()earray.set()Função. A ordem de índices dos elementos no conjunto é 0 para o primeiro elemento e 1 para o próximo.

A partir de agora, o que é mais importante para nós é que os nossos clientes tenham acesso ao nosso site e que tenham acesso ao nosso site.

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

Declaração

Utilizaçãoarray<int> afloat[] bArquivos declarados ou apenas uma variável declarada podem ser atribuídos a arquivos, por exemplo:

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

Inicialização de variáveis para matrizesarray.newearray.from函数。Pine语言中还有很多和类型相关的与array.new类似的函数:array.new_int()array.new_bool()array.new_color()array.new_string()E assim por diante.

A palavra-chave var também pode funcionar com o modo de declaração da matriz, sendo que a matriz declarada com a palavra-chave var é initializada apenas no primeiro BAR.

var a = array.from(0)
b = array.from(0)

if bar_index == 1
    array.push(a, bar_index)
    array.push(b, bar_index)
else if bar_index == 2 
    array.push(a, bar_index)
    array.push(b, bar_index)
else if barstate.islast
    runtime.log("a:", a)
    runtime.log("b:", b)
    runtime.error("stop")

Pode-se ver que as mudanças do conjunto a são continuamente definidas e não reorganizadas. O conjunto b é inicial em cada BAR.barstate.islastA impressão em tempo real ainda tem apenas um elemento, o valor 0.

Leia e escreva elementos em uma matriz

Use array.get para obter elementos que especificam a posição do índice em uma matriz e use array.set para modificar elementos que especificam a posição do índice em uma matriz.

O primeiro parâmetro do array.get é o conjunto de matrizes a serem processadas e o segundo parâmetro é o índice designado. O primeiro parâmetro de array.set é o conjunto a ser processado, o segundo parâmetro é o índice especificado e o terceiro parâmetro é o elemento a ser escrito.

A partir de agora, a maioria dos usuários da rede social não pode usar o aplicativo.

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 exemplo inicializa a cor básica verde, declara e inicializa uma matriz para guardar a cor e, em seguida, atribui uma transparência diferente ao valor da cor (usando a função color.new); calcula a classificação da cor calculado pela distância máxima do valor high no ciclo de 100 visualizações do BAR atual; a distância máxima do high no ciclo de 100 visualizações mais recentes é a distância mais próxima, a classificação mais alta e a correspondente classificação da cor mais profunda (a transparência mais baixa); muitas estratégias semelhantes são usadas dessa maneira para indicar o nível do preço no ciclo de visualizações atual N;

Atravesse os elementos da matriz

Como percorrer um conjunto, podemos fazer isso usando as instruções for/for in/while que aprendemos 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")

Os resultados são os mesmos em todas as três maneiras.

Arrays podem ser declarados no âmbito global do script ou no âmbito local da função ou do ramo if

Referências históricas

Para o uso de elementos em matrizes, a seguinte maneira é equivalente, como podemos ver no exemplo a seguir, desenhando dois conjuntos de linhas no gráfico, com dois números de linhas em cada grupo e dois números de linhas em cada grupo que são exatamente iguais.

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)

Adicionar e remover funções de operação

1, função relacionada com a operação de adição do conjunto de matrizes:

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

2, funções relacionadas com a operação de exclusão da matriz:

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

Usamos o exemplo a seguir para testar a função de adição, remoção e operação dessas matrizes.

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

Aplicações de adição e remoção: Arrays as queues

Usando matrizes, e algumas funções de adição e remoção de matrizes, podemos construir estruturas de dados de "colunas". As colunas podem ser usadas para calcular a média móvel do preço do tick, e alguns colegas podem perguntar: por que construir estruturas de colunas?

A coleta é uma estrutura frequentemente usada no campo da programação, caracterizada por:

Os elementos que entram na fila primeiro, saem da fila primeiro.

Isso garante que os dados que existem na fila são atualizados e que o comprimento da fila não é infinitamente inflado (o código infinitamente inflado só pode ser escrito ao meio-dia, pois o que está acontecendo é que o que está acontecendo é que o que está acontecendo é que o que está acontecendo está acontecendo).

No exemplo a seguir, usamos uma estrutura de fila para registrar o preço de cada tick, calcular o preço médio móvel no nível do tick e compará-lo com o nível da linha K observado em 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")

Observe que quando declaramos a matriz, nós especificamos o modo de declaração usando a palavra-chavevaripO valor de cada variação de preço é registrado em uma matriz.

Computação aritmética comum, funções operacionais

Calcule funções relacionadas:

array.avg()O valor médio de todos os elementos da matriz.array.min()O menor elemento de um conjunto de matrizes.array.max()O maior elemento do conjunto de matrizes.array.stdev()A diferença padrão de todos os elementos da matriz é a diferença padrão de todos os elementos.array.sum()A soma de todos os elementos da matriz.

Funções relacionadas com a operação:array.concat()Combine ou ligue dois arquivos.array.copy()Replicação de matrizes.array.joinConecte todos os elementos da matriz em uma única string.array.sort()A ordem é ascendente ou descendente.array.reverse()Artigos de inversão.array.slice()A partir daí, a matriz é cortada.array.includes()Afinal, o que é que você está a fazer?array.indexof()Retorna o índice em que o valor do parâmetro foi transmitido pela primeira vez. Se não for encontrado, retorna -1.array.lastindexof()Encontre o valor que apareceu pela última vez.

Exemplos de testes de funções relacionadas com o 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 são as funções de cálculo de arquivos mais comuns.

Exemplos de funções 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")

Funções

Funções personalizadas

A linguagem Pine pode projetar funções personalizadas, e em geral, as funções personalizadas da linguagem Pine têm as seguintes regras:

1, todas as funções são definidas no âmbito global do script. Não é possível declarar uma função em outra função. 2, não permite que funções chamem a si mesmas em seu próprio código. 3, em princípio, todas as linguagens PINE têm funções gráficas embutidasbarcolor()、 fill()、 hline()、plot()、 plotbar()、 plotcandle()) não pode ser chamado dentro de funções personalizadas. 4, a função pode ser escrita em uma única linha, ou em várias linhas. O valor de retorno da última frase é o valor de retorno da função atual, que pode retornar a forma de um conjunto de elementos.

Em tutoriais anteriores, também usamos funções personalizadas várias vezes, como projetar funções personalizadas em uma única linha:

barIsUp() => close > open

A função retorna se o BAR atual é o raio solar.

A função é projetada para ser uma função personalizada de várias linhas:

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)

A função que nós mesmos realizamos com funções personalizadas é uma função calculada pela linha média de uma SMA.

Além disso, podemos retornar exemplos de funções personalizadas com duas variáveis:

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)

Uma função pode calcular uma linha rápida, uma linha lenta, dois indicadores de EMA equiláteros.

Funções embutidas

A função embutida pode ser facilmenteFMZ PINE Script documentaçãoA partir daí, o blogueiro começou a escrever.

Classificação de funções embutidas na linguagem Pine:

Função de processamento de stringsstr.A série. 2, função de processamento de valor de corcolor.A série. 3, função de entrada de parâmetrosinput.A série. 4, função de cálculo de indicadoresta.A série. 5, função gráficaplot.A série. Função de processamento de matrizes 6.array.A série. 7 Funções relacionadas com transaçõesstrategy.A série. Funções relacionadas com o cálculo matemáticomath.A série. 9, Outras funções ((Tempo de processamento, funções de gráficos de séries não-plotadas,request.Funções de série, funções de processamento de tipo, etc.) ⇒

Funções de transação

strategy.Funções de série são funções que usamos com frequência em nossas estratégias de design e que são intimamente relacionadas com a execução de transações quando as estratégias são executadas especificamente.


1、strategy.entry

strategy.entryA função é uma função sub-função que é mais importante quando escrevemos a política, que é mais importante em alguns parâmetros:id, direction, qty, whenE assim por diante.

Parâmetros:

  • id: pode ser entendido como um nome para uma posição de negociação usado como referência. Pode ser usado como o id de revogação, alteração de ordem, liquidação.
  • direction: se a direção do pedido for fazer mais (= comprar) o parâmetro é transmitidostrategy.longEsta variável é transmitida se você quiser fazer um espaço (venda).strategy.shortEsta variável.
  • qty: especifique o volume a ser encomendado, se não passar este parâmetro é usado o volume de encomenda padrão.
  • when: condição de execução, pode ser especificado para controlar se a operação sub-ordenada atual é ou não desencadeada.
  • limitO preço é o seguinte: indique o preço limite do pedido.
  • stopO preço do produto é o mesmo que o preço do produto.

strategy.entryDetalhes específicos de execução da funçãostrategyO controle de configuração de parâmetros quando a função é chamada também pode ser feito através de"Parâmetros do modelo da biblioteca de transações da linguagem Pine"Configuração de controles, Parâmetros de configuração de parâmetros do painel de transações da biblioteca de linguagem Pine.

Aqui estão os pontos-chave.strategyA funçãopyramidingdefault_qty_valueParâmetros. Utilize o seguinte código para testar:

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

Início do código/*backtest ... */A parte do pacote é configurada para o retest, para registrar informações como o tempo de configuração do retest no momento, para facilitar o depurador, e não código de estratégia.

O código é:strategy(title = "open long example", pyramiding = 3, default_qty_value=0.1, overlay=true)Quando nós especificamospyramidingQuando o parâmetro é 3, nós estamos configurados para negociar no máximo três vezes na mesma direção. Portanto, quatro vezes no exemplo.strategy.entryUma das operações abaixo não foi executada.default_qty_valueO parâmetro é 0.1, então o ID é um "long 1" desta vez.strategy.entryO volume de menus para a operação de subordem é definido por default como 0.1.strategy.entryA função é chamada como a função que nós indicamos.directionTodos sãostrategy.longA partir de agora, a maioria dos testes de retestamento será pago.

Atenção no código.strategy.entry("long3", ...A operação abaixo foi chamada duas vezes, para o mesmo ID: long3.strategy.entryO pedido não foi cumprido, segunda chamadastrategy.entryA função é para alterar o ID da ordem (os dados exibidos no retest também mostram que o volume da ordem foi alterado para 0.3). Outra situação, por exemplo, se a primeira ordem for feita com o ID de 3 toneladas, continue usando o ID de 3 toneladas.strategy.entryQuando a função encomenda, todas as posições serão acumuladas no ID-long3.


2、strategy.close

strategy.closeA função é usada para especificar o ID do equilíbrio do posicionamento de entrada. Os principais parâmetros são:idwhenqtyqty_percent

Parâmetros:

  • idO ID de entrada que é necessário é o que nós usamos.strategy.entryO ID indicado quando a função de ingressos é aberta.
  • whenA partir de agora, o governo vai continuar a fazer isso.
  • qtyO número de transações.
  • qty_percentPorcentagem de equilíbrio.

Para se familiarizar com os detalhes de uso desta função, veja um exemplo: No 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

A estratégia de teste mostra que é possível iniciar três entradas consecutivas com ID de entrada de 1long e usar o ID de entrada de 1long.strategy.closeDiferentes resultados são obtidos quando os diferentes parâmetros da função são definidos em equilíbrio.strategy.closeA função não tem parâmetros para especificar o preço do pedido de liquidação, e é usada principalmente para liquidar imediatamente o preço atual do mercado.


3、strategy.close_all

strategy.close_allA função é usada para estabilizar todas as posições atuais, uma vez que o script de posicionamento da linguagem Pine só pode ser executado em uma direção, ou seja, se houver um sinal de ação oposto ao da posição atual, estabilizará a posição atual e abrirá a posição de acordo com o sinal.strategy.close_allA posição do banco em relação à direção em que está posicionado será eliminada quando for chamada.strategy.close_allOs principais parâmetros da função são:when

Parâmetros:

  • whenA partir de agora, o governo vai continuar a fazer isso.

A partir de agora, o que é mais importante para nós é que os nossos filhos sejam educados.

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

Quando o código de teste começa, a quantidade de armazenamento é 0 (ou seja,strategy.position_size==0Para ser verdadeiro), então executar o ID como um longínquo só quando estiver de acordo com a condição do parâmetro when.strategy.entryFunção de entrada.strategy.position_sizeA função de entrada do ID para o "short" pode ser executada apenas quando o valor é maior que 0, e, como o posicionamento é atualmente de várias cabeças, o sinal de reverso de vazio que aparece neste momento causa o vazio de várias cabeças. Em seguida, escrevemos na condição if quandostrategy.position_size < 0Quando a posição está em vazio, a posição em vazio é igual a toda a posição na direção em que a posição está em vazio.enableStop := trueNão é fácil de ver o log.

O que você pode verstrategy.close_allA função não tem parâmetros para especificar o preço do pedido de liquidação, e é usada principalmente para liquidar imediatamente o preço atual do mercado.


4、strategy.exit

strategy.exitA função é usada para operações de liquidação de posições de entrada, diferente da funçãostrategy.closeestrategy.close_allA função é o equilíbrio imediato no preço atual do mercado.strategy.exitA função planeja o equilíbrio de acordo com a configuração dos parâmetros.

Parâmetros:

  • id: ID de ordem para a lista de condições de liquidação atual.
  • from_entry: Usado para especificar o ID de entrada para a operação de liquidação.
  • qtyO número de transações.
  • qty_percentPercentagem de equilíbrio, faixa: 0 ~ 100.
  • profitO objetivo do lucro, expresso em pontos.
  • lossO objetivo é parar de perder, em pontos.
  • limitO objetivo do lucro é o preço.
  • stopO objetivo é parar com o preco.
  • whenA partir de agora, o governo vai continuar a fazer isso.

Use uma estratégia de teste para entender o uso de cada parâmetro.

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

Usando o teste de retrospecção do modelo de preços em tempo real, esta estratégia de teste começa com a execução de três operações de entrada.strategy.entryFunção), o "long1" é definido de propósito.limitParâmetro, preço de um pedido pendente é 1 para que ele não possa ser transacionado; e então testar a condição de saída funçãostrategy.exitO que é mais importante, é que o sistema de negociação é muito simples. O sistema de negociação é muito simples. O sistema de negociação é muito simples.strategy.exitA função também possui parâmetros de rastreamento de stop loss mais complexos:trail_pricetrail_pointstrail_offsetTambém é possível testar a aprendizagem do uso neste exemplo.


5、strategy.cancel

strategy.cancelFunções usadas para cancelar / desativar todos os comandos de prelocação. Estas funçõesstrategy.order, strategy.entry , strategy.exitPode ser gerado um ID de entrada.idwhen

Parâmetros:

  • idO ID de entrada a ser cancelado.
  • whenA partir de agora, o governo vai continuar a fazer isso.

Esta função é bem compreendida, pois é usada para cancelar ordens de entrada sem transação.

/*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_allFunções estrategy.cancelFunções semelhantes: ≪ cancelar / desativar todos os comandos pré-enganados≫ pode ser especificadowhenParâmetros.

Parâmetros:

  • whenA partir de agora, o governo vai continuar a fazer isso.
/*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.orderFunções, configuração de parâmetros, etc.strategy.entryA diferença é:strategy.orderA função não éstrategyFunçõespyramidingA configuração dos parâmetros é influenciada, sem restrições de número de vezes.

Parâmetros:

  • id: pode ser entendido como um nome para uma posição de negociação usado como referência. Pode ser usado como o id de revogação, alteração de ordem, liquidação.
  • direction: se a direção do pedido for fazer mais (= comprar) o parâmetro é transmitidostrategy.longEsta variável é transmitida se você quiser fazer um espaço (venda).strategy.shortEsta variável.
  • qty: especifique o volume a ser encomendado, se não passar este parâmetro é usado o volume de encomenda padrão.
  • when: condição de execução, pode ser especificado para controlar se a operação sub-ordenada atual é ou não desencadeada.
  • limitO preço é o seguinte: indique o preço limite do pedido.
  • stopO preço do produto é o mesmo que o preço do produto.

Nós usamosstrategy.orderNão há restrições para essa característica, combinandostrategy.exitFunção de saída condicional ─ construir um script semelhante a uma transação de rede ─ exemplo muito simples, apenas para aprendizado:

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

Padrões estratégicos

Os exemplos de estratégias neste tutorial são usados apenas para instruir estratégias e ideias de design de estratégias de orientação, e não fazem qualquer tipo de orientação ou sugestão de negociação.

Estratégias de indicadores de super-tendência

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

É muito simples escrever estratégias de tendência usando o linguagem Pine, aqui nós criamos uma estratégia simples de rastreamento de tendências com um indicador de tendência super. Vamos analisar o código fonte da estratégia juntos.

Primeiro, o código estratégico é usado.strategyA função faz algumas configurações simples:strategy("supertrend", overlay=true), basta configurar um título de estratégia para a barra de supertrend.overlayO parâmetro étrueQuando desenhamos uma estratégia Pine ou aprendemos um script de estratégia Pine, o primeiro que devemos ver é o design dos parâmetros da interface da estratégia.inputFunções

[supertendência, direção] = ta.supertendência ((input ((5, factor),input.int(10, atrPeriodo))

inputAs chamadas de funções são usadas diretamente parata.supertrendOs parâmetros da função de indicador são usados para calcular os indicadores de supertrend.

  • input ((5, factor)
  • input.int(10, atrPeriodo)

Por padrão, a função define dois controles de parâmetros na interface de políticas da linguagem Pine, como se veja:

img

Como você pode ver, o padrão do controle é:inputFunções einputA função de série (( aqui éinput.intO primeiro parâmetro de () também foi explicado nos capítulos anteriores. Com essas duas funções, podemos definir a interface da estratégiata.supertrendO parâmetro da função. A função do indicador de supertrend calcula um dado de preço.supertrende dados de uma direção.directionE depois usá-lo.plotDiagrama de função, note que, quando o gráfico é desenhado, o gráfico é desenhado de acordo com a direção do indicador de supertendência, e apenas desenha a direção atual; quandodirectionA tendência do mercado atual é para cima, quandodirectionA tendência atual do mercado é para baixo, por isso podemos ver que a tendência atual é para baixo, por isso podemos ver que a tendência atual é para baixo.plotQuando você desenha um gráfico de funçõesdirectionÉ maior ou menor que 0.

A seguir:if ... else ifA lógica é o julgamento do sinal de transação, quando a expressãodirection < 0O indicador de tempo real indica que o mercado está no estágio de alta, quando os dados de preços no indicador de super-tendência mostram que o mercado está em um estágio de alta.supertrendO preço do indicador de super-tendência acima dos dois primeiros BARs (ou seja,supertrend[2],还记得历史操作符引用某个变量历史数据吧Se houver uma posição atual, uma chamada de função única inversa para baixo irá estabilizar a posição anterior e abrir a posição de acordo com a direção atual da negociação.supertrend > supertrend[2]A situação não é boa.strategy.position_size < 0A posição de cabeça vazia também pode ser desencadeada.strategy.close_all()A função é executada, com todas as posições paradas.

direction > 0O mesmo acontece quando estamos em uma fase de tendência descendente, se houver várias posições e todas elas estiverem paradas, então a condição é cumprida.supertrend < supertrend[3]Por que é que aqui é definido como[3]A referência aos dados de preços do indicador de super-trend no primeiro terceiro BAR? Pode ser intencional, pois em alguns mercados, como o mercado de negociação de contratos, o risco de fazer pouco é um pouco maior do que o risco de fazer mais.

Parata.supertrendO indicador, se alguns dos seus colegas estão interessados em saber como ele determina se a atual tendência é para cima ou para baixo?

O indicador também pode ser implementado em funções personalizadas da linguagem 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 função é a função padrão e a função embutida.ta.supertrendO algoritmo é o mesmo e, claro, os dados de indicadores são os mesmos. A partir deste algoritmo de funções personalizadas, podemos ver que o cálculo do indicador de supertrend embutido do Pine é usado para calcular a taxa de crescimento do mercado.hl2A variável interna ((máximo preço, mínimo preço somado e dividido por 2, ou seja, a média do preço mais alto e menor preço) e calcula o indicador de ATR para determinado ciclo (amplitude de onda) com base no parâmetro trPeriod. Em seguida, use o hl2 e o ATR para construir o trajeto.

Atualização com base na expressão triangular no códigolowerBandeupperBand

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

LowerBand: linha de tração inferior, usada para determinar se a tendência ascendente está mudando. UpperBand: linha de tração superior, usada para determinar se a tendência descendente está mudando.

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

Aqui, se o valor do preço do supertrend no último BAR for igual aprevUpperBandA tendência atual é para baixo, ou seja, para cima.closeMais deupperBandO preço quebrou, pensando que havia uma mudança de tendência e se transformou em uma tendência ascendente.directionA variável de direção é definida como -1 (tendência ascendente); caso contrário, permanece definida como 1 (tendência descendente).if direction < 0A partir daí, a empresa começou a produzir o produto.direction > 0A partir de agora, o sistema de transmissão de dados será aberto.

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

Por fim, os dados de preços e direção dos indicadores de supertendência específicos são devolvidos, dependendo da direção escolhida.

Estratégias de equilíbrio 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 a aprender alguns exemplos de design de estratégias da linguagem Pine, e desta vez vamos ver uma estratégia de equilíbrio dinâmico.BaseCurrency(variedades negociadas) eQuoteCurrencyA quantidade de (moeda) de contabilidade é sempre tratada como um equilíbrio. O preço relativo de um ativo aumenta e o valor do ativo na conta aumenta para vender o ativo. Se o preço relativo de um ativo diminui e o valor da conta diminui, o ativo é comprado. Esta é a chamada estratégia de equilíbrio dinâmico.

A desvantagem é que, como mostra o gráfico de retrospectiva da estratégia, a estratégia de flutuação é mais pesada no momento em que o preço está em alta (ou baixa).

A partir daí, o Google lançou um novo projeto de código para o Google Maps.

Nós usamos um design simplificado para simular uma estratégia que é muito simples.balance(ou seja, o número de ativos da moeda) estocksA informação de balanço. Nós não vamos ler o número de ativos reais na conta, nós apenas usamos o valor simulado para calcular a compra e venda apropriadas.maxDiffValueEste parâmetro é o critério de julgamento para o equilíbrio.BaseCurrencyeQuoteCurrencyA desviação excedemaxDiffValueA partir daí, o país começou a vender ativos mais caros e comprar ativos mais baratos para equilibrar os ativos.

Os sinais de negociação estratégica devem ser desencadeados apenas na fase BAR em tempo real, então as condições de negociação estratégica são definidas no julgamento senot barstate.ishistoryOs preços são muito baixos e os preços são muito baixos.balanceO valor é superiorstocksComprar no momento do valor; vender ao invés disso; atualizar após a execução da declaração de transaçãobalanceestocksA diferença é que, se você tiver uma variável, então espere até que o próximo equilíbrio seja desencadeado.

A mensagem de retorno da estratégia acima contém o preço da variedade para o início da retorno da estratégia, que é 1458, então eu definiu o parâmetro de forma intencional.balanceParâmetros definidos para: 4374 ((1458*3)stocksPara: 3. Deixar os ativos em equilíbrio no início.

Uma estratégia de super-tendências com rastreamento de stop-loss e stop-loss

E, em outras lições, aprendemos:strategy.exitA função de saída de posição, onde a função de stop loss stop stop stop não é explicada por exemplo.strategy.exitA função de rastreamento stop-loss stop-gap funciona para otimizar uma estratégia de supertrend.

Primeiro, vamos ver.strategy.exitParâmetros de paragem de paragem de paragem de paragem de paragem de paragem de paragem de paragem da função:

1、trail_priceParâmetros: acionar a colocação de rastrear o comportamento lógico da ordem de equilíbrio de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros de parâmetros


Mais.