English Русский 中文 Español Deutsch 日本語
Expert Advisors baseado em sistemas de trading populares e alquimia da otimização de robô de trading (Parte II)

Expert Advisors baseado em sistemas de trading populares e alquimia da otimização de robô de trading (Parte II)

MetaTrader 4Sistemas de negociação | 4 fevereiro 2016, 15:37
571 0
Nikolay Kositsin
Nikolay Kositsin

Introdução

A otimização dos sistemas de negociação é amplamente discutida em várias literaturas e seria ilógico escrever aqui em maiores detalhes o que pode ser facilmente encontrado na internet. Aqui então falaremos em detalhes somente ideias simples fundamentais que permeiam a lógica do entendimento da razão para usar os resultados da otimização de sistemas automatizados em geral e utilidade prática da otimização em particular.


Suponho que você saiba que é fácil carregar em um testador de estratégia um Expert Advisor construído com base mesmo em um relativamente simples sistema de negociações, após sua otimização você pode obter resultados fantásticos quase em qualquer dado histórico que coincidir com o dado histórico da otimização. Aqui ocorre uma pergunta natural: "O que o resultado tem em comum com a previsão de um comportamento de um sistema automatizado, mesmo que o resultado seja tremendo mas foi alcançado após ajustar o sistema de acordo com o histórico?"


No momento, essa pergunta é bem contundente. Uma das razões para tal é que após as primeiras otimizações com sucesso, um escritor de um EA iniciante pode ter a ideia errada sobre o uso impensado dos resultados de otimização nas negociações ao vivo e as consequências dela podem ser prejudiciais. E os escritores de EA iniciantes podem perder seu dinheiro ou o dinheiro destes que utilizarão o Expert Advisor já pronto. Então vou começar meu artigo com esse tópico.


As simulações ou testes dos resultados otimizados sem fanatismo

Geralmente após a primeira experiência de otimização do EA o escritor pode decidir construir uma estratégia utilizando resultados de otimização com rentabilidade máxima nos negócios com mínimas perdas, esperando que o sistema com o conjunto similar de parâmetros será rentável não somente no período de otimização mas também no futuro próximo. Esquematicamente se parecerá da seguinte forma:


Essa é a lógica usada por muitos escritores iniciantes de EA após o primeiro contato com um testador de estratégias de negócios. Mas infelizmente não podemos prever o futuro e definir a eficácia de um sistema de negócios utilizando essa lógica, e testar uma estratégia em uma conta de demonstração no modo de tempo real nos termos de um mercado real para uma gravação regular dos seus resultados operacionais é uma ocupação bem cansativa!


Se você for paciente para esperar os resultados por anos, então não há problemas! Entretanto, após tanto tempo esse sistema pode se tornar totalmente inútil e será bem frustrante ter tanto tempo perdido e tráfego de internet. Além disso, tal abordagem não permite o teste de muitas estratégias de negociação. Um ou, no máximo, dois! E a última coisa - muitos esforços investidos nos testes de tais estratégias de negociação evitam a possibilidade do seu criador estimar criticamente seus resultados operacionais!


Psicologicamente em tal situação é bem difícil encarar a verdade e admitir que a estratégia resultante foi somente uma mera perda de tempo e esforços. Naturalmente, tal desperdício de esforço e tempo dificilmente pode levar à criação de um Expert Advisor rentável.


Então, nesta situação a única maneira possível é modelar o futuro com base nos dados históricos. É muito fácil. Tudo que precisamos é mudar as bordas do tempo do esquema anterior para a esquerda ao longo do eixo de tempo. Em tal caso após a otimização você terá tempo suficiente para estimar os resultados de otimização nos dados recentes que estão mais próximos do presente do que os dados de otimização.


Em muitos casos, incluindo o descrito acima, tal abordagem permite estimar a eficácia atual das estratégias similares para utilizar os resultados de otimização para qualquer Expert Advisor que possua parâmetros otimizados. Esquematicamente o significado de tal análise das estratégias de otimização podem ser apresentadas da seguinte forma:



Eu suponho que esse diagrama é muito claro. Por exemplo, tomamos o ano de 2007 como o período de análise. Para a primeira otimização o período de otimização será de 01.01.2007 para 31.03.2007, e o período de testes - de 01.04.2007 a 31.05.2007. Após os testes e a gravação dos resultados, mudamos os períodos de otimização e testes em um mês para frente: o período de otimização será de 01.02.2007 a 30.04.2007, e o período de teste - de 01.05.2007 a 30.06.2007. E assim por diante. Como resultado temos uma tabela para gravar os resultados de cada otimização, por exemplo, esta:


Parâmetro de teste final/Execução 01 02 03 04 05 06 07 08 09 10 11 12
Lucro líquido











Lucro total











Perda total











Rentabilidade











Perda absoluta











Perda relativa











Negócios totais












Naturalmente, você terá que preencher as células das tabelas após cada etapa de otimização. Isso não causará problemas maiores ao analisar tal tabela e processar a informação contida nela, então você pode facilmente tirar conclusões desta análise. Suponho que esse tipo de análise do comportamento do EA nos dados de histórico disponíveis ajuda a estimar corretamente os resultados de otimização do EA e evitar ilusões com relação a esse processo. E salvar tempo comparado aos testes em uma conta de demonstração é fantástico!


A técnica de testes de simulação é muito fácil de entender pelos escritores iniciantes de EA, embora essa investigação também exija tempo e esforços. Mesmo se você obter resultados ruins durante seus testes de simulação do EA, não se chateie: perdas virtuais são muito melhores do que reais usando estratégias de perdas que pareceriam ser fortemente rentáveis.


Isso é tudo que eu queria dizer a você sobre os testes de simulação. Note que selecionar os excedentes máximos com perda mínima não é a única estratégia de otimização possível do sistema. Ela é oferecida a você somente para a introdução do procedimento de testes de simulação. Geralmente, a maior parte do tempo durante os testes de simulação é investida na otimização, enquanto os testes das estratégias de otimização exigem, muito pouco tempo, então é mais razoável testar diversas estratégias ao mesmo tempo para ter material estatístico maior para conclusões posteriores. Consequentemente a tabela de resultados de testes será muito maior.


Estratégia de negociação por oscilador

Com base nos osciladores, podem ser construídas muitas estratégias de negociação diferentes. Neste artigo descreverei o sistema mais popular com base nas entradas e saídas realizadas em áreas com sobrecompra e sobrevenda:




A maioria dos osciladores muda seus valores de um certo mínimo para algum máximo, cada oscilador tem seus próprios valores. Em alguma distância dos extremos, os níveis de UpLevel e DownLevel são colocados.


Em tal sistema um sinal para comprar ocorre se o oscilador sair da área fora de tendência e entrar na área de sobrecompra:

Um sinal para vender ocorre quando o oscilador sair da área fora de tendência e entrar na área de sobrevenda:

Além destes sinais, o sistema também tem sinais adicionais que aparecem quando o oscilador sai das áreas de sobrevenda e sobrecompra e entra na área fora de tendência, os sinais da então chamada correção.


Um sinal para comprar ocorre quando o oscilador sai da área de sobrevenda e entra na área fora de tendência (correção de uma tendência em queda):

Um sinal para vender ocorre quando ele sai da área de sobrecompra e entra na área fora de tendência (correção de uma tendência em ascensão):


Código de um Expert Advisor para o sistema de negociação por oscilador


Assim temos quatro algoritmos para entrar no mercado. Olhando atentamente nas duas variáveis de algoritmos para posições longas podemos concluir que eles são absolutamente idênticos e diferem somente na posição de um nível de rompimento, que é absolutamente irrelevante do ponto de vista da escrita do código de programação. A situação é análoga para posições curtas. Aqui está minha variante implementando o sistema de negociação por oscilador:

//+==================================================================+
//|                                                        Exp_3.mq4 |
//|                             Copyright © 2007,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2007, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up1 = true;//filter of trade calculations direction
extern int    Timeframe_Up1 = 240;
extern double Money_Management_Up1 = 0.1;
extern double IndLevel_Up1 = 0.8; // breakout level of the indicator
extern int    JLength_Up1 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Up1 = 8;  // depth of JurX smoothing of obtained indicator 
extern int    Phase_Up1 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Up1 = 0;/* Selecting prices on which the indicator will be calculated
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Up1 = 50;  // stoploss
extern int    TAKEPROFIT_Up1 = 100; // takeprofit
extern int    TRAILINGSTOP_Up1 = 0; // trailing stop
extern bool   ClosePos_Up1 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
///---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up2 = true;//filter of trade calculations direction
extern int    Timeframe_Up2 = 240;
extern double Money_Management_Up2 = 0.1;
extern double IndLevel_Up2 = -0.8; // breakout level of the indicator
extern int    JLength_Up2 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Up2 = 8;  // depth of JurX smoothing of obtained indicator
extern int    Phase_Up2 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Up2 = 0;/* Selecting prices on which the indicator will be calculated 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Up2 = 50;  // stoploss
extern int    TAKEPROFIT_Up2 = 100; // takeprofit
extern int    TRAILINGSTOP_Up2 = 0; // trailing stop
extern bool   ClosePos_Up2 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn1 = true;//filter of trade calculations direction
extern int    Timeframe_Dn1 = 240;
extern double Money_Management_Dn1 = 0.1;
extern double IndLevel_Dn1 = 0.8; // breakout level of the indicator
extern int    JLength_Dn1 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Dn1 = 8;  // depth of JurX smoothing of obtained indicator 
extern int    Phase_Dn1 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Dn1 = 0;/* Selecting prices on which the indicator will be calculated 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Dn1 = 50;  // stoploss
extern int    TAKEPROFIT_Dn1 = 100; // takeprofit
extern int    TRAILINGSTOP_Dn1 = 0; // trailing stop
extern bool   ClosePos_Dn1 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES
extern bool   Test_Dn2 = true;//filter of trade calculations direction
extern int    Timeframe_Dn2 = 240;
extern double Money_Management_Dn2 = 0.1;
extern double IndLevel_Dn2 = -0.8; // breakout level of the indicator
extern int    JLength_Dn2 = 8;  // depth of JJMA smoothing of entering price
extern int    XLength_Dn2 = 8;  // depth of JurX smoothing of obtained indicator 
extern int    Phase_Dn2 = 100; // parameter changing in the range -100 ... +100, 
                              //influences the quality of transient processes of smoothing
extern int    IPC_Dn2 = 0;/* Selecting prices on which the indicator will be calculated 
(0-CLOSE, 1-OPEN, 2-HIGH, 3-LOW, 4-MEDIAN, 5-TYPICAL, 6-WEIGHTED, 7-Heiken Ashi Close, 
8-SIMPL, 9-TRENDFOLLOW, 10-0.5*TRENDFOLLOW, 11-Heiken Ashi Low, 12-Heiken Ashi High,  
13-Heiken Ashi Open, 14-Heiken Ashi Close.) */
extern int    STOPLOSS_Dn2 = 50;  // stoploss
extern int    TAKEPROFIT_Dn2 = 100; // takeprofit
extern int    TRAILINGSTOP_Dn2 = 0; // trailing stop
extern bool   ClosePos_Dn2 = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- Integer variables for the minimum of calculation bars
int MinBar_Up1, MinBar_Dn1;
int MinBar_Up2, MinBar_Dn2;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up1 variable value
   TimeframeCheck("Timeframe_Up1", Timeframe_Up1);                             
