English Русский 中文 Español Deutsch 日本語 한국어 Français Italiano Türkçe
Como escrever um indicador na base de um outro indicador

Como escrever um indicador na base de um outro indicador

MetaTrader 5Exemplos | 26 dezembro 2013, 15:31
4 816 0
Dmitry Fedoseev
Dmitry Fedoseev

Introdução

No MQL5 além da criação de um novo indicador personalizado a partir do zero, conforme descrito no artigo "MQL5: Crie seu próprio indicador", você pode escrever um indicador se baseando em outro, embutido na plataforma do cliente, ou um personalizado. Existem duas maneiras: a primeira é aprimorar um indicador, adicionar novos cálculos e planos (esta variante se aplica apenas aos indicadores personalizados que possuem código-fonte aberto), a segunda maneira é usar um indicador embutido na plataforma ou usar um indicador personalizado através das funções iCustom() ou IndicatorCreate().

Primeira maneira. Adicionando um plano

Vamos considerar esta forma de criação de um indicador em detalhes no exemplo de aprimoramento do indicador Índice de Força Verdadeira_ver3 do artigo "Aplicando um Indicador a Outro". Vamos adicionar uma linha de sinal com uma possibilidade de escolha do tipo e período de nivelamento para o indicador. O processo inteiro consiste em 8 fases.

1. Fazendo a cópia do arquivo

Abra o indicador True_Strength_Index_ver3 no MetaEditor e salve-o com um novo nome, por exemplo, TSIs. O novo arquivo deve ser salvo no diretório MQL5/indicador da pasta raiz do terminal.

2. Mudando as propriedades do indicador

Procure as propriedades do indicator_buffers e indicator_plots no código do indicador. A propriedade indicator_buffers determina o número total de indicadores de memória de armazenamento (buffer) usados no indicador, a propriedade indicator_plots - o número de memórias de armazenamento (buffers) mostradas em um gráfico. Atualmente oito memórias de armazenamento (buffers) são usadas no indicador; uma delas é mostrada em um gráfico. Precisamos adicionar uma outra memória de armazenamento (buffer) que deve ser mostrada em um gráfico. Aumente os valores do indicator_buffers e do indicator_plots por um.

#property indicator_buffers 8 
#property indicator_plots 2

3. Determinando as propriedades de exibição da nova memória de armazenamento (buffer)

Configure as propriedades de exibição da nova memória de armazenamento (buffer). Use o código já preparado deste indicador. Usando o mouse, copie todo o código que determina as propriedades de exibição da primeira linha do indicador.

//---- plot TSI
#property indicator_label1 "TSI"
#property indicator_type1 DRAW_LINE
#property indicator_color1 Blue
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1

Insira-o abaixo das propriedades da primeira linha e modifique-o.

//---- plot TSI Signal
#property indicator_label2 "TSISignal" // Line name that is displayed in a pop up help when the mouse cursor is put over the line
#property indicator_type2 DRAW_LINE    // Type of buffer 
#property indicator_color2 Red         // Color of the line
#property indicator_style2 STYLE_SOLID // Style
#property indicator_width2 1           // Thickness of the line

Primeiramente, mude o número das propriedades de 1 para 2 porque esta é a propriedade para a segunda memória de armazenamento (buffer). Mude a propriedade do indicator_label2 para TSISignal - este é o nome da linha que é mostrada em uma janela de ajuda quando o cursor do mouse é colocado sobre a linha assim como o exibido na janela de dados. A propriedade indicator_type2 não deve ser modificada, a memória de armazenamento (buffer) deve ser exibida como uma linha. Modifique a propriedade indicator_color2 para Vermelho - a nova linha terá a cor vermelha. A propriedade indicator_style2 continua a mesma - a linha de sinal é sólida como a linha principal. A propriedade indicator_width2 também deve continuar a mesma - a nova linha terá 1 pixel de espessura.

4. Declarando as variáveis externas

As variáveis externas que podem ser trocadas através do indicador (linhas que começam com a palavra "input") são localizadas abaixo das propriedades das linhas no código. A linha de sinal também deve ter seus parâmetros - período e tipo de nivelamento.

Declare uma variável externa do tipo int com valor 5 e a nomeie "sp" (período de nivelamento), e uma variável do tipo ENUM_MA_METHOD de nome "sm" (método de nivelamento) com valor MODE_EMA (a linha de sinal terá período de nivelamento 5 e tipo de nivelamento exponencial predefinido). Agora as seções do código que contém as variáveis externas aparecem a seguir:

