Descargar MetaTrader 5

Cómo evaluar los resultados de los Asesores Expertos

28 enero 2016, 12:34
Slawa
0
251

Primero de todo, vamos a explicar el procedimiento de las pruebas en unas cuantas líneas. Antes de comenzar con las pruebas, el subsistema carga el asesor experto, estableciendo los parámetros previamente definidos por el usuario, y llama a la función init(). A continuación el Probador recorre la secuencia generada y llama cada vez a la función start(). Al terminar la secuencia de pruebas, el Probador llama a la función deinit(). Entonces está disponible el historial de trading completo, generado durante las pruebas. La eficiencia del asesor experto se puede analizar en ese momento.

La función CalculateSummary proporciona los cálculos de los resultados de las pruebas, es decir, los datos del informe estándar del Probador de Estrategias.

void CalculateSummary(double initial_deposit)
  {
   int    sequence=0, profitseqs=0, lossseqs=0;
   double sequential=0.0, prevprofit=EMPTY_VALUE, drawdownpercent, drawdown;
   double maxpeak=initial_deposit, minpeak=initial_deposit, balance=initial_deposit;
   int    trades_total=HistoryTotal();
//---- inicializamos los resúmenes
   InitializeSummaries(initial_deposit);
//----
   for(int i=0; i<trades_total; i++)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      int type=OrderType();
      //---- depósito inicial no considerado
      if(i==0 && type==OP_BALANCE) continue;
      //---- calculamos el beneficio
      double profit=OrderProfit()+OrderCommission()+OrderSwap();
      balance+=profit;
      //---- comprobación de la reducción
      if(maxpeak<balance)
        {
         drawdown=maxpeak-minpeak;
         if(maxpeak!=0.0)
           {
            drawdownpercent=drawdown/maxpeak*100.0;
            if(RelDrawdownPercent<drawdownpercent)
              {
               RelDrawdownPercent=drawdownpercent;
               RelDrawdown=drawdown;
              }
           }
         if(MaxDrawdown<drawdown)
           {
            MaxDrawdown=drawdown;
            if(maxpeak!=0.0) MaxDrawdownPercent=MaxDrawdown/maxpeak*100.0;
            else MaxDrawdownPercent=100.0;
           }
         maxpeak=balance;
         minpeak=balance;
        }
      if(minpeak>balance) minpeak=balance;
      if(MaxLoss>balance) MaxLoss=balance;
      //---- solo órdenes de mercado
      if(type!=OP_BUY && type!=OP_SELL) continue;
      SummaryProfit+=profit;
      SummaryTrades++;
      if(type==OP_BUY) LongTrades++;
      else             ShortTrades++;
      //---- operaciones perdedoras
      if(profit<0)
        {
         LossTrades++;
         GrossLoss+=profit;
         if(MinProfit>profit) MinProfit=profit;
         //---- cambio de suerte
         if(prevprofit!=EMPTY_VALUE && prevprofit>=0)
           {
            if(ConProfitTrades1<sequence ||
               (ConProfitTrades1==sequence && ConProfit2<sequential))
              {
               ConProfitTrades1=sequence;
               ConProfit1=sequential;
              }
            if(ConProfit2<sequential ||
               (ConProfit2==sequential && ConProfitTrades1<sequence))
              {
               ConProfit2=sequential;
               ConProfitTrades2=sequence;
              }
            profitseqs++;
            AvgConWinners+=sequence;
            sequence=0;
            sequential=0.0;
           }
        }
      //---- operaciones ganadoras (profit>=0)
      else
        {
         ProfitTrades++;
         if(type==OP_BUY)  WinLongTrades++;
         if(type==OP_SELL) WinShortTrades++;
         GrossProfit+=profit;
         if(MaxProfit<profit) MaxProfit=profit;
         //---- cambio de suerte
         if(prevprofit!=EMPTY_VALUE && prevprofit<0)
           {
            if(ConLossTrades1<sequence ||
               (ConLossTrades1==sequence && ConLoss2>sequential))
              {
               ConLossTrades1=sequence;
               ConLoss1=sequential;
              }
            if(ConLoss2>sequential ||
               (ConLoss2==sequential && ConLossTrades1<sequence))
              {
               ConLoss2=sequential;
               ConLossTrades2=sequence;
              }
            lossseqs++;
            AvgConLosers+=sequence;
            sequence=0;
            sequential=0.0;
           }
        }
      sequence++;
      sequential+=profit;
      //----
      prevprofit=profit;
     }
