Tutorial de introdução à linguagem PINE quantitativa do Inventor

Criado em: 2022-05-30 16:23:43, atualizado em: 2022-09-28 17:10:21
comments   0
hits   8860

[TOC]

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Acompanhado de um vídeo tutorial: É muito difícil entrar em um negócio quantificado?

A plataforma de negociação quantitativa do inventor suporta a estratégia de programação da linguagem Pine, suporta a retrospectiva, a estratégia de linguagem Pine em tempo real e é compatível com versões mais baixas da linguagem Pine.Praça da EstratégiaO blog é uma coleção de várias estratégias e scripts de Pine.

O FMZ não apenas suporta a linguagem Pine, mas também suporta o poderoso recurso de gráficos da linguagem Pine. Os recursos da plataforma FMZ, as ferramentas práticas e eficientes e fáceis de gerenciar, também aumentam a praticidade da estratégia e do script do Pine. O FMZ é baseado na compatibilidade com a linguagem Pine, e também faz um certo grau de extensão, otimização e corte na linguagem Pine.

A seguir, um breve resumo de algumas das diferenças mais evidentes:

  • 1 Política Pine no FMZ, versão identificada no início do código//@versionE o código começastrategyindicatorA frase não é obrigatória e o FMZ não o suporta por enquantoimportImportaçãolibraryfunção.

O blogueiro também escreveu sobre a estratégia do Facebook:

  //@version=5
  indicator("My Script", overlay = true)
  src = close
  a = ta.sma(src, 5)
  b = ta.sma(src, 50)
  c = ta.cross(a, b)
  plot(a, color = color.blue)
  plot(b, color = color.black)
  plotshape(c, color = color.red)

Ou então:

  //@version=5
  strategy("My Strategy", overlay=true)

  longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
  if (longCondition)
      strategy.entry("My Long Entry Id", strategy.long)

  shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
  if (shortCondition)
      strategy.entry("My Short Entry Id", strategy.short)

Em FMZ, pode ser simplificado como:

  src = close
  a = ta.sma(src, 5)
  b = ta.sma(src, 50)
  c = ta.cross(a, b)
  plot(a, color = color.blue, overlay=true)
  plot(b, color = color.black, overlay=true)
  plotshape(c, color = color.red, overlay=true)

Ou:

  longCondition = ta.crossover(ta.sma(close, 14), ta.sma(close, 28))
  if (longCondition)
      strategy.entry("My Long Entry Id", strategy.long)

  shortCondition = ta.crossunder(ta.sma(close, 14), ta.sma(close, 28))
  if (shortCondition)
      strategy.entry("My Short Entry Id", strategy.short)
  • Algumas configurações relacionadas a transações são definidas pelo parâmetro “Pine language transaction class library” na interface de estratégia do FMZ.

    • Modelos de preços de fechamento e modelos de preços em tempo real Na visão de trading, podemos passar porstrategyFunção decalc_on_every_tickParâmetros para definir o script de estratégia para executar a lógica da estratégia em tempo real a cada mudança de preçocalc_on_every_tickOs parâmetros devem ser definidos comotruePor padrãocalc_on_every_tickO parâmetro éfalseA lógica da estratégia só é executada quando a linha K BAR atual da estratégia está completa. No FMZ, é configurado através dos parâmetros do modelo “Pine Language Transaction Classroom”.

    Tutorial de introdução à linguagem PINE quantitativa do Inventor

    • Precisa-se de um controle de precisão numérica na FMZ, como o preço e a quantidade de encomendas no momento da execução da estratégia Na visão de negociação, como só é possível fazer testes em simulação, não há problemas de precisão de encomendas em tempo real. Na FMZ, é possível executar a estratégia Pine em tempo real. Então, a estratégia precisa ser flexível para especificar a precisão do preço da variedade de negociação e a precisão da quantidade de encomendas. Essas configurações de precisão controlam o número pequeno de dados relevantes, evitando que os dados não atendam aos requisitos de notificação da bolsa e, portanto, não possam ser encomendados.

    • Código de contrato a prazo O tipo de transação no FMZ, se for um contrato, tem duas propriedades: “contract pair” e “contract code”. Além da necessidade de definir um par de transação explicitamente no disco e na retrospectiva, também é necessário definir um código de contrato específico no parâmetro “variety code” do modelo “Pine language trading library”. Por exemplo, o contrato de permanência é preenchidoswap, Código de contrato para ver se a troca de operação específica tem esse contrato. Por exemplo, todos os contratos trimestrais de algumas transações podem ser preenchidos aquiquarterEstes códigos de contratos coincidem com os códigos de contratos futuros definidos na documentação da API de linguagem Javascript/python/c++ da FMZ.

Outras configurações, como a quantidade mínima, a quantidade padrão, etc., podem ser encontradas na documentação do idioma Pine sobre“Pine Language Exchange” (em inglês)Introdução aos parâmetros.

  • 3、runtime.debugruntime.logruntime.errorFunção de extensão FMZ, usada para a delimitação .

Três funções foram adicionadas à plataforma FMZ para a delimitação.

  • runtime.debug: Esta função não é geralmente usada para imprimir informações de variáveis no console.

  • runtime.logOutput content in the log. Funções específicas da linguagem FMZ PINE.

    runtime.log(1, 2, 3, close, high, ...),可以传多个参数。
    
  • runtime.error: quando chamado, pode causar erros de execução e trazer uma mensagem de erro especificada no parâmetro de mensagem.

    runtime.error(message)
    
  • 4 - Expansão em parte da função gráficaoverlayparâmetro

Função de desenho em linguagem Pine no FMZplotplotshapeplotcharAumentou.overlaySuporte de parâmetros, permitindo especificar imagens no mapa principal ou no mapa secundário.overlayconfigurartrueDesenho no mapa principal, configurado parafalseDesenhar em subdivisões. Permite que a estratégia Pine em FMZ seja executada ao mesmo tempo que o mapa principal e o subdivisão.

  • 5、syminfo.mintickValor de variável embutida

