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 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ãoswitch
O 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.string
、input.int
Função.input.string
O que é que é isso?input.int
A função é usada para retornar valores inteiros.options
O uso dos parâmetros.options
Os 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.switch
A 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 < open
Em 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.switch
No exemplo "Executar a ramificação é definido e não é alterado durante a execução da estratégia").
返回值 = 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 ciclobreak
Palavras-chave: Quando executadobreak
Depois de uma frase, o ciclo pára.
For usado no ciclocontinue
Palavras-chave: Quando executadocontinue
Depois de uma frase, o ciclo é ignorado.continue
O 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 ... in
A 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 testArray
A 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.sma
O 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.sum
A 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.
while
A 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
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))
Utilizaçãoarray<int> a
、float[] b
Arquivos 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.new
earray.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.islast
A impressão em tempo real ainda tem apenas um elemento, o valor 0.
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;
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
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)
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-chavevarip
O valor de cada variação de preço é registrado em uma matriz.
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.join
Conecte 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")
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.
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.) ⇒
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.entry
A 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
, when
E 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.long
Esta variável é transmitida se você quiser fazer um espaço (venda).strategy.short
Esta 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.limit
O preço é o seguinte: indique o preço limite do pedido.stop
O preço do produto é o mesmo que o preço do produto.strategy.entry
Detalhes específicos de execução da funçãostrategy
O 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.strategy
A funçãopyramiding
、default_qty_value
Parâ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 especificamospyramiding
Quando 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.entry
Uma das operações abaixo não foi executada.default_qty_value
O parâmetro é 0.1, então o ID é um "long 1" desta vez.strategy.entry
O volume de menus para a operação de subordem é definido por default como 0.1.strategy.entry
A função é chamada como a função que nós indicamos.direction
Todos sãostrategy.long
A 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: strategy.entry
O pedido não foi cumprido, segunda chamadastrategy.entry
A 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.entry
Quando a função encomenda, todas as posições serão acumuladas no ID-long3.
2、strategy.close
strategy.close
A função é usada para especificar o ID do equilíbrio do posicionamento de entrada. Os principais parâmetros são:id
,when
,qty
,qty_percent
。
Parâmetros:
id
O ID de entrada que é necessário é o que nós usamos.strategy.entry
O ID indicado quando a função de ingressos é aberta.when
A partir de agora, o governo vai continuar a fazer isso.qty
O número de transações.qty_percent
Porcentagem 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 1strategy.close
Diferentes resultados são obtidos quando os diferentes parâmetros da função são definidos em equilíbrio.strategy.close
A 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_all
A 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_all
A posição do banco em relação à direção em que está posicionado será eliminada quando for chamada.strategy.close_all
Os principais parâmetros da função são:when
。
Parâmetros:
when
A 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==0
Para 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.entry
Função de entrada.strategy.position_size
A 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 < 0
Quando 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 := true
Não é fácil de ver o log.
O que você pode verstrategy.close_all
A 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.exit
A função é usada para operações de liquidação de posições de entrada, diferente da funçãostrategy.close
estrategy.close_all
A função é o equilíbrio imediato no preço atual do mercado.strategy.exit
A 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.qty
O número de transações.qty_percent
Percentagem de equilíbrio, faixa: 0 ~ 100.profit
O objetivo do lucro, expresso em pontos.loss
O objetivo é parar de perder, em pontos.limit
O objetivo do lucro é o preço.stop
O objetivo é parar com o preco.when
A 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.entry
Função), o "long1" é definido de propósito.limit
Parâ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.exit
O 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.exit
A função também possui parâmetros de rastreamento de stop loss mais complexos:trail_price
、trail_points
、trail_offset
Também é possível testar a aprendizagem do uso neste exemplo.
5、strategy.cancel
strategy.cancel
Funções usadas para cancelar / desativar todos os comandos de prelocação. Estas funçõesstrategy.order
, strategy.entry
, strategy.exit
Pode ser gerado um ID de entrada.id
、when
。
Parâmetros:
id
O ID de entrada a ser cancelado.when
A 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_all
Funções estrategy.cancel
Funções semelhantes: ≪ cancelar / desativar todos os comandos pré-enganados≫ pode ser especificadowhen
Parâmetros.
Parâmetros:
when
A 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.order
Funções, configuração de parâmetros, etc.strategy.entry
A diferença é:strategy.order
A função não éstrategy
Funçõespyramiding
A 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.long
Esta variável é transmitida se você quiser fazer um espaço (venda).strategy.short
Esta 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.limit
O preço é o seguinte: indique o preço limite do pedido.stop
O preço do produto é o mesmo que o preço do produto.Nós usamosstrategy.order
Não há restrições para essa característica, combinandostrategy.exit
Funçã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)
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.
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.strategy
A função faz algumas configurações simples:strategy("supertrend", overlay=true)
, basta configurar um título de estratégia para a barra de supertrend.overlay
O parâmetro étrue
Quando 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.input
Funções
[supertendência, direção] = ta.supertendência ((input ((5,
factor input.int(10,), atrPeriodo ))
input
As chamadas de funções são usadas diretamente parata.supertrend
Os parâmetros da função de indicador são usados para calcular os indicadores de supertrend.
Por padrão, a função define dois controles de parâmetros na interface de políticas da linguagem Pine, como se veja:
Como você pode ver, o padrão do controle é:input
Funções einput
A função de série (( aqui éinput.int
O primeiro parâmetro de () também foi explicado nos capítulos anteriores. Com essas duas funções, podemos definir a interface da estratégiata.supertrend
O parâmetro da função. A função do indicador de supertrend calcula um dado de preço.supertrend
e dados de uma direção.direction
E depois usá-lo.plot
Diagrama 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; quandodirection
A tendência do mercado atual é para cima, quandodirection
A 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.plot
Quando você desenha um gráfico de funçõesdirection
É maior ou menor que 0.
A seguir:if ... else if
A lógica é o julgamento do sinal de transação, quando a expressãodirection < 0
O 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.supertrend
O 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 < 0
A 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 > 0
O 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.supertrend
O 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.supertrend
O 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.hl2
A 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ódigolowerBand
eupperBand
。
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 aprevUpperBand
A tendência atual é para baixo, ou seja, para cima.close
Mais deupperBand
O preço quebrou, pensando que havia uma mudança de tendência e se transformou em uma tendência ascendente.direction
A variável de direção é definida como -1 (tendência ascendente); caso contrário, permanece definida como 1 (tendência descendente).if direction < 0
A partir daí, a empresa começou a produzir o produto.direction > 0
A 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.
/*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)
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) eQuoteCurrency
A 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) estocks
A 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.maxDiffValue
Este parâmetro é o critério de julgamento para o equilíbrio.BaseCurrency
eQuoteCurrency
A desviação excedemaxDiffValue
A 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.ishistory
Os preços são muito baixos e os preços são muito baixos.balance
O valor é superiorstocks
Comprar no momento do valor; vender ao invés disso; atualizar após a execução da declaração de transaçãobalance
estocks
A 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.balance
Parâmetros definidos para: 4374 ((1458*3)stocks
Para: 3. Deixar os ativos em equilíbrio no início.
E, em outras lições, aprendemos:strategy.exit
A função de saída de posição, onde a função de stop loss stop stop stop não é explicada por exemplo.strategy.exit
A função de rastreamento stop-loss stop-gap funciona para otimizar uma estratégia de supertrend.
Primeiro, vamos ver.strategy.exit
Parâmetros de paragem de paragem de paragem de paragem de paragem de paragem de paragem de paragem da função:
1、trail_price
Parâ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