//---- comprobación de reducción final
   drawdown=maxpeak-minpeak;
   if(maxpeak!=0.0)
     {
      drawdownpercent=drawdown/maxpeak*100.0;
      if(RelDrawdownPercent<drawdownpercent)
        {
         RelDrawdownPercent=drawdownpercent;
         RelDrawdown=drawdown;
        }
     }
   if(MaxDrawdown<drawdown)
     {
      MaxDrawdown=drawdown;
      if(maxpeak!=0) MaxDrawdownPercent=MaxDrawdown/maxpeak*100.0;
      else MaxDrawdownPercent=100.0;
     }
//---- consideramos la última transacción
   if(prevprofit!=EMPTY_VALUE)
     {
      profit=prevprofit;
      if(profit<0)
        {
         if(ConLossTrades1<sequence ||
            (ConLossTrades1==sequence && ConLoss2>sequential))
           {
            ConLossTrades1=sequence;
            ConLoss1=sequential;
           }
         if(ConLoss2>sequential ||
            (ConLoss2==sequential && ConLossTrades1<sequence))
           {
            ConLoss2=sequential;
            ConLossTrades2=sequence;
           }
         lossseqs++;
         AvgConLosers+=sequence;
        }
      else
        {
         if(ConProfitTrades1<sequence ||
            (ConProfitTrades1==sequence && ConProfit2<sequential))
           {
            ConProfitTrades1=sequence;
            ConProfit1=sequential;
           }
         if(ConProfit2<sequential ||
            (ConProfit2==sequential && ConProfitTrades1<sequence))
           {
            ConProfit2=sequential;
            ConProfitTrades2=sequence;
           }
         profitseqs++;
         AvgConWinners+=sequence;
        }
     }
//---- recopilación hecha
   double dnum, profitkoef=0.0, losskoef=0.0, avgprofit=0.0, avgloss=0.0;
//---- ganancias y pérdidas consecutivas medias
   dnum=AvgConWinners;
   if(profitseqs>0) AvgConWinners=dnum/profitseqs+0.5;
   dnum=AvgConLosers;
   if(lossseqs>0)   AvgConLosers=dnum/lossseqs+0.5;
//---- valores absolutos
   if(GrossLoss<0.0) GrossLoss*=-1.0;
   if(MinProfit<0.0) MinProfit*=-1.0;
   if(ConLoss1<0.0)  ConLoss1*=-1.0;
   if(ConLoss2<0.0)  ConLoss2*=-1.0;
//---- factor de beneficio
   if(GrossLoss>0.0) ProfitFactor=GrossProfit/GrossLoss;
//---- rentabilidad esperada
   if(ProfitTrades>0) avgprofit=GrossProfit/ProfitTrades;
   if(LossTrades>0)   avgloss  =GrossLoss/LossTrades;
   if(SummaryTrades>0)
     {
      profitkoef=1.0*ProfitTrades/SummaryTrades;
      losskoef=1.0*LossTrades/SummaryTrades;
      ExpectedPayoff=profitkoef*avgprofit-losskoef*avgloss;
     }
//---- disminución absoluta
   AbsoluteDrawdown=initial_deposit-MaxLoss;
  }
Hay que conocer el valor inicial del depósito para que los cálculos sean correctos. Para ello hay que llamar a la función AccountBalance() en la función init(). Esto calculará el valor del depósito justo cuando comiencen las pruebas.
void init()
  {
   ExtInitialDeposit=AccountBalance();
  }
El beneficio se calcula en la divisa del depósito, tanto en la función CalculateSummary como en el informe estándar. Los resultados de trading tales como la "Mayor operación de beneficios" o la "Pérdida consecutiva máxima" se calculan en función del beneficio, y también se miden en términos de dinero. Por lo tanto, recalcular el beneficio en puntos es sencillo.
...
      //---- solo órdenes de mercado
      if(type!=OP_BUY && type!=OP_SELL) continue;
      //---- calculamos el beneficio en puntos
      profit=(OrderClosePrice()-OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT);
      SummaryProfit+=profit;
