English Русский 中文 Español Deutsch 日本語
Transferência de um Código Indicador para um Código Expert Advisor. Esquemas da estrutura geral de um Expert Advisor e funções indicadoras

Transferência de um Código Indicador para um Código Expert Advisor. Esquemas da estrutura geral de um Expert Advisor e funções indicadoras

MetaTrader 4Exemplos | 19 fevereiro 2016, 13:03
2 323 0
Nikolay Kositsin
Nikolay Kositsin

Introdução

No artigo anterior (Transferência de um Código Indicador para um Código Expert Advisor. Estrutura do indicador) analisamos a estrutura geral de um indicador, o código que se destina para a transferência de um código Expert Advisor e descrevemos as principais ideias de um ajuste preliminar de um código indicador. Agora vamos tentar transformar o código obtido em uma função personalizada, porque esta é, talvez, a forma mais conveniente de apresentar um código indicador em um Expert Advisor. A função personalizada pode ser apresentada como um arquivo mqh e sua declaração em um Expert Advisor usando a diretiva #include tomará muito pouco espaço e chamar essa função não é muito mais difícil que chamar um indicador personalizado. O mais importante é que essas funções personalizadas podem ser universais para utilização posterior em quaisquer Expert Advisors.

Antes de começar a escrever tal função, vamos analisar como essa função irá interagir com a outra parte do Expert Advisor, independentemente da estrutura interna da função.

Estrutura de um EA com indicador de chamada personalizado

Vamos primeiro estudar a estrutura esquemática de um EA que recebe dados de indicadores personalizados. Neste EA, estamos primeiramente interessados apenas na parte que recebe dados de indicadores personalizados. Até agora, não discutiremos a forma como o EA processa esses dados, transferindo-os em sinais de negociações e a estrutura de uma parte executiva do EA. Vamos analisar como um indicador personalizado neste EA, discutido no artigo anterior. Aqui está um exemplo de uma estrutura de um Expert Advisor:


//+------------------------------------------------------------------+
//|                                               ExpertIndPlan0.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- EA input parameters
extern int period10 = 15;
extern int period11 = 15;
extern int period12 = 15;
//---- EA input parameters
extern int period20 = 15;
extern int period21 = 15;
extern int period22 = 15;
//---- Declaring buffers for indicator values
double Ind_Buffer1[6];
double Ind_Buffer2[6];
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
// Here is the code of EA initialization
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(iBars(Symbol(), 0) < period10 + period11 + period12 + 10)
       return(0);
   if(iBars(Symbol(), 0) < period20 + period21 + period22 + 10)
       return(0);
//---- getting indicator values for further calculation
   for(int bar = 5; bar >= 1; bar--)
     {
       Ind_Buffer1[bar] = iCustom("IndicatorPlan", Symbol(), 0, period10, 
                                  period11, period12, 0, bar);
       Ind_Buffer2[bar] = iCustom("IndicatorPlan", Symbol(), 0, period20, 
                                  period21, period22, 0, bar);
     }
// Here is the EA code, forming trade signals 
// based on the values of indicator buffer cells 
//----
// here is the EA executive part code, 
// requesting for placing an order 
//----
   return(0);
  }
//+------------------------------------------------------------------+

Neste esquema a cada crédito que tomamos de um buffer zero do indicador personalizado, o IndicatorPlan.mq4 conta os valores em duas chamadas e os coloca em matrizes comuns Ind_Buffer1 [] e Ind_Buffer2 []. O esquema de chamar um indicador é feito considerando que para outros cálculos vamos precisar apenas dos cinco últimos valores dos indicadores, exceto o zero.

Estrutura de um EA com função personalizada de chamada
Enquanto estamos desenvolvendo uma função de indicador universal adequada para um Expert Advisor, ela deve enviar os valores recebidos para o buffer de indicador análogo, que irá armazenar valores do indicador para todas as barras do gráfico. Claro que poderíamos desenvolver uma função indicadora, chamando o que seria completamente análogo ao chamar um indicador personalizado, mas escrever tal função levaria muito tempo e seu código seria bastante longo.