input int r=25;
input int s=13;
input int sp=5;
input ENUM_MA_METHOD sm=MODE_EMA;

5. Declarando um arranjo para um nova memória de armazenamento (buffer)

Vamos definir um arranjo que será usado pela memória de armazenamento (buffer) do indicador. Procure pela função OnInit() no código e encontre onde as ativações da função SetIndexBuffer() estão localizadas para se guiar através dos arranjos das memórias de armazenamento (buffer) do indicador já existentes no indicador. No indicador True_Strength_Index_ver3 os arranjos são TSIBuffer, MTMBuffer, AbsMTMBuffer, EMA_MTMBuffer, EMA2_MTMBuffer, EMA_AbsMTMBuffer, EMA2_AbsMTMBuffer.

A função SetIndexBuffer() do arranjo TSIBuffer é ativado com o parâmetro INDICATOR_DATA, isto significa que a memória de armazenamento (buffer) é mostrada no gráfico. Todas os outros arranjos são ativados com o parâmetro INDICATOR_CALCULATIONS. Isso significa que os arranjos são auxiliares e são usados para cálculos intermediários.

A nova memória de armazenamento (buffer) deve ser mostrada em um gráfico, então vamos ativá-la após a definição do arranjo TSIBuffer para manter a ordem lógica e para uma orientação mais fácil no código no caso de um futuro aprimoramento do indicador.

Assim, primeiro definimos dois arranjos para as memórias de armazenamento (buffers) que são mostrados em um gráfico, então os arranjos para as memórias de armazenamento (buffers) que são usados para os cálculos intermediários.

//--- indicator buffers
double TSIBuffer[];
double TSISigBuffer[]; // Array for new buffer of the signal line
double MTMBuffer[];
double AbsMTMBuffer[];
double EMA_MTMBuffer[];
double EMA2_MTMBuffer[];
double EMA_AbsMTMBuffer[];
double EMA2_AbsMTMBuffer[]; 

6. Associando um arranjo a uma memória de armazenamento (buffer)

Este é um passo muito importante que exige mais atenção e cuidado - associação de um arranjo a uma memória de armazenamento (buffer) do indicador. A associação é realizada utilizando a função SetIndexBuffer(). O primeiro parâmetro na ativação da função é o índice do arranjo; o segundo é o nome do arranjo; o terceiro - o identificador que indica a finalidade da memória de armazenamento (buffer). As memórias de armazenamento (buffers) são localizadas pelas cores da guia da janela Propriedades do indicador de acordo com o índice (o primeiro parâmetro), na mesma ordem eles são traçados em um gráfico, o primeiro é a memória de armazenamento (buffer) 0, então memória de armazenamento (buffer) 1 sobre ela, etc.

Não é necessário a função SetIndexBuffer() ser ativada em sequência pelas memórias de armazenamento (buffers) com índices 0, 1, 2,..., entretanto, vamos manter a ordem das ativações das funções SetIndexBuffer(). Execute a ativação do arranjo TSISigBuffer após ativar a função para o arranjo TSIBuffer. A memória de armazenamento (buffer) da linha principal (o arranjo TSIBuffer) tem índice 0, isto significa que a memória de armazenamento (buffer) (o arranjo TSISigBuffer) deverá ter índice 1.

O terceiro parâmetro de ativação da função SetIndexBuffer() para o arranjo TSISigBuffer é a constante INDICATOR_DATA (memória de armazenamento (buffer) é exibida em um gráfico).

SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);

Crie os índices do restante das memórias de armazenamento (buffers) para a função SetIndexBuffer() a ser chamada com o valor do primeiro parâmetro aumentado sequencialmente.

