Desenhos
Introdução
A partir da versão v4 , indicadores e estratégias podem criar objetos de desenho no gráfico.
2 tipos de desenhos suportados no momento são:
Essas funções permitem criar estudos mais sofisticados através de componentes visuais, por exemplo, pontos de pivot, linhas de suporte e resistência, linhas zig zag, e rótulos contendo texto dinâmicos, etc.
A diferença para funções de plotagem (plot, plotshape, plotchar) é a de que as funções de desenho podem ser criadas em barras históricas e barras futuras, ou seja aonde ainda elas não existem.
Criando Desenhos
//@version=4
study("My Script", overlay=true)
label.new(bar_index, high)
O rótulo é criado com os parâmetros x=bar_index (o index da barra atual) e y=high (máxima do preço da barra atual). Quando uma nova barra é criada, um novo rótulo é criado em cima da nova barra.
Rótulos ficam no gráfico a não ser que sejam explicitamente removidos usando a função:
//@version=4
study("My Script", overlay=true)
label.new(bar_index, high, style=label.style_none,
text="x=" + tostring(bar_index) + "\n y=" + tostring(high))
<code javascript>
* Neste exemplo style=label.style_none significa que o rótulo não terá uma coloração de fundo.
* Neste próximo exemplo uma linha é criada
<code javascript>
//@version=4
study("My Script", overlay=true)
line.new(x1=bar_index[1], y1=low[1], x2=bar_index, y2=high)
Cálculo na atualização das Barras
//@version=4
study("My Script", overlay=true)
label.new(bar_index, high)
Enquanto label.new criar um novo rótulo a cada nova iteração do script (quando o preço muda em gráfico de tempo real) - o rótulo mais recente (criado na iteração anterior) é automaticamente apagado por causa do rollback antes da próxima iteração.
Apenas o último rótulo criado antes da barra de tempo real fechar será commited e portanto persistirá no gráfico.
Coordenadas
//@version=4
study("My Script", overlay=true)
if barstate.islast
label.new(timenow, close, xloc=xloc.bar_time)
Modificando Desenhos
Um objeto de desenho pode ser modificado após sua criação. As funções label.new e line.new retornam uma referência ao objetos criados (do tipo series label e series line respectivamente).
Esta referência pode então ser usada como primeiro argumento nas funções:
//@version=4
study("My Script", overlay=true)
l = label.new(bar_index, na)
if close >= open
label.set_text(l, "green")
label.set_color(l, color.green)
label.set_yloc(l, yloc.belowbar)
label.set_style(l, label.style_labelup)
else
label.set_text(l, "red")
label.set_color(l, color.red)
label.set_yloc(l, yloc.abovebar)
label.set_style(l, label.style_labeldown)
Este script cria um rótulo na barra atual e então grava uma referência para este rótulo na variável l. Então, dependendo da barra (baseado na condição de close >= open) as propriedades do rótulo são modificadas : texto, cor, coordenada y e estilo do rótulo.
Nota: na é passado como o argumento para a função label.new. Isto é porque neste exemplo o rótulo usa yloc.belowbar ou yloc.abovebar - que não requerem um valor y. Um valor absoluto y somente é requerido quando o rótulo usa yloc.price.
Argumentos para função de linha:
line.set_color - altera a cor da linha.
line.set_extend - altera o atributo extensão da linha.
extend.none - um segmento de linha.
extend.left - estende a linha para esquerda.
extend.right - estende a linha para direita.
extend.both - estende a linha para esquerda e para direita.
line.set_style - altera o estilo da linha.
line.set_width - altera o comprimento da linha.
line_set_xloc - altera o parâmetro x-location da linha (ambos x1 e x2).
line.set_x1 - altera a coordenada x1 da linha.
line.set_y1 - altera a coordenada y1 da linha.
line.set_xy1 - altera ambas coordenadas x1 e y1 da linha.
line.set_x2 - altera a coordenada x2 da linha.
line.set_y2 - altera a coordenada y2 da linha.
line.set_xy2 - altera ambas coordenadas x2 e y2 da linha.
Estilos do Rótulo
Estilos das Linhas
Apagar Desenhos
//@version=4
study("Last Bar Close 1", overlay=true)
c = close >= open ? color.lime : color.red
l = label.new(bar_index, na,
text=tostring(close), color=c,
style=label.style_labeldown, yloc=yloc.abovebar)
label.delete(l[1])
Em cada atualização de uma nova barra - um novo objeto é criado e gravado na variável l do tipo series label, portanto o operador [ ] é usado para retornar o rótulo do objeto da barra anterior. Este rótulo anterior é então passado para a função label.delete para ser apagado.
As funções label.delete e line.delete não fazem nada caso um valor na é usado com um id o que faz o seguinte código desnecessário.
if not na(l[1])
label.delete(l[1])
//@version=4
study("Last Bar Close 2", overlay=true)
var label l = na
label.delete(l)
c = close >= open ? color.lime : color.red
l := label.new(bar_index, na,
text=tostring(close), color=c,
style=label.style_labeldown, yloc=yloc.abovebar)
Quando o estudo recebe uma nova barra, a variável l ainda está referenciando o objeto de rótulo antigo criado na barra anterior. Este rótulo é apagado com a chamada de label.delete(l). Um novo rótulo é então criado e o seu id é gravado em l. Usando este formato não há necessidade de usar o operador [ ].
//@version=4
study("Last Bar Close 3", overlay=true)
var label l = label.new(bar_index, na,
style=label.style_labeldown, yloc=yloc.abovebar)
c = close >= open ? color.lime : color.red
label.set_color(l, c)
label.set_text(l, tostring(close))
label.set_x(l, bar_index)
Limites de Desenho
Desenhar objetos de desenho consomem recursos do servidor e é por isso que existe um limite de desenhos por estudo ou estratégia (study ou strategy).
Quando muitos desenhos são criados, desenhos antigos são automaticamente apagados durante a execução em um processo chamado como “garbage collection” (coleta de lixo).
Este código desenha um rótulo em cada barra, rolando a barra para a esquerda você notará que não haverão rótulos desenhados a partir de 50 barras.
//@version=4
study("My Script", overlay=true)
label.new(bar_index, high)
//@version=4
study("My Script", overlay=true, max_labels_count=100)
label.new(bar_index, high)
Ativos Adicionais
//@version=4
study("My Script", overlay=true)
if barstate.isrealtime
label.new(bar_index[10], na, text="Label", yloc=yloc.abovebar)
Porém irá falhar durante execução. O editor Pine não consegue determinar o tamanho do buffer para valores históricos da plotagem time, mesmo que time não esteja sendo explicitamente mencionado no código.
Isto acontece porque a variável nativa bar_index usa a série time dentro da sua construção. Acessando o valor de bar_index 10 barras no passado requer que o tamanho do buffer histórico da série time seja do tamanho 10 ou maior.
Em Pine há um mecanismo que automaticamente detecta o tamanho histórico do buffer na maioria das vezes.
Autodetecção funciona deixando o script Pine acessar valores históricos qualquer número de barras no passado por uma duração limitada. Neste script, if barstate.isrealtime previne o acesso ocorra então o tamanho histórico do buffer não pode ser inferido e o código falha.
A solução é usar a função max_bar_back para explicitamente configurar o tamanho histórico do buffer para a series time.
//@version=4
study("My Script", overlay=true)
max_bars_back(time, 10)
if barstate.isrealtime
label.new(bar_index[10], na, text="Label", yloc=yloc.abovebar)