English Русский 中文 Español Deutsch 日本語
preview
Teste e otimização de estratégias para opções binárias no MetaTrader 5

Teste e otimização de estratégias para opções binárias no MetaTrader 5

MetaTrader 5Testador | 23 maio 2023, 09:36
243 0
Roman Poshtar
Roman Poshtar

Introdução

Boa tarde, caros usuários da comunidade MQL5. Recentemente, eu me interessei pelo tema de opções binárias. Depois de explorar o vasto espaço da Internet e analisar diferentes corretoras, constatei que praticamente todas usam suas próprias plataformas para negociação. Essas plataformas não possuem a capacidade de testar estratégias e, na melhor das hipóteses, possuem um conjunto limitado de indicadores padrão. Depois de revisar uma ampla variedade de estratégias para opções binárias, surgiu a questão de como verificar essas estratégias, sem mencionar a otimização. Como sempre, o nosso querido MetaTrader 5 veio ao meu auxílio. Como de costume, farei o meu melhor para compartilhar com vocês minhas experiências da maneira mais simples possível, apresentando o material sem recorrer a fórmulas e códigos complexos. Mas, antes de mais nada, um pouco de teoria e argumentos sobre se vale a pena ou não se envolver com opções binárias.


Teoria

Uma opção binária é um contrato digital cujo objeto é a previsão da direção do preço de um ativo em um intervalo de tempo escolhido. Como trabalhar com opções binárias? A tarefa é corretamente determinar um dos dois possíveis cenários para o desenvolvimento da situação de mercado: se o ativo irá aumentar ou diminuir de valor. Hoje, uma vasta seleção de opções online para moedas, valores mobiliários e commodities está disponível. O ativo neste tipo de procedimento pode ser qualquer coisa, como foi demonstrado, até mesmo a previsão do tempo. Começar a negociar não requer grandes investimentos nem profundo conhecimento financeiro e econômico no campo dos processos de negociação de mercado.


Tipos de opções binárias

"Alta/Baixa" (Call/Put) é o tipo mais simples e compreensível de opções binárias, aqui para lucrar, basta que o trader determine a direção em que o preço irá se mover, para cima ou para baixo. Em uma tendência de alta, é aconselhável comprar "Alta" (Call). A opção "Baixa" (Put) é comprada se for esperado um movimento de queda do ativo. O lucro das opções Alta/Baixa varia de 10% a 80% da aposta.

"One Touch" (Um Toque) representa um acordo no qual é necessário determinar se o preço atingirá o nível de preço desejado. Onde as cotações estarão no fechamento não é relevante; o fato de tocar o nível definido será decisivo. A lucratividade do "One touch" é maior do que o normal, pois na maioria dos casos é muito difícil prevê-los e pode chegar a 95%, mas também é possível perder todos os 100%.

"Intervalo" (Range) determina o corredor de preço, dentro do qual o valor do ativo estará localizado no momento da expiração. Também é difícil de entender e prever. Rendimento de até 95%.

Abaixo, no artigo, iremos realizar testes e otimização de estratégias para as opções "Alta/Baixa", que, na minha opinião, são as mais populares.


Vantagens e desvantagens

As vantagens incluem:

  • Simplicidade: A obtenção de uma fixação na quantidade de perdas ou lucros potenciais permite evitar a necessidade de realizar cálculos complexos de stop loss e estabelecer níveis de lucro. Isso é especialmente benéfico para iniciantes, que não possuem experiência como traders e desejam evitar complicações.
  • Cadastro simples no site da corretora de opções: É necessário um tempo mínimo sem a necessidade de enviar pacotes de documentos extensos, o que é comum em bolsas de valores ou futuros.
  • Maior variedade de recursos: É possível negociar ações de empresas, índices de ações, petróleo, ouro, criptomoedas e muito mais com um valor mínimo de fundos, a partir de $100. Algumas corretoras até possuem valores mínimos ainda menores. Em comparação, ao negociar nos mercados de ações ou futuros, são necessários depósitos iniciais mais substanciais.

Algumas desvantagens:

  • Alto risco e expectativa negativa: A relação entre vitórias e derrotas é desfavorável, exigindo duas vitórias para compensar uma derrota. Eficiência lucrativa de até 80%: Embora possa ser lucrativa, a eficiência da operação é limitada a 80%, o que pode não ser ideal em certas situações.
  • Falhas no modo "Casino" à distância: Algumas pessoas tentam aplicar truques de cassino ao negociar, como a estratégia de "Martingale", que contradiz as regras da negociação adequada. Isso pode levar à perda total do depósito à distância.
  • Comissões consideráveis ​​cobradas em qualquer caso conveniente ao negociar: Ao negociar, comissões substanciais são aplicadas, independentemente da situação, o que pode afetar os lucros.

    Par de moedas, alcance da otimização e testes avançados, bem como opções

    Aqui vou dar todos os parâmetros para otimização e teste para que não se repitam no texto:

    • Mercado Forex;
    • Par de moedas EURUSD;
    • Período M5, M15, M30, H1;
    • Tempo de expiração 5, 15, 30 minutos e 1 hora.
    • Faixa de otimização 1 ano. De 28/01/2021 a 2022.01.28.
    • Intervalo de teste forward 1 ano. De 28/01/2022 a 28/01/2023;
    • Depósito inicial 10000;
    • Aposta 10;
    • O percentual da remuneração é de 80%.

      Aspectos técnicos

      Para realizar os testes e a otimização, precisamos de parâmetros de entrada:

      1. StartDepo - depósito inicial;
      2. OptionRate - aposta;
      3. ExpirationTime - tempo de expiração;
      4. ProfitPercent - percentual de lucro;
      5. TimeFrame - período gráfico dos indicadores;
      6. Optimization - interruptor de otimização;
      7. OptimizationFileName – nome do arquivo para armazenar os resultados da otimização.
      input string N0 = "------------Open settings----------------";
      input double StartDepo = 10000;
      input int OptionRate = 10;
      input string N1 = "------------Close settings---------------";
      input int ExpirationTime = 1; //ExpirationTime 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input double ProfitPercent = 80;
      input string N2 = "------------Optimization settings--------";
      input int TimeFrame = 1; //TimeFrame 1=5 min, 2=15 min, 3=30 min, 4=60 min
      input bool Optimization = false;
      input string OptimizationFileName = "Optimization.csv";
      input string N3 = "------------Other settings---------------";
      input int Slippage = 10;
      input int Magic = 111111;
      input string EAComment = "2Ma+RSI+Stochastic Oscillator";

      Também serão necessárias variáveis para armazenar e acompanhar as alterações no depósito e o número de compras de opções lucrativas e perdedoras:

      1. XStartDepo - armazenamento do depósito atual;
      2. Profit - armazenamento do número de compras de opções lucrativas;
      3. Loss - armazenamento do número de compras de opções não lucrativas;
      double XStartDepo = StartDepo;
      int Profit=0;
      int Loss=0;

      Para rastrear o tempo de abertura da posição e fechar a posição após o tempo de expiração no MetaTrader 5, usaremos uma função que retorna o tempo de abertura da posição.

      //+------------------------------------------------------------------+
      //| Get open time in positions                                       |
      //+------------------------------------------------------------------+
      datetime GetTime(string symb="0", int type=-1, int mg=-1,int index=0) {
       datetime p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Time();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

      Para rastrear a lucratividade de uma posição e decidir se ganhamos uma aposta ou não, usaremos uma função que retorna o lucro de uma posição aberta no momento atual. Comissões e swaps não são levados em consideração.

      //+------------------------------------------------------------------+
      //| Get profit in positions                                          |
      //+------------------------------------------------------------------+
      double GetProfit(string symb="0", int type=-1, int mg=-1,int index=0) {
       double p[];
       int c=-1, pr=0;
        if(symb=="0") { symb=Symbol();}
         for(int i=PositionsTotal()-1;i>=0;i--){
            if(position.SelectByIndex(i)) {
           if(position.PositionType()==POSITION_TYPE_BUY || position.PositionType()==POSITION_TYPE_SELL) {
            if((position.Symbol()==symb||symb=="")&&(type<0||position.PositionType()==type)&&(mg<0||position.Magic()==mg)) {
             c++;
             ArrayResize(p, c+1);
             p[c]=position.Profit();
             pr=c>=index?index:c;
             
       }}}}
        return(c==-1?0:p[pr]);
       }

      Para utilizar apenas um novo sinal de entrada, utilizamos vários gatilhos. Isso significa que a permissão para entrar no mercado só é concedida quando há um sinal novo. Entradas repetidas no mesmo sinal são ignoradas.

      1. TrigerSell - compra de uma opção Put;
      2. TrigerBuy - compra de uma opção Call;
      int TrigerSell=0;
      int TrigerBuy=0;

      A saída de uma posição, a adição e retirada de fundos do depósito inicial, bem como o cálculo das compras de opções lucrativas e não lucrativas são realizados rastreando o tempo atual em relação à abertura da posição e o tempo de expiração.

      //Sell (Put)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Durante a otimização, usamos variáveis para determinar o período gráfico desejado e o tempo de expiração. O modo de otimização é ativado pela variável Optimization. A otimização, por sua vez, se resume ao uso de arquivos CSV. Depois que o teste é concluído em OnDeinit, escrevemos todas as variáveis necessárias em um arquivo. Ao otimizar, nossos EAs criam um arquivo CSV que contém o resultado no caminho "C:\Users\Your username\AppData\Roaming\MetaQuotes\Terminal\Common\Files".

      1. Depósito final;
      2. Número de negociações lucrativas;
      3. Número de negociações não lucrativas;
      4. Período gráfico
      5. Tempo de expiração.
      //+------------------------------------------------------------------+
      //| Expert deinitialization function                                 |
      //+------------------------------------------------------------------+
      void OnDeinit(const int reason)
        {
      
      if (Optimization==true){
       if (FileIsExist(OptimizationFileName)==false){
         filehandle = FileOpen(OptimizationFileName,FILE_WRITE|FILE_READ|FILE_CSV|FILE_COMMON|FILE_ANSI, ";");
          if(filehandle!=INVALID_HANDLE)
           {
            FileSeek(filehandle, 0, SEEK_END);
            FileWrite(filehandle,DoubleToString(XStartDepo),IntegerToString(Profit),IntegerToString(Loss),IntegerToString(XTimeFrame),IntegerToString(XExpirationTime));
            FileClose(filehandle);
           }
       }
      }
      
        }

      É possível observar o teste no modo de visualização usando Comment() para apresentar o resultado atual de forma simples.

      Resultado atual


      Estratégias

      Estratégia "2Ma+RSI+Stochastic Oscillator"

      Essa estratégia é disponibilizada por uma corretora bem conhecida como uma estratégia de escalpelamento para opções binárias, sugerindo um período gráfico de 5 minutos e um tempo de expiração de 5 minutos.

      Indicadores:

      1. Um par de médias móveis exponenciais com períodos de 5 e 10;
      2. Índice de força relativa (RSI), configurações padrão;
      3. Oscilador estocástico com configurações 14, 3, 3.

      Um sinal "para cima", ou uma opção Call de compra, aparece se várias condições forem atendidas:

      1. A média móvel vermelha cruza a média móvel azul de baixo para cima;
      2. O índice de força relativa está acima do nível 50;
      3. A linha estocástica rápida cruza a linha lenta (pontilhada) de baixo para cima.

      Estratégia para cima 1

      Um sinal “para baixo”, ou a compra de uma opção Put, aparece também se várias condições forem atendidas:
      1. O movimento vermelho cruza o azul de cima para baixo;
      2. RSI está abaixo do nível 50;
      3. A linha rápida do oscilador estocástico cruza a lenta de cima para baixo.

      Estratégia para baixo 1

      Escolhi o cruzamento da MA na direção oposta como o gatilho para o novo sinal nessa estratégia. Abaixo está o código da estratégia.

      //Sell (Put)
      
      if((ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[2]>ind_In2S1[2])){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[0]<ind_In2S1[0]) && (ind_In4S1[1]<50) && (ind_In4S1[0]<50) && (ind_In3S1_1[1]<ind_In3S1_2[1])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if((ind_In1S1[1]<ind_In2S1[1]) && (ind_In1S1[2]<ind_In2S1[2])){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1[1]>ind_In2S1[1]) && (ind_In1S1[0]>ind_In2S1[0]) && (ind_In4S1[1]>50) && (ind_In4S1[0]>50) && (ind_In3S1_1[1]>ind_In3S1_2[1])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Após o teste, obtemos o resultado:

      • Depósito final 1964;
      • Negociações lucrativas 1273;
      • Negociações perdedoras 1822.

      Resultado

      Após a otimização, obtemos o resultado. Como podemos ver, não obtivemos um aumento positivo em nosso depósito em nenhum período e tempo de expiração.

      Resultado da otimização


      Estratégia "Maverick"

      Vejamos uma estratégia fascinante e descomplicada para opções, chamada Maverick. Essa estratégia se fundamenta em dois indicadores de análise técnica e é conhecida por sua precisão ao determinar os momentos de entrada e saída. Ela é ideal para negociações com duração de 1 a 5 minutos, e para obter mais sinais, é possível abrir múltiplos gráficos com diferentes ativos simultaneamente.

      Indicadores:

      1. Indicador Bollinger Bands com parâmetros 20 e StDev (desvio padrão) 2;
      2. Indicador RSI. Parâmetros do RSI - 4, com bordas de 80 e 20.

      Previsão de crescimento. Compra de opção Call:

      Depois que a linha do indicador RSI entra na zona de sobrevenda, abaixo de 20, e a linha de preço toca ou ultrapassa as Bandas de Bollinger, esperamos pela primeira vela de alta e abrimos uma negociação PARA CIMA.

      Compra para cima

      Previsão de queda. Compra de opção Put:

      Depois que a linha do indicador RSI entra na zona de sobrecompra, acima de 80, e a linha de preço ultrapassa os limites superiores do Bollinger, esperamos pela primeira vela de baixa e abrimos uma negociação PARA BAIXO.

      Compra para baixo

      Como gatilho nessa estratégia para um novo sinal, escolhi o fechamento da vela anterior dentro do canal do Bollinger. Abaixo está o código da estratégia.

      //Sell (Put)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)<ind_In1S1_1[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)>ind_In1S1_1[2]) && (ind_In2S1[2]>80) && (iClose(symbolS1.Name(),XTimeFrame,1)<iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(iClose(symbolS1.Name(),XTimeFrame,1)>ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (iClose(symbolS1.Name(),XTimeFrame,2)<ind_In1S1_2[2]) && (ind_In2S1[2]<20) && (iClose(symbolS1.Name(),XTimeFrame,1)>iOpen(symbolS1.Name(),XTimeFrame,1))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Passemos à verificação. Testamos no período gráfico M5. Obtemos o resultado:

      • Depósito final 3312;
      • Negociações lucrativas 1589;
      • Negociações perdedoras 1940.

      Resultado

      O que obtivemos foi uma perda, embora o resultado seja um pouco melhor do que na estratégia anterior. Vamos realizar a otimização esperando valores positivos para o depósito. Mas, infelizmente, a estratégia não funciona:

      Resultado da otimização


      Estratégia "Vortex+TSI"

      Essa estratégia de opções binárias é chamada de Vortex, por causa do uso do indicador de mesmo nome. De fato, há dois indicadores envolvidos na estratégia - o principal e o secundário como filtro. O período gráfico sugerido é de 1 a 5 minutos.

      Indicadores:

      1. Vortex com parâmetro 14;
      2. True Strength Indicator (TSI) com parâmetros 25, 13, 5, Exponencial.

      Para compra de opção com o crescimento do preço:

      1. Espera até que ambos os indicadores se cruzem ao mesmo tempo, com as linhas azuis subindo e as linhas vermelhas descendo;
      2. As linhas do indicador Vortex devem divergir.

      Crescimento

      Para compra uma opção com a queda do preço:

      1. Espera até que ambos os indicadores se cruzem ao mesmo tempo, com as linhas vermelhas subindo e as linhas azuis descendo;
      2. As linhas do indicador Vortex devem divergir.

      Queda

      O gatilho para o novo sinal é um cruzamento invertido do True Strength Indicator (indicador de força real). Abaixo está o código da estratégia.
      //Sell (Put)
      
      if(ind_In1S1_1[1]>ind_In1S1_2[1]){TrigerSell=1;}
      
         if ((TrigerSell==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (ind_In1S1_1[0]<ind_In1S1_2[0]) && (ind_In1S1_1[1]<ind_In1S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_2[0]) && (ind_In2S1_1[1]<ind_In2S1_2[1]) && (ind_In2S1_1[0]<ind_In2S1_1[1]) && (ind_In2S1_2[0]>ind_In2S1_2[1]) && (ind_In2S1_1[1]<ind_In2S1_1[2]) && (ind_In2S1_2[1]>ind_In2S1_2[2])){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerSell=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
      if(ind_In1S1_1[1]<ind_In1S1_2[1]){TrigerBuy=1;}
      
         if ((TrigerBuy==1) && (CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (ind_In1S1_1[0]>ind_In1S1_2[0]) && (ind_In1S1_1[1]>ind_In1S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_2[0]) && (ind_In2S1_1[1]>ind_In2S1_2[1]) && (ind_In2S1_1[0]>ind_In2S1_1[1]) && (ind_In2S1_2[0]<ind_In2S1_2[1]) && (ind_In2S1_1[1]>ind_In2S1_1[2]) && (ind_In2S1_2[1]<ind_In2S1_2[2])){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         TrigerBuy=0;
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Procedemos ao teste de nossa estratégia com uso de indicadores. Testamos no período gráfico M5. Obtemos o resultado:

      • Depósito final -3118;
      • Negociações lucrativas 1914;
      • Negociações perdedoras 2843.

      Negociações perdedoras são muito mais do que as lucrativas. O depósito final foi negativo. Talvez a otimização ajude.

      Resultado

      Os resultados da otimização falam por si:

      Resultado da otimização


      Após testar mais umas 10 estratégias diferentes e não obter o resultado desejado, resolvi desenvolver minha própria estratégia. Com base na experiência adquirida de que os próprios indicadores não funcionam, decidi tentar uma abordagem diferente. Decidi chamar a estratégia pelo nome simples de "New".

      Estratégia "New"

      Usaremos as situações de sobrevenda e sobrecompra como ideia principal. Também decidimos adicionar o cálculo de média. Embora eu seja contra essa solução, é interessante experimentar o que acontecerá.

      Indicadores:

      Um indicador Envelopes com configurações padrão de 14, 0, 0,1 método Simole aplicado ao Close .

      Um sinal "para cima" ou a compra de uma opção Call:

      1. O preço Ask é menor que a linha inferior do indicador Envelopes;
      2. A distância em pips da linha inferior do indicador Envelopes até o preço Ask é maior do que o valor Distance.

      Para cima

      Sinal “para baixo” ou compra de uma opção Put:

      1. O preço de compra é maior que a linha superior do indicador Envelopes;
      2. A distância em pips da linha inferior do indicador Envelopes até o preço Bid é maior do que o valor Distance.

      Para baixo

      Essa estratégia não utiliza gatilho. Um novo sinal de entrada é monitorado continuamente se as condições forem atendidas e não houver nenhuma negociação aberta. Abaixo está o código da estratégia sem usar a média:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((OptionRate*ProfitPercent)/100);
           Profit++;
          }
          else{
           XStartDepo=XStartDepo-OptionRate;
           Loss++;
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Testamos no período gráfico de 5 minutos. Parâmetro Distance=150. O resultado do teste sem usar o cálculo da média é mostrado na captura de tela abaixo:

      Resultado 1

      Depósito Final 8952; Negociações lucrativas 874;

      Negociações perdedoras 804.

      As entradas lucrativas superam as perdedoras, mas perdemos parte do depósito. É isso: retorno esperado negativo. Com essa abordagem, a série máxima de entradas perdedoras consecutivas foi de 2, o que considero bom para fazermos a média. 

      O resultado da otimização sem usar a média está na captura de tela abaixo. Optou-se por incluir no relatório apenas situações lucrativas por conveniência e clareza:

      Resultado da otimização 1

      Vamos adicionar o cálculo da média. Decidimos limitar o número de entradas com cálculo da média. Para isso, introduzimos um novo parâmetro Averaging, cujo valor padrão é 4. Abaixo está o código da estratégia com cálculo de média:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+(((XOptionRate*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-(XOptionRate*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Resultados de teste com média. Viva, conseguimos:

      Média 1

      Resultados de otimização com média:

      Resultado da otimização 1

      Resultados de uma variante mais interessante com a multiplicação da aposta depois de negociações perdedoras. Abaixo está o código:

      //Sell (Put)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)==0) && (BidS1>(ind_In1S1_1[0]+(Distance*PointS1)))){
         OpenSell(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_SELL, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_SELL, EAComment);
         }
      
      //Buy (Call)
      
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)==0) && (AskS1<(ind_In1S1_2[0]-(Distance*PointS1)))){
         OpenBuy(symbolS1.Name(), 0.01, 0, 0, EAComment);
         Print(((XOptionRate*LossIn)*LossIn));
         }
         
         if ((CalculatePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment)>0) && (TimeCurrent()>=(GetTime(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)+(XExpirationTime*60)))){
          if(GetProfit(symbolS1.Name(), POSITION_TYPE_BUY, Magic, 0)>0){
           XStartDepo=XStartDepo+((((XOptionRate*LossIn)*LossIn)*ProfitPercent)/100);
           Profit++;
           LossIn=1;
          }
          else{
           XStartDepo=XStartDepo-((XOptionRate*LossIn)*LossIn);
           Loss++;
           LossIn++;
           if(LossIn>Averaging){LossIn=1;}
          }
         Comment("Depo = ",XStartDepo," Profit = ",Profit," Loss = ",Loss); 
         ClosePositions(symbolS1.Name(), Magic, POSITION_TYPE_BUY, EAComment);
         }

      Resultados da otimização de uma variante interessante:

      Resultado da otimização 2


      Considerações finais

      Que conclusões podem ser tiradas de todo esse trabalho? Que 99% de todas as estratégias baseadas em indicadores praticamente não funcionam. Se mudarmos um pouco a abordagem, é possível desenvolver uma boa estratégia que trará lucro. É necessário verificar tudo antes de usá-lo no mercado, e o MetaTrader 5 sempre nos ajudará nisso. A propósito, já existem opções com 100% de lucratividade, o que dá mais o que pensar. Você pode baixar todas as estratégias apresentadas aqui na forma de Expert Advisors no arquivo anexo. Obrigado por sua atenção, amigos, e até breve.


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

      Arquivos anexados |
      MQL5.zip (25.52 KB)
      Como escolher um Expert Advisor: Vinte caraterísticas de um robô de baixa qualidade Como escolher um Expert Advisor: Vinte caraterísticas de um robô de baixa qualidade
      Neste artigo, iremos responder à pergunta de como escolher o Expert Advisor correto. Quais são os mais adequados para o nosso portfólio e como podemos filtrar a maioria dos robôs de negociação disponíveis no mercado? Este artigo apresenta vinte caraterísticas evidentes de um EA de baixa qualidade. Ele ajudará você a tomar decisões mais informadas e criar uma coleção de EAs lucrativos.
      Desenvolvendo um sistema de Replay - Simulação de mercado (Parte 12): Nascimento do SIMULADOR (II) Desenvolvendo um sistema de Replay - Simulação de mercado (Parte 12): Nascimento do SIMULADOR (II)
      Desenvolver um simulador pode ser muito mais interessante do que parece. Então vamos dar mais alguns passos nesta direção, pois a coisa está começando a ficar empolgante.
      Exemplo de criação da estratégia de negociação abrangente Owl Exemplo de criação da estratégia de negociação abrangente Owl
      Minha estratégia se baseia em fundamentos clássicos de negociação e no aprimoramento de indicadores amplamente usados em todos os tipos de mercados. Na verdade, trata-se de uma ferramenta pronta para trabalhar integralmente com a nova estratégia de negociação lucrativa que proponho.
      Desenvolvendo um sistema de Replay - Simulação de mercado (Parte 11): Nascimento do SIMULADOR (I) Desenvolvendo um sistema de Replay - Simulação de mercado (Parte 11): Nascimento do SIMULADOR (I)
      Para poder usar dados que formam barras, precisamos abandonar o replay e começar a desenvolver um simulador. Não sabemos como ela foi criada. Estaremos utilizando as barras de 1 minuto, justamente pelo motivo, de elas nos darem, um nível de complexidade mínimo.