English Русский 中文 Español Deutsch 日本語
Método da área

Método da área

MetaTrader 5Sistemas de negociação | 30 junho 2016, 15:16
1 873 0
Vladimir Karputov
Vladimir Karputov

Tabela de conteúdos


Introdução

Como instalar corretamente os indicadores e conselheiros a partir dos arquivos no final do artigo: é necessário descompactar os arquivos "Indicators.zip" e "Experts.zip" no <diretório de dados>\MQL5\

A descrição do método da área foi publicada pela primeira vez em 2004 [1]. Este método é fascinante devido à sua perspectiva incomum sobre os dados do indicador RSI, pois sugere avaliar a área que o oscilador desenha sobre/sob a linha 50 desde o seu último cruzamento. Considerando as mudanças drásticas dos mercados em 2004 e a existência da linguagem MQL5, chegou a hora de testar a estratégia na linguagem MQL5 e no mercado moderno.


1. Método corrente de avaliação das leituras do indicador RSI

O método usual de negociação de acordo com os sinais do indicador RSI consiste numa avaliação das leituras do indicador para: sobrecompra/sobrevenda, procura da divergência entre as leituras do indicador e o preço, reversão após a o indicador visitar as zonas de sobrecompra/sobrevenda, e failure swing. Assim, para análise técnica do oscilador RSI é aplicado pelo menos quatro sinais, e isso complica o sistema de tomada de decisão.

Além disso, sabemos que o indicador RSI não se pode encontrar na zona de sobrecompra (acima da linha 70)/sobrevenda (abaixo da linha 30) por muito tempo, pois ele sempre volta e cruza a linha média 50:

RSI

Fig. 1. O oscilador RSI sempre volta das zonas de sobrecompra/sobrevenda

A Figura 1 mostra que o tempo total que o oscilador passou nas zonas de sobrevenda/sobrecompra é muito insignificante em comparação com o resto do tempo. Também, o RSI cruza a linha média 50, após entrar nas zonas de sobrevenda/sobrecompra. Como oscilador RSI sempre retorna e cruza a linha 50 e a análise técnica das leituras oscilador RSI deve ser simplificada, formou-se a base para desenvolver o método da área.


2. Método da área

O método da área sugere avaliar as leituras do oscilador RSI com base num critério: a área formada pelo oscilador sobre/sob a linha 50. Esse valor será usado para descrever o nível de sobrevenda/sobrecompra:

area_figure

Fig. 2. O método da área é uma avaliação da área sobre/sob a linha 50

Neste caso, o sinal para abrir uma posição é o tamanho da área sobre/sob a linha 50 desde o seu último cruzamento com o indicador RSI.   

  • Quando o RSI está sobre a linha 50 por muito tempo, e depois ele supera um determinado valor de área (por exemplo, 300), uma posição SELL será aberta: 

SELL signal 

Fig. 3. Sinal para abertura da posição SELL, assim que a área se tornou igual a 300

  • Da mesma forma, quando o RSI está abaixo da linha de 50 por um longo tempo, e depois ele supera um determinado valor da área, será aberta uma posição BUY.

O sinal de fechamento é gerado quando o oscilador RSI cruza a linha 50 com a subseqüente formação de um máximo/mínimo local e o seu recuo de 4% da escala.

  • Por exemplo, ao estar sobre a linha 50 por um longo tempo, em algum momento temos uma posição SELL aberta. Em seguida, o valor do indicador começa a diminuir e atinge a linha 40, por exemplo, após o qual o valor do indicador começa a aumentar (ou seja, forma-se um mínimo local). Quando o valor do indicador atinge 44, isto será um sinal para fechar a posição: 

Close SELL signal 

Fig. 4. Sinal para fechar uma posição SELL após a formação do mínimo local e um recuo de 4%

  • Uma lógica semelhante é aplicada quando o indicador está abaixo da linha 50 por um longo tempo. Só então podemos esperar a formação do máximo local.

O indicador RSIAreaIndicator ajudará com a visualização da área sobre/sob a linha 50.  


3. Indicador RSIAreaIndicator_v1

O indicador RSIAreaIndicator baseia-se no oscilador RSI. A principal diferença é que o RSIAreaIndicator tem dois buffers. Um buffer tem o estilo de construção DRAW_HISTOGRAM, e o segundo, DRAW_LINE. Os valores dos buffers são obtidos pela fórmula

formula RSIAreaIndicaor

Aparência do indicador RSIAreaIndicator version 1.00:

RSIAreaIndicator 

Fig. 5. Indicador RSIAreaIndicator _v1

 