syminfo.mintickA variável embutida é definida como o valor de medida mínimo da variedade atual.Oferta Firme/Testes retrospectivosO valor pode ser controlado pela precisão de precificação monetária, um parâmetro do modelo na interface “Pine Language Transaction Classroom”. A definição de precisão monetária 2 significa que o preço é exato para o segundo lugar de um número menor quando o preço é negociado, com uma mínima variação de 0,01syminfo.mintickO valor de um valor de 0,01 é 0.01 .

  • 6o Os preços médios do FMZ PINE Script incluem taxas

Por exemplo: o preço de encomenda é de 8000, a direção de venda, a quantidade é de 1 mão, o preço médio após a transação não é de 8000, é inferior a 8000, o custo inclui a taxa de processamento.

Fundamentos da linguagem Pine

Quando começamos a aprender o básico da linguagem Pine, talvez não estejamos familiarizados com as instruções e a gramática do código de alguns exemplos. Não importa se não entendemos ou não, podemos primeiro familiarizar-nos com os conceitos, entender o objetivo do teste, ou consultar a documentação da linguagem Pine da FMZ para ver as instruções.

Execução do modelo

Quando se inicia a aprendizagem da linguagem Pine, é muito necessário entender os conceitos relacionados, como o processo de execução de scripts da linguagem Pine. A estratégia da linguagem Pine é baseada em gráficos e pode ser entendida como uma série de cálculos e operações, executadas na tabela em ordem cronológica, a partir dos primeiros dados já carregados.bar_indexReferência ao valor de índice da linha K Bar atual na execução do script Pine.

plot(bar_index, "bar_index")

Tutorial de introdução à linguagem PINE quantitativa do Inventor

plotA função é uma das funções que mais usaremos no futuro. É muito simples de usar, é apenas desenhar uma linha no gráfico com base nos parâmetros de entrada, e os dados são:bar_indexA linha é denominadabar_index。 A linha chamada bar_index na primeira barra tem um valor de 0 e aumenta 1 。 à medida que a barra aumenta para a direita.

Dependendo da configuração da estratégia, o modelo de execução da estratégia é diferente.收盘价模型e实时价模型◦ O conceito de modelo de preço de fechamento, modelo de preço em tempo real, já foi apresentado anteriormente.

  • Modelo de preço de fechamento

Quando o código de estratégia é executado, o ciclo do atual Bar de linha K é executado completamente. Quando o K é fechado, o ciclo de linha K está terminado.

  • Modelo de preço em tempo real

Quando o código da estratégia é executado, a barra de linha K atual, seja ela fechada ou não, executa a lógica da estratégia de pin em cada mudança de movimento, e o sinal de transação acionado é executado imediatamente.

Quando a estratégia da linguagem Pine é executada de esquerda para direita no gráfico, a linha K do gráfico é dividida em历史Bare实时Bar- Não.

  • História Bar

Quando a estratégia é configurada como um “modelo de preço real” e começa a ser executada, todas as barras K do gráfico, exceto a barra K na parte direita, são历史BarA lógica da estratégia em cada raiz历史BarExecutar apenas uma vez. Quando a estratégia é definida como um “modelo de preço de fechamento” e começa a ser executada, todas as barras do gráfico são历史BarA lógica da estratégia em cada raiz历史BarExecutar apenas uma vez.

Baseado no cálculo da barra de histórico: O código da estratégia é executado uma vez no estado de fechamento da barra de histórico, e o código da estratégia continua a ser executado na próxima barra de histórico até que todas as barras de histórico sejam executadas uma vez.

  • Bar em tempo real

Quando a estratégia é executada na última linha K Bar à direita, a barra é a barra do tempo real. Quando a barra do tempo real é fechada, a barra torna-se uma barra do tempo real passada (transformando-se em uma barra do tempo histórico). A direita do gráfico gera uma nova barra do tempo real.

Quando a estratégia é configurada como um “modelo de preço em tempo real” e começa a ser executada, uma lógica de estratégia é executada em cada mudança de comportamento na barra em tempo real. Quando a estratégia é definida como “modelo de preço de fechamento” e começa a ser executada, o gráfico não exibe a barra real.

Baseado em cálculos em tempo real do Bar: Se a estratégia for configurada como um gráfico de “modelo de preço de fechamento” e não for exibida a barra em tempo real, o código da estratégia será executado apenas uma vez no fechamento da barra atual. Se a estratégia é definida como “modelo de preço de parada real”, o cálculo na barra de tempo real e o histórico na barra de tempo real são completamente diferentes. Cada mudança de comportamento na barra de tempo real é executada por um código de estratégia.highlowcloseNo Bar histórico é certo, no Bar em tempo real, esses valores podem mudar a cada vez que a situação muda. Portanto, os indicadores e outros dados calculados com base nesses valores também podem mudar em tempo real.closeO preço é sempre o mais atualizado e o preço é sempre o mais baixo.highelowSempre representa o máximo máximo e o mínimo mínimo atingidos desde o início da barra atual. Estas variáveis embutidas representam o valor final da última atualização da barra.

Mecanismos de reversão da execução da estratégia no Bar em tempo real (modelo de preço em tempo real): Quando executado em Bar em tempo real, cada nova geração da estratégia executa uma variável redefinida pelo usuário anterior, chamada de reversão. Para entender o mecanismo de reversão com um exemplo, vamos testar o código.

Perceber:

  /*backtest 
  ...
  ..
  .
  */

