Desenhando Resistência e Níveis de Suporte Com MQL5

Aleksandr Teleguz | 29 fevereiro, 2016

Tabela de conteúdos

  1. Introdução
  2. Propósito de escrever este artigo
  3. Métodos anteriormente apresentados de desenho de níveis de suporte e resistência de forma resumida
  4. Princípio para encontrar os extremos
  5. Função para encontrar a barra extrema com o índice mais baixo (primeira barra) Ext_1
  6. Função geral para encontrar todos os extremos subseqüentes Ext_2
  7. Processando os resultados
  8. Exemplo de indicador mostrando níveis de suporte e resistência
  9. Conclusão

Introdução

Primeiramente, explicarei brevemente o que são linhas suporte e resistência, como elas são criadas e como usá-las em operações.

Todas as figuras de tendência, linhas e modelos são combinações de linhas de suporte e resistência, que fundamentam a análise de tendência clássica. Linha de resistência é baseada na máxima dos preços, que ocorrem quando os operadores (\"bulls\") param de comprar a moeda a um preço superior e começam a fechar posições abertas para a compra. O preço de um instrumento financeiro responde a isto com uma reversão, até uma situação semelhante ocorrer entre os \"bears\", ou seja, a linha de suporte é baseada na mínima dos preços.

Assim, pode-se supor que o pontos máximos são formados quando moeda está sobrecomprada, e pontos mínimos - quando ela está sobrevendida. Esta é a razão por que para desenhar linhas de suporte e resistência, eu uso um indicador padrão do conjunto do MetaTrader - Índice de Força Relativa (RSI), que foi desenvolvido e publicado pela John Wilder em 1978. Este indicador determina zonas sobrecompradas e sobrevendidas de moeda.

Eu uso o indicador RSI com período 8. Esse valor não é um resultado de minhas observações - esta ordem do RSI foi recomendada pelo Eric L. Nyman no seu livro "The Small Trader's Encyclopedia" para todos os períodos gráficos exceto diário e superiores. Estou completamente satisfeito com os resultados do meu indicador, quando opero com RSI (8).

Existem duas opiniões opostas, se a sombra das velas devem ser consideradas durante a procura de preços máximos e mínimos (preços de alta/baixa). Eu, pessoalmente, considero comparar preços altos a preços baixos, quando procuro pontos extremos. Se você não quer levá-los em consideração, você pode simplesmente fazer pequenas alterações ao código do indicador colocado abaixo.

Negociações com linhas de suporte e resistência podem ocorrer fora dessas linhas, bem como a variação de preço dentro da figura formada por estas linhas.

Negociação com um rompimento dos níveis de suporte e resistência

Fig.1. Sinal de compra

Considero o segundo método menos eficaz, especialmente se a reversão do preço de uma das linhas desempenha um papel fundamental na tomada das decisões de negociações. A Figura 1 mostra o caso, quando o preço, após uma reversão da linha de resistência, não atinge a linha suporte, reverte e rompe a linha de resistência, isto leva a um sinal de compra mais forte. Através da análise de ângulos formados a partir das linhas cruzando o eixo do tempo, podemos definir uma direção da tendência geral, quando o preço do instrumento financeiro atravessa uma das linhas, permite fazer uma conclusão sobre a inversão da tendência existente ou ganho de força. Muitas vezes, antes de cruzar a linha suporte, por exemplo, o preço chega apenas até o meio da linha de resistência (este fator aumenta um sinal de negociação).

Há uma plataforma chamada "Autochartist" projetada para reconhecimento de figuras de tendência e modelos. Como um experimento, há dois meses tenho negociado com uma conta de demonstração usando sinais de reversão do nível preço de resistência ou suporte - a maioria das transações neste caso foram fechados com perda, ao contrário de negociações usando sinais de níveis de rompimento.

Níveis de suporte e resistência são também utilizados para determinar a aceleração ou desaceleração da tendência. Aumentar o ângulo de uma linha de tendência numa tendência de alta implica em sua aceleração, aparentemente levando a continuação da tendência. O aumento do ângulo numa tendência de baixa, ao contrário, indica a tendência de desaceleração. Uma linha de suporte (desenhada pelas mínimas dos preços) atua como uma linha de tendência na tendência de alta, e uma linha de resistência (desenhada pelas máximas dos preços) atua como uma linha de tendência numa tendência de baixa.

Desaceleração da tendência de alta

Fig.2. Desaceleração da tendência de alta

Desaceleração da tendência de baixa

Fig.3. Desaceleração da tendência de baixa

A desaceleração da tendência pode sugerir a sua reversão no futuro próximo.


Propósito de escrever este artigo

Análise das figuras de gráfico, formada por linhas de suporte e resistência, é um dos mais antigos métodos de análise técnica. Da minha experiência de negociação no mercado cambial, posso afirmar que o método acima mencionado não é apenas antigo, mas também é eficaz. Acredito que muitos operadores usem isso. Construção de linhas de suporte e resistência manualmente com terminal MetaTrader 5 é uma tarefa fácil para qualquer operador que tem conhecimento teórico. Mas não é o caso quando se cria um programa que desenha essas linhas automaticamente.

Neste artigo, quero propor meu próprio método de desenho de linhas suporte e resistência que podem ser implementadas tanto com MQL5 com em MQL4. Esperançosamente, você vai achar esta informação útil.


Métodos anteriormente apresentados de desenho de níveis de suporte e resistência de forma resumida

Na maior parte do tempo, cotações de pares de moeda variam dentro de linhas suporte e resistência - este fato está no artigo de Gleb Slobodov, sobre como desenhar essas linhas. Como resultado, temos dois níveis horizontais que definem um intervalo de flutuações de preços. O rompimento de um deles, provavelmente, nos dá um sinal para comprar ou vender. No entanto, o princípio proposto tem várias desvantagens:

  • O número de barras analisados é selecionado manualmente e esse parâmetro define uma variação de preço, ou seja, o valor dos níveis de suporte e resistência.
  • O processo de elaboração dos níveis não é totalmente automatizado, eliminando a possibilidade de criar um sistema de trading automatizado.
  • Usando esse método, obtemos níveis horizontais que não nos permitem analisar a direção e a força da tendência.

O indicador de níveis de suporte e resistência utilizados na estratégia de negociação de Igor Gerasko também define níveis horizontais.

Neste artigo, quero apresentar a vocês o princípio de desenhar linhas de suporte e resistência, permitindo determinar a direção da tendência, formação de figuras e modelos de tendência. As linhas são desenhadas com base nas mínimas e máximas dos pontos extremos.


Princípio para encontrar os extremos

Determinar os preços máximos e mínimos num período de tempo não apresenta qualquer dificuldade. É importante escolher o comprimento do gráfico analisado (intervalo de tempo), que está em constante mutação e, portanto, não pode ser definido manualmente. Para encontrar esta seção do gráfico de moeda, vou usar o indicador Índice de Força Relativa (RSI), que está incluído no conjunto padrão de indicadores do terminal MetaTrader 5.

Níveis sobrecomprados e sobrevendidos são determinados de acordo com os níveis do indicador RSI. Nesses momentos, o gráfico do nosso par de moeda desvia sua direção (tendência), levando a uma reversão do preço. Especificamente aqui nosso extremo será formado, nestas lacunas que serão procurados as máximas e mínimas dos preços.

Como um nível sobrevendido, pego o valor do indicador RSI igual a 35; nível sobrecomprado - 65 (níveis superiores e inferiores são igualmente posicionados no meio da RSI = 50). O período de indicador RSI é igual a 8.

Ocorre muitas vezes durante uma forte tendência, por exemplo, numa tendência crescente, o RSI repetidamente atravessa o nível superior, mas não consegue alcançar o fundo. Isto leva a uma necessidade de ajuste do nível, que não corresponde à direção da tendência.

Busca de pontos extremos

Fig.4. Zonas de pesquisa para barras extremas

Na figura acima, designei uma zona de pesquisa para barras extremas: primeiro, segundo, terceiro e quarto lugar respectivamente, com os números 1, 2, 3 e 4. Antes de cruzar um limite de baixa (RSI = 35), o indicador RSI, começando da barra atual, está incluído na zona sobrecomprada (RSI >= 65), portanto haverá três intervalos de tempo para procurar o primeiro extremo. As zonas de pesquisa estão sendo determinadas para consequentes três barras.

Nas zonas 1 e 3, irá a procura de barras com preços mais altos e nas zonas 2 e 4 para os preços mais baixos. Como resultado, obteremos 4 pontos extremos — combinando-os com os raios, teremos o canal de preço ascendente.

Fig.5. Canal ascendente

Fig.5. Canal ascendente

Se você prestou atenção, você provavelmente observou que havia apenas algumas barras para pesquisa de preços mínimos, somente 4 (2 para cada zona). Devido a tendência predominante, o indicador RSI mal tocou o nível mínimo, fora do RSI = nível 65, o indicador praticamente andou dentro do canal 35 < RSI < 65. Portanto, o código do indicador, que apresentarei neste artigo para encontrar os pontos № 2 e 4, usará o nível RSI deslocado para o meio (no sentido do nível 50). Dependendo de qual foi o primeiro extremo (máxima ou mínima), será definido o nível da máxima ou mínima do RSI.

Todos os pares de moedas, todos os períodos do nível RSI do valor de gráfico e os subsequentes desvios, são selecionados experimentalmente. Considero que isso seja uma desvantagem do meu sistema para a determinação dos extremos.


Função para encontrar a barra extrema com o índice mais baixo (primeira barra) Ext_1

A função para encontrar barras extremas, que chamei de "Ext_1", tem os seguintes parâmetros de entrada:

int Ext_1(double low,      //mínima do nível RSI, nível sobrebvendido
          double high,     //máxima do nível RSI, nível sobrecomprado
          int bars,        //número de barras analisadas, para evitar copiar dados desnecessários
                           //possibilidade para definir barras = 300
          int h_rsi,       //handle do indicador RSI
          string symbol,   //símbolo do gráfico
          float distans,   //distância do desvio de um dos níveis do indicador
                           //permite definir limites de busca da primeira extremidade de barra 
          ENUM_TIMEFRAMES period_trade) //período do gráfico

Os dois primeiros parâmetros de entrada da função são os parâmetros do indicador RSI. Eles não desempenham nenhum papel no cálculo da linha de indicador e são usados apenas para conveniência na avaliação visual do valor (localização da linha do indicador no que diz respeito aos níveis informados). Eu uso estes níveis para determinar intervalos de preço, entre os quais irei procurar os valores mínimo e máximo. Parâmetros "low" e "high" obtém valores de variáveis externas relevantes definidas no código do indicador no nível global:

input double Low_RSI = 35.0; // Mínima do nível RSI para procurar os extremos
input double High_RSI= 65.0; // Máxima do nível RSI para procurar os extremos

O parâmetro de entrada "bars" define o número de elementos copiados para os "arrays" contendo as Máximas e Mínimas das barras, bem como os valores do indicador RSI:

double m_rsi[],m_high[],m_low[];                              //inicialização dos arrays
int h_high = CopyHigh(symbol, period_trade, 0, bars, m_high); //preenche o array das máximas dos preços das velas
int h_low = CopyLow(symbol, period_trade, 0, bars, m_low);    //preenche o array das mínimas dos preços das velas
if(CopyBuffer(h_rsi, 0, 0, bars, m_rsi)<bars)                 //preenche a lista com os dados do indicador RSI
{
   Print("Falha ao copiar o buffer do indicador!");
}

Os arrays m_rsi[],m_high[] and m_low[] tem ordem inversa de indexação:

ArraySetAsSeries(m_rsi,true); 
ArraySetAsSeries(m_high,true); 
ArraySetAsSeries(m_low,true);

Como eu disse anteriormente, com prevalência de uma tendência de alta, a linha do indicador RSI, que tem uma escala de valores de 0 a 100, na maioria das vezes terá um valor > 50. Às vezes quando o ponto mínimo é formado, o valor do RSI será menos remoto a partir do centro (50) do que durante a formação do ponto máximo. Portanto, no primeiro cruzamento de um dos valores do indicador (máxima ou mínima), outro valor tem de ser deslocado mais para o meio. A magnitude do desvio é determinada pelo parâmetro de entrada "distans", que é dado o valor por uma variável externa:

input float Distans=13.0;    // Nível de desvio do RSI

O parâmetro de entrada "h_rsi" da função "Ext_1" obtém o valor do "handle" do RSI, obtido durante a inicialização do indicador com função iRSI():

h_RSI=iRSI(Trade_Symbol,Period_Trade,Period_RSI,PRICE_CLOSE);  //retorna o handle do indicador RSI

As variáveis Trade_Symbol e Period_Trade são inicializadas no nível global e contêm informações sobre o par de moeda e o período gráfico, respectivamente. A variável Period_RSI contém o valor do período do indicador RSI especificado nos parâmetros externos do meu indicador:

input uchar Period_RSI =8;   // Período RSI

Uma vez que criamos e preenchemos o "array" contendo as maximas e mínimas dos preços das barras, bem como o valor do indicador RSI, correspondente a estas barras, você pode prosseguir para a pesquisa real do primeiro extremo. A fim de determinar onde estará o primeiro extremo (linha de suporte ou resistência) e parar a barra de análise no momento certo, são necessárias duas variáveis do tipo boleana:

bool ext_max = true;    //variáveis do tipo boleana são utilizadas com objetivo de parar
bool ext_min = true;    //a análise da barra no tempo certo

O valor ext_max = verdadeiro permite a busca de extremo máximo, o valor ext_min = verdadeiro, respectivamente, permite a pesquisa de extremo mínimo. Na primeira intersecção do indicador RSI com um dos níveis (máxima ou mínima), o valor de uma das variáveis boleana é alterado para falso, e o nível do cruzamento do RSI, cuja análise de barra é desativada, significando que o número necessário de barras foi analisado e o primeiro extremo foi encontrado. 

Se, ao analisar a primeira barra, o valor do indicador RSI está fora de um dos seus níveis, é provável que a formação da faixa de preço, na qual o extremo tem de ser procurado, ainda não está completa e não existe nenhum ponto para analisar. A análise de tais barras deve ser excluída. Na figura abaixo eu destaquei a faixa de preço em que a análise não é realizada (observe a posição da linha do indicador RSI em relação ao nível superior):

Desativada a análise na faixa de preço incompleta

Fig.6. Desativada a análise na faixa de preço incompleta

Para implementar tal operação, é necessário criar outra variável do tipo boleana:

bool flag=false;

Para determinar os preços máximos e mínimos entre as barras analisadas, é necessário criar as seguintes variáveis adicionais do tipo double:

double min = 100000.0;  //variável para identificar preços máximos e mímimos
double max = 0.0;       //...

O loop inteiro para busca de barras com o primeiro extremo será o seguinte:

for(int i=0;i<bars;i++) //loop de barra
{
   double rsi = m_rsi[i];                                   //Obtém o valor do indicador RSI
   double price_max = NormalizeDouble(m_high[i], digits);   //Preços altos
   double price_min = NormalizeDouble(m_low[i], digits);    //Preços baixos da barra selecionada
   if(flag==false) //condição para evitar buscas dos extremos em tendência incompleta
   {
      if(rsi<=low||rsi>=high) //se a primeira barra está em zona supercomprada ou sobrevendida
         continue;            //então mova para a próxima barra
      else flag = true;       //se não, siga com a análise
   }
   if(rsi<low) //se encontrar um cruzamento do RSI com nível mínimo
   {
      if(ext_min==true) //se o RSI não cruzou o nível máximo
      {
        if(ext_max==true) //se a busca por extremos de máximas não estiver desabilitada
        {
           ext_max=false;     //então desabilite a busca de extremos de máxima
           if(distans>=0) high=high-distans; //muda o nível máximo, em seguida
        }                                    //a busca da segunda barra é executada
        if(price_min<min) //busca e memoriza o índice da primeira barra
        {                 //comparando as minimas de preços das velas
           min=price_min;
           index_bar=i;
        }
      }
      else break; /*Loop de saída desde que a busca dos extremos mínimos já estiver desabilitada, 
                    isso significa que o máximo foi encontrado*/
   }
   if(rsi>high) //Além disso, o algoritmo é o mesmo, apenas pesquisa o extremo máximo
   {
      if(ext_max==true)
      {
        if(ext_min==true)
        {
           ext_min=false;
           if(distans>=0) low=low+distans;
        }
        if(price_max>max)
        {
           max=price_max;
           index_bar=i;
        }
      }
      else break; /*Loop de saída desde que a busca dos extremos máximos já estiver desabilitada,
                    isso significa que o mínimo foi encontrado*/
   }
}

Função geral para encontrar todos os extremos subseqüentes Ext_2

Esta função irá receber os mesmos parâmetros de entrada que a função Ext_1, além de três outros parâmetros importantes:

  1. O parâmetro que contém uma referência a uma estrutura onde os índices das barras extremas serão salvas. É necessário determinar em qual índice da barra a procura de extremos começará.
  2. O número de série da barra no extremo que tem de ser encontrado (leva valores de 2 a 4). É necessário escolher o índice da barra desejada a partir da estrutura, bem como determinar em qual a linha (suporte ou resistência) o extremo desejado será localizado.
  3. O parâmetro de tipo boleano que determina em qual linha (suporte ou resistência) a primeira barra extrema está localizada. Sem esta informação, é impossível determinar em qual linha a barra desejada deve ser localizada com base no número de série.
int Ext_2(double low,    //mínima do nível RSI, nível sobrebvendido
          double high,   //máxima do nível RSI, nível sobrecomprado
          int bars,      //número de barras analisadas, para evitar copiar dados desnecessários dentro dos arrays
          int h_rsi,     //handle do indicador RSI
          string symbol, //símbolo do gráfico
          st_Bars &bars_ext,//estrutura contendo códigos das barras encontradas
          char n_bar,    //número ordinal da barra necessária para pesquisa (2,3 ou 4)
          float distans, //distância do desvio de um dos níveis do indicador

          bool first_ext,//tipo da primeira barra
          ENUM_TIMEFRAMES period_trade)//período do gráfico

A nível global, nós criamos um tipo de estrutura que irá conter os índices de todas as 4 barras extremas:

struct st_Bars //inicialização da estrutura
  {
   int               Bar_1;
   int               Bar_2;
   int               Bar_3;
   int               Bar_4;
  };

st_Bars Bars_Ext; //declaração da variável do tipo estrutura

Para determinar a linha do indicador onde o extremo desejado será localizado, primeiramente duas variáveis do tipo boleana precisam ser criadas:

bool high_level= false; //variáveis para determinar o tipo das barras desejadas
bool low_level = false; //...

Se o número ordinal da barra extrema desejada é igual a 2 ou 4,e ainda, a primeira barra extrema situa-se na linha de suporte, a barra desejada deve estar na linha de resistência e, portanto, é necessário analisar as barras, cujo valor do RSI é maior ou igual a nível superior (parâmetro máximo). Se o número ordinal da barra extrema desejada é igual a 3, e ainda, a primeira barra de extremo está localizado na linha de suporte, então a barra desejada também será localizado nesta linha. Se a primeira barra de extremo está na linha de resistência, a posição da barra desejada é escolhida em conformidade.

if(n_bar!=3)
{
   if(first_ext==true)//se o primeiro ponto foi o n máximo
   {
      low_level=true;//então este deve ser mínimo
      if(distans>=0) low=low+distans; //se necessário, desloca o nível mínimo do RSI
   }
   else //se mínimo
   {
      high_level = true;
      if(distans>=0) high=high-distans; //se necessário, desloca o nível máximo do RSI
   }
}
else
{
   if(first_ext==false)//se o primeiro ponto foi mínimo
   {
      low_level=true;//então este ponto tem que ser mínimo
      if(distans>=0) high=high-distans; //se necessário, desloca o nível máximo do RSI
   }
   else //se máximo
   {
      high_level = true;
      if(distans>=0) low=low+distans; //se necessário, desloca o nível mínimo do RSI
   }
}

Outra variável do tipo boleana é necessária para determinar o momento em que o extremo desejado será encontrado e a análise de barras pode ser parada.

bool _start = false;    

O valor dessa variável é alterado para verdadeiro, quando encontrarmos o intervalo necessário das barras para análise na histórico. A análise de barras é terminada, se _start = verdadeiro e quando low_level = verdadeiro, a linha de indicador RSI cruza o nível máximo e se high_level = verdadeiro, a linha de indicador RSI cruza o nível mínimo.

if(_start==true && ((low_level==true && rsi>=high) || (high_level==true && rsi<=low)))
  break; //saída do loop se o segundo extremo é encontrado, e o RSI cruzar o nível oposto

O loop para pesquisa de barra extrema será o seguinte:

for(int i=bar_1;i<bars;i++) //analisa as barras restantes
{
   rsi=m_rsi[i];
   price_max = NormalizeDouble(m_high[i], digits);
   price_min = NormalizeDouble(m_low[i], digits);
   if(_start==true && ((low_level==true && rsi>=high) || (high_level==true && rsi<=low)))
   {
      break; //saída do loop se o segundo extremo é encontrado e o RSI cruza o nível oposto
   }
   if(low_level==true) //se estiver procurando por extremo de mínima
   {
      if(rsi<=low)
      {
         if(_start==false) _start=true;
         if(price_min<min)
         {
            min=price_min;
            index_bar=i;
         }
      }
   }
   else //se estiver procurando por extremo de máxima
   {
      if(rsi>=high)
      {
         if(_start==false) _start=true;
         if(price_max>=max)
         {
            max=price_max;
            index_bar=i;
         }
      }
   }
}

A variável Bar_1 contém o índice da barra extrema anterior, que é calculado usando o operador "switch":

switch(n_bar) //encontra o índice da barra anterior
{
   case 2: bar_1 = bars_ext.Bar_1; break;
   case 3: bar_1 = bars_ext.Bar_2; break;
   case 4: bar_1 = bars_ext.Bar_3; break;
}

Para descobrir em qual linha do indicador (suporte ou resistência) a primeira barra extrema está localizada, é suficiente obter o índice e o valor do indicador RSI na barra com o índice obtido:

bool One_ext (st_Bars & bars_ext, // variável do tipo estrutura para obter o índice da primeira barra
             string symbol,     //símbolo do gráfico
             int h_rsi,         //handle do indicador
             double low,        //determina o nível sobrevendido do RSI(nível máximo pode ser usado)
             ENUM_TIMEFRAMES period_trade) //período do gráfico
  {
   double m_rsi[];               //inicialização do array de dados do indicador
   ArraySetAsSeries(m_rsi,true); //indexando
   CopyBuffer(h_rsi,0,0,bars_ext.Bar_1+1,m_rsi); //preeche o array com os dados do RSI
   double rsi=m_rsi[bars_ext.Bar_1]; //define o valor do RSI na barra com o primeiro extremo
   if(rsi<=low)                      //se o valor está abaixo do nível mínimo
      return(false);                 //então o primeiro extremo é mínimo
   else                              //se não,
   return(true);                     //então máximo
  }

Processando os resultados

Agora sabemos que os índices de todas as quatro barras e seus preços correspondentes (maxima ou mínima). Para preencher os "arrays" que combinarão o valor das linhas de indicador em cada barra é necessário obter as equações de duas linhas correspondentes as linhas de resistência e suporte. A equação da reta bem conhecida (linha) usada para essa finalidade é: y = kx + b. No nosso caso, "x" é um índice da barra e "y" é um preço (para linha suporte - mínima do preço da vela preço, para a linha de resistência - máxima do preço da vela).

Para encontrar os valores dos coeficientes "k" e "b", substitua os valores correspondentes de duas barras extremas conhecidas na equação de linha, então combine as expressões obtidas no sistema de equações. Como resultado, obtemos as seguintes expressões no sistema:

K=(price_2-price_1)/(_bar2-_bar1);  //encontra o coeficiente K
B=price_1-K*_bar1;                  //encontra o coeficiente B

Onde

double K,B;

"K" e "B" são variáveis globais que correspondem aos valores dos coeficientes "k" e "b" na equação de linha;

int _bar1,_bar2;

Estes são índices de barras localizados na mesma linha;

double price_1,price_2;

Estes são os preços baixos das respectivas barras, se deve definir as linhas de suporte "K" e "B" ou o preço alto das respectivas barras, você precisa determinar o "K" e "B" para a linha de resistência.

A função abaixo apresentada preenche os valores da variáveis globais "K" e "B" para a linha suporte com o parâmetro "_line" sendo falso; para a linha de resistência, se o parâmetro "_line" for verdadeiro:

void Level(bool _line,              //parâmetro que define a linha resistência/suporte, cujos coeficientes tem de ser encontrados
           bool _first_ext,         //tipo do primeiro extremo (já familiar para você)
           st_Bars &bars_ext,       //estrutura que contém índices das barras
           string _symbol,          //símbolo
           ENUM_TIMEFRAMES _period) //período do gráfico
  {
   int bars=Bars_H;           //número de barras analisadas
   double m_high[],m_low[];         //inicialização dos arrays
   ArraySetAsSeries(m_high,true);   //arrays são indexados a partir do primeiro elemento
   ArraySetAsSeries(m_low,true);    //...
   int h_high = CopyHigh(_symbol, _period, 0, bars, m_high); //preenche o array com as máxímas dos preços das velas
   int h_low = CopyLow(_symbol, _period, 0, bars, m_low);    //preenche o array com as mínimas dos preços das velas
   double price_1,price_2;
   int _bar1,_bar2;
   int digits=(int)SymbolInfoInteger(_symbol,SYMBOL_DIGITS);//número de casas decimais no símbolo atual
   if(_line==true)                                          //se a linha de resistência for necessária
     {
      if(_first_ext==true) //se o primeiro extremo é máximo
        {
         price_1 = NormalizeDouble(m_high[bars_ext.Bar_1], digits);
         price_2 = NormalizeDouble(m_high[bars_ext.Bar_3], digits);
         _bar1 = bars_ext.Bar_1;
         _bar2 = bars_ext.Bar_3;
        }
      else                                                  //se mínimo
        {
         price_1 = NormalizeDouble(m_high[bars_ext.Bar_2], digits);
         price_2 = NormalizeDouble(m_high[bars_ext.Bar_4], digits);
         _bar1 = bars_ext.Bar_2;
         _bar2 = bars_ext.Bar_4;
        }
     }
   else                                                     //se a linha suporte é necessária
     {
      if(_first_ext==true) //se o primeiro extremo é de máxima
        {
         price_1 = NormalizeDouble(m_low[bars_ext.Bar_2], digits);
         price_2 = NormalizeDouble(m_low[bars_ext.Bar_4], digits);
         _bar1 = bars_ext.Bar_2;
         _bar2 = bars_ext.Bar_4;
        }
      else                                                  //se mínimo
        {
         price_1 = NormalizeDouble(m_low[bars_ext.Bar_1], digits);
         price_2 = NormalizeDouble(m_low[bars_ext.Bar_3], digits);
         _bar1 = bars_ext.Bar_1;
         _bar2 = bars_ext.Bar_3;
        }
     }
   K=(price_2-price_1)/(_bar2-_bar1);  //encontra o coeficiente K
   B=price_1-K*_bar1;                  //encontra o coeficiente B
  }

A equação da linha é: y = kx + b, onde o preço do instrumento financeiro é usado para o eixo "y" e índice da barra para eixo "x". Se para "x" usamos o número de segundos desde 1 de janeiro de 1970, o gráfico de linhas na área do dia em "off" terá um resultado "caótico", motivo pelo qual eu usei as barras de índice.

A partir da função "OnCalculate", a função "level" é chamada duas vezes: pela primeira vez antes de preecher o "array" para a linha de resistência, e a segunda vez para preencher o "array" com valores de preço para a linha de suporte:

for(int i=0;i<Bars_H;i++)
{
   resistanceBuffer[i]=NormalizeDouble(K*i+B,Dig);
}
Level(false,First_Ext,Bars_Ext,Trade_Symbol,Period_Trade); //obtém os coeficientes K e B para a linha de resistência
for(int i=0;i<Bars_H;i++)
{
   supportBuffer[i]=NormalizeDouble(K*i+B,Dig);
}

Exemplo do indicador exibindo os níveis de suporte e resistência

O resultado da operação do indicador que usa todas as funções acima e desenha as linhas suporte e resistência é o seguinte:

O resultado da operação do indicador

Fig.7. O resultado da operação do indicador

O indicador é construído de tal forma que, após a formação de uma nova barra de extremo, os valores do "array" de linhas suporte e resistência podem ser alterados, então os níveis serão automaticamente redesenhados. No entanto, se calcularmos e memorizarmos o ângulo de uma das linhas para o eixo de tempo do gráfico e então compará-lo com o novo ângulo da mesma linha, é possível concluir se a tendência está em aceleração e desaceleração, como já mencionado neste artigo.

O código completo do indicador está no arquivo anexado a este artigo.


Conclusão

Certamente que é muito mais fácil de construir estas linhas manualmente, pois não é necessário selecionar os parâmetros do indicador para cada símbolo e o período. No entanto, este indicador pode servir como uma base ou parte da estratégia de sistema de negociação automático. Após receber um array de dados das linhas do indicador, você pode analisar o ângulo de inclinação, a direção da tendência, bem como identificar a forma gráfica formada por estas linhas. Tudo isso, em última análise, torna possível analisar a intensidade do sinal de compra ou venda, operar dentro do canal de preços, bem como o rompimento das linhas suporte e resistência.