3.1. Criamos um projeto para o indicador 

Sugiro colocar os indicadores criados por você numa pasta separada. No meu caso, essa pasta é chamada de "MyInd". Para começar a escrever o indicador, é preciso criar o seu cabeçalho no editor de código MetaEditor usando o assistente MQL5 Wizard. Os passos iniciais para a criação do projeto são descritos neste vídeo:


Você pode ver o projeto criado no final do artigo — o indicador armazenado sob o nome "RSIAreaIndicatorStep1.mq5". 

3.2. Preenchemos o "cabeçalho" do indicador

A próxima etapa envolve a adição de uma descrição para o indicador. Posteriormente, ele sempre aparecerá nas propriedades do indicador na aba "Comum". Todo o código adicionado ao artigo será destacado para uma melhor percepção visual:

#property version   "1.00"
#property description   "The indicator displays area RSI over/under line 50"
#property indicator_separate_window

Lembremos que o indicador RSIAreaIndicator tem dois indicadores de buffers. Além destes, precisamos de mais um adicional. Desta forma, haverá um total de três buffers usados no indicador. Vamos começar a editar o código na linha do "cabeçalho" do indicador:

#property indicator_separate_window
#property indicator_buffers 3
#property indicator_plots   2
#property indicator_type1   DRAW_HISTOGRAM
#property indicator_type2   DRAW_LINE
#property indicator_color1  clrGray
#property indicator_color2  clrGray
//--- input parameters
input int      ExtRSIPeriod=13;

Agora, é preciso declarar as três matrizes que armazenarão os valores do indicador e do buffer adicional:

//--- input parameters
input int      ExtRSIPeriod=13;
//---- buffers
double ExtMapBuffer1[];
double ExtMapBuffer2[];
double ExtMapBuffer3[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |

Além disso, como o nosso indicador RSIAreaIndicator é calculado com base no indicador RSI padrão e vamos precisar dos valores do indicador, é necessária uma variável para armazenar o identificador do indicador de Força Relativa (Relative Strength Index):

double ExtMapBuffer3[];
//--- variable for storing the handle of the iRSI indicator 
int    handle;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |

E, finalmente, três variáveis de serviço devem ser declaradas na linha de "cabeçalho". Na variável name será armazenado o nome do símbolo no qual foi executado o indicador, na variável short_name, o nome corto do indicador, e na variável bars_calculated, a quantidade de barras calculadas no indicador RSI:

int    handle;
//--- variable for storing 
string name=Symbol();
//--- name of the indicator on a chart 
string short_name;
//--- we will keep the number of values in the Relative Strength Index indicator 
int    bars_calculated=0;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |

A linha de "cabeçalho" do indicador está preenchida, então agora podemos prosseguir com a edição da função de OnInit().

3.3. Editamos a função OnInit() do indicador 

Uma vez que estamos escrevendo um indicador, os nossos buffers de indicador devem estar associados as matrizes dinâmicas do tipo double declaradas anteriormente:

int OnInit()
  {
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtMapBuffer1,INDICATOR_DATA);
   SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS);
//---
   return(INIT_SUCCEEDED);

Depois, imediatamente após a ligação dos buffers com as matrizes, definiremos a indexação dos elementos da matriz, como na série de tempo (há um bom exemplo que vale a pena conferir em ArraySetAsSeries). O elemento mais à direita da matriz terá índice "0":

   SetIndexBuffer(1,ExtMapBuffer2,INDICATOR_DATA);
   SetIndexBuffer(2,ExtMapBuffer3,INDICATOR_CALCULATIONS);
   ArraySetAsSeries(ExtMapBuffer1,true);
   ArraySetAsSeries(ExtMapBuffer2,true);
   ArraySetAsSeries(ExtMapBuffer3,true);
//---
   return(INIT_SUCCEEDED);

Agora, vamos definir a correção de exibição — o indicador será exibido com 2 casas decimais:

   ArraySetAsSeries(ExtMapBuffer3,true);
//--- set accuracy 
   IndicatorSetInteger(INDICATOR_DIGITS,2);
//---
   return(INIT_SUCCEEDED);

 Na função OnInit() resta obter o identificador da função RSIndex, preencher a variável short_name e atribuir um nome curto para o nosso indicador:

   ArraySetAsSeries(ExtMapBuffer2,true);
   ArraySetAsSeries(ExtMapBuffer3,true);
//--- set accuracy 
   IndicatorSetInteger(INDICATOR_DIGITS,2);
   handle=iRSI(name,0,ExtRSIPeriod,PRICE_CLOSE);