O pacote contém informações de configuração de retrospectiva armazenadas em código na plataforma FMZ.

  /*backtest
  start: 2022-06-03 09:00:00
  end: 2022-06-08 15:00:00
  period: 1m
  basePeriod: 1m
  exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
  */

  var n = 0
  if not barstate.ishistory
      runtime.log("n + 1之前, n:", n, " 当前bar_index:", bar_index)
      n := n + 1
      runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index)

  plot(n, title="n")

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Nós só examinamos cenas executadas em tempo real no Bar, então usamosnot barstate.ishistoryA restrição de expressão é somente aplicada à variável n em tempo real no Bar e é usada antes e depois de executar a operação de agregaçãoruntime.logA função de saída de informações no log da estratégia. A partir do uso da função de gráficoplotA curva n desenhada pode ser vista como sempre 0 quando a estratégia está na barra de histórico. A operação n + 1 é acionada quando executada na barra de tempo real, e a operação n + 1 é executada em cada rodada de execução da estratégia na barra de tempo real. Pode ser observado a partir da informação do log que a cada rodada de execução do código da estratégia n é reinstalado como o valor que a estratégia de execução da barra de tempo real anterior finalmente enviou.

Para resumir: 1 Quando a estratégia começa a ser executada na barra de tempo real, um código de estratégia é executado para cada atualização de situação. 2. Quando executado na barra de tempo real, a variável é revertida antes de cada código de política executado. 3 Quando executado na barra de tempo real, a variável é submetida uma vez na atualização do fechamento.

Uma vez que os dados são rebocados, as operações de desenho, como as curvas no gráfico, também podem causar um redesenho, por exemplo, se modificarmos o código de teste que acabamos de fazer, o teste em disco rígido:

  var n = 0
  if not barstate.ishistory
      runtime.log("n + 1之前, n:", n, " 当前bar_index:", bar_index)
      n := open > close ? n + 1 : n
      runtime.log("n + 1之后, n:", n, " 当前bar_index:", bar_index)

  plot(n, title="n")

Imagem do momento A Tutorial de introdução à linguagem PINE quantitativa do Inventor

Imagem do momento B Tutorial de introdução à linguagem PINE quantitativa do Inventor