//---- Checking the correctness of Timeframe_Up2 variable value
   TimeframeCheck("Timeframe_Up2", Timeframe_Up2);                              
//---- Checking the correctness of Timeframe_Dn1 variable value 
   TimeframeCheck("Timeframe_Dn1", Timeframe_Dn1);  
//---- Checking the correctness of Timeframe_Dn2 variable value 
   TimeframeCheck("Timeframe_Dn2", Timeframe_Dn2);  
//---- Initialization of variables
   MinBar_Up1 = 3 + 3 * XLength_Up1 + 30;
   MinBar_Up2 = 3 + 3 * XLength_Up2 + 30;
   MinBar_Dn1 = 3 + 3 * XLength_Dn1 + 30;
   MinBar_Dn2 = 3 + 3 * XLength_Dn2 + 30;                                     
//---- end of initialization
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- End of EA deinitialization
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaring local variables
   double Osc1, Osc2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static int LastBars_Up1, LastBars_Dn1;
   static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1;
   //----+ +---------------------------------------------------------------+
   static int LastBars_Up2, LastBars_Dn2;
   static bool BUY_Sign2, BUY_Stop2, SELL_Sign2, SELL_Stop2;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up1) 
    {
      int IBARS_Up1 = iBars(NULL, Timeframe_Up1);
      
      if (IBARS_Up1 >= MinBar_Up1)
       {
         if (LastBars_Up1 != IBARS_Up1)
          {
           //----+ Initialization of variables 
           BUY_Sign1 = false;
           BUY_Stop1 = false;
           LastBars_Up1 = IBARS_Up1; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up1, 
                 "JCCIX", JLength_Up1, XLength_Up1,
                                Phase_Up1, IPC_Up1, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up1, 
                 "JCCIX", JLength_Up1, XLength_Up1,
                                Phase_Up1, IPC_Up1, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up1)
             if (Osc1 > IndLevel_Up1)
                          BUY_Sign1 = true;
                          
           if (Osc1 < IndLevel_Up1)
                          BUY_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyOrder1(BUY_Sign1, 1, Money_Management_Up1, 
                                          STOPLOSS_Up1, TAKEPROFIT_Up1))
                                                                 return(-1);
          if (ClosePos_Up1)
                if (!CloseOrder1(BUY_Stop1, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up1))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 2
   if (Test_Up2) 
    {
      int IBARS_Up2 = iBars(NULL, Timeframe_Up2);
      
      if (IBARS_Up2 >= MinBar_Up2)
       {
         if (LastBars_Up2 != IBARS_Up2)
          {
           //----+ Initialization of variables 
           BUY_Sign2 = false;
           BUY_Stop2 = false;
           LastBars_Up2 = IBARS_Up2; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up2, 
                 "JCCIX", JLength_Up2, XLength_Up2,
                                Phase_Up2, IPC_Up2, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up2, 
                 "JCCIX", JLength_Up2, XLength_Up2,
                                Phase_Up2, IPC_Up2, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up2)
             if (Osc1 > IndLevel_Up2)
                          BUY_Sign2 = true;
                          
           if (Osc1 < IndLevel_Up2)
                          BUY_Stop2 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyOrder1(BUY_Sign2, 2, Money_Management_Up2, 
                                          STOPLOSS_Up2, TAKEPROFIT_Up2))
                                                                 return(-1);
          if (ClosePos_Up2)
                if (!CloseOrder1(BUY_Stop2, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Up2))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+ 
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn1) 
    {
      int IBARS_Dn1 = iBars(NULL, Timeframe_Dn1);
      
      if (IBARS_Dn1 >= MinBar_Dn1)
       {
         if (LastBars_Dn1 != IBARS_Dn1)
          {
           //----+ Initialization of variables 
           SELL_Sign1 = false;
           SELL_Stop1 = false;
           LastBars_Dn1 = IBARS_Dn1; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn1, 
                 "JCCIX", JLength_Dn1, XLength_Dn1,
                                Phase_Dn1, IPC_Dn1, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn1, 
                 "JCCIX", JLength_Dn1, XLength_Dn1,
                                Phase_Dn1, IPC_Dn1, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn1)
             if (Osc1 < IndLevel_Dn1)
                          SELL_Sign1 = true;
                          
           if (Osc1 > IndLevel_Dn1)
                          SELL_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellOrder1(SELL_Sign1, 3, Money_Management_Dn1, 
                                          STOPLOSS_Dn1, TAKEPROFIT_Dn1))
                                                                 return(-1);
          if (ClosePos_Dn1)
                if (!CloseOrder1(SELL_Stop1, 3))
                                        return(-1);
                                        
          if (!Make_TreilingStop(3, TRAILINGSTOP_Dn1))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 2
   if (Test_Dn2) 
    {
      int IBARS_Dn2 = iBars(NULL, Timeframe_Dn2);
      
      if (IBARS_Dn2 >= MinBar_Dn2)
       {
         if (LastBars_Dn2 != IBARS_Dn2)
          {
           //----+ Initialization of variables 
           SELL_Sign2 = false;
           SELL_Stop2 = false;
           LastBars_Dn2 = IBARS_Dn2; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn2, 
                 "JCCIX", JLength_Dn2, XLength_Dn2,
                                Phase_Dn2, IPC_Dn2, 0, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn2, 
                 "JCCIX", JLength_Dn2, XLength_Dn2,
                                Phase_Dn2, IPC_Dn2, 0, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn2)
             if (Osc1 < IndLevel_Dn2)
                          SELL_Sign2 = true;
                          
           if (Osc1 > IndLevel_Dn2)
                          SELL_Stop2 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellOrder1(SELL_Sign2, 4, Money_Management_Dn2, 
                                          STOPLOSS_Dn2, TAKEPROFIT_Dn2))
                                                                 return(-1);
          if (ClosePos_Dn2)
                if (!CloseOrder1(SELL_Stop2, 4))
                                        return(-1);
                                        
           if (!Make_TreilingStop(4, TRAILINGSTOP_Dn2))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+ 
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Esse código é duas vezes maior do que o código apresentado no artigo anterior. A propósito, imagine o quão longo esse código de EA poderia ser se tivesse todo o código do programa completo ao invés de chamadas de funções de gerenciamento de pedidos! Deve ser notado aqui que esse EA contém novos parâmetros de entrada: IndLevel_Up1, IndLevel_Up2, IndLevel_Dn1, IndLevel_Dn2. IndLevel_Up1 e IndLevel_Up2 definem os valores de Uplevel e DownLevel para dois algoritmos de posições longas, enquanto IndLevel_Dn1 e IndLevel_Dn2 definem valores de DownLevel e Uplevel para dois algoritmos de posições curtas.


Durante a otimização desse Expert Advisor seria levado em consideração que o valor destes níveis pode variar de -1.0 a +1.0. Se você quiser substituir o oscilador JCCIX neste EA por qualquer outro oscilador, leve em consideração que os valores mínimos e máximos destes níveis podem ser diferentes. O indicador de fonte JCCIX é o análogo do indicador CCI, em que o algoritmo de suavização por médias móveis comuns é substituído por JMA e suavização ultralinear. O EA usa Paradas Móveis, valores dos quais são definidos pelos parâmetros de entrada do EA como TRAILINGSTOP_Up1, TRAILINGSTOP_Up2, TRAILINGSTOP_Dn1, TRAILINGSTOP_Dn2. Com relação a todos os outros termos, este EA é totalmente análogo ao EA descrito no artigo anterior.


Alterando o mercado imediato ao entrar em pedidos pendentes

Em muitos casos nos EAs análogos ao descrito acima, alterar o mercado imediato ao entrar em pedidos pendentes permite que sejam feitas entradas de mercado mais precisas e obter lucros maiores com menor possibilidade de alcançar o Parar Perdas. Um conjunto de funções do arquivo Lite_EXPERT1.mqh permite fazer facilmente tal substituição.


Tudo que precisamos é substituir as funções OpenBuyOrder1() e OpenSellOrder1() por OpenBuyLimitOrder1() e OpenSellLimitOrder1() respectivamente. Durante tal substituição de função, novas variáveis de entrada destas funções devem ser inicializadas: LEVEL e Expiration. Por exemplo, podemos construir uma estratégia de negociação na qual a variável LEVEL será definida pelos parâmetros de entrada do EA. A data de cancelamento de pedidos pendentes pode ser definida como o tempo da próxima alteração da barra atual.


Não repetirei o mesmo código aqui. O código alterado do EA acima está anexado ao artigo (Exp_4.mq4). Como exemplo para usar pedidos pendentes eu descreverei um sistema oscilador usando o oscilador OSMA:

//For the EA operation the Metatrader\EXPERTS\indicators folder 
//must contain the 5c_OsMA.mq4 indicator
//+==================================================================+
//|                                                        Exp_5.mq4 |
//|                             Copyright © 2008,   Nikolay Kositsin | 
//|                              Khabarovsk,   farria@mail.redcom.ru | 
//+==================================================================+
#property copyright "Copyright © 2008, Nikolay Kositsin"
#property link "farria@mail.redcom.ru"
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR BUY TRADES 
extern bool   Test_Up = true;//filter of trade calculations direction
extern int    Timeframe_Up = 240;
extern double Money_Management_Up = 0.1;
extern double IndLevel_Up = 0; // breakout level of the indicator
extern int    FastEMA_Up = 12;  // period of quick EMA
extern int    SlowEMA_Up = 26;  // period of slow EMA
extern int    SignalSMA_Up = 9;  // period of signal SMA
extern int    STOPLOSS_Up = 50;  // stoploss
extern int    TAKEPROFIT_Up = 100; // takeprofit
extern int    TRAILINGSTOP_Up = 0; // trailing stop
extern int    PriceLevel_Up =40; // difference between the current price and
                                         // the price of pending order triggering
extern bool   ClosePos_Up = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- EA INPUT PARAMETERS FOR SELL TRADES 
extern bool   Test_Dn = true;//filter of trade calculations direction
extern int    Timeframe_Dn = 240;
extern double Money_Management_Dn = 0.1;
extern double IndLevel_Dn = 0; // breakout level of the indicator
extern int    FastEMA_Dn = 12;  // period of quick EMA
extern int    SlowEMA_Dn = 26;  // period of slow EMA
extern int    SignalSMA_Dn = 9;  // period of signal SMA
extern int    STOPLOSS_Dn = 50;  // stoploss
extern int    TAKEPROFIT_Dn = 100; // takeprofit
extern int    TRAILINGSTOP_Dn = 0; // trailing stop
extern int    PriceLevel_Dn = 40; // difference between the current price and 
                                         // the price of pending order triggering
extern bool   ClosePos_Dn = true; // forced position closing allowed
//----+ +--------------------------------------------------------------------------+
//---- Integer variables for the minimum of calculation bars
int MinBar_Up, MinBar_Dn;
//+==================================================================+
//| TimeframeCheck() functions                                       |
//+==================================================================+
void TimeframeCheck(string Name, int Timeframe)
  {
//----+
   //---- Checking the correctness of Timeframe variable value
   if (Timeframe != 1)
    if (Timeframe != 5)
     if (Timeframe != 15)
      if (Timeframe != 30)
       if (Timeframe != 60)
        if (Timeframe != 240)
         if (Timeframe != 1440)
           Print(StringConcatenate("Parameter ",Name,
                     " cannot ", "be equal to ", Timeframe, "!!!"));    
//----+ 
  }
//+==================================================================+
//| Custom Expert functions                                          |
//+==================================================================+
#include <Lite_EXPERT1.mqh>
//+==================================================================+
//| Custom Expert initialization function                            |
//+==================================================================+
int init()
  {
//---- Checking the correctness of Timeframe_Up variable value
   TimeframeCheck("Timeframe_Up", Timeframe_Up);                                                          
//---- Checking the correctness of Timeframe_Dn variable value 
   TimeframeCheck("Timeframe_Dn", Timeframe_Dn);  
//---- Initialization of variables
   MinBar_Up  = 3 + MathMax(FastEMA_Up, SlowEMA_Up) + SignalSMA_Up;
   MinBar_Dn  = 3 + MathMax(FastEMA_Dn, SlowEMA_Dn) + SignalSMA_Dn;                               
//---- end of initialization
   return(0);
  }
//+==================================================================+
//| expert deinitialization function                                 |
//+==================================================================+  
int deinit()
  {
//----+
   
    //---- End of EA deinitialization
    return(0);
//----+ 
  }
//+==================================================================+
//| Custom Expert iteration function                                 |
//+==================================================================+
int start()
  {
   //----+ Declaring local variables
   double Osc1, Osc2;
   //----+ Declaring static variables
   //----+ +---------------------------------------------------------------+
   static datetime StopTime_Up, StopTime_Dn; 
   static int LastBars_Up, LastBars_Dn;
   static bool BUY_Sign1, BUY_Stop1, SELL_Sign1, SELL_Stop1;
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR LONG POSITIONS 1
   if (Test_Up) 
    {
      int IBARS_Up = iBars(NULL, Timeframe_Up);
      
      if (IBARS_Up >= MinBar_Up)
       {
         if (LastBars_Up != IBARS_Up)
          {
           //----+ Initialization of variables 
           BUY_Sign1 = false;
           BUY_Stop1 = false;
           LastBars_Up = IBARS_Up;
           StopTime_Up = iTime(NULL, Timeframe_Up, 0)
                                            + 60 * Timeframe_Up;
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Up, 
                         "5c_OsMA", FastEMA_Up, SlowEMA_Up,
                                               SignalSMA_Up, 5, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Up, 
                         "5c_OsMA", FastEMA_Up, SlowEMA_Up,
                                               SignalSMA_Up, 5, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 < IndLevel_Up)
             if (Osc1 > IndLevel_Up)
                          BUY_Sign1 = true;
                          
           if (Osc1 < IndLevel_Up)
                          BUY_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenBuyLimitOrder1(BUY_Sign1, 1, 
              Money_Management_Up, STOPLOSS_Up, TAKEPROFIT_Up,
                                            PriceLevel_Up, StopTime_Up))
                                                                 return(-1);
          if (ClosePos_Up)
                if (!CloseOrder1(BUY_Stop1, 1))
                                        return(-1);
                                        
          if (!Make_TreilingStop(1, TRAILINGSTOP_Up))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
   //----++ CODE FOR SHORT POSITIONS 1
   if (Test_Dn) 
    {
      int IBARS_Dn = iBars(NULL, Timeframe_Dn);
      
      if (IBARS_Dn >= MinBar_Dn)
       {
         if (LastBars_Dn != IBARS_Dn)
          {
           //----+ Initialization of variables 
           SELL_Sign1 = false;
           SELL_Stop1 = false;
           LastBars_Dn = IBARS_Dn;
           StopTime_Dn = iTime(NULL, Timeframe_Dn, 0) 
                                            + 60 * Timeframe_Dn; 
           
           //----+ CALCULATING INDICATOR VALUES AND UPLOADING THEM TO BUFFERS        
           Osc1 = iCustom(NULL, Timeframe_Dn, 
                         "5c_OsMA", FastEMA_Dn, SlowEMA_Dn,
                                               SignalSMA_Dn, 5, 1);
                                
           Osc2 = iCustom(NULL, Timeframe_Dn, 
                         "5c_OsMA", FastEMA_Dn, SlowEMA_Dn,
                                               SignalSMA_Dn, 5, 2);
           
           //----+ DEFINING SIGNALS FOR TRADES                                           
           if (Osc2 > IndLevel_Dn)
             if (Osc1 < IndLevel_Dn)
                          SELL_Sign1 = true;
                          
           if (Osc1 > IndLevel_Dn)
                          SELL_Stop1 = true;                                           
          }
          //----+ EXECUTION OF TRADES
          if (!OpenSellLimitOrder1(SELL_Sign1, 2, 
              Money_Management_Dn, STOPLOSS_Dn, TAKEPROFIT_Dn,
                                            PriceLevel_Dn, StopTime_Dn))
                                                                 return(-1);
          if (ClosePos_Dn)
                if (!CloseOrder1(SELL_Stop1, 2))
                                        return(-1);
                                        
          if (!Make_TreilingStop(2, TRAILINGSTOP_Dn))
                                                  return(-1);
        }
     }
   //----+ +---------------------------------------------------------------+
//----+ 
    
    return(0);
  }
//+------------------------------------------------------------------+

Ao invés de dois níveis de rompimento UpLevel e DownLevel, um nível é usado, é por isso que o EA contém somente dois algorítmos de gerenciamento de posição. Geralmente em um sistema de negociação conectado com o OsMA este nível é selecionado igual a zero, mas eu decidi deixá-lo em variáveis externas do EA, para que ele possa ser mudado. Isto é, deve ser levado em consideração que o indicador OSMA não possui máximo e mínimo dentro do que o indicador altera, consequentemente o nível de rompimento não possui limitações dos seus valores. Embora, como eu tenha dito, geralmente é igual a zero. Para definir o tempo de cancelamento de pedidos pendentes, as variáveis estáticas StopTime_Up e StopTime_Dn são usadas, uma vez que a barra seja alterada eles são inicializados no momento da alteração da próxima barra.

Conclusão

Em conclusão eu gostaria de adicionar que sistemas de negociação por oscilador retornam muitos sinais falsos contra a tendência do mercado atual. Então é melhor incluir tais EAs para operação em períodos de mercados estáveis ou usados para abrir posições somente por tendências.


Para testes de simulação, posso dizer novamente que essa é provavelmente a melhor maneira para um escritor iniciante de EA para estimar corretamente os resultados de otimização. E não há problemas com EAs que mostram resultados tremendos no ajuste ao histórico. Entretanto, é mais difícil entender como os EAs prontos devem ser usados para evitar situações onde o mercado destoa muito dos parâmetros otimizados do EA.




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

Arquivos anexados |
EXPERTS.zip (7.48 KB)
INCLUDE.zip (24.26 KB)
indicators.zip (5.59 KB)
TESTER.zip (5.28 KB)
Análise comparativa de 30 indicadores e osciladores Análise comparativa de 30 indicadores e osciladores
O artigo descreve um Expert Advisor que permite conduzir a análise comparativa de 30 indicadores e osciladores com foco na formação de um pacote eficaz de índices para negociações.
Expert Advisors baseado em sistemas de trading populares e alquimia da otimização de robô de trading Expert Advisors baseado em sistemas de trading populares e alquimia da otimização de robô de trading
Esse artigo trata do algoritmo de implementação dos sistemas de negociação mais simples. O artigo será útil para investidores iniciantes e desenvolvedores de EA.
Um assistente de investidores com base em análise MACD estendida Um assistente de investidores com base em análise MACD estendida
O script 'Trader's Assistant' (assistente de investidores) ajuda você a tomar uma decisão sobre posições de abertura, com base na análise estendida do estado MACD para as últimas três barras na negociação em tempo real, em qualquer período de tempo. Ele também pode ser usado para testes de fundo.
Caça de tendências Caça de tendências
O artigo descreve um algoritmo de aumento de volume de lucros em uma negociação. Sua implementação usando os recursos do MQL4 é apresentada no artigo.