//--- if the handle is not created 
   if(handle==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",
                  name,
                  EnumToString(PERIOD_CURRENT),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//--- show the symbol/timeframe the RSI Area Indicator is calculated for 
   short_name=StringFormat("RSIArea(%d)",ExtRSIPeriod);
   IndicatorSetString(INDICATOR_SHORTNAME,short_name);
//--- normal initialization of the indicator 
   return(INIT_SUCCEEDED);

Então, temos preenchido a linha de "cabeçalho" da função de OnInit(). Você pode ver o código editado no final do artigo — o indicador é salvo sob o nome "RSIAreaIndicatorStep2.mq5".  

3.4. Criamos a função auxiliar do indicador 

Para trabalhar com o indicador RSIAreaIndicator, é preciso, em cada entrada à função OnCalculate(), obter os dados do indicador RSI. É igualmente importante assegurar a facilidade de leitura do código e dividir a funcionalidade do programa. Portanto, o código adicional para receber valores RSI e a cópia desse valores num dos buffer RSIAreaIndicator, foram movidos para a função separada FillArrayFromBuffer(). Será colocada depois de OnCalculate(). Os valores são copiados usando a função CopyBuffer.

//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+ 
//| Filling indicator buffers from the iRSI indicator                | 
//+------------------------------------------------------------------+ 
bool FillArrayFromBuffer(double &rsi_buffer[],  // indicator buffer of Relative Strength Index values 
                         int ind_handle,        // handle of the iRSI indicator 
                         int amount             // number of copied values 
                         )
  {
//--- reset error code 
   ResetLastError();
//--- fill a part of the iRSIBuffer array with values from the indicator buffer that has 0 index 
   if(CopyBuffer(ind_handle,0,0,amount,rsi_buffer)<0)
     {
      //--- if the copying fails, tell the error code 
      PrintFormat("Failed to copy data from the iRSI indicator, error code %d",GetLastError());
      //--- quit with zero result - it means that the indicator is considered as not calculated 
      return(false);
     }
//--- everything is fine 
   return(true);
  }
//+------------------------------------------------------------------+

3.5. Criamos o código básico de trabalho para o indicador 

O código básico de operação (ou lógica) do indicador RSIAreaIndicator está localizado na função OnCalculate(). Aqui, é declarada a variável principal values_to_copy. Posteriormente, a variável values_to_copy irá armazenar o número de valores que devem ser copiados a partir do indicador RSI.

                const int &spread[])
  {
//--- number of values copied from the iRSI indicator 
   int values_to_copy;
//--- determine the number of values calculated in the indicator 
   int calculated=BarsCalculated(handle);
   if(calculated<=0)
     {
      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Cálculo do valor values_to_copy:

      PrintFormat("BarsCalculated() returned %d, error code %d",calculated,GetLastError());
      return(0);
     }
//--- if it is the first start of calculation of the indicator or if the number of values in the iRSI indicator changed 
//---or if it is necessary to calculated the indicator for two or more bars (it means something has changed in the price history) 
   if(prev_calculated==0 || calculated!=bars_calculated || rates_total>prev_calculated+1)
     {
      //--- if the iRSIBuffer array is greater than the number of values in the iRSI indicator for symbol/period, then we don't copy everything  
      //--- otherwise, we copy less than the size of indicator buffers 
      if(calculated>rates_total) values_to_copy=rates_total;
      else                       values_to_copy=calculated;
     }
   else
     {
      //--- it means that it's not the first time of the indicator calculation, and since the last call of OnCalculate() 
      //--- for calculation not more than one bar is added 
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- return value of prev_calculated for next call
   return(rates_total);

Por que o valor values_to_copy é calculado desta forma? No indicador MQL5, os elementos de matrizes (time[], open[], high[], low[], close[], tick_volume[], volume[] e spread[]), passados para a função OnCalculate(), têm indexação desde o início da matriz até o fim. Assim é como fica no gráfico:

Array Not Series

Fig. 6. Indexação dos elementos da matriz, quando a matriz não é uma série de tempo 

Isso é, na matriz que não é uma série de tempo, o elemento mais à direita terá o índice máximo. Isto deve ser tomado em consideração nos cálculos matemáticos.

Agora, quando o valor values_to_copy é calculado, é possível chamar a função auxiliar функцию FillArrayFromBuffer() e preencher com valores os buffers dos indicadores ExtMapBuffer1[]ExtMapBuffer2[]:

      //--- for calculation not more than one bar is added 
      values_to_copy=(rates_total-prev_calculated)+1;
     }
//--- fill the array with values of the iRSI indicator 
//--- if FillArrayFromBuffer returns false, it means the information is nor ready yet, quit operation 
   if(!FillArrayFromBuffer(ExtMapBuffer3,handle,values_to_copy)) return(0);
//---
   for(int i=0;i<values_to_copy;i++)
     {
      ExtMapBuffer1[i]=ExtMapBuffer2[i]=ExtMapBuffer3[i]-50.0;
     }
//--- memorize the number of values in the Relative Strength Index indicator 
   bars_calculated=calculated;
//--- return value of prev_calculated for next call
   return(rates_total);

O indicador RSIAreaIndicator version 1.00 está pronto. Ele pode ser baixado no final do arquivo sob o nome "RSIAreaIndicatorv1.mq5". Agora, podemos prosseguir com a escritura do conselheiro RSIAreaEA version 1.00 que irá negociar segundo o método das áreas.


4. Conselheiro RSIAreaExpert version 1.00

Da mesma forma como com indicadores, recomendo mudar o conselheiro criado para uma pasta separada. Por exemplo, a pasta para os meus conselheiros é chamada de "MyExp". Por analogia com o indicador, criamos o projeto do conselheiro RSIAreaExpert_v1. Esclarecimento importante: numa das etapas, é necessário desmarcar todas as caixas de seleção:


 

 Fig. 7. Configurações ao criar o conselheiro

Você pode ver o projeto criado no final do artigo — o conselheiro armazenado sob o nome "RSIAreaExpert_v1_Step1.mq5". 

4.1. Editamos o "cabeçalho" do conselheiro

Adicionamos a descrição do conselheiro. Será visto na aba "Comuns" do conselheiro:

#property version   "1.00"
#property description "EA trades on \"Method areas\""
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

Escrever imediatamente uma descrição pode parecer algo incômodo, mas, eventualmente, essa prática será uma grande ajuda para você. 

O conselheiro vai utilizar a biblioteca padrão — classe CTrade para executar as operações de negociação. Para isso, é necessário conectar a classe CTrade e anunciar a variável my_trade:

#property description "EA trades on \"Method areas\""
#include <Trade\Trade.mqh>
//--- global variables
CTrade      my_trade;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

Também adicionaremos três variáveis (para armazenar o identificador do indicador Relative Strength Index, a atual área calculada e uma variável auxiliar):

//--- global variables
CTrade      my_trade;
int         handle;     // variable for storing the handle of the iRSI indicator 
double      RSIArea;    // the calculated area
double      RSIOpen;    // the auxiliary variable
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

E a última etapa é a edição da linha do "cabeçalho" do conselheiro, isto é, a adição dos parâmetros de entrada:

double      RSIOpen;    // the auxiliary variable
//--- input parametres
input int   ExtRSIPeriod=13;    // period of RSI
input int   AreaCondition=300;  // area
input ENUM_TIMEFRAMES period=PERIOD_M15;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |

A variável period introduzida exclusivaente para comodidade ao usar o testador de estratégias, desta forma podemos definir várias gamas de períodos testados:


Fig. 8. A variável period permite testar o conselheiro numa ampla gama de períodos 

O "cabeçalho" do conselheiro está preenchido, agora é a vez da função OnInit(). OnInit() terá apenas uma função, isto é, vai receber o identificador do símbolo atual (Symbol()) no período estabelecido (period):

int OnInit()
  {
//---
   handle=iRSI(Symbol(),period,ExtRSIPeriod,PRICE_CLOSE);
//--- if the handle is not created 
   if(handle==INVALID_HANDLE)
     {
      //--- tell about the failure and output the error code 
      PrintFormat("Failed to create handle of the iRSI indicator for the symbol %s/%s, error code %d",
                  Symbol(),
                  EnumToString(period),
                  GetLastError());
      //--- the indicator is stopped early 
      return(INIT_FAILED);
     }
//---
   return(INIT_SUCCEEDED);
  }

Todas estas alterações no processo de edição do conselheiro podem ser vistas no arquivo "RSIAreaExpert_v1_Step2.mq5".

4.2. Função auxiliar RSIAreaFunc 

A função para determinar a área RSIAreaFunc() está composta por várias partes funcionais. Nós adicionaremos gradualmente a funcionalidade. Primeiro bloco (explicação após o código):

void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |
//+------------------------------------------------------------------+
double RSIAreaFunc(int &RSIAreaShift,int BeginShift)
  {
   int    shift,limit;
   double rsivalue,result;
//--- get current RSI 
   limit=Bars(Symbol(),period)-ExtRSIPeriod;
   if(limit>100)
      limit=100;
   double   arr_rsi[];
   ArrayResize(arr_rsi,limit);
   ArraySetAsSeries(arr_rsi,true);
   if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return(0);
     }
   return(result);
  }

