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
568 14
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)
      Últimos Comentários | Ir para discussão (14)
      sydiya63
      sydiya63 | 20 set. 2023 em 11:02
      Muito interessante. Há cerca de 10 anos que estou sentado em um binário. As únicas estratégias que ainda não inventei. Os indicadores padrão não funcionam, na minha opinião. Acho que você precisa se aprofundar na análise de velas, corpo da vela, sombras. Ainda estou no negativo.
      HeAic
      HeAic | 3 fev. 2024 em 19:29

      Para opções binárias (tempo de expiração de 3 minutos), usei uma vez com sucesso o indicador OsMA padrão.

      O único problema é que a precisão da entrada não foi suficiente devido à falta de um período de tempo de 30 segundos no MT4 :)

      Procure o desequilíbrio do mercado - procure o início do movimento em direção ao equilíbrio, este sinal é sempre cumprido ;)

      maxvoronin74
      maxvoronin74 | 15 abr. 2024 em 09:07

      Tentei sua concatenação

         int         total            = PositionsTotal();
         for(int i=total-1; i>=0; i--)
         {
            int    position_magic        = position.Magic();
            string position_symbol       = position.Symbol(); /*PositionGetString(POSITION_SYMBOL)*/;
            ulong  position_ticket       = position.SelectByIndex(i);

      MetaEditor não passa: 'position' - identificador não declarado

      MrBrooklin
      MrBrooklin | 15 abr. 2024 em 09:50

      Você tem essa parte do código?

      #include <Trade\PositionInfo.mqh>
      CPositionInfo  position;

      Caso contrário, insira-a logo após

      #property version   "1.000"

      Atenciosamente, Vladimir.

      maxvoronin74
      maxvoronin74 | 15 abr. 2024 em 15:33
      MrBrooklin #:

      Você tem essa parte do código?

      Caso contrário, insira-a logo após

      Atenciosamente, Vladimir.

      Muito obrigado. Funcionou.
      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.