...
Los resultados obtenidos se escriben en el archivo del informe con la función WriteReport.
void WriteReport(string report_name)
  {
   int handle=FileOpen(report_name,FILE_CSV|FILE_WRITE,'\t');
   if(handle<1) return;
//----
   FileWrite(handle,"Depósito inicial          ",InitialDeposit);
   FileWrite(handle,"Beneficio neto total      ",SummaryProfit);
   FileWrite(handle,"Beneficio bruto           ",GrossProfit);
   FileWrite(handle,"Pérdida bruta             ",GrossLoss);
   if(GrossLoss>0.0)
      FileWrite(handle,"Factor de beneficio       ",ProfitFactor);
   FileWrite(handle,"Rentabilidad esperada     ",ExpectedPayoff);
   FileWrite(handle,"Disminución absoluta      ",AbsoluteDrawdown);
   FileWrite(handle,"Disminución máxima        ",
                     MaxDrawdown,
                     StringConcatenate("(",MaxDrawdownPercent,"%)"));
   FileWrite(handle,"Disminución relativa      ",
                     StringConcatenate(RelDrawdownPercent,"%"),
                     StringConcatenate("(",RelDrawdown,")"));
   FileWrite(handle,"Total de operaciones         ",SummaryTrades);
   if(ShortTrades>0)
      FileWrite(handle,"Posiciones cortas (ganado %)    ",
                        ShortTrades,
                        StringConcatenate("(",100.0*WinShortTrades/ShortTrades,"%)"));
   if(LongTrades>0)
      FileWrite(handle,"Posiciones largas (ganado %)     ",
                        LongTrades,
                        StringConcatenate("(",100.0*WinLongTrades/LongTrades,"%)"));
   if(ProfitTrades>0)
      FileWrite(handle,"Operaciones de beneficios (% del total)",
                        ProfitTrades,
                        StringConcatenate("(",100.0*ProfitTrades/SummaryTrades,"%)"));
   if(LossTrades>0)
      FileWrite(handle,"Operaciones de pérdidas (% del total)  ",
                        LossTrades,
                        StringConcatenate("(",100.0*LossTrades/SummaryTrades,"%)"));
   FileWrite(handle,"Mayor operación de beneficios      ",MaxProfit);
   FileWrite(handle,"Mayor operación de pérdidas        ",-MinProfit);
   if(ProfitTrades>0)
      FileWrite(handle,"Operación de beneficios media      ",GrossProfit/ProfitTrades);
   if(LossTrades>0)
      FileWrite(handle,"Operación de pérdidas media        ",-GrossLoss/LossTrades);
   FileWrite(handle,"Media de ganancias consecutivas  ",AvgConWinners);
   FileWrite(handle,"Media de pérdidas consecutivas",AvgConLosers);
   FileWrite(handle,"Ganancias consecutivas máximas (beneficios en dinero)",
                     ConProfitTrades1,
                     StringConcatenate("(",ConProfit1,")"));
   FileWrite(handle,"Pérdidas consecutivas máximas (pérdidas en dinero)",
                     ConLossTrades1,
                     StringConcatenate("(",-ConLoss1,")"));
   FileWrite(handle,"Máximo beneficio consecutivo (número de ganancias)",
                     ConProfit2,
                     StringConcatenate("(",ConProfitTrades2,")"));
   FileWrite(handle,"Máxima pérdida consecutiva (número de pérdidas)",
                     -ConLoss2,
                     StringConcatenate("(",ConLossTrades2,")"));
//----
   FileClose(handle);
  }
El siguiente ejemplo ilustra cómo generar un informe con estas funciones.
void deinit()
  {
   if(!IsOptimization())
     {
      if(!IsTesting()) ExtInitialDeposit=CalculateInitialDeposit();
      CalculateSummary(ExtInitialDeposit);
      WriteReport("MACD_Sample_Report.txt");
     }
  }
Como se observa, los informes se generan no solo después de realizar las pruebas, sino también en la desinicialización del asesor experto. Tal vez usted se pregunte cómo se puede conocer el tamaño del depósito inicial si el historial de la cuenta se descarga en el terminal sólo parcialmente, por ejemplo, con los datos de un solo mes. La función CalculateInitialDeposit ayuda a resolver este problema.
double CalculateInitialDeposit()
  {
   double initial_deposit=AccountBalance();
//----
   for(int i=HistoryTotal()-1; i>=0; i--)
     {
      if(!OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)) continue;
      int type=OrderType();
      //---- depósito inicial no considerado
      if(i==0 && type==OP_BALANCE) break;
      if(type==OP_BUY || type==OP_SELL)
        {
         //---- calculamos el beneficio
         double profit=OrderProfit()+OrderCommission()+OrderSwap();
         //---- disminuimos el depósito
         initial_deposit-=profit;
        }
      if(type==OP_BALANCE || type==OP_CREDIT)
         initial_deposit-=OrderProfit();
     }
//----
   return(initial_deposit);
  }
Los informes se generan de este modo en el terminal cliente MetaTrader 4.


Se puede comparar con los datos calculados por el programa.
Depósito inicial             10000
Beneficio neto total            -13.16
Beneficio bruto                20363.32
Pérdida bruta                  20376.48
Factor de beneficio               0.99935416
Rentabilidad esperada             -0.01602923
Disminución absoluta           404.28
Disminución máxima            1306.36 (11.5677%)
Disminución relativa           11.5966%    (1289.78)
Total de operaciones                    821
Posiciones cortas(ganado %)      419 (24.821%)
Posiciones largas(ganado %)       402 (31.592%)
Operaciones de beneficios (% del total)  231 (28.1364%)
Operaciones de pérdidas (% del total)    590 (71.8636%)
Mayor operación de beneficios        678.08
Mayor operación de pérdidas          -250
Operación de beneficios media        88.15290043
Operación de pérdidas media          -34.53640678
Media de ganancias consecutivas    1
Media de pérdidas consecutivas  4
Ganancias consecutivas máximas (beneficios en dinero)  4   (355.58)
Pérdidas consecutivas máximas (pérdidas en dinero)  15  (-314.74)
Máximo beneficio consecutivo (número de ganancias)  679.4   (2)
Máxima pérdida consecutiva (número de pérdidas)  -617.16 (8)
Se recomienda poner el archivo SummaryReport.mq4 en el directorio experts\include, e insertarlo mediante la directiva #include. Dicho archivo se adjunta en este artículo.
#include <SummaryReport.mq4>
 
double ExtInitialDeposit;
 

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

Archivos adjuntos |
MetaTrader 5 - ¡Más de lo que puedas imaginar! MetaTrader 5 - ¡Más de lo que puedas imaginar!

El terminal de cliente de MetaTrader 5 ha sido desarrollado desde cero y mejora con creces a su predecesor. La nueva plataforma ofrece oportunidades ilimitadas para operar en cualquier mercado financiero. Además, se ha ampliado su funcionalidad para ofrecer aún más características y facilidad de uso. Todo ello hace que sea muy difícil la enumeración de todas las ventajas de MetaTrader 5. Hemos intentado describir brevemente todas estas ventajas en un único artículo y nos ha sorprendido ver que el resultado ¡no ha sido nada breve!

Aumente la velocidad de los cálculos con la red en la nube de MQL5 Aumente la velocidad de los cálculos con la red en la nube de MQL5

¿Cuántos procesadores tiene tu ordenador? ¿Cuántos ordenadores puedes usar para optimizar una estrategia de trading? Aquí mostraremos cómo usar la red en la nube de MQL5 para acelerar los cálculos recibiendo la capacidad de procesamiento a través de la red mundial con solo el clic de un ratón. La frase "el tiempo es dinero" se hace más evidente aun con el paso de los años, y no podemos permitirnos esperar para realisar cálculos importantes durante decenas de horas o incluso días.

Trabajando con cestas de parejas de divisas en el mercado fórex Trabajando con cestas de parejas de divisas en el mercado fórex

En el artículo se analizan cuestiones relacionadas con la división en grupos de las parejas de divisas, las cestas; también sobre cómo obtener datos sobre el estado de estas cestas (por ejemplo, sobrecompra o sobreventa); qué indicadores pueden proporcionar estos datos; y al fin, sobre cómo se puede aplicar la información obtenida en el trading práctico.

Red neuronal profunda con Stacked RBM. Auto-aprendizaje, auto-control Red neuronal profunda con Stacked RBM. Auto-aprendizaje, auto-control

El artículo es la continuación de artículos anteriores sobre neuroredes profundas y elección de predictores. En este veremos las particularidades de una neurored iniciada con Stacked RBM, así como su implementación en el paquete "darch".