A variável limit é responsável pela quantidade de valore do indicador iRSI, nós vamos copiar para a matriz arr_rsi[] usando CopyBuffer. Restringimos a variável limit usando o valor "100", ou seja, sempre vamos copiar os últimos 100 valores do indicador iRSI. Todas estas alterações no processo de edição do conselheiro podem ser vistas no arquivo "RSIAreaExpert_v1_Step3.mq5".

4.3 Código de verificação ao trabalhar com a função CopyBuffer 

Se você não consegue entender como trabalha a função CopyBuffer e quais são os valores contidos na matriz sob o índice "0", é possível escrever um código de verificação simples: na função OnTick() escrevemos a chamada da função auxiliar RSIAreaFunc().

void OnTick()
  {
//---
   static int RSIAreaShift=0;
   RSIAreaFunc(RSIAreaShift,0);
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |
//+------------------------------------------------------------------+
double RSIAreaFunc(int &RSIAreaShift,int BeginShift)

No final do primeiro bloco da função RSIAreaFunc() adicionaremos a saída do comentário — os valores dos elementos início e fim da matriz arr_rsi[]:

   if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return(0);
     }
//---
   Comment("arr_rsi[",limit-1,"]=",DoubleToString(arr_rsi[limit-1],2),
           "; arr_rsi[0]=",DoubleToString(arr_rsi[0],2));
   return(result);
  }