SetIndexBuffer(0,TSIBuffer,INDICATOR_DATA);
SetIndexBuffer(1,TSISigBuffer,INDICATOR_DATA);
SetIndexBuffer(2,MTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,AbsMTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(4,EMA_MTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(5,EMA2_MTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(6,EMA_AbsMTMBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(7,EMA2_AbsMTMBuffer,INDICATOR_CALCULATIONS);

Para esta situação específica é recomendado manter a sequência de chamada da função SetIndexBufer() de acordo com o aumento dos índices. Assim, no caso de futuros aprimoramentos será necessário menos atenção e trabalho.

Agora temos oito memórias de armazenamento (buffers), duas delas são mostradas em um gráfico. Certifique-se de que os valores estão especificados nas propriedades dos indicadores indicator_buffers e indicator_plots (passo 2).

7. Calculando os valores da linha de sinal

A linha de sinal representa um desenho da média móvel nos dados da linha principal do indicador. Não precisamos fazer qualquer cálculo para isso; a entrega da plataforma do cliente inclui uma biblioteca de cálculos das médias móveis em um arranjo de informação (arquivo MovingAverages.mqh). A propósito, já está incluso no código do indicador (linha 14):

#include 

A única coisa a fazer é usar seus recursos.

Na função OnCalculate() encontre um ponto onde os cálculos da linha principal do indicador são finalizados (o arranjo TSIBuffer). Vamos usar a função de busca; selecione o nome do arranjo TSIBuffer, por exemplo, na parte do código onde está definido (fig. 1). Então execute o comando "Menu Principal" - "Editar" - "Pesquisar e substituir" - "Pesquisar" ou use a combinação de teclas Ctrl+F.


Fig. 1. Nome do arranjo selecionado

A palavra "TSIBuffer" já será digitada no campo "Pesquisar o que" da janela "Pesquisar" aberta. Selecione "Para cima" na seção "Direção". Agora, quando a janela "Find" estiver aberta, coloque o cursor logo após a função OnCalculate(), pressione o botão "Pesquisar Próxima" uma vez e você vai encontrar o local onde os cálculos do arranjo TSIBuffer são concluídos imediatamente. Os cálculos são efetuados no ciclo "for". Adicionaremos o código para cálculo da linha de sinal logo após este ciclo (fig. 2).


A última localização encontrada do cálculo do valor TSIBuffer (arranjo vermelho) O ciclo onde os cálculos são efetuados é marcado com um quadro vermelho
Fig. 2. A última localização encontrada do cálculo do valor TSIBuffer (arranjo vermelho) O ciclo onde os cálculos são efetuados é marcado com um quadro vermelho

As funções para cálculo dos quatro tipos principais de médias móveis estão inclusas na biblioteca MovingAverages.mqh:

  • Para a simples - SimpleMAOnBuffer(),
  • Para a exponencial - SimpleMAOnBuffer(),
  • Para a ponderação linear - LinearWeightedMAOnBuffer(),
  • Para a nivelada - SimpleMAOnBuffer().

Todas essas funções tem o mesmo conjunto de parâmetros:

const int rates_total, const int prev_calculated, const int begin, const int period, const double& price[],double& buffer[]

O parâmetro de preço[] da função determina um arranjo com os dados iniciais, o cálculo de uma média móvel será efetuado. O parâmetro da memória de armazenamento (buffer) é o arranjo que irá armazenar os valores de média móvel. Os parâmetros rates_total e prev_calculated são iguais aos parâmetros rates_total e prev_calculated da função onCalculate(), eles determinam o tamanho do arranjo de preço[] e o número de elementos já processados do arranjo. O parâmetro begin é o índice de um elemento do arranjo a partir do qual os dados significativos começam.

Considerando as peculiaridades dos algoritmos de cálculo das médias móveis na biblioteca MovingAverages.mqh (estas características não são pertinentes ao tema deste artigo), precisamos de uma abordagem cuidadosa para a configuração do parâmetro begin.

Este parâmetro em qualquer caso não deve ser estabelecido para um elemento anterior do arranjo a não ser aquele em que o valor dos dados de origem tem início (o arranjo TSIBuffer). É permitido especificar um elemento posterior se ele não causar erros nos cálculos.

Para determinar um valor aceitável de begin, fique atento aos parâmetros do for cycle, onde os valores do arranjo TSIBuffer são calculados - o ciclo começa a partir do valor da variável start. Precisamos descobrir o valor da variável start durante o primeiro cálculo do indicador (quando o valor prev_calculated é igual a 0). O valor da variável "start" é calculado antes do ciclo, quando prev_calculated=0; o cálculo é realizado usando a seguinte fórmula:

start=begin+r+s-1;

O valor da variável begin que é passado para a função de cálculo de médias móveis deve ser igual àquele valor.

Após o ciclo de cálculo do arranjo TSIBuffer declare a variável begin2 e atribua o valor begin+r+s-1 a ela.

int begin2=begin+r+s-1; 

Para fornecer a possibilidade de usar funções diferentes de nivelamento dependendo do valor do parâmetro externo "sm", use o trocar operador. Para cada variante do valor da variável sm escreva a ativação da função correspondente.

switch(sm)
  {
   case MODE_EMA:
      ExponentialMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
   case MODE_LWMA:
      LinearWeightedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
   case MODE_SMA:
      SimpleMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
   case MODE_SMMA:
      SmoothedMAOnBuffer(rates_total,prev_calculated,begin2,sp,TSIBuffer,TSISigBuffer);
      break;
  }

Em seguida, podemos ver o indicador com a linha de sinal. Pressione o botão "Compile", abra a plataforma do cliente e anexe o indicador ao gráfico (fig. 3).



Fig. 3. Indicador TSIs, azul - linha principal, vermelho - nova, linha de sinal

8. Cortando o início de desenho da memória de armazenamento (buffer)

Se você mover o gráfico com o indicador para a margem esquerda, verá que o indicador traça linhas na parte para a qual os valores não foram calculados. Isso não aparenta bem (fig. 4).



Fig. 4. Desenho do indicador na parte onde os cálculos não foram efetuados.

Usando a função PlotIndexSetInteger() que é chamada com o identificador PLOT_DRAW_BEGIN determina o número das primeiras barras onde o memória de armazenamento (buffer) não é traçada. A ativação da função deveria ser efetuada de dentro da função OnInit() do indicador. Adicione a chamada da função ao final da OnInit(), mas antes da chamada do return(0), por via de regra.

PlotIndexSetInteger(1,PLOT_DRAW_BEGIN,r+s+sp);

Pressione o botão "Compile" novamente e obtenha o início correto do desenho do indicador (fig. 5).



Fig. 5. Início correto do desenho do indicador

Segunda maneira. Crie um novo indicador sobre a base de um existente


Consideraremos esta forma utilizando um exemplo da criação de um indicador de convergência e divergência das linhas principais e de sinal do indicador de TSIs. O indicador será traçado com um histograma e terá duas cores como os indicadores AO, AC. Se o valor do indicador aumentar, o histograma será colorido de verde; se diminuir, o histograma será colorido de vermelho. Como já mencionado acima na introdução, para se referir a outro indicador você pode usar as funções iCustom() ou IndicatorCreate(). Primeiro, vamos dar uma olhada na criação de um indicador usando a função iCustom().

Criando um indicador usando a função iCustom()


1. Criando um novo indicador

Vamos criar um novo indicador. Para criar um novo indicador no MetaEditor você deve executar o comando "Menu Principal" - "Arquivo" - "Novo" - "Indicador Personalizado" ou pressionar a combinação de teclas "Ctrl+N". No campo "Nome" na janela que aparecer especifique o nome do novo indicador - TSIsCDiCust, então pressione o botão "Adicionar". Adicione um parâmetro externo, seu nome não é tão importante quanto a determinação de uma parte para os parâmetros externos no código; mais adiante será mais fácil copiar todos os parâmetros externos a partir do indicador TSIs (fig. 6).


A primeira etapa da criação de um indicador personalizado no assistente.
Fig. 6. A primeira etapa da criação de um indicador personalizado no assistente

Pressione o botão "Próxima".

Na próxima janela especifique que o indicador será traçado em uma janela distinta. Não defina mínimo e máximo. Pressione o botão "Adicionar" e uma nova memória de armazenamento (buffer) irá aparecer na lista de memória de armazenamento (buffer) de indicador; especifique seu nome - TSIsCD (ele será exibido em uma janela de ajuda se você colocar o cursor do mouse sobre a linha do indicador e na janela de dados) e seu tipo - histograma de cor.

Em seguida vários exemplos de cores irão aparecer no campo "Color". Especifique a cor Verde para o primeiro exemplo, a cor Vermelha para o segundo e não altere os outros. Adicione mais duas memórias de armazenamento (buffers) nomeadas Tsi e TsiSignal, elas serão usadas para receber e armazenar valores do indicador TSIs (fig. 7).


A segunda etapa da criação de um indicador personalizado no assistente.
Fig. 7. A segunda etapa da criação de um indicador personalizado no assistente

Pressione o botão "Terminar" e o modelo do novo indicador será aberto no MetaEditor.

2. Editando as propriedades do indicador e as memórias de armazenamento (buffer) do indicador

Na etapa 1 determinamos 3 memórias de armazenamento (buffers); no entanto o valor da #property indicator_buffers é igual a 4. O fato é que um histograma colorido usa duas memórias de armazenamento (buffers) - uma é exibida em um gráfico e destinada aos valores de um indicador; e a segunda se destina a determinar a cor de exibição da primeiro memória de armazenamento (buffer). Deixe o valor #property indicator_buffers sem alteração. Modifique o valor #property indicator_plots para 1 - apenas uma memória de armazenamento (buffer) deve ser mostrado em um gráfico.

As memórias de armazenamento (buffers) Tsi e TsiSignal não devem ser exibidas em um gráfico, esta é a razão porque apagamos todas as suas propriedades (todas as propriedades do indicador que terminam em 2 e 3).

//--- plot Tsi
#property indicator_label2 "Tsi"
#property indicator_type2 DRAW_LINE
#property indicator_color2 Red
#property indicator_style2 STYLE_SOLID
#property indicator_width2 1
//--- plot TsiSignal
#property indicator_label3 "TsiSignal"
#property indicator_type3 DRAW_LINE
#property indicator_color3 Red
#property indicator_style3 STYLE_SOLID
#property indicator_width3 1
Na função OnInit() encontre as ativações da função SetIndexBuffer() para essas memórias de armazenamento (buffers) (os nomes dos arranjos são TsiBuffer e TsiSignalBuffer), mude o valor do terceiro parâmetro de INDICATOR_DATA para INDICATOR_CALCULATIONS.
SetIndexBuffer(2,TsiBuffer,INDICATOR_CALCULATIONS);
SetIndexBuffer(3,TsiSignalBuffer,INDICATOR_CALCULATIONS);

Modifique a propriedade indicator_color1 - deixe apenas as duas primeiras cores.

#property indicator_color1 Green,Red

3. Declarando os parâmetros externos

Abra o indicador TSIs no MetaEditor e copie todas as variáveis externas dele, substitua a atual variável externa Input1 por esses parâmetros.

//--- input parameters
input int r=25;
input int s=13;
input int sp=5;                 // Smoothing period
input ENUM_MA_METHOD sm=MODE_EMA; // Smoothing type

4. Declarando uma variável para o nome do indicador e chamando o indicador

Na seção comum do indicador declare uma variável do tipo int e a nomeie como Handle. Ative a função iCustom() na parte inferior do OnInit(). A função retorna o handle do indicador criado; precisamos dela para receber os valores do indicador. Atribua o valor retornado através da função para a variável Handle.

Os dois primeiros parâmetros da função iCustom() determinam o símbolo e o prazo que os dados serão usados para o cálculo do indicador. Vamos especificar um símbolo e um prazo aos quais o indicador está anexado - _Symbol e PERIOD_CURRENT. O terceiro parâmetro é o nome de um indicador personalizado; neste caso é TSIs. Todos os parâmetros externos do indicador ativado estão listados a seguir:

Handle=iCustom(_Symbol,PERIOD_CURRENT,"TSIs",r,s,sp,sm);

5. Preparando a função OnCalculate()

Vamos passar para função OnCalculate(). O indicador TSIs é calculado em uma memória de armazenamento (buffer) de dados, então vamos usar a primeira forma da função OnCalculate(). Modifique a segunda forma existente da função OnCalculate() no modelo para a primeira.

int OnCalculate(const int rates_total,         // size of the price[] array
                const int prev_calculated,   // bars processed during the previous call
                const int begin,             // from where the significant data begin
                const double &price[]        // array for calculation
                )
  {
   return(rates_total);
  }

O trabalho posterior no indicador será efetuado dentro desta função.

6. Determinando os limites do cálculo do indicador

A prioridade máxima e a importância no desenvolvimento de qualquer indicador é a determinação dos limites da variedade de barras processadas. No início do indicador, devemos efetuar o cálculo do indicador para cada barra, durante sua operação - apenas para cada uma que é atualmente formada. Você pode detectar o momento do início do indicador através do valor da variável prev_calculated. Se este valor for igual a zero, então esta é a primeira execução da função OnCalculate() desde o início do indicador.

À primeira execução da função OnCalculate() você deve determinar o índice da primeira barra a partir da qual os cálculos deverão iniciar. Seu valor é determinado pelo número de barras que são necessárias para o cálculo do valor do indicador (a indexação é efetuada da esquerda para a direita).

A inclinação da linha do indicador é determinada por duas barras, então precisaremos de uma barra prévia. A indexação de uma barra, a partir da qual os dados significativos do arranjo de preço[] começam é conhecida - é o valor da variável begin; então começamos o cálculo das barras a partir da barra start=begin+1.

Adiante, durante o trabalho do indicador, o índice de uma barra, o cálculo inicia a partir do que é determinado pelo valor da variável prev_calculated - esta variável contém o número de barras já processadas. Assim, para descobrir o índice da última barra para a qual os cálculos foram efetuados, você deve subtrair 1 da prev_calculated.

A última das barras já processadas será levada para cálculo novamente porque ela pode ser uma barra de formação. O limite do cálculo é determinado pelo tamanho do arranjo de preço[] - a variável rates_total. O índice da última barra para a qual os cálculos foram efetuados é igual a rates_total-1 (é menor que o tamanho do arranjo por um).

Uma vez que o indicador usa os dados de um outro indicador para seu cálculo, devemos obter esses dados. Você pode obter os dados de um outro indicador usando a função CopyBuffer(). No primeiro parâmetro da função você deve especificar o identificador de um indicador, os dados que deverão ser copiados (handle é obtido no estágio 4); no segundo parâmetro especifique um índice da memória de armazenamento (buffer) copiado (o valor necessário pode ser determinado através da guia "Color" das propriedades do indicador copiado, a contagem começa do zero).

O terceiro parâmetro é o índice de uma barra a partir da qual a contagem se inicia; neste caso, a indexação é efetuada da direita para a esquerda então a barra mais à direita é a zero. O quarto parâmetro é o número de elementos do arranjo a serem copiados. Você deve ter cuidado ao determinar o número de elementos copiados assim como ao determinar a variedade de barras incluídas no cálculo. Isto afeta o desempenho do indicador. Índice de uma barra, o cálculo do indicador começa a partir de sua preliminar determinada, então, o número de elementos copiados é calculado como rates_total-start. Durante o processo de trabalho, quando o indicador é calculado apenas para a barra de formação, apenas um elemento do arranjo é copiado.

Se as funções CopyBuffer() retornam -1 na tentativa de copiar informação, isso significa que os dados não podem ser copiados, então não existe razão para que os cálculos sejam efetuados. Esse erro deve ser trabalhado. Ao início da CopyBuffer() declare a variável estática do tipo bool e a nomeie "error". Se ocorrer um erro durante o processo de cálculo do indicador, particularmente o erro da cópia dos dados do indicador, atribua o valor verdadeiro a esta variável e finalize a execução da função OnCalculate().

Recalcule todo o indicador novamente no próximo tique se o valor do erro indicar que existe um erro durante a prévia execução da função OnCalculate(). Assim, o início da função OnCalculate() será o seguinte:

   static bool error=true; 
   int start;
   if(prev_calculated==0) // First execution of the OnCalculate() function after the indicator start
     {
      error=true; // Set the value True for the indicator to be calculated for all bars
     }
   if(error) // If value of error=true, then it is the first execution of the function after 
             // the start of the indicator, or there was an error of copying of data at the previous start
     {
      start=begin+1;
      error=false;
     }
   else
     {
      start=prev_calculated-1;
     }

   if(CopyBuffer(Handle,0,0,rates_total-start,TsiBuffer)==-1) // Copying data of main line of the indicator
     {
      error=true; // Failed to copy data, set the value True for the error variable to recalculate the whole 
                 // indicator at the next call of OnCalculate()
      return(0);  // End working of the function
     }
   if(CopyBuffer(Handle,1,0,rates_total-start,TsiSignalBuffer)==-1) // Copy data of the signal line of the indicator
     {
      error=true; // Failed to copy data, set the value true for the error variable to recalculate the whole
                 // indicator at the next call of the OnCalculate() function
      return(0);  // End working of the function
     }

Os limites de cálculo do indicador estão determinados, faça um loop dos cálculos nesta variedade de barras.

for(int i=start;i<rates_total;i++)
  {

  }

Calcule o valor do indicador (o código está localizado dentro do loop que acabou de ser criado).

TsiCDBuffer[i]=TsiBuffer[i]-TsiSignalBuffer[i];

Agora a parte mais importante - colorir a memória de armazenamento (buffer). Anteriormente no estágio 1 determinamos o uso de um histograma colorido para a memória de armazenamento (buffer) do indicador. Esse tipo de desenho exige duas memórias de armazenamento (buffers) - uma para o valor do indicador e outra para a cor. A lista de cores é configurada na propriedade indicator_color1. Quando o valor 0 é configurado para o elemento da memória de armazenamento (buffer), o indicador é exibido na cor verde; quando o valor 1 é configurado, o indicador é vermelho (de acordo com sua localização no indicator_color1 na lista; a numeração começa do zero).

Não é possível evitar uma situação quando os valores do indicador são iguais em duas barras adjacentes; nesse caso, o indicador deve ser exibido com as cores prévias (porque temos apenas duas cores para os movimentos de subida e descida). Assim, no início dos cálculos copiaremos o valor da memória de armazenamento (buffer) TsiCDColors na barra prévia:

TsiCDColors[i]=TsiCDColors[i-1];

Quando fizer o movimento para cima pinte o indicador com a cor Verde:

if(TsiCDBuffer[i]>TsiCDBuffer[i-1])TsiCDColors[i]=0;

Quando fizer o movimento para baixo pinte o indicador com a cor Vermelha:

if(TsiCDBuffer[i]<TsiCDBuffer[i-1])TsiCDColors[i]=1;

Esse é quase o final do trabalho com o indicador; falta determinar o início do desenho do indicador.

7. Completando o trabalho no indicador

Apesar da variável begin ser utilizada para determinar o cálculo do indicador, não significa que os dados do indicador comecem a partir da barra que está identificada com a variável begin. Se o algoritmo de um indicador personalizado não é conhecido, é quase impossível detectar o número de barras necessário para o cálculo do indicador. Essa é a razão pela qual este estágio pode ser ignorado ou você pode detectar o valor na base da experiência. De qualquer forma, sabemos o algoritmo do indicador TSIs, então podemos detectar exatamente o início do indicador. Adicione a chamada da função PlotIndexSetInteger() com o indicador PLOT_DRAW_BEGIN à função OnInit().

PlotIndexSetInteger(0,PLOT_DRAW_BEGIN,r+s+sp);

O indicador TSIs mostra os valores exatos para duas casas decimais; configure a mesma exatidão usando a função IndicatorSetInteger() com o identificador INDICATOR_DIGITS.

IndicatorSetInteger(INDICATOR_DIGITS,2);

Compile o indicador e o anexe em um gráfico (fig. 8).


Fig. 8. Indicador TSIsCDiCust

Criando um indicador usando a função IndicatorCreate()


A criação de um indicador usando a função IndicatorCreate() e mesma criação usando a função iCustom() exceto pelo estágio 4 - a função usada é a IndicatorCreate() ao invés da iCustom().

1. Salve uma cópia do indicador TSIsCDiCust sob o nome de TSIsCDiCreate.

2. Encontre o local onde a função iCustom() é ativada no código. A partir de agora a ativação da função IndicatorCreate() será efetuada no lugar da iCustom(). Assim como em iCustom(), os dois primeiros parâmetros da função IndicatorCreate() determinam um símbolo e o período de tempo em que serão usados para o cálculo do indicador. O terceiro parâmetro é um identificador do tipo do indicador, para um indicador personalizado é o IND_CUSTOM. Os parâmetros do indicador create são passados para a função utilizando o array de estruturas MqlParam.

O MqlParam contém quatro variáveis - três delas são variáveis de tipos diferentes usadas para valores: double_value, integer_value and string_value; e a outra é a type, ela determina o tipo de variável usada. O indicador TSIs possui quatro parâmetros externos. Desde que o indicador seja personalizado, o primeiro elemento do arranjo determina o nome do indicador personalizado, assim, o arranjo deve conter cinco elementos. Declare um arranjo de estruturas (o código é localizado onde a iCustom() era chamada):

MqlParam Params[5];

Preencha a arranjo com valores:

   Params[0].type=TYPE_STRING;
   Params[0].string_value="TSIs"; // Specify name of the called custom indicator in the first parameter
   
   Params[1].type=TYPE_INT;
   Params[1].integer_value=r;
   
   Params[2].type=TYPE_INT;
   Params[2].integer_value=s;   
   
   Params[3].type=TYPE_INT;
   Params[3].integer_value=sp;      
   
   Params[4].type=TYPE_INT;
   Params[4].integer_value=sm;  

Já lidamos com os três primeiros parâmetros passados para a função IndicatorCreate(). O tamanho do arranjo dos parâmetros é passado através do quarto parâmetro, o último é o próprio arranjo com os parâmetros:

Handle=IndicatorCreate(_Symbol,PERIOD_CURRENT,IND_CUSTOM,5,Params);

Falta pressionar o botão "Compile" e checar o indicador na plataforma do cliente.

Conclusão

Vamos repetir brevemente as principais ideias que você deve ficar atento enquanto cria um indicador personalizado na base de outro indicador.

Ao aprimorar um indicador, você deve especificar corretamente o número de memórias de armazenamento (buffers) e o número de memórias de armazenamento (buffers) a serem desenhadas (as propriedades do indicator_buffers, indicator_plots); você deve determinar as propriedades das novas memórias de armazenamento (buffers) (as propriedades ndicator_label, indicator_type, indicator_color, indicator_style, indicator_width ). Quando ativar a função SetIndexBufer() para as novas memórias de armazenamento (buffers), você deve especificar o valor correto do terceiro parâmetro (INDICATOR_DATA ou INDICATOR_CALCULATIONS); e especificar corretamente os valores do primeiro parâmetro (índice da memória de armazenamento (buffer)); efetue a criação dos índices das memórias de armazenamento (buffers) se necessário.

Quando criar um novo indicador usando um outro indicador personalizado, você deve passar corretamente os parâmetros para a função iCustom(); e preencher a estrutura de parâmetros quando usar a função IndicatorCreate(). Aqui você também deve inspecionar a especificação correta dos parâmetros quando ativar a função SetIndexBuffer(); e a parte mais importante é não esquecer de efetuar a ativação da função SetIndexBuffer() para as novas memórias de armazenamento.

Toda vez que você trabalhar com indicadores, você deve ficar atento a determinação da variedade de cálculos das barras - use os valores das variáveis prev_calculated, rates_total, begin. O MetaEditor o ajudará a lidar com outros erros que possam aparecer durante a programação (as mensagens de erro que aparecem durante a compilação são exibidas na guia "Errors").

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/127

Arquivos anexados |
tsis.mq5 (7.59 KB)
tsiscdicreate.mq5 (3.46 KB)
tsiscdicust.mq5 (3.11 KB)
20 sinais de negociação no MQL5 20 sinais de negociação no MQL5
Este artigo o ensinará a como receber os sinais de negócio que são necessários para um sistema de negócio funcionar. O exemplo de formação de 20 sinais de negócio é forncedio aqui como funções de personalização separadas que podem ser usadas ao desenvolver Expert Advisors. Para sua conveniência, todas as funções utilizadas no artigo são combinadas em um único arquivo mqh que pode ser facilmente conectado a um futuro Expert Advisor.
Funções para gerenciamento de dinheiro em um conselheiro especialista Funções para gerenciamento de dinheiro em um conselheiro especialista
O desenvolvimento das estratégias de negócio foca principalmente em buscar padrões para entrar e sair do mercado, bem como manter posições. Se formos capazes de formalizar alguns padrões em regras para negociação automatizada, então, o negociante enfrenta o problema de cálculo do volume das posições, o tamanho das margens, bem como manter um nível seguro dos fundos de hipoteca para garantir posições abertas no modo automatizado. Neste artigo, usaremos a linguagem do MQL5 para construir exemplos simples para realizar estes cálculos.
O protótipo do robô de negócio O protótipo do robô de negócio
Este artigo resume e sintetiza os princípios da criação de algoritmos e elementos dos sistemas de negócio. O artigo considera o planejamento do algoritmo de especialista. Como um exemplo, a classe CExpertAdvisor é considerada, o que pode ser usado para facilmente e rapidamente desenvolver sistemas de negócio.
Criar um quadro de informação utilizando classes de biblioteca padrão e o Google Chart API Criar um quadro de informação utilizando classes de biblioteca padrão e o Google Chart API
A linguagem de programação MQL5 foca principalmente na criação dos sistemas de negociação automatizada e instrumentos complexos da análise técnica. Mas, fora isso, ela permite criar sistemas de informação interessantes para rastrear situações de mercado e fornece uma conexão de retorno com o negociante. O artigo descreve os componentes da Biblioteca Padrão MQL5, e mostra exemplos de seu uso na prática para alcançar estes objetivos. Ela também demonstra um exemplo para utilizar o Google Chart API para criação de gráficos.