A única coisa que mudamos foi a seguinte frase:n := open > close ? n + 1 : n, o Bar real atual é negativo ((ou seja, o preço de abertura é superior ao preço de fechamento) só quando a n acumula 1 ≠. Pode ser visto no primeiro gráfico ((momento A) porque o preço de abertura era superior ao preço de fechamento ((o sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de um sinal de

  • Contexto das variáveis na função

A seguir, vamos examinar as variáveis das funções da linguagem Pine. De acordo com a descrição de alguns dos tutoriais do Pine, as variáveis da função diferem das variáveis fora da função da seguinte maneira:

O histórico das variáveis de série usadas na função Pine é criado por cada chamada contínua da função. Se a função não for chamada em cada coluna do script executado, isso levará a uma diferença entre os valores de história do bloco interno e externo da função. Portanto, se a função não for chamada em cada coluna, a série que utiliza o mesmo valor de índice dentro e fora da função não irá citar o mesmo ponto de história.

Não importa, vamos entender isso com um código de teste que está sendo executado no FMZ:

  /*backtest
  start: 2022-06-03 09:00:00
  end: 2022-06-08 15:00:00
  period: 1m
  basePeriod: 1m
  exchanges: [{"eid":"Bitfinex","currency":"BTC_USD"}]
  */

  f(a) => a[1]
  f2() => close[1]  

  oneBarInTwo = bar_index % 2 == 0
  plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A")   
  plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B")   
  plot(close[2], title = "close[2]", color = color.red, overlay = true)
  plot(close[1], title = "close[1]", color = color.green, overlay = true)

Captura de imagem da detecção em funcionamento

Tutorial de introdução à linguagem PINE quantitativa do Inventor

O código de teste é simples, e visa examinar os dados citados de duas maneiras:f(a) => a[1]ef2() => close[1]

  • f(a) => a[1]A forma como a função retorna no final usando os parâmetros:a[1]

  • f2() => close[1]Utilização direta de variáveis embutidascloseA função é a última que retorna.close[1]

[]O símbolo é usado para referenciar o valor histórico de uma variável de uma série de dados, close[1] é uma referência ao preço de fechamento de uma barra anterior ao preço de fechamento atual. Nosso código de teste desenhou quatro tipos de dados no gráfico:

  • plotchar(oneBarInTwo ? f(close) : na, title = "f(close)", color = color.red, location = location.absolute, style = shape.xcross, overlay = true, char = "A") Desenhe um caractere A, colorido em vermelho, quando oneBarInTwo for verdadeiro, e a posição desenhada (no eixo Y) é:f(close)Retornará o valor:

  • plotchar(oneBarInTwo ? f2() : na, title = "f2()", color = color.green, location = location.absolute, style = shape.circle, overlay = true, char = "B") Desenhe um caractere em B, colorido em verde, quando oneBarInTwo é verdadeiro, e a posição desenhada (no eixo Y) é:f2()Retornará o valor:

  • plot(close[2], title = "close[2]", color = color.red, overlay = true) A linha, colorida em vermelho, é desenhada na posição ((no eixo Y) como:close[2]Ou seja, o preço de fechamento no Bar atual na 2a linha à frente (a 2a linha à esquerda).

  • plot(close[1], title = "close[1]", color = color.green, overlay = true) A linha, colorida em verde, é desenhada na posição (no eixo Y):close[1]Ou seja, o preço de fechamento do Bar atual na 1a raiz à esquerda.

A retrospectiva de funcionamento através da estratégia pode ser visto no screenshot, embora a função usada para marcar o desenho Af(a) => a[1]Funções usadas para marcar e desenhar Bf2() => close[1]Todos são usados.[1] para referenciar dados históricos da série de dados, mas a posição dos marcadores “A” e “B” no gráfico é completamente diferente. A posição do marcador “A” sempre cai na linha vermelha, ou seja, o código da estratégiaplot(close[2], title = "close[2]", color = color.red, overlay = true)A linha que ele desenhou e os dados que ele usou foram:close[2]

Tutorial de introdução à linguagem PINE quantitativa do Inventor

A razão é que o índice através da barra de linha K, ou seja, a variável embutidabar_indexCalcular se a marca “A” e “B” deve ser desenhada. A marca “A” e “B” não devem ser desenhadas em cada barra de linha K.f(a) => a[1]Se a função não for chamada em cada Bar, o valor que será citado dessa maneira será relacionado à funçãof2() => close[1]Este método cita valores diferentes, mesmo que ambos usem[1] com o mesmo índice).

  • Algumas funções embutidas precisam ser calculadas em cada barra para calcular seus resultados corretamente.

Para ilustrar, um exemplo simples:

  res = close > close[1] ? ta.barssince(close < close[1]) : -1
  plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)

Vamos chamar a função de código.ta.barssince(close < close[1])Escrever em um operador triangularcondition ? value1 : value2Isso levou a que apenasclose > close[1]A função ta.barssince.ta.barssinceA função é calculada a partir da última vezclose < close[1]Número de linhas K criadas. Quando a função ta.barssince é chamada, é sempre close > close[1], ou seja, o preço de fechamento atual é maior que o preço de fechamento do Bar anterior, quando a função ta.barssince é chamada com a condição close < close[1] não foi criado, e não foi criado na última vez.

ta.barssince: Quando chamada, a função retorna na。 se esta condição nunca foi satisfeita antes da linha K atual.

Conforme mostrado na figura:

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Então, quando desenhamos um gráfico, apenas desenhamos dados quando a variável res tem um valor ((-1) }}.

Para evitar esse problema, nós apenas usamosta.barssince(close < close[1])A chamada de função é extraída do operador triangular e escrita no exterior de qualquer possível sub-branche condicional. Ela executa o cálculo em cada linha K Bar.

  a = ta.barssince(close < close[1])
  res = close > close[1] ? a : -1
  plot(res, style = plot.style_histogram, color=res >= 0 ? color.red : color.blue)

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Sequência de tempo

O conceito de sequência de tempo é muito importante na linguagem Pine, e é um conceito que temos que entender quando aprendemos a linguagem Pine. A sequência de tempo não é um tipo, mas sim uma estrutura básica para armazenar valores contínuos de variáveis ao longo do tempo. Sabemos que o script Pine é baseado em gráficos, e o conteúdo mais básico exibido nos gráficos é o gráfico de linha K.openÉ uma variável interna da linguagem Pine, construída para armazenar a sequência de tempo do preço de abertura de cada linha K de Bar. Pode ser interpretada comoopenEsta estrutura de sequência de tempo representa o preço de abertura de todas as barras de linha K no diagrama K atual, desde o primeiro Bar no início até o Bar executado no script atual. Se o diagrama K atual for de um período de 5 minutos, então nós referimos o código de estratégia do Pine (ou usamos)openÉ o preço de abertura da barra de linha K na execução atual do código da estratégia. É necessário usar o valor de abertura da barra de linha K para referenciar o valor histórico na sequência de tempo.[]O operador é usado quando a estratégia Pine é executada em uma barra de linha K.open[1]Indicar referênciaopenO preço de abertura do Bar de linha K anterior executado pelo script atual na sequência de tempo (ou seja, o preço de abertura do ciclo de linha K anterior).

  • As variáveis na sequência de tempo são muito fáceis de calcular. Nós construímos uma funçãota.cumPor exemplo:
  ta.cum

  Cumulative (total) sum of `source`. In other words it's a sum of all elements of `source`.
  ta.cum(source) → series float
  RETURNS
  Total sum series.
  ARGUMENTS
  source (series int/float)
  SEE ALSO
  math.sum

Código de teste:

  v1 = 1
  v2 = ta.cum(v1)
  plot(v1, title="v1")
  plot(v2, title="v2")
  plot(bar_index+1, title="bar_index")

Há muitas semelhanças.ta.cumEssa função embutida pode processar dados diretamente na sequência de tempo, comota.cumÉ somar os valores correspondentes das variáveis de entrada em cada barra de linha K, e depois usamos um gráfico para facilitar a compreensão.

O processo de execução da estratégia é a variável interna bar_index | - | - | - | - | A estratégia é executada na primeira linha de K-bar, onde 0 é a raiz de 1 e 1 é a raiz de 1. A estratégia é executada na linha K2 Bar 1 1 2 A estratégia é executada na terceira raiz K. |…|…|…|…| A estratégia é executada em N+1 raiz K.

Pode-se ver que, na verdade, v1, v2 e até mesmo bar_index são estruturas de sequência de tempo, com dados correspondentes em cada barra. Este código de teste não se diferencia entre o “modelo de preço em tempo real” ou o “modelo de preço de encerramento” apenas para mostrar o Bar real no gráfico. Para medir a velocidade, usamos o teste de retorno do “modelo de preço de encerramento”.

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Porque v1 é igual a 1 em cada barra.ta.cum(v1)A função é executada na primeira linha de K, Bar, e, como só existe a primeira linha de Bar, o resultado é 1, atribuindo o valor à variável v2。 Quandota.cum(v1)Quando executado na segunda linha K Bar, já existem 2 linhas K Bar ((a primeira correspondente à variável interna bar_index é 0, a segunda correspondente à variável interna bar_index é 1), então o resultado é 2, atribuindo o valor à variável v2, e assim por diante. Na verdade, pode-se observar que v2 é o número de linhas K Bar no gráfico, já que o índice das linhas Kbar_indexEntão isso é a partir de zero.bar_index + 1Na verdade, é o número de linhas de K. O gráfico de observação também mostra as linhas.v2ebar_indexÉ verdade.

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Também posso usarta.cumA função embutida calcula a soma dos preços de fechamento de todas as barras no gráfico atual, e então pode ser escrita apenas como:ta.cum(close), quando a estratégia é executada na barra de tempo real do lado direitota.cum(close)O resultado do cálculo é a soma dos preços de fechamento de todas as barras no gráfico (sem a operação para o lado mais à direita, somando-se apenas à barra atual).

As variáveis de uma sequência de tempo também podem ser calculadas usando operadores, como o código:ta.sma(high - low, 14)A variável interna.high(o preço máximo da linha K Bar) menoslow(Preço mínimo do K-Line Bar), uso finalta.smaA função busca a média.

  • Os resultados das chamadas de funções também deixam um rastro de valores na sequência de tempo
  v1 = ta.highest(high, 10)[1]
  v2 = ta.highest(high[1], 10)
  plot(v1, title="v1", overlay=true)
  plot(v2, title="v2", overlay=true)

O código de teste foi executado durante a retomada e pode ser observadov1ev2Se os valores dos números são idênticos, as linhas desenhadas no gráfico também se sobrepõem completamente. O resultado do cálculo de uma chamada de função deixará um rastro de valores na sequência de tempo, como o códigota.highest(high, 10)[1]Dentre eles,ta.highest(high, 10)O resultado da chamada de uma função também pode ser usado[1] para citar seu valor histórico.ta.highest(high, 10)O resultado é o seguinte:ta.highest(high[1], 10)Por isso.ta.highest(high[1], 10)eta.highest(high, 10)[1]É a mesma coisa.

Avaliar a informação de saída usando outra função gráfica:

  a = ta.highest(close, 10)[1]
  b = ta.highest(close[1], 10)
  plotchar(true, title="a", char=str.tostring(a), location=location.abovebar, color=color.red, overlay=true)
  plotchar(true, title="b", char=str.tostring(b), location=location.belowbar, color=color.green, overlay=true)

Pode-se ver os valores das variáveis a e b na sequência de tempo mostrados acima e abaixo da correspondente barra. Este código de desenho pode ser mantido durante o aprendizado, pois pode ser necessário frequentemente a saída de informações no gráfico para observação durante testes e experimentos.

Tutorial de introdução à linguagem PINE quantitativa do Inventor

Estrutura do script

Estrutura geral

Na parte inicial do tutorial, resumimos algumas diferenças entre o uso da linguagem Pine no FMZ e o uso da linguagem Pine no Trading View.indicator()strategy()E, temporariamente, não.library()É claro que, para ser compatível com as versões anteriores do script Pine, a estratégia foi escrita com coisas como://@version=5indicator()strategy()Também é possível. Algumas configurações de política também podem ser feitas emstrategy()Configuração de parâmetros na função.

<version>
<declaration_statement>
<code>

<version>Informações de controle de versão podem ser omitidas.

Comentários

Língua Pine//Como notação de linha única, a notação de linha é ampliada pela FMZ, uma vez que a linguagem Pine não possui notação de linha múltipla./**/Para notas de várias linhas.

Código

As linhas de um script que não são comentários ou instruções do compilador são sentenças, que implementam o algoritmo do script. Uma sentença pode ser um desses conteúdos.

  • Declaração de variáveis
  • Reatribuição de variáveis
  • Declaração de função
  • Chamadas de funções embutidas, chamadas de funções definidas pelo usuário
  • ifforwhileouswitchEstrutura de equivalência

As frases podem ser organizadas de várias maneiras.

  • Algumas declarações podem ser expressas em uma única linha, como a maioria das declarações de variáveis, que contêm apenas uma linha de chamada de função ou uma declaração de função de uma única linha. Outras, como as estruturas, sempre precisam de várias linhas, pois precisam de um bloco local.
  • As declarações de âmbito global do script (ou seja, as partes que não pertencem ao bloco local) não podem ser consideradas como空格ou制表符Comece (tabulação) O primeiro caractere deles também deve ser o primeiro caractere da linha As linhas que começam na primeira posição da linha, por definição, fazem parte do alcance global do script
  • Uma estrutura ou uma declaração de função de várias linhas sempre requer umlocal blockUm bloco local deve ser encolhido em um marcador ou em quatro espaços (caso contrário, será analisado como uma sequência da linha anterior de código, ou seja, julgado como um contínuo da linha anterior de código), e cada bloco local define um alcance local diferente.
  • Várias frases de uma linha podem ser seqüenciadas em uma linha usando a vírgula ((,) como separador.
  • Uma linha pode conter comentários ou apenas comentários.
  • As linhas também podem ser fechadas (continua em linhas múltiplas).

Por exemplo, incluindo três blocos locais, um na declaração de função personalizada e dois usando a estrutura if na declaração de variável, com o seguinte código:

indicator("", "", true)             // 声明语句(全局范围),可以省略不写

barIsUp() =>                        // 函数声明(全局范围)
    close > open                    // 本地块(本地范围)

plotColor = if barIsUp()            // 变量声明 (全局范围)
    color.green                     // 本地块 (本地范围)
else
    color.red                       // 本地块 (本地范围)

runtime.log("color", color = plotColor)  // 调用一个内置函数输出日志 (全局范围)

Código de mudança de linha

As linhas longas podem ser divididas em várias linhas, ou “enroladas”. As linhas enroladas devem ser encolhidas em qualquer número de espaços, desde que não sejam múltiplos de 4.

a = open + high + low + close

Pode ser embalado como ((observe que o número de espaços em cada linha não é um múltiplo de 4):

a = open +
      high +
          low +
             close

Uma chamada longa de plot ((() pode ser embalada como ▽.

close1 = request.security(syminfo.tickerid, "D", close)      // syminfo.tickerid 当前交易对的日线级别收盘价数据系列
close2 = request.security(syminfo.tickerid, "240", close)    // syminfo.tickerid 当前交易对的240分钟级别收盘价数据系列
plot(ta.correlation(close, open, 100),                       // 一行长的plot()调用可以被包装
   color = color.new(color.purple, 40),
   style = plot.style_area,
   trackprice = true)

A frase na declaração de função definida pelo usuário também pode ser empacotada. No entanto, como o bloco local deve começar gramaticalmente com uma contração (((4 espaços ou 1 símbolo), quando dividido para a linha seguinte, a parte de continuação da frase deve começar com uma contração ou mais (((não é igual ao múltiplo de 4 espaços)).

test(c, o) =>
    ret = c > o ?
       (c > o+5000 ? 
          1 :
              0):
       (c < o-5000 ? 
          -1 : 
              0)
           
                   
a = test(close, open)
plot(a, title="a")

Identificadores e operadores

Identificador

Antes de entendermos a variável, devemos primeiro entender o conceito de um identificador de barra. O identificador de barra comum é usado comofunçãoeVariaçõesO nome de uma função é usado para nomear uma variável.funçãoComo veremos em outros tutoriais, primeiro aprendemos o símbolo de identificação de um alfinete: 。

  • 1 - Os identificadores devem ser em maiúsculas(A-Z)Ou em letras minúsculas.(a-z)Letras ou sublinhados(_)Início, como o primeiro caractere do identificador.
  • 2 - O primeiro caractere do identificador pode ser seguido por outroAlfabetoSublinheouNúmeros
  • 3. O nome do identificador é em maiúsculas e minúsculas.

Por exemplo, o identificador com os seguintes nomes:

fmzVar
_fmzVar
fmz666Var
funcName
MAX_LEN
max_len
maxLen
3barsDown  // 错误的命名!使用了数字字符作为标识符的开头字符

Como a maioria das linguagens de programação, a linguagem Pine também tem recomendações de escrita. Geralmente, é recomendado quando se nomeia um identificador:

  • 1, todas as letras maiúsculas são usadas para nomear as constantes.
  • 2. UsarRegra do Pico do CameloNome para outros identificadores.
// 命名变量、常量
GREEN_COLOR = #4CAF50
MAX_LOOKBACK = 100
int fastLength = 7

// 命名函数
zeroOne(boolValue) => boolValue ? 1 : 0

Operador

Os operadores são alguns símbolos de operação usados em linguagens de programação para construir expressões, enquanto expressões são regras de cálculo projetadas para algum tipo de computação quando escrevemos uma estratégia. Os operadores da linguagem Pine são classificados por função como:

Operadores de atribuição de valor, operadores de aritmética, operadores de comparação, operadores lógicos,? :Os operadores de tríade.[]O operador de referência histórica.

O operador aritmético*Por exemplo, para distinguir o tipo de problema causado pelo resultado do operador de linguagem Pine no Trading View, há o seguinte código de teste:

//@version=5
indicator("")
lenInput = input.int(14, "Length")
factor = year > 2020 ? 3 : 1
adjustedLength = lenInput * factor
ma = ta.ema(close, adjustedLength)  // Compilation error!
plot(ma)

O erro de compilação é causado por um erro de compilação de um script executado no Trading View.adjustedLength = lenInput * factorDepois da multiplicação, temosseries intTipo (série), no entantota.emaO segundo parâmetro da função não suporta esse tipo de função. No entanto, não há restrições rigorosas desse tipo no FMZ, e o código acima pode funcionar normalmente.

A seguir, vamos ver o uso de vários operadores.


Operador de atribuição

Existem dois tipos de operadores de atribuição:=:=A partir de agora, você pode fazer o que você quiser, mas não é o que você quer fazer.

=O operador é usado para atribuir um valor a uma variável quando esta é iniciada ou declarada.=Inicialização, declaração e atribuição de valor de uma variável começam com esse valor em cada barra subsequente. Estas são declarações de variáveis válidas:

a = close           // 使用内置变量赋值给a
b = 10000           // 使用数值赋值
c = "test"          // 使用字符串赋值
d = color.green     // 使用颜色值赋值
plot(a, title="a")
plot(b, title="b")
plotchar(true, title="c", char=str.tostring(c), color=d, overlay=true)

Percebera = closeDeclaração de atribuição, onde a variável a em cada Bar é o preço de fechamento atual do Bar (closed) ⋅ outras variáveisbcdÉ invariável e pode ser testado em um sistema de feedback no FMZ, e os resultados podem ser vistos em um gráfico.

:=Usado para atribuir valores a variáveis existentes, pode ser entendido simplesmente como o uso de:=Os operadores são usados para modificar o valor de uma variável declarada e inicializada. Se for usado:=Um operador atribui um valor a uma variável não iniciada ou declarada, gerando erros, como:

a := 0

Então,:=Os operadores de atribuição são geralmente usados para re-atribuir valores a variáveis já existentes, como:

a = close > open 
b = 0 
if a
    b := b + 1

plot(b)

A julgar seclose > open(ou seja, o BAR atual é a linha do sol), a variável é o valor verdadeiro (true) executa o código no bloco local da declaração ifb := b + 1, usando o operador de atribuição:=Re-atribuir a b, acrescentando um 1 ◦ e, em seguida, usar a função plot para desenhar no gráfico o valor da variável b em cada BAR da sequência de tempo, em linha ◦

Será que nós pensamos que se houver um solenoide BAR, b continuará acumulando 1? Claro que não, aqui nós não usamos nenhuma palavra-chave para declarar a variável b, quando a inicialização é 0.b=0E isso é executado em cada BAR, então você pode ver que o resultado de executar este código é que a variável b é redefinida para 0 a cada vez que a variável a é verdadeira, então isso corresponde aclose > openEntão, nesta rodada de execução do código, b é adicionado 1, quando a função de plot é 1, mas na próxima rodada de execução do código, b é re-atribuído a 0.

Quando falamos de operadores de atribuição, temos que estender a explicação a duas palavras-chave:varvarip

  • var

Na verdade, essa palavra-chave, que já vimos e usamos em tutoriais anteriores, só que não foi explorada em detalhes.

var é uma palavra-chave usada para alocar e inicializar variáveis de uma só vez. Normalmente, a sintaxe de atribuição de variáveis que não contém a palavra-chave var leva a que os valores das variáveis sejam cobertos sempre que os dados são atualizados. Por outro lado, quando as variáveis de alocamento são usadas com a palavra-chave var, elas podem ser mantidas em um estado semelhante, mesmo que os dados sejam atualizados.

Nós ainda usamos esse exemplo, mas nós usamos para atribuir um valor a bvarPalavras-chave:

  a = close > open 
  var b = 0 
  if a
      b := b + 1

  plot(b)

varA palavra-chave permite que a variável b execute apenas a primeira atribuição inicial, sem que a lógica da estratégia de execução de cada vez que b seja redefinida para 0, de modo que a linha desenhada no tempo de execução pode ser observada para obter b, ou seja, o número de BARs de linha de onda que ocorreram quando o atual K BAR foi medido.

As variáveis de uma declaração var podem ser escritas não apenas em escala global, mas também em blocos de código, como neste exemplo:

  strategy(overlay=true)
  var a = close
  var b = 0.0
  var c = 0.0
  var green_bars_count = 0
  if close > open
      var x = close
      b := x
      green_bars_count := green_bars_count + 1
      if green_bars_count >= 10
          var y = close
          c := y
  plot(a, title = "a")
  plot(b, title = "b")
  plot(c, title = "c")

A variável ‘a’ mantém o preço de fechamento da primeira linha da série. A variável ‘b’ mantém o preço de fechamento da primeira barra de preço de alumínio verde da série. A variável ‘c’ mantém o preço de fechamento da décima chiclete verde da série.

  • varip

varipA primeira vez que vimos a palavra-chave, podemos ver a descrição da palavra-chave:

varip ((var intrabar persist) é uma palavra-chave usada para a distribuição e inicialização de variáveis de uma só vez. É semelhante à palavra-chave var, mas a variável que usa a declaração varip mantém seu valor entre as atualizações de linha K em tempo real.

Não é difícil de entender, mas é fácil de entender com um exemplo.

  strategy(overlay=true)

  // 测试 var varip
  var i = 0
  varip ii = 0  

  // 将策略逻辑每轮改变的i、ii打印在图上
  plotchar(true, title="ii", char=str.tostring(ii), location=location.abovebar, color=color.red)
  plotchar(true, title="i", char=str.tostring(i), location=location.belowbar, color=color.green)  

  // 每轮逻辑执行都给i、ii递增1
  i := i + 1
  ii := ii + 1

Este código de teste funciona de forma diferente em modelos de preços de fechamento e modelos de preços em tempo real:

Modelos de preços em tempo real: Lembram-se de quando nós dissemos que a estratégia era executada em um período de BAR histórico e um período de BAR em tempo real?varvaripVariáveis declaradasiiiCada vez que o código da estratégia é executado, uma operação de incremento é executada. Assim, é possível ver que os números exibidos na linha KBAR do resultado da retomada são incrementados um por um. Quando a fase histórica da linha K termina, começa a fase de linha K em tempo real. As variáveis das declarações var e varip começam a mudar.i := i + 1eii := ii + 1A diferença é que ii é modificado a cada vez. Embora i seja modificado a cada vez, a próxima rodada de execução da lógica da estratégia retorna ao valor anterior (lembre-se do mecanismo de rolagem que explicamos no capítulo anterior “Execução do modelo”?), até que o atual KBAR seja executado e o valor de i seja atualizado (ou seja, a próxima rodada de execução da lógica da estratégia não retorna ao valor anterior). Portanto, pode-se ver que a variável i ainda é aumentada a cada BAR.1.

Modelo de fechamento: Como o modelo de preço de fechamento executa uma lógica de estratégia para cada linha K BAR. Assim, no modelo de preço de fechamento, a fase de linha K histórica e a fase de linha K em tempo real, as variáveis das declarações var, varp apresentam um desempenho excessivo perfeitamente consistente no exemplo acima, aumentando 1 para cada linha K BAR.


Operador de aritmética
Operador ilustrar
+ Adição
- Subtração
* Multiplicação
/ Eliminação
% Buscar exemplos

+-Um operador pode ser usado como um operador binário ou como um operador unitário. Outros operadores aritméticos só podem ser usados como um operador binário.

1 , o operador de aritmética é de ambos os lados do tipo de valor, o resultado é o tipo de valor, inteiro ou número de ponto flutuante, dependendo do resultado da operação. 2. Se um número de operações é uma string, o operador é+, o resultado é uma string, o valor é convertido em forma de string, e depois as strings são empilhadas. Se for outro operador de aritmética, tentaremos converter a string em um valor, e depois operar. 3. Se um dos números de operação for na, o resultado será nulo, mostrando NaN quando impresso no FMZ.

a = 1 + 1 
b = 1 + 1.1
c = 1 + "1.1"
d = "1" + "1.1"
e = 1 + na 

runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e)   
// a: 2 , b: 2.1 , c: 11.1 , d: 11.1 , e: NaN

A linguagem Pine no FMZ é um pouco diferente da linguagem Pine no Trading View, a linguagem Pine no FMZ não é muito exigente quanto aos requisitos de tipo de variável. Por exemplo:

a = 1 * "1.1"
b = "1" / "1.1"
c = 5 % "A" 

plot(a)
plot(b)
plot(c)

Pode ser executado no FMZ, mas será reportado um erro de tipo no trading view. Para um operador de aritmética, quando os números de operação de ambos os lados são strings, o sistema irá converter a string em um valor numérico e depois calcular. Se uma string não-numérica não puder ser calculada, o resultado da operação do sistema será um valor nulo na.


Comparar o operador

Os operadores de comparação são binários.

Operador ilustrar
< Menos de
> Maior do que
<= Menos que igual a
>= Maior do que igual a
== Equivalência
!= Desigualdade

Exemplo de teste:

a = 1 > 2 
b = 1 < 2 
c = "1" <= 2 
d = "1" >= 2 
e = 1 == 1 
f = 2 != 1 
g = open > close 
h = na > 1 
i = 1 > na

runtime.log("a:", a, ", b:", b, ", c:", c, ", d:", d, ", e:", e, ", f:", f, ", g:", g, ", h:", h, ", i:", i)   
// a: false , b: true , c: true , d: false , e: true , f: true , g: false , h: false , i: false

Como você pode ver, o operador de comparação é muito simples de usar, mas é o operador que mais usamos quando escrevemos estratégias. Você pode comparar valores, mas também pode comparar variáveis internas, comocloseopenespere. Como um operador de cálculo, o FMZ é diferente do Pine no Trading View, o FMZ não tem um tipo de requisição particularmente rigoroso, então declarações como essad = "1" >= 2No FMZ, não há erro, a execução é feita primeiro com a conversão da string para um valor numérico e depois a operação de comparação. No Trading View, há erro.


Operador lógico
Operador Código de identificação ilustrar
Não. not Operador unitário, não operativo
e and Operador binário, com () e ()
ou or Operador binário, ou operação

Quando falamos de operadores lógicos, temos que falar de tabelas de valores reais. Tal como aprendemos quando estávamos no ensino médio, só que aqui estamos testando e aprendendo no sistema de feedback:

a = 1 == 1  // 使用比较运算符构成的表达式,结果为布尔值
b = 1 != 1
c = not b   // 逻辑非操作符
d = not a   // 逻辑非操作符

runtime.log("测试逻辑操作符:and", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a and c:", a and c)
runtime.log("a:", a, ", b:", b, ", a and b:", a and b)
runtime.log("b:", b, ", c:", c, ", b and c:", b and c)
runtime.log("d:", d, ", b:", b, ", d and b:", d and b)

runtime.log("测试逻辑操作符:or", "#FF0000")
runtime.log("a:", a, ", c:", c, ", a or c:", a or c)
runtime.log("a:", a, ", b:", b, ", a or b:", a or b)
runtime.log("b:", b, ", c:", c, ", b or c:", b or c)
runtime.log("d:", d, ", b:", b, ", d or b:", d or b)

runtime.error("stop")

Para evitar que o sistema de rastreamento fosse influenciado pela impressão contínua de informações, usamosruntime.error("stop")A frase é executada uma vez que a impressão é executada, e o erro anormal é lançado para que a detecção seja interrompida. Depois, você pode observar a informação de saída e descobrir que o conteúdo da impressão e a tabela de valores reais são na verdade os mesmos.


Operador de terciário

Utilização do operador triangular? :Expressões trigonométricas combinadas com números operacionaiscondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseNós já vimos isso nos cursos anteriores. O que chamamos de expressão triangular, um operador triangular significa que há um total de três operações.

condition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseO que está acontecendo?conditionÉ um critério de julgamento, se o valor da expressão de verdade for:valueWhenConditionIsTrueSeconditionO valor da expressão para o caso évalueWhenConditionIsFalse

O blogueiro, que não tem nenhuma utilidade prática, mas é fácil de demonstrar:

a = close > open
b = a ? "阳线" : "阴线"
c = not a ? "阴线" : "阳线"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)

A expressão triangular também pode ser embutida, como fizemos no tutorial anterior.

a = close > open
b = a ? math.abs(close-open) > 30 ? "阳线" : "十字星" : math.abs(close-open) > 30 ? "阴线" : "十字星"
c = not a ? math.abs(close-open) > 30 ? "阴线" : "十字星" : math.abs(close-open) > 30 ? "阳线" : "十字星"
plotchar(a, location=location.abovebar, color=color.red, char=b, overlay=true)
plotchar(not a, location=location.belowbar, color=color.green, char=c, overlay=true)

Isso é o equivalente acondition ? valueWhenConditionIsTrue : valueWhenConditionIsFalseEmvalueWhenConditionIsTruevalueWhenConditionIsFalseEm vez disso, usamos outras expressões tridimensionais.


Operador Histórico

Utilização do operador Histórico[], referindo-se aos valores históricos na sequência de tempo. Estes valores históricos são os valores da variável na linha K BAR anterior à linha K BAR atual no tempo de execução do script.[]O operador é usado para chamadas de variáveis, expressões e funções.[]O valor entre parênteses é o desvio do histórico que queremos citar do BAR da linha K atual. Por exemplo, se eu quiser citar o preço de fechamento de uma linha K BAR anterior, escrevo:close[1]

A forma de escrever a palavra é a mesma que a forma de escrever a palavra em português.

high[10]
ta.sma(close, 10)[1]
ta.highest(high, 10)[20]
close > nz(close[1], open)

[]O operador só pode ser usado uma vez no mesmo valor, então isso é errado, e vai falhar:

a = close[1][2]   // 错误

Talvez você veja aqui, alguns colegas de aula dizem que os operadores[]E o problema é que o que é usado para construções de séries é muito parecido com o que é usado para construções de séries. Em seguida, vamos usar um exemplo para ilustrar a diferença entre uma série (series) e um conjunto (array) na linguagem Pine.

strategy("test", overlay=true)

a = close
b = close[1]
c = b[1]

plot(a, title="a")
plot(b, title="b")
plot(c, title="c")

Embora dizendoa = close[1][2]O blogueiro também escreve sobre o assunto:

b = close[1]
c = b[1]

A partir daí, a sequência de números, que é a sequência de números, não é um erro, se entendermos a sequência de números como uma sequência normal.b = close[1]Depois de atribuir um valor, b deve ser um número, masc = b[1], b ainda pode ser novamente usado para usar o operador de referência histórico. Como pode ser visto na linguagem Pine, o conceito de série não é tão simples quanto o de arquivos. Pode ser entendido c