Este é um código de verificação, ele é adicionado apenas no arquivo  RSIAreaExpert_v1_Step3_check.mq5, e ele não estará no conselheiro principal. Para verificação, executamos o seguinte:

  • compilar (se ainda não o tenha feito) o arquivo do conselheiro RSIAreaExpert_v1_Step3_check.mq5;
  • abrir um novo gráfico de qualquer instrumento e mudar para o timeframe M15 (pous nos parâmetros de entrada, a variável period=PERIOD_M15 é padrão);
  • inserir no gráfico o indicador RSI (menu "Inserir" -> "Indicadores" -> "Osciladores" -> "Índice de Força Relativa" com as seguintes definições: "Período" 13 e "Aplicar a" Close);
  • adicionar ao gráfico o conselheiro RSIAreaExpert_v1_Step3_check.mq5.

O gráfico mostrará instantaneamente que o valor do elemento com índice "0", na matriz arr_rsi, corresponde ao valor do indicador RSI na barra mais à direita:

  check function CopyBuffer 

Fig. 9. Testando a função CopyBuffer  

4.4. Mais sobre a edição da função auxiliar

Próximo bloco da função RSIAreaFunc():

   if(CopyBuffer(handle,0,0,limit,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return(0);
     }

   result=arr_rsi[0]-50.0; // values from the bars that has 0 index

   for(shift=BeginShift+1;shift<limit;shift++)
     {
      rsivalue=arr_rsi[shift]-50;
      if((result>0 && rsivalue<-3) || (result<0 && rsivalue>3))
        {
         RSIAreaShift=shift;
         break;
        }
      result+=rsivalue;
     }
   return(result);
  }

Primeiro, a variável result adota o valor do indicador RSI na barra mais à direita menos 50. Depois, ele é seguido pelo ciclo segundo a matriz arr_rsi, começando com o elemento com índice "1" até o elemento com índice limit-1. Neste ciclo, é verificada a seguinte condição: "houve ou não cruzamento da linha zero". Se houver cruzamento, em seguida, o código da barra (vista da direita para a esquerda) será armazenado na variável RSIAreaShift.

4.5. Função OnTick() do conselheiro

Nós terminamos de editar a função auxiliar RSIAreaFunc(). e continuamos com a função de negociação OnTick(): Vamos adicionar o seguinte código para OnTick(): 

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   static int RSIAreaShift=0;
   int      shift;
   double   RSICurrent,RSILocalMin,RSILocalMax,value;
   double   arr_rsi[1],rsi;
   MqlTick  last_tick;
//---
   if(CopyBuffer(handle,0,0,1,arr_rsi)==-1)
     {
      Print("CopyBuffer from iRSI failed, no data");
      return;
     }
   rsi=arr_rsi[0];
//--- 
   if(!SymbolInfoTick(Symbol(),last_tick))
      Print("SymbolInfoTick() failed, error = ",GetLastError());