Podemos fazer isto de uma maneira mais fácil. Esta função deve receber como parâmetros de entrada os parâmetros de um indicador personalizado e buffer, e deve retornar o mesmo buffer com uma emulação de modo indicador, onde as células são preenchidas com valores de indicadores calculados. Isto pode ser feito facilmente declarando em nossa função de uma variável externa ligada por referência para a função correspondente de um buffer de indicador. Na linguagem MQL4 ele parecerá com este: double & inputbuffer. A função do indicador deve ser declarada de maneira lógica, retornando 'verdadeiro', se um cálculo foi bem-sucedido, ou "falso", se um cálculo foi mal sucedido devido à ausência de um número adequado de barras no gráfico. Após estas explicações a função do indicador, construída a partir do esquema do indicador, discutido no artigo anterior, deve ter o seguinte formato:


bool Get_IndSeries(int Number,string symbol, int timeframe, 
                   bool NullBarRecount, int period0, int period1, 
                   int period2, double& InputBuffer0[],
                   double& InputBuffer1[], double& InputBuffer2[])

A função do indicador tem mais um Númerovariável externo que aceita o valor desta função do indicador de número de chamada.

É natural que, com exceção do buffer de indicador InputBuffer0 as variáveis externas também irão conter buffers para cálculos intermediários InputBuffer1 e InputBuffer2, porque é muito problemático fazer esses buffers dentro da função. É melhor emular o modo do indicador desses buffers de operação dentro da função. Não irá causar problemas. Agora vamos nos debruçar sobre o significado da variável externa NullBarRecount. Na verdade, a maioria dos EAs não precisa de cálculos na barra zero, e enquanto estamos escrevendo um código de função universal do indicador, ele irá recalcular valores do indicador na barra zero, o que pode aumentar substancialmente o tempo de execução. Ao indicar o parâmetro externo da função NullBarRecount como "falso", nós proibimos cálculos desnecessários da função na barra zero.

Agora podemos apresentar o esquema de uma estrutura EA para chamar indicadores em uma variante com funções de chamada:

//+------------------------------------------------------------------+
//|                                               ExpertIndPlan1.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- EA input parameters
extern int period10 = 15;
extern int period11 = 15;
extern int period12 = 15;
//---- EA input parameters
extern int period20 = 15;
extern int period21 = 15;
extern int period22 = 15;
//---- Indicator buffers declaration
double Ind_Buffer10[], Ind_Buffer11[], Ind_Buffer12[];
double Ind_Buffer20[], Ind_Buffer21[], Ind_Buffer22[];
//+------------------------------------------------------------------+
//| Get_IndSeries() function                                         |
//+------------------------------------------------------------------+
//---- Declaration of the function Get_IndSeries()
bool Get_IndSeries(int Number,string symbol, int timeframe, 
                   bool NullBarRecount, int period0, int period1, 
                   int period2, double& InputBuffer0[], 
                   double& InputBuffer1[], double& InputBuffer2[]) 
  {
    //---- 
    // Here is the code of the function GetIdicator()
    //----
    return(true);
  }
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
//----
// Here is the code of the EA initialization
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- Checking whether the bars number is enough for further calculation
   if(iBars(Symbol(), 0) < period10 + period11 + period12 + 10)
      return(0);
   if(iBars(Symbol(), 0) < period20 + period21 + period22 + 10)
      return(0);
//---- getting indicator values for further calculation
   if(!Get_IndSeries(0,Symbol(), 0, false, period10, period11, period12,
      Ind_Buffer10, Ind_Buffer11, Ind_Buffer12))
       return(0);
   if(!Get_IndSeries(1, Symbol(), 0, false, period20, period21, period22, 
      Ind_Buffer20, Ind_Buffer21,Ind_Buffer22))
       return(0);  
//----
// Here is the EA code, forming trade signals 
// based on the values of indicator buffer cells 
//----
// here is the EA executive part code, 
// requesting for placing an order
//----
 
   return(0);
  }
//+------------------------------------------------------------------+


Esquema geral de transformação de um código indicador em função personalizada

Após este trabalho preliminar, podemos passar para a construção de um esquema geral de uma estrutura interna de uma função do indicador. Vamos tomar como base o último esquema do indicador no artigo anterior. Não há dificuldades.

1. Leve em consideração apenas o conteúdo da função start int();
2. Adicione declaração da função Get_IndSeries():

bool Get_IndSeries(string symbol, int timeframe, bool NullBarRecount,
                   int period0, int period1, int period2, 
                   double& InputBuffer0, double& InputBuffer1, 
                   double& InputBuffer2)


3. Altere os nomes dos buffers de indicador dentro do código (Ind_Buffer) de acordo com os nomes do buffer (InputBuffer) das variáveis externas da função Get_IndSeries();
4. Adicione declaração da variável LastCountBar;
5. Verifique a veracidade da variável NullBarRecount:

if(!NullBarRecount)
    LastCountBar = 1;

6. Em todos os ciclos do cálculo do indicador mude para zero em LastCountBar;
7. Faça mudanças no início do código, ao verificar se o número de barras é suficiente para cálculo posterior: retorno (0) em retorno (falso);
8. No final da alteração do código retorno (0) em retorno (verdadeiro);

A função do indicador está pronta:

//+------------------------------------------------------------------+
//|                                                Get_IndSeries.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+ 
bool Get_IndSeries(int Number, string symbol,int timeframe, 
                   bool NullBarRecount, int period0, int period1, 
                   int period2, double& InputBuffer0[], 
                   double& InputBuffer1[], double& InputBuffer2[])  
  {
//---- getting the number of all bars of a chart
   int IBARS = iBars(symbol, timeframe);
//---- Checking whether the bars number is enough for further calculation
   if(IBARS < period0 + period1 + period2)
      return(false);
//---- EMULATION OF INDICATOR BUFFERS
   if(ArraySize(InputBuffer0) < IBARS)
     {
       ArraySetAsSeries(InputBuffer0, false);
       ArraySetAsSeries(InputBuffer1, false);
       ArraySetAsSeries(InputBuffer2, false);
       //----  
       ArrayResize(InputBuffer0, IBARS); 
       ArrayResize(InputBuffer1, IBARS); 
       ArrayResize(InputBuffer2, IBARS); 
       //----
       ArraySetAsSeries(InputBuffer0, true);
       ArraySetAsSeries(InputBuffer1, true);
       ArraySetAsSeries(InputBuffer2, true); 
     } 
//----+ introducing static memory variables
   static int IndCounted[];
//----+ changing the size of static variables
   if(ArraySize(IndCounted) < Number + 1)
       ArrayResize(IndCounted, Number + 1); 
//----+ introducing an integer variable
   int LastCountBar;
//----+ Checking if the recalculation of the zero bar is allowed
   if(!NullBarRecount)
       LastCountBar = 1;
   else 
       LastCountBar = 0;
//----+ Inserting a variable with a floating point
   double Resalt0, Resalt1, Resalt2;
//----+ Inserting integer variables and getting already calculated bars
   int limit, MaxBar, bar, counted_bars = IndCounted[Number];
//----+ Remembering the number of all bars of a chart (we do not count the zero bar!)
   IndCounted[Number] = IBARS - 1;
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   limit = IBARS - counted_bars - 1; 
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated
   MaxBar = IBARS - 1 - (period0 + period1 + period2); 
//---- initialization of zero 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = IBARS - 1; bar >= 0; bar--)
         {
           InputBuffer0[bar] = 0.0;
           InputBuffer1[bar] = 0.0;
           InputBuffer2[bar] = 0.0;
         }
     }
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     {
       // Here code of the variable Resalt1 calculation  
       // based on the external variable period1
       InputBuffer1[bar] = Resalt1;
     }
//----+ THE SECOND CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     {
       // Here code of the variable Resalt2 calculation 
       // based on the values of the buffer Ind_Buffer1[] 
       // and external variable period2
       InputBuffer2[bar] = Resalt2;
     }
//----+ THE MAIN CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     {
       // Here code of the variable Resalt0 calculation 
       // based on the values of the buffer Ind_Buffer2[] 
       // and external variable period0
       InputBuffer0[bar] = Resalt0;
     }
   return(true);
  }
//+------------------------------------------------------------------+

Acho que caso o leitor use o MQL4 muito bem, depois de ler as ações descritas acima, ele não terá nenhum problema em escrever funções dos indicadores de acordo com o esquema dado.

Exemplo de como escrever uma função de indicador personalizada
Agora vamos escrever uma função do indicador. Vamos pegar de exemplo um indicador extremamente simples:

//+------------------------------------------------------------------+
//|                                                         RAVI.mq4 |
//|                      Copyright © 2005, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2005, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- drawing the indicator in a separate window
#property indicator_separate_window 
//---- number of indicator buffers
#property indicator_buffers 1 
//---- indicator color
#property indicator_color1 Red 
//---- INPUT PARAMETERS OF THE INDICATOR 
extern int Period1 = 7; 
extern int Period2 = 65; 
extern int MA_Metod = 0;
extern int PRICE = 0;
//---- indicator buffers
double ExtBuffer[]; 
//+------------------------------------------------------------------+ 
//| RAVI initialization function                                     | 
//+------------------------------------------------------------------+ 
int init() 
  { 
//---- indicator drawing style
   SetIndexStyle(0, DRAW_LINE); 
//---- indicator buffers 
   SetIndexBuffer(0,ExtBuffer); 
//---- indicator name and labels for subwindows 
   IndicatorShortName("RAVI (" + Period1+ ", " + Period2 + ")"); 
   SetIndexLabel(0, "RAVI"); 
//---- initialization end
   return(0); 
  } 
//+------------------------------------------------------------------+ 
//| RAVI iteration function                                          | 
//+------------------------------------------------------------------+ 
int start() 
  {
   int MinBars = MathMax(Period1, Period2); 
//---- checking whether the bars number is enough for further calculation
   if(Bars < MinBars)
       return(0);
//----+ Introducing variables with a floating point 
   double MA1, MA2, result; 
//----+ Introducing integer variables and getting already calculated bars
   int MaxBar, bar, limit, counted_bars = IndicatorCounted();
//---- checking for possible errors
   if(counted_bars < 0)
       return(-1);
//---- the last calculated bar should be recalculated 
   if(counted_bars > 0)
       counted_bars--;
//---- defining the number of the oldest bar, 
// starting from which all bars will be recalculated 
   MaxBar = Bars - 1 - MinBars;
//---- defining the number of the oldest bar, 
// starting from which new bars will be recalculated 
   limit = Bars - counted_bars - 1; 
//---- zero initialization
   if(limit > MaxBar)
     {
       for(int ii = Bars - 1; ii >= MaxBar; ii--)
           ExtBuffer[ii] = 0.0;
       limit = MaxBar;
     }
//---- main cycle 
   for(bar = 0; bar <= limit; bar++) 
     { 
       MA1 = iMA(NULL, 0, Period1, 0, MA_Metod, PRICE,bar); 
       MA2 = iMA(NULL, 0, Period2, 0, MA_Metod, PRICE,bar); 
       //---- 
       result = ((MA1 - MA2) / MA2)*100; 
       ExtBuffer[bar] = result; 
     }  
//---- 
   return(0); 
  } 
//+------------------------------------------------------------------+



Fixação de algoritmo

1. Livre-se de todos os elementos desnecessários no código indicador;
2. Escreva o código de emulação do buffer de indicador para um único buffer ExtBuffer[];
3. Substitua a função IndicatorCounted() pela variável IndCounted;
4. Inicialize a variável IndCounted pelo montante das barras do gráfico menos um;
5. Altere as barras de variáveis predeterminadas na chamada de séries cronológicas iBars(símbolo, calendário);
6. Delete verificação desnecessária para counted_bars:

//---- checking possible errors
if(counted_bars < 0)
    return(-1);
//---- the last calculated bar must be recalculated 
if(counted_bars > 0) 
    counted_bars--;

7. Leve em consideração apenas o conteúdo da função start int ();


8. Adicione declaração da função Get_RAVISeries():

bool Get_RAVISeries(int Number, string symbol,int timeframe, 
                    bool NullBarRecount, int Period1, 
                    int Period2, int MA_Metod, int  PRICE, 
                    double& InputBuffer[])

9. Substitua os nomes do buffer de indicador dentro do código (ExtBuffer) de acordo com os nomes do buffer (InputBuffer) de variáveis externas da função Get_RAVISeries();


10. Adicione declaração da variável LastCountBar;
11. Transforme a variável estática IndCounted em uma matriz IndCounted[Number] e adicione um código para alterar o tamanho das variáveis de acordo com os número de chamadas da função Get_RAVISeries. mqh:

//----+ changing the size of static variables
   if(ArraySize(IndCounted) < Number + 1)
     {
       ArrayResize(IndCounted, Number + 1); 
     }

12. Verifique a veracidade da variável NullBarRecount:

if(!NullBarRecount)
    LastCountBar = 1;

13. Em todos os ciclos de cálculo do indicador altere para zero em LastCountBar:


for(bar = limit; bar >= LastCountBar; bar--)

14. Ao verificar se o número de barras é suficiente para cálculo posterior: retorno (0) em retorno (falso), faça uma mudança no início do código;


15. No final, substitua retorno(0) para retorno(verdadeiro).


Após o código inteiro mudar, temos a função do indicador Get_RAVISeries():

//+------------------------------------------------------------------+
//|                                               Get_RAVISeries.mqh |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
bool Get_RAVISeries(int Number, string symbol,int timeframe, 
                    bool NullBarRecount, int Period1, int Period2, 
                    int MA_Metod, int  PRICE, double& InputBuffer[])    
  {
//---- getting the number of all bars of a chart
   int IBARS = iBars(symbol, timeframe);  
//---- Checking whether the bars number is enough for further calculation
   if(IBARS < MathMax(Period1, Period2))
       return(false);
//---- EMULATION OF INDICATOR BUFFERS
   if(ArraySize(InputBuffer) < IBARS)
     {
       ArraySetAsSeries(InputBuffer, false);
       //----  
       ArrayResize(InputBuffer, IBARS); 
       //----
       ArraySetAsSeries(InputBuffer, true);
     } 
//----+  inserting static variables of memory
   static int IndCounted[]; 
//----+ changing the size of static variables
   if(ArraySize(IndCounted) < Number + 1)
     {
       ArrayResize(IndCounted, Number + 1); 
     }
 //----+ Introducing an integer variable
   int LastCountBar;
//----+ Checking whether the recalculation of the zero bar is allowed
   if(!NullBarRecount)
       LastCountBar = 1;
//----+ Introducing floating point variables 
   double MA1,MA2,result; 
//----+ Introducing integer variables and getting alreadu calculated bars
   int MaxBar, bar, limit, counted_bars = IndCounted[Number];
//----+ Remembering the amount of all chart bars
   IndCounted[Number] = IBARS - 1;
//---- determining the number of the oldest bar, 
// starting from which new bars will be recalculated
   limit = IBARS - counted_bars - 1; 
   // Print(IBARS - counted_bars); 
//---- determining the number of the oldest bar, 
// starting from which all bars will be recalculated
   MaxBar = IBARS - 1 - MathMax(Period1, Period2); 
//---- zero initialization 
   if(limit > MaxBar)
     {
       limit = MaxBar;
       for(bar = IBARS - 1; bar >= 0; bar--)
         {
           InputBuffer[bar] = 0.0;
         }
     } 
//----+ THE FIRST CYCLE OF INDICATOR CALCULATION 
   for(bar = limit; bar >= LastCountBar; bar--)
     { 
       MA1 = iMA(symbol, timeframe, Period1, 0, MA_Metod, PRICE, bar); 
       MA2 = iMA(symbol, timeframe, Period2, 0, MA_Metod, PRICE, bar); 
       //---- 
       result = ((MA1 - MA2) / MA2)*100; 
       InputBuffer[bar] = result; 
     } 
//----+  
   return(true);
  }
//+------------------------------------------------------------------+


Certamente, tudo isso é ótimo! Mas não é muito simples. Mas surge uma pergunta: será que esta função do indicador vai calcular da mesma forma que um indicador personalizado?

Teste da função do indicador para precisão de cálculo
Precisamos verificar se os resultados dos cálculos da função são iguais aos resultados dos cálculos dos indicadores personalizados. Para este propósito o Expert Advisor mais adequado é o que não negocia e só recebe valores do indicador personalizado RAVI.mq4 e da função personalizada Get_RAVISeries(), encontra a diferença e depois disso envia para um arquivo de log o valor do indicador, o valor da função personalizada e a diferença entre eles. Tudo que precisamos fazer é analisar o conteúdo do arquivo de log para fazer a conclusão final sobre a correspondência do nosso algoritmo da função personalizada Get_RAVISeries() e o indicador RAVI.mq4:

//+------------------------------------------------------------------+
//|                                           Get_RAVISeriesTest.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                       https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
//---- INPUT EA PARAMETERS
extern bool NullBarRecount = true;
//---- indicator buffers
double RAVI_Buffer0[];
double RAVI_Buffer1[];
double RAVI_Buffer2[];
//+------------------------------------------------------------------+
//| Get_RAVISeries() function                                        |
//+------------------------------------------------------------------+
#include <Get_RAVISeries.mqh>
//+------------------------------------------------------------------+
//| Custom Expert initialization function                            |
//+------------------------------------------------------------------+
int init()
  {
//---- initialization end
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom Expert iteration function                                 |
//+------------------------------------------------------------------+
int start()
  {
//---- 
   double Ind_Velue, Resalt;
//---- 
   if(!Get_RAVISeries(0, Symbol(), 0, NullBarRecount, 10, 20, 1, 0,
      RAVI_Buffer0))
       return(0);  
   if(!Get_RAVISeries(1, Symbol(), 240, NullBarRecount, 25, 66, 2, 1,
      RAVI_Buffer1))
       return(0);
   if(!Get_RAVISeries(2, Symbol(), 1440, NullBarRecount, 30, 70, 3, 3,
      RAVI_Buffer2))
       return(0);
//---- getting indicator values for the test 0
   Ind_Velue = iCustom(NULL, 0, "RAVI", 10, 20, 1, 0, 0, 2); 
   Resalt = RAVI_Buffer0[2] - Ind_Velue; 
   Print("  " + Ind_Velue + "    " + RAVI_Buffer0[2] + "    " + Resalt+"");
//---- getting indicator values for the test 1
   Ind_Velue = iCustom(NULL, 240, "RAVI", 25, 66, 2, 1, 0, 2);
   Resalt = RAVI_Buffer1[2] - Ind_Velue; 
   Print("  " + Ind_Velue + "    " + RAVI_Buffer1[2] + "    " + Resalt+"" );
//---- getting indicator values for the test 2
   Ind_Velue = iCustom(NULL, 1440, "RAVI", 30, 70, 3, 3, 0, 2);
   Resalt = RAVI_Buffer2[2] - Ind_Velue; 
   Print("  " + Ind_Velue + "    " + RAVI_Buffer2[2] + "    " + Resalt + "");
//----
   return(0);
  }
//+------------------------------------------------------------------+

No strategy tester inicie o Expert Advisor Get_RAVISeriesTest. Naturalmente, o arquivo compilado RAVI.ex4 já deve estar na pasta \expert\indicators, e o arquivo Get_RAVISeries.mqh na pasta \ \expert \include do Terminal do cliente MetaTrader. No strategy tester journal e no arquivo de log podemos visualizar duas colunas com valores do indicador e o seu análogo na forma de uma função; A terceira coluna mostra a diferença desses valores. Todos os valores da última coluna são iguais a zero. Isso significa que os valores são idênticos em ambos os casos. Podemos concluir que a tarefa de escrever uma função personalizada de indicador foi resolvida com sucesso!



Conclusão

Assim, conseguimos resolver a tarefa de transferência de um código indicador de um indicador personalizado para um código Expert Advisor fazendo um análogo do indicador, como uma função personalizada universal, que pode ser colocada em um arquivo mqh e utilizada no código de qualquer Expert Advisor de forma análoga a um indicador personalizado.

No próximo artigo, dedicado a este tema, vamos analisar um exemplo mais difícil de como escrever funções deste tipo e a implementação de um Expert Advisor simples baseado em tais funções.


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

Arquivos anexados |
ExpertIndPlan0.mqh (2.27 KB)
ExpertIndPlan1.mqh (2.89 KB)
RAVI.mq4 (2.93 KB)
Terminal Service Client. Como tornar o Pocket PC um amigo do Big Brother Terminal Service Client. Como tornar o Pocket PC um amigo do Big Brother
O artigo descreve como conectar o PC remoto com o MT4 Client Terminal instalado via PDA.
Transferência de um Código Indicador para um Código Expert Advisor. Estrutura do Indicator Transferência de um Código Indicador para um Código Expert Advisor. Estrutura do Indicator
Este artigo trata sobre formas de transferência de um código indicador para um código Expert Advisor e sobre a escrita de Expert Advisors sem convocar indicadores personalizados, e com todo o código do programa para o cálculo dos valores dos indicadores necessários dentro do Expert Advisor. Este artigo fornece um esquema geral de uma estrutura de indicador, emulação de buffers indicadores no Expert Advisor e a substituição da função IndicatorCounted (). O artigo destina-se para leitores com experiência de programação na linguagem MQL4.
Um Expert Advisor feito sob encomenda Manual para um operador Um Expert Advisor feito sob encomenda Manual para um operador
Nem todos os operadores são programadores. E nem todos programadores são realmente bons. Então, o que deve ser feito para você automatizar seu sistema sem ter tempo e vontade de estudar o MQL4?
Princípios de transformação de tempo em negociações intraday Princípios de transformação de tempo em negociações intraday
Este artigo contém o conceito de tempo de operação que permite receber mais até com fluxo de preço. Ele também contém o código de mudança de média móvel com auxílio para essa transformação de tempo.