English Русский 中文 Deutsch 日本語 Português
preview
Probando y optimizando estrategias de opciones binarias en MetaTrader 5

Probando y optimizando estrategias de opciones binarias en MetaTrader 5

MetaTrader 5Probador | 12 mayo 2023, 16:06
691 0
Roman Poshtar
Roman Poshtar

Introducción

Buenas tardes, estimados usuarios de la comunidad MQL5. Hace no mucho, comencé a interesarme por el tema de las opciones binarias. Tras navegar por la red y buscar brókeres, resulta que casi todos utilizan sus propias plataformas para operar. Estas plataformas no tienen capacidad de probar estrategias y cuentan, en el mejor de los casos, con un exiguo conjunto de indicadores estándar. Después de revisar un gran número de estrategias diferentes para las opciones binarias, me planteé la tarea de probar estas estrategias, y también de optimizarlas. Como siempre, nuestro querido MetaTrader 5 vino al rescate. Y como siempre, trataré de compartir mis experimentos con usted de la forma más sencilla posible, sin fórmulas ni códigos complicados. Pero antes, veamos un poco de teoría y algunos argumentos sobre si conviene o no dedicarse a las opciones binarias.


Teoría

Una opción binaria es un contrato digital que predice la dirección del precio de un activo en el intervalo temporal seleccionado. ¿Cómo trabajar con opciones binarias? El reto se reduce a identificar correctamente una de las dos evoluciones probables del mercado: si el activo subirá o bajará. En la actualidad, existe una amplia gama de opciones en línea para divisas, valores y materias primas. Prácticamente cualquier cosa, incluido el pronóstico del tiempo, puede ser un activo. Para empezar a comerciar no se requiere una gran inversión ni amplios conocimientos financieros y económicos sobre los procesos bursátiles del mercado.


Tipos de opciones binarias

"Up/Down" es la más fácil y directa de todas las opciones binarias: todo lo que un tráder tiene que hacer para obtener beneficios es determinar en qué dirección irá el precio, hacia arriba o hacia abajo. En una tendencia alcista, resulta aconsejable comprar "Up" (Call). La opción "Down" (Put) se compra si se espera un movimiento a la baja del activo. El beneficio de las opciones "Up/Down" oscila entre el 10% y el 80% de la apuesta.

"One touch" representa un acuerdo en el que se exige determinar la consecución del nivel de precios deseado. No importa dónde se encuentren las cotizaciones al cierre; lo decisivo es que toquen un nivel determinado. La rentabilidad de "One touch" es superior a la habitual, ya que en la mayoría de los casos resulta muy difícil de predecir, y alcanza el 95%, pero se puede perder el 100%.

"Límite" ("Range") define el corredor de precios dentro del cual se situará el valor del activo en el momento del vencimiento. También resulta difícil de entender y predecir. La rentabilidad alcanza el 95%.

Más abajo en este artículo, probaremos y optimizaremos estrategias para las opciones "Up/Down" como las más populares, en mi opinión.


Ventajas e inconvenientes

Ventajas:

  • Simplicidad - usted fija la cantidad de las pérdidas o los beneficios potenciales evitando la necesidad de realizar cálculos complejos para los niveles de Stop Loss y Take Profit, lo que resulta especialmente útil si es principiante.
  • Registro sencillo en el sitio web del bróker de opciones - ocupa poco tiempo y no hay trámites burocráticos, cosa que en el caso de la bolsa de valores o el mercado de futuros resulta imprescindible.
  • Amplia variedad de recursos - acciones de empresas, índices bursátiles, petróleo, oro, criptomonedas, pero con fondos mínimos a partir de 100 dólares, y con algunos brókeres menos. Al comerciar en los mercados de valores o de futuros, la suma del depósito inicial debe ser mayor.

Desventajas:

  • Alto riesgo y una expectativa de rentabilidad negativa. Se necesitan dos victorias para compensar una derrota. Eficiencia de ingresos de hasta el 80%. Una operación fallida costará más que una operación ganadora.
  • El modo "Casino" trae pérdidas a largo plazo. Algunos intentan usar técnicas de casino o métodos de promediación como el "Martingale", que va categóricamente en contra de las reglas del trading correcto. Eso es lo que considero una fuga de depósitos del 100% a largo plazo.
  • Comisiones bastante elevadas que se cobran a la mínima ocasión al comerciar.

    Pareja de divisas. Rango de optimización y pruebas forward. Ajustes

    Aquí ofreceremos todos los parámetros para la optimización y las pruebas, para no repetirnos más en el texto:

    • Mercado Fórex;
    • Pareja de divisas EURUSD;
    • Periodo M5, M15, M30, H1;
    • plazo de expiración 5, 15, 30 minutos y 1 hora.
    • Rango de optimización 1 año. Desde 2021.01.28 hasta 2022.01.28
    • El intervalo de pruebas forward es de 1 año. Del 2022.01.28 al 2023.01.28;
    • Depósito inicial 10000;
    • Tasa 10;
    • El porcentaje de remuneración es del 80%.

      Aspectos técnicos

      Para probar y optimizar, requeriremos los parámetros de entrada:

      1. StartDepo - depósito inicial;
      2. OptionRate - tasa;
      3. ExpirationTime - Hora de expiración;
      4. ProfitPercent - porcentaje de rentabilidad;
      5. TimeFrame - marco temporal de los indicadores;
      6. Optimization - interruptor de optimización;
      7. OptimizationFileName - nombre del archivo para almacenar los resultados de la optimización.
      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";

      También necesitaremos las variables para almacenar y monitorear los cambios en el depósito y el número de compras de opciones rentables y perdedoras:

      1. XStartDepo - para guardar el depósito actual;
      2. Profit - para almacenar el número de compras de opciones rentables
      3. Loss - para almacenar el número de compras de opciones perdedoras;
      double XStartDepo = StartDepo;
      int Profit=0;
      int Loss=0;

      Para monitorear la hora de apertura de una posición y cerrar esta después de la hora de expiración, vamos a usar una función en MetaTrader 5 que retorna la hora de apertura de una posición.

      //+------------------------------------------------------------------+
      //| 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 monitorear la rentabilidad de una posición y decidir si hemos ganado o no la apuesta, usaremos una función que retornará el beneficio de una posición abierta en el momento actual. Las comisiones y el swap no están incluidos.

      //+------------------------------------------------------------------+
      //| 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 que solo entre en funcionamiento la nueva señal entrante, podemos aplicar varios disparadores. Es decir, el permiso de entrada solo se dará al recibir una nueva señal. Las entradas repetidas en la misma señal se ignorarán:

      1. TrigerSell - comprar una opción de venta;
      2. TrigerBuy - comprar una opción de compra;
      int TrigerSell=0;
      int TrigerBuy=0;

      La salida de una posición, la suma y la resta de fondos del depósito inicial y el cálculo de las pérdidas y beneficios de las compras de opciones se realizan mediante el seguimiento de la hora actual en relación con la hora de apertura y el vencimiento de la posición.

      //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);
         }

      Para la optimización, utilizaremos variables para determinar el plazo y la hora de expiración correctos. El modo de optimización se activará con la ayuda de la variable Optimization. La esencia de la optimización se reduce al uso de archivos de tipo CSV. Al finalizar la prueba, escribimos todas las variables necesarias en el archivo en OnDeinit. Al realizar la optimización, nuestros asesores crean un archivo CSV con el resultado en la ruta «C:\Users\Su nombre de usuario\AppData\Roaming\MetaQuotes\Terminal\Common\Files».

      1. Depósito final;
      2. Número de transacciones rentables;
      3. Número de transacciones perdedoras;
      4. Marco temporal;
      5. Hora de expiración.
      //+------------------------------------------------------------------+
      //| 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);
           }
       }
      }
      
        }

      La prueba puede monitorearse en el modo de visualización. Para mayor sencillez, usaremos Comment() para mostrar el resultado actual.

      Resultado actual


      Estrategias

      Estrategia «2Ma+RSI+Stochastic Oscillator»

      Esta estrategia la ofrece un conocido bróker como estrategia de scalping para opciones binarias. El marco temporal sugerido es de 5 minutos. El tiempo de expiración es de 5 minutos.

      Indicadores:

      1. Un par de medias móviles exponenciales con periodos de 5 y 10;
      2. Índice de fuerza relativa (RSI), configuración por defecto;
      3. "Stochastic Oscillator" (Oscilador Estocástico) con ajustes de 14, 3, 3.

      La señal «Up», o compra de una opción Call, aparece si se cumplen una serie de condiciones:

      1. La media de color rojo ha cruzado la media azul de abajo hacia arriba;
      2. El índice de fuerza relativa se sitúa por encima del nivel 50;
      3. La línea estocástica rápida ha cruzado la línea lenta (línea punteada) de abajo hacia arriba.

      Estrategia Up 1

      La señal «Down», o compra de una opción Put, también se forma cuando se dan determinados factores:
      1. La media roja ha cruzado la azul de arriba hacia abajo;
      2. El RSI se encuentra por debajo del nivel 50;
      3. La línea rápida del oscilador estocástico cruza la línea lenta de arriba hacia abajo.

      Estrategia Down 1

      Como disparador para la nueva señal en esta estrategia, he elegido el cruce de la MA en la dirección opuesta. A continuación, mostramos el código de la estrategia.

      //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);
         }

      Tras la prueba, obtenemos el resultado:

      • Depósito final 1964;
      • 1273 transacciones rentables;
      • Hay 1822 transacciones perdedoras.

      Resultado

      Una vez realizada la optimización, obtendremos el resultado. Como podemos ver, en ningún marco temporal o tiempo de expiración hemos obtenido un aumento positivo de nuestro depósito.

      Resultado de la optimización


      Estrategia «Maverick»

      Una estrategia interesante y sin complicaciones para las opciones, lleva el nombre en clave «Maverick». La estrategia se basa en dos indicadores de análisis técnico. En teoría, determina los puntos de entrada y salida con bastante precisión. Presupone comerciar en marcos temporales de 1 a 5 minutos, y puede abrir varios gráficos con diferentes activos al mismo tiempo para obtener más señales.

      Indicadores:

      1. Indicador de Bandas de Bollinger con parámetros 20 y StDev (desviación estándar) 2;
      2. Indicador RSI. Los parámetros de RSI son 4, con límites de 80 y 20.

      Pronóstico de crecimiento. Compra de una opción Call:

      Tan pronto como la línea del indicador RSI entre en la zona de sobreventa por debajo de 20, al tiempo que la línea de precios toca o va más allá de las Bandas de Bollinger, esperaremos a la primera vela alcista y entraremos en una operación UP.

      Compra Up (alcista)

      Pronóstico de caída. Compra de una opción Put:

      Tan pronto como la línea del indicador RSI entre en la zona de sobrecompra por encima de 80, al tiempo que la línea de precios toca o va más allá de las Bandas de Bollinger, esperaremos a la primera vela bajista y entraremos en una operación DOWN.

      Compra DOWN (bajista)

      Como disparador de una nueva señal en esta estrategia, hemos elegido el cierre de la vela anterior dentro del canal de Bollinger. A continuación, mostramos el código de la estrategia.

      //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);
         }

      Vamos a proceder a la prueba. Realizaremos la prueba en el marco temporal M5. Y obtenemos el siguiente resultado:

      • El depósito final es de 3312;
      • Tenemos 1589 transacciones rentables;
      • Las transacciones perdedoras son 1940.

      Resultado

      Qué podemos decir: tenemos pérdidas, aunque el resultado es ligeramente mejor que en la estrategia anterior. Tras realizar una optimización con la esperanza de obtener valores de depósito positivos, vemos que, por desgracia, la estrategia no funciona:

      Resultado de la optimización


      Estrategia «Vortex+TSI»

      La estrategia de opciones binarias se llama Vortex porque se utiliza el indicador del mismo nombre. De hecho, hay dos indicadores involucrados en la estrategia: el indicador principal, más un segundo indicador como filtro. El marco temporal sugerido va de 1 a 5 minutos.

      Indicadores:

      1. Vortex con parámetro 14;
      2. True Strength Indicator (TSI) con parámetros 25, 13, 5, Exponential.

      Para comprar una opción de aumento de precio:

      1. Esperaremos a la intersección simultánea de las líneas de ambos indicadores, cuando las líneas azules estén en la parte superior y las rojas bajen;
      2. Las líneas del indicador Vortex deberían divergir.

      Crecimiento

      Para comprar una opción de caída de precio:

      1. Esperaremos a la intersección simultánea de las líneas de ambos indicadores, cuando las líneas rojas estén en la parte superior y las azules bajen;
      2. Las líneas del indicador Vortex deberían divergir.

      Caída

      El disparador de la nueva señal será el cruce inverso del indicador True Strength Indicator. A continuación, mostramos el código de la estrategia.
      //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);
         }

      Vamos a probar nuestra estrategia de indicadores. Realizaremos la prueba en el marco temporal M5. Y obtenemos el siguiente resultado:

      • El depósito final es -3118;
      • Transacciones rentables 1914;
      • Hay 2843 transacciones perdedoras.

      Hay muchas más transacciones perdedoras que rentables. El último depósito ha entrado en negativo. Quizá la optimización sirva de ayuda.

      Resultado

      Los resultados de la optimización realizada hablan por sí solos:

      Resultado de la optimización


      Tras probar unas 10 estrategias diferentes y no obtener los resultados deseados, he decidido desarrollar mi propia estrategia. Basándome en mi experiencia de que los indicadores en sí no funcionan, he decidido probar un enfoque diferente. Llamaremos a la estrategia con un nombre sencillo: «New».

      Estrategia «New»

      Usaremos las situaciones de sobreventa y sobrecompra como idea básica. También he decidido añadir la promediación. Aunque me opongo a esta solución, me interesa probar qué sucederá.

      Indicadores:

      Un indicador Envelopes con ajustes estándar 14, 0, 0,1 y un método Simole aplicado a Close.

      Señal "Up", o compra de una opción Call:

      1. El precio Ask es inferior a la línea inferior del indicador Envelopes;
      2. La distancia en pips desde la línea inferior del indicador Envelopes hasta el precio Ask es mayor que el valor Distance.

      Up

      Señal «Down», o compra de una opción Put:

      1. El precio Bid es superior a la línea superior del indicador Envelopes;
      2. La distancia en pips desde el precio Bid hasta la línea del indicador Envelopes es mayor que el valor Distance.

      Down

      En esta estrategia no se utiliza disparador. La nueva señal de entrada se monitorea constantemente, si se cumplen las condiciones y no hay ninguna transacción abierta. A continuación, le mostramos el código de la estrategia sin el uso de promediación:

      //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);
         }

      Probaremos en un marco temporal de 5 minutos. Parámetro Distance=150. El resultado de la prueba sin utilizar promediación se muestra en la siguiente captura de pantalla:

      Resultado 1

      Depósito final 8952; Transacciones rentables 874;

      Hay 804 transacciones perdedoras.

      Las entradas rentables superan a las no rentables, pero hemos perdido parte de nuestro depósito. Aquí lo tenemos: una esperanza matemática negativa. Con este enfoque, la serie máxima de entradas perdedoras seguidas ha sido de 2, lo cual, a mi juicio, jugará a nuestro favor a la hora de promediar. 

      El resultado de la optimización sin utilizar el promedio se muestra en la siguiente captura de pantalla. He decidido informar solo de las situaciones rentables por comodidad y claridad:

      Resultado de la optimización 1

      Vamos a añadir la promediación. He decidido limitar el número de entradas de promediación. Para ello, hemos introducido un nuevo parámetro, Averaging, que por defecto es 4. A continuación, le mostramos el código de la estrategia con promediación:

      //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 las pruebas con promediación. ¡Hurra! ¡Lo hemos conseguido!:

      Promediación 1

      Resultados de la optimización con promediación:

      Resultado de la optimización 1

      Resultados de la opción más interesante con multiplicación de la apuesta tras operaciones perdedoras. A continuación, le mostramos el 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 de optimización de la opción interesante:

      Resultado de la optimización 2


      Conclusión

      ¿Qué conclusiones podemos extraer de todo el trabajo realizado? Bueno, el 99% de las estrategias con indicadores prácticamente no funcionan. Con un ligero cambio de enfoque, podemos desarrollar una buena estrategia que resulte rentable. Eso sí, deberemos comprobar todo antes de utilizarlo en el mercado, y como siempre, MetaTrader 5 nos ayudará con ello. Por cierto, ya existen opciones con una rentabilidad del 100%, lo cual da que pensar. Podrá descargar todas las estrategias presentadas aquí en forma de asesores en el archivo adjunto. Gracias por su atención, amigos, y hasta la próxima.


      Traducción del ruso hecha por MetaQuotes Ltd.
      Artículo original: https://www.mql5.com/ru/articles/12103

      Archivos adjuntos |
      MQL5.zip (24.76 KB)
      Cómo construir un EA que opere automáticamente (Parte 13): Automatización (V) Cómo construir un EA que opere automáticamente (Parte 13): Automatización (V)
      ¿Sabes lo que es un diagrama de flujo? ¿Sabes cómo utilizarlo? ¿Cree que los diagramas de flujo son sólo cosas de aprendiz de programador? Pues echa un vistazo a este artículo y aprende a trabajar con diagramas de flujo.
      Teoría de categorías en MQL5 (Parte 2) Teoría de categorías en MQL5 (Parte 2)
      La teoría de categorías es una rama diversa y en expansión de las matemáticas, relativamente inexplorada aún en la comunidad MQL5. Esta serie de artículos tiene como objetivo destacar algunos de sus conceptos para crear una biblioteca abierta y seguir utilizando esta maravillosa sección para crear estrategias comerciales.
      Perceptrón multicapa y algoritmo de retropropagación (Parte 3): Integración con el simulador de estrategias - Visión general (I) Perceptrón multicapa y algoritmo de retropropagación (Parte 3): Integración con el simulador de estrategias - Visión general (I)
      El perceptrón multicapa es una evolución del perceptrón simple, capaz de resolver problemas separables no linealmente. Junto con el algoritmo de retropropagación, es posible entrenar eficientemente esta red neuronal. En la tercera parte de la serie sobre el perceptrón multicapa y la retropropagación, mostraremos cómo integrar esta técnica con el simulador de estrategias. Esta integración permitirá utilizar análisis de datos complejos y tomar mejores decisiones para optimizar las estrategias de negociación. En este resumen, analizaremos las ventajas y los retos de la aplicación de esta técnica.
      Recetas MQL5 - Base de datos de eventos macroeconómicos Recetas MQL5 - Base de datos de eventos macroeconómicos
      El presente artículo analiza las posibilidades de trabajar con bases de datos que utilizan el motor SQLite como base. Hemos creado una clase CDatabase para usar de forma cómoda y eficaz los principios de la programación orientada a objetos. Posteriormente se utilizará para crear y gestionar una base de datos de eventos macroeconómicos. Asimismo, ofreceremos ejemplos de muchos métodos de la clase CDatabase.