//---
  }

Usando a função CopyBuffer, obtemos um valor do indicador RSI na barra mais à direita e, a seguir, ele será atribuído para a variável rsi -. No código, vamos referir esta variável varias vezes. Depois, obtemos os valores atuais desse símbolo e armazenamos esses valores na variável last_tick.

O seguinte bloco do código é processado, desde que haja uma posição aberta nesse instrumento:

   if(!SymbolInfoTick(Symbol(),last_tick))
      Print("SymbolInfoTick() failed, error = ",GetLastError());
//--- check the conditions for opening a position
   if(!PositionSelect(Symbol()))
     {
      RSIArea=RSIAreaFunc(RSIAreaShift,0);
      //--- check at the chance to take a long position
      if(RSIArea<-AreaCondition)
        {
         my_trade.Buy(1.0,NULL,last_tick.ask,0.0,0.0,NULL);
         RSIOpen=rsi;
         return;
        }
      //--- check at the chance to take a short position
      if(RSIArea>AreaCondition)
        {
         my_trade.Sell(1.0,NULL,last_tick.bid,0.0,0.0,NULL);
         RSIOpen=rsi;
         return;
        }
      RSIAreaShift=0;
     }
//---
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

No código, são verificadas as condições para abertura da posição: se a área calculada nesse momento (variável RSIArea) inferior/superior ao parâmetro de entrada (AreaCondition), então, respetivamente, será aberta uma posição Buy/Sell.

Depois, a variável RSICurrent é atribuído o valor da variável rsi (lembre-se que ele mantém o valor do indicador RSI no lado direito da barra) e é verificada a condição de saída a partir da função OnTick():

  • se a posição for aberta acima da linha "50" (RSIOpen>50) e nós estivermos nesse momento acima da linha "50" (RSICurrent>50);
  • se a posição for aberta abaixo da linha "50" (RSIOpen<50) e nós estarmos nesse momento abaixo da linha "50" (RSICurrent<50):
      RSIAreaShift=0;
     }
   RSICurrent=rsi;
   if(RSIOpen>50 && RSICurrent>50) return;
   if(RSIOpen<50 && RSICurrent<50) return;

   RSILocalMin = RSICurrent;
   RSILocalMax = RSICurrent;

//---
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

O próximo bloco de código encontra mínimos/máximos locais e atribui esses valores para as variáveis RSILocalMinRSILocalMax:

   RSILocalMin = RSICurrent;
   RSILocalMax = RSICurrent;
   
//--- search local minimum/maximum
   if(RSIAreaShift>1)
     {
      double   arr_rsi_1[];
      ArrayResize(arr_rsi_1,RSIAreaShift);
      ArraySetAsSeries(arr_rsi_1,true);
      if(CopyBuffer(handle,0,0,RSIAreaShift,arr_rsi_1)==-1)
        {
         Print("CopyBuffer from iRSI failed, no data");
         return;
        }
      for(shift=1; shift<RSIAreaShift; shift++)
        {
         value=arr_rsi_1[shift];
         if(value<RSILocalMin && RSIArea>0) RSILocalMin=value;
         if(value>RSILocalMax && RSIArea<0) RSILocalMax=value;
        }
     }
//---
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

Finalmente, o último bloco de código:

         if(value>RSILocalMax && RSIArea<0) RSILocalMax=value;
        }
     }

//--- check for rollback
   if(PositionSelect(Symbol()))
     {
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY)
        {
         //--- check, can it is time already be closing?
         if(RSILocalMax>=RSICurrent+4 && RSILocalMax>50)
            my_trade.PositionClose(Symbol(),20);
        }
      if(PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_SELL)
        {
         //--- check, can it is time already be closing?
         if(RSILocalMin<=RSICurrent-4 && RSILocalMin<50)
            my_trade.PositionClose(Symbol(),20);
        }
     }
//---
   return;
  }
//+------------------------------------------------------------------+
//| Area calculation                                                 |

Aqui (se você tiver uma posição aberta) é verificada a condição de fechamento da posição pela regra:

O oscilador RSI cruza a linha com 50 com a subseqüente formação de um máximo/mínimo local e o seu recuo de 4% da escala.
Por exemplo, ao estar sobre a linha 50 por um longo tempo, em algum momento temos uma posição SELL aberta. Em seguida, o valor do indicador começa a diminuir e atinge a linha 40, por exemplo, após o qual o valor do indicador começa a aumentar (ou seja, forma-se um mínimo local). O sinal para fechar a posição será o momento em que o valor do indicador atinja a linha 44.

Aqui finaliza a criação do conselheiro RSIAreaExpert_v1 . O arquivo "RSIAreaExpert_v1.mq5" pode ser baixado no final do artigo.


5. Teste do conselheiro RSIAreaExpert version 1.00 em vários períodos e símbolos

Inicialmente, o conselheiro RSIAreaExpert foi testado no período H1 [1] do gráfico, mas desde 2004 os mercados mudaram drasticamente, tornaram-se mais voláteis e, portanto, para avaliar o desempenho do método de áreas, decidiu-se realizar o teste numa grande variedade de períodos: a partir do M10 a H6. Também foi significativamente ampliado a gama de áreas para testes: 100-800. Período de teste, 2015.01.05 — 2016.01.05.

Assi, os resultados do teste do conselheiro RSIAreaExpert version 1 par o símbolo AUDCAD:

  RSIAreaExpert version 1 AreaCondition to Profit AUDCAD

Fig. 10. Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo AUDCAD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6 

No período H2, vemos uma boa densidade de resultados. É possível até mesmo levar em conta o período H3. Agora olhamos para a figura e estimamos o número de transações por ano no símbolo AUDCAD ao testar o conselheiro RSIAreaExpert version 1:

RSIAreaExpert version 1 Trades to Profit AUDCAD

Fig. 11.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo AUDCAD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6 

Nos períodos H2 e H3, o número de transações por ano flutua à volta de 50. Isto é um pouco, e a margem de erro é alta. Podemos concluir que no símbolo AUDCAD a estratégia do método funciona mal.

Resultados de teste do conselheiro RSIAreaExpert version 1 para o símbolo AUDUSD

RSIAreaExpert version 1 AreaCondition to Profit AUDUSD 

 Fig. 12.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo AUDUSD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6 

Se considerarmos a rentabilidade da estratégia no símbolo AUDUSD, podemos considerar a negociação nos períodos H2 e H3. Nestos períodos o parâmetro AreaCondition flutua entre 250 e 400. Para justificar a negociação nos períodos H2 e H3, é necessário ver o número de transações por o ano nestes períodos:

RSIAreaExpert version 1 Trades to Profit AUDUSD 

 Fig. 13.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo AUDUSD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6 

Como você pode ver, é desastrosamente baixo. Por isso, no AUDUSD, não é recomendado negociar segundo o método da área.

Os resultados do teste do conselheiro RSIAreaExpert version 1 para o símbolo EURUSD:

RSIAreaExpert version 1 AreaCondition to Profit EURUSD

 Fig. 14. Resultados do teste do conselheiro RSIAreaExpert. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6  

A figura 4 revela no período M10 uma boa densidade de resultados de lucro para a área de 400 a 550, para o período de M12, de 300 a 400, e para o período de M15, de 300 a 400. Não são considerados os períodos superiores, porque o número dos seus negócios ao longo do ano é muito pequeno (см. fig. 5).

A figura 5 revela o gráfico das dependências da quantidade de negociações e o lucro para o símbolo EURUSD:

RSIAreaExpert version 1 Trades to Profit EURUSD

Fig. 15. Resultados do teste do conselheiro RSIAreaExpert. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6 

Aqui claramente é mostrado que o número de negociações é menor em períodos de altos (de H1 a H6), o que não justifica a aplicação do método das áreas sobre tais períodos. No entanto, o número de negociações nos períodos M10, M12 e M15 é suficiente para confirmar da rentabilidade do método das áreas sobre estes timeframes. Certamente o símbolo EURUSD é apropriado para negociação segundo o método das áreas.

Resultado de teste do conselheiro RSIAreaExpert version 1 para o símbolo GBPUSD:

RSIAreaExpert version 1 AreaCondition to Profit GBPUSD 

 Fig. 16.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo GBPUSD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6 

No símbolo GBPUSD há uma boa densidade de lucros positivos para o período M20. O parâmetro AreaCondition varia de 300 a 500.

RSIAreaExpert version 1 Trades to Profit GBPUSD 

Fig. 17.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo GBPUSD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6  

Para o símbolo GBPUSD e no período M20, a quantidade de transações por ano flutua entre 140 e 250. Certamente não é um registro fantástico, mas, é possível tomar nota dele. Em outras palavras, negociar no símbolo GBPUSD usando o método da área não é adequado para todos 

Resultados do teste do conselheiro RSIAreaExpert version 1 para o símbolo USDCAD:

 

Fig. 18.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo USDCAD. Intervalo das áreas 100-800. Intervalo dos períodos M10-H6  

No símbolo USDCAD, gostaria de considerar apenas o período M30, pois tem uma boa densidade de lucro positivo. Além disso, o parâmetro AreaCondition é alterado na faixa entre 280 e 550.

RSIAreaExpert version 1 Trades to Profit USDCAD 

 Fig. 19.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo USDCAD. Intervalo das áreas 100-800. Intervalo de períodos M10-H6  

Neste par de moedas, no timeframe M30, o número de negociações por ano flutua entre 90 e 200. Isto não é muito, por isso não recomendo o método das áreas para o símbolo USDCAD.

Resultado de teste do conselheiro RSIAreaExpert version 1 para o símbolo USDJPY:

RSIAreaExpert version 1 AreaCondition to Profit USDJPY 

Fig. 20.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo USDJPY. Intervalo das áreas 100-800. Intervalo de períodos M10-H6  

No símbolo USDJPY existem dois períodos: M10 e M30. O parâmetro AreaCondition para o período M10 situa-se na gama de 320-650, para o período M30, 550-600.

RSIAreaExpert version 1 Trades to Profit USDJPY 

Fig. 21.  Resultados do teste do conselheiro RSIAreaExpert version 1. Símbolo USDJPY. Intervalo das áreas 100-800. Intervalo de períodos M10-H6  

Para o símbolo USDJPY, o número de transações por ano segundo o método das áreas para o período M10 na gama de 150-200, para o período M30, 50-150. Assim, vemos que aqui as recomendações de negociação são muito vagas.


Conclusão

Ainda é cedo para copiar uma negociação de acordo com o método da área. Realmente, o sistema tem começado a mostrar perdas em relação ao período H1, nas atuais condições de mercado, no entanto, anteriormente [1] era usado para manter o lucro principal. Negociar com EURUSD, nos períodos M10, M12 e M15, usando o método das áreas, provou ser o mais rentável e eficiente no mercado moderno. Precisamente, foram os testes que mostraram um número suficiente de negociações anuais com este par de moedas.

 

Bibliografia

  1. Morozov I. V., Fatkhullin R.R. FOREX: do simples ao complexo. Novos recursos para o terminal de cliente "MetaTrader". - "Teletrade LTD", 2004. - 448 p.
Como instalar corretamente os indicadores e conselheiros a partir dos arquivos no final do artigo: é necessário descompactar os arquivos "Indicators.zip" e "Experts.zip" no <diretório de dados>\MQL5\

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

Arquivos anexados |
Indicators.zip (3.91 KB)
Experts.zip (5.37 KB)
Guia Prático MQL5 - Programando os Canais Móveis Guia Prático MQL5 - Programando os Canais Móveis
Este artigo apresenta um método de programação de um sistema de canais equidistantes. Alguns detalhes da construção de tais canais estarão sendo considerados aqui. É fornecido a tipificação do canal, propondo um método de canais móveis do tipo universal. Para implementar o código, foi utilizado a Programação Orientada a Objetos (POO).
Calculadora de sinais Calculadora de sinais
A calculadora de sinais funciona diretamente a partir do terminal MetaTrader 5, e esta é a sua grande vantagem, pois o terminal pré-seleciona e classifica os sinais. Assim, no terminal MetaTrader 5, o usuário vê apenas os sinais com o máximo de compatibilidade com a sua conta de negociação.
Expert Advisor Universal: Estratégias Personalizadas e Classes Auxiliares de Negociação (Parte 3) Expert Advisor Universal: Estratégias Personalizadas e Classes Auxiliares de Negociação (Parte 3)
Neste artigo, vamos continuar a análise dos algoritmos do motor de negociação CStrategy. A terceira parte da série contém uma análise detalhada com exemplos de como desenvolver estratégias de negociação específicas usando esta abordagem. É dada uma atenção especial aos algoritmos auxiliares - sistema de registro Expert Advisor e acesso a dados usando um indexador convencional (Close[1], Open[0], etc).
Criamos um auxiliar na negociação manual Criamos um auxiliar na negociação manual
O número de robôs de negociação para trabalhar nos mercados de moedas ultimamente está crescendo como uma bola de neve. Neles estão compilados diversos conceitos e estratégias, mas vale a pena referir que ainda ninguém conseguiu criar um modelo de inteligência artificial que não esteja submetido a ricos de perda. Por isso, muitos traders continuam empenhados em negociar manualmente. E para esses especialistas são criados assistentes robóticos, chamados de painéis de negociação. Esse artigo é outro exemplo de como criar um painel de negociação "do zero".