Descargar MetaTrader 5

Simulación de patrones que surgen al comerciar con cestas de parejas de divisas. Parte I

5 septiembre 2017, 16:20
Andrei Novichkov
0
1 096

Introducción

En pasados artículos dedicados al comercio con uso de cestas de parejas de divisas, hemos analizado el propio principio comercial, los recursos de análisis técnico y los patrones que se pueden detectar con dichos recursos. Está claro que trabajar con estas metodologías no es posible sin confirmar ciertos parámetros de los patrones. Por ejemplo, es necesario especificar los valores concretos según los cuales se deberán colocar los niveles de sobrecopra / sobreventa. Aquí y en lo sucesivo, nos dedicaremos a esclarecer los parámetros de los patrones localizados, así como al desarrollo de recomendaciones para los tráders en lo que respecta al comercio.

Herramientas de investigación

Para trabajar, usaremos el indicador "WPR combinado", que ya desarrollamos previamente. En la anterior serie de artículos se usó más de una vez, precisamente con él detectamos la mayoría de los patrones.

Para suavizar un poco el gráfico del indicador, aumentaremos el periodo de WPR de catorce (14) a veinte (20). Esto permitirá "enderezar" el gráfico sin perder calidad de representación.

Realizaremos la investigación con tres marcos temporales: D1, H4 y H1. Usted podrá obtener los resultados de otros periodos usando los métodos descritos en este artículo. 

La terminología básica y los principios de la metodología se explican aquí.

Patrones para la investigación

Vamos a comenzar la investigación por el patrón №3, descrito aquí. El patrón no es demasiado complejo, ya hace mucho que conocemos su análogo para una pareja de divisas aparte. Para el comercio con cestas de parejas de divisas, se aplicará así:

El tráder recibe la señal de entrada para todas las parejas de divisas de la cesta con la condición de que el nivel de sobrecompra haya sido roto de arriba hacia abajo o el nivel de sobreventa haya sido roto de abajo hacia arriba por el gráfico del indicador WPR combinado después del cierre de la vela.

Así que de inmediato surge la pregunta: ¿dónde se encuentran estos niveles de sobrecompra y sobreventa?  En el caso del indicador WPR estándar para una pareja aparte, la respuesta a esta pregunta es conocida:

  • Nivel de sobrecompra: - 20%
  • Nivel de sobreventa: - 80%

Esto nos dará un punto de partida en las investigaciones. Utilizando estos datos, intentaremos precisar la ubicación de los niveles para el WPR combinado. Los resultados nos serán de ayuda, no solo al realizar comprobaciones sobre el patrón analizado, sino también en otros casos análogos. También nos será útil la metodología aplicada.

Para que el gráfico del indicador rompa uno de los niveles, antes de la ruptura deberá o bien estar por encima del nivel de sobrecompra, o bien por debajo del nivel de sobreventa. Vamos a ver en la historia qué número de entradas potenciales nos ha proporcionado el mercado. En esta etapa no utilizaremos los asesores, sino que usaremos los indicadores testIndexZig-Zag1.mq5 y testWPReur.mq5, desarrollados con anterioridad. En testWPReur.mq5 simplemente sustituiremos los datos según los componentes de la cesta. Simplificaremos ligeramente el código fuente del indicador  testIndexZig-Zag1.mq5, puesto que ya conocemos los valores máximo y mínimo del indicador(de 100% a -100%):

#property copyright "Copyright 2016, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_separate_window
#property indicator_buffers 6
#property indicator_plots   3
//--- plot High
#property indicator_label1  "High"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrGreen
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot Low
#property indicator_label2  "Low"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrGreen
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot ZigZag
#property indicator_label3  "ZigZag"
#property indicator_type3   DRAW_SECTION
#property indicator_color3  clrRed
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- plot Direction
#property indicator_label4  "Direction"
#property indicator_type4   DRAW_LINE
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- plot LastHighBar
#property indicator_label5  "LastHighBar"
#property indicator_type5   DRAW_LINE
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1
//--- plot LastLowBar
#property indicator_label6  "LastLowBar"
#property indicator_type6   DRAW_LINE
#property indicator_style6  STYLE_SOLID
#property indicator_width6  1

#include <ZigZag\CSorceData.mqh>
#include <ZigZag\CZZDirection.mqh>
#include <ZigZag\CZZDraw.mqh>
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum EDirection
  {
   Dir_NBars=0,
   Dir_CCI=1
  };
//--- input parameters
input EDirection  DirSelect=Dir_NBars;
input int                  CCIPeriod   =  14;
input ENUM_APPLIED_PRICE   CCIPrice    =  PRICE_TYPICAL;
input int                  ZZPeriod=14;

string               name;

CZZDirection*dir;
CZZDraw*zz;

//--- indicator buffers
double         HighBuffer[];
double         LowBuffer[];
double         ZigZagBuffer[];
double         DirectionBuffer[];
double         LastHighBarBuffer[];
double         LastLowBarBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int h;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   switch(DirSelect)
     {
      case Dir_NBars:
         dir=new CNBars(ZZPeriod);
         break;
      case Dir_CCI:
         dir=new CCCIDir(CCIPeriod,CCIPrice);
         break;
     }
   if(!dir.CheckHandle())
     {
      Alert("Error al cargar el indicador 2");
      return(INIT_FAILED);
     }
   zz=new CSimpleDraw();
//--- indicator buffers mapping
   SetIndexBuffer(0,HighBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,LowBuffer,INDICATOR_DATA);
   SetIndexBuffer(2,ZigZagBuffer,INDICATOR_DATA);
   SetIndexBuffer(3,DirectionBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,LastHighBarBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,LastLowBarBuffer,INDICATOR_CALCULATIONS);
   name = _Symbol + TimeFrameToShortString(Period()) + ".txt";
   h=FileOpen(name,FILE_CSV|FILE_WRITE|FILE_ANSI,',');
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

   if(CheckPointer(dir)==POINTER_DYNAMIC)
     {
      delete(dir);
     }
   if(CheckPointer(zz)==POINTER_DYNAMIC)
     {
      delete(zz);
     }
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int ind=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[]
                )
  {
   int start;

   if(prev_calculated==0)
     {
      start=0;
     }
   else
     {
      start=prev_calculated-1;
     }

   for(int i=start;i<rates_total;i++)
     {
      HighBuffer[i]=price[i];
      LowBuffer[i]=price[i];
     }

   int rv;
   rv=dir.Calculate(rates_total,
                    prev_calculated,
                    HighBuffer,
                    LowBuffer,
                    DirectionBuffer);
   if(rv==0)return(0);
   zz.Calculate(rates_total,
                prev_calculated,
                HighBuffer,
                LowBuffer,
                DirectionBuffer,
                LastHighBarBuffer,
                LastLowBarBuffer,
                ZigZagBuffer);

   if(ind<= 10) ind++;
   if(ind == 10)
     {
      double mx=100,mn=-100;
      double lg;
      lg=mx-mn;
      lg/=100;
      double levels[100];
      int    count[100];
      ArrayInitialize(count,0);
      for(int i=1; i<101; i++) levels[i-1]=NormalizeDouble(lg*i + mn,_Digits);
      for(int i=0;i<rates_total;i++)
        {
         if(ZigZagBuffer[i]==0 || ZigZagBuffer[i]==EMPTY_VALUE) continue;
         else 
           {
            for(int j=0; j<100; j++) 
              {
               if(ZigZagBuffer[i]<levels[j]) 
                 {
                  count[j]++;
                  break;
                 }
              }
           }
        }
      for(int i=0; i<100; i++)
        {
         FileWrite(h,i,levels[i],count[i]);
        }
      FileClose(h);
      Print("Work complete: ",name);
     }
   return(rates_total);
  }
//+------------------------------------------------------------------+


string TimeFrameToShortString(ENUM_TIMEFRAMES period)
{
   switch (period )
   {
      case PERIOD_M1:  return ("M1");
      case PERIOD_M2:  return ("M2");
      case PERIOD_M3:  return ("M3");
      case PERIOD_M4:  return ("M4");
      case PERIOD_M5:  return ("M5");
      case PERIOD_M6:  return ("M6");
      case PERIOD_M10: return ("M10");
      case PERIOD_M12: return ("M12");
      case PERIOD_M15: return ("M15");
      case PERIOD_M20: return ("M20");
      case PERIOD_M30: return ("M30");
      case PERIOD_H1:  return ("H1");
      case PERIOD_H2:  return ("H2");
      case PERIOD_H3:  return ("H3");
      case PERIOD_H4:  return ("H4");
      case PERIOD_H6:  return ("H6");
      case PERIOD_H8:  return ("H8");
      case PERIOD_H12: return ("H12");
      case PERIOD_D1:  return ("D1");
      case PERIOD_W1:  return ("W1");
      case PERIOD_MN1: return ("MN1");
   }
   return ("");
} 

Como ya se ha mencionado anteriormente, el código principal del indicador ha sido desarrollado y amablemente puesto a la disposición de la comunidad por parte de nuestro querido colega Dmitry Fedoseev en este artículo. Ambos indicadores mencionados se pueden encontrar en el fichero anexo test.zip. Ya disponemos de las herramientas necesarias, ahora vamos a averiguar la información que nos interesa.

Número posible de transacciones

El diapasón del WPR combinado oscila entre -100% y +100%, por eso, por el momento consideraremos que el nivel de sobrecompra se encuentra en el nivel +60%, y el de sobreventa, en el -60%, lo que corresponde al valor estándar. Vamos a aclarar cuántas veces ha salido el gráfico del indicador de los niveles de sobrecompra / sobreventa. Para ello, usaremos el método descrito aquí:

  • Agregaremos al gráfico el WPR combinado  (testWPReur.mq5) el indicador testIndexZig-Zag1.mq5. Nuestro objetivo es definir el número de extremos que superan el nivel en +70% y +80%, o -70% y -80%, como en la imagen de más abajo. Preste atención a la zona problemática, marcada con un rectángulo azul. Por el momento, estos extremos entrarán en el cálculo, pero en lo sucesivo intentaremos filtrar los que se asemejen a ellos:

  • El indicador testIndexZig-Zag1.mq5 utilizado, divide el diapasón del indicador testWPReur.mq5 en intervalos de un 1% y calcula el número de extremos que entran en cada intervalo. Los resultados se muestran en el archivo. Repetiremos el cálculo para todos los marcos temporales elegidos. A continuación, cambiamos los datos que componen la cesta en testWPReur.mq5 y continuamos trabajando ya desde la siguiente cesta de divisas.

Para que resulte cómodo, los datos obtenidos se han reunido en un recuadro con todas las cestas y todos los marcos temporales seleccionados. Más abajo mostramos un fragmento del recuadro, dedicado a EUR. Vamos a aclarar el sentido de los valores en las líneas y las columnas de este recuadro:

  • Num. — número ordinal.
  • Indicator — valor del indicador en tanto por ciento. Por ejemplo, una línea con el valor -96 designa el intervalo de -96% al -98% del WPR combinado.
  • EUR — tres columnas con el número de extremos de cada marco temporal seleccionado. Por ejemplo, en la ya mencionada línea Num.1, con un valor del indicador de WPR combinado de 96% a 98% se indica que en la historia se ha encontrado el siguiente número de extremos que entran en este intervalo: en D1 - cero, en H4 y H1, uno para cada uno.
  • History Depth — profundidad de la historia disponible para los cálculos.
  • Trade count (80%) — número total de posibles entradas para cada marco temporal. Por ejemplo, en la cesta EUR en el marco temporal H4 se han dado 83 entradas potenciales, es decir, el indicador del WPR combinado ha superado el valor (ha tenido extremos) del 80% o ha sido menor al valor del -80% ese número de veces.
  • Trade count (70%) — lo mismo, pero solo para un valor del WPR combinado del 70%.
  • Trade total (80%) — número total de entradas potenciales para todas las cestas y todos los marcos temporales para un valor del WPR combinado del 80%.
  • Trade total (70%) - lo mismo para el 70%.


EUR ----
Num. Indicador Timeframe ----
D1 H4 H1 ----
0 -98 2 3 4 ----
1 -96 0 1 1 ----
2 -94 0 0 1 ----
3 -92 0 3 3 ----
4 -90 1 4 5 ----
5 -88 3 4 10 ----
6 -86 1 2 7 ----
7 -84 2 8 7 ----
8 -82 1 8 21 ----
9 -80 4 6 22 ----
---- ---- ---- ---- ---- ----
95 92 0 2 6 ----
96 94 0 1 4 ----
97 96 0 0 3 ----
98 98 0 3 0 ----
99 100 0 0 0 ----
History Depth 2000.11.09 2005.04.12 2006.01.17 ----





----
Trade count (80%) 25 83 165 ----
Trade count (70%) 45 207 449 ----












Trade total (80%) 3793


Trade total (70%) 7885


El recuadro se adjunta al archivo y se encuentra en el fichero Pair.zip.

Las dos últimas líneas del recuadro contienen los valores buscados. Se trata de una cantidad bastante grande de posibles entradas, incluso teniendo en cuenta que parte de las señales será filtrada. Por eso, de momento dejaremos los valores de los niveles de sobrecompra / sobreventa en el lugar anterior. Hay que recordar que todos los valores encontrados (y los que ya tenemos) son de carácter probable y podrían corregirse.

Forma del patrón

Vamos a definir la forma del patrón que necesitamos identificar para entrar en el mercado.

  • El tráder vende una cesta de parejas de divisas si el indicador WPR combinado cruza el nivel de sobrecompra +60% de arriba hacia abajo. En este caso, además, en el cierre de la vela el valor del indicador no ha sido inferior a +50%.  El descenso de la línea del indicador deberá tener lugar desde un valor no inferior a +70%. La segunda variante para este punto es de +80% y superior, mientras que para el nivel de sobrecompra, es de un +70%.
  • El caso de la compra de cestas de parejas de divisas es simétrico al descrito.

Los tres patrones marcados en la figura más arriba cumplen con las condiciones dadas. Obtenemos un patrón "bonito", claro, visible para todos, con valores numéricos y condiciones que pueden convertirse en un algoritmo.

Esto significa que después necesitaremos un asesor.

Asesor para la simulación del patrón

Para comenzar, vamos a aclararnos con la compra / venta de la cesta. En este artículo se habla sobre las operaciones comerciales con cestas de divisas y se muestra un recuadro con consejos prácticos sobre cada cesta. Vamos a guiarnos por dicho recuadro e implementar este mismo principio en el código del asesor.

Mostraremos de nuevo qué patrones vamos a buscar:

Patrón buscado
Sin padrón



Suponemos que el nivel de sobrecompra / sobreventa puede fluctuar en el diapasón 60% - 70%. Vamos a verificarlo en cuanto al número de transacciones para el patrón comprobado, la longitud de las transacciones, la reducción y la rentabilidad potencial. Nuestro objetivo no es lograr que el funcionamiento del asesor dé un beneficio estable, esto es por el momento un poco prematuro. Nuestra meta es dar un primer paso para concretar la forma del patrón. Por eso tampoco vamos a publicar los informes del simulador, puesto que para nosotros lo importante no es la rentabilidad del asesor, y además la información necesaria no sale en los informes. Vamos a prestar especial atención a la representación de los resultados obtenidos.

Empezaremos analizando las cestas de divisas de USD, colocando el siguiente asesor en EURUSD en los marcos temporales elegidos previamente:

//+------------------------------------------------------------------+
//|                                                   testBasket.mq5 |
//|                        Copyright 2017, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
//--- input parameters

#include <Trade\\Trade.mqh>


#define LG 7

input int SELLPROFIT =   0;
input int SELL1LIMIT =  70;
input int SELL2FROM  =  60;
input int SELL2TO    =  50;

input int BUYPROFIT  =   0;
input int BUY1LIMIT  = -70;
input int BUY2FROM   = -60;
input int BUY2TO     = -50;

input int WPR=20;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
enum BSTATE 
  {
   BCLOSE = 0,
   BBUY   = 1,
   BSELL  = 2
  };

string pair[]={"EURUSD","GBPUSD","AUDUSD","NZDUSD","USDCAD","USDCHF","USDJPY"};
bool bDirect[]={false,false,false,false,true,true,true};
datetime TimeParam[3];

double dWpr[3];
ulong  Ticket[LG];
double TradeResult[LG];
double TradeCurrency;
double Drw;
string sLog;

double TradeTotalResult[LG];
double TradeTotalCurrency;
int    iTradeCount;
double mDrw;

int h1[LG];
BSTATE bstate;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double GetValue1(int shift)
  {
   double dBuf[1];
   double res=0.0;
   for(int i=0; i<LG; i++)
     {
      CopyBuffer(h1[i],0,shift,1,dBuf);
      if(bDirect[i]==true)
         res+=dBuf[0];
      else
         res+=-(dBuf[0]+100);
     }//end for (int i = 0; i < iCount; i++)      
   res=res/LG;
   return (NormalizeDouble((res + 50) * 2, _Digits) );
  }

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int lh;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   EventSetTimer(1);

   for(int i=0; i<LG; i++)
     {
      h1[i]=iWPR(pair[i],0,WPR);
     }
   bstate=BCLOSE;

   ArrayInitialize(TradeTotalResult,0);
   ArrayInitialize(dWpr,EMPTY_VALUE);
   TradeTotalCurrency=0;
   iTradeCount=0;
   mDrw=1000000;

   lh=INVALID_HANDLE;
   string lname = _Symbol + "_" + TimeFrameToShortString(Period() );
   string t1, t = lname;
   int i=0;
   for(;;) 
     {
      t+=".html";
      long lg=FileFindFirst(t,t1);
      if(lg==INVALID_HANDLE) 
        {
         lh= FileOpen(t,FILE_WRITE | FILE_TXT | FILE_ANSI);
         Print("CREATE ",t);
         break;
        }
      FileFindClose(lg);
      t=lname+"_"+IntegerToString(i++);
     }

   FileWriteString(lh,"<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Strict//EN\" \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd\">\r\n");
   FileWriteString(lh,"<html xmlns=\"http://www.w3.org/1999/xhtml\">\r\n");
   FileWriteString(lh,"<head>\r\n");
   FileWriteString(lh,"<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\"/>\r\n");
   FileWriteString(lh,"<title>"+lname+"</title>\r\n");
   FileWriteString(lh,"</head>\r\n<body>\r\n");
   FileWriteString(lh,"<H2>"+_Symbol+" "+TimeFrameToShortString(Period())+"</H2>\r\n");
   FileWriteString(lh,"<H3>Pattern Params:</H3>\r\n");
   FileWriteString(lh,"<table width=\"100%\" cellspacing=\"0\" cellpadding=\"5\">\r\n");
   FileWriteString(lh,"<thead>\r\n<tr>\r\n<th>BUY</th>\r\n<th>SELL</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n<tr>\r\n");
   t=StringFormat("Point 1: %d Point 2 from: %d to: %d Close at: %d",BUY1LIMIT,BUY2FROM,BUY2TO,BUYPROFIT);
   FileWriteString(lh,"<td style=\"text-align:center;\">\r\n<ul>\r\n<li>"+t+"</li>\r\n</ul>\r\n</td>\r\n");
   t=StringFormat("Point 1: %d Point 2 from: %d to: %d Close at: %d",SELL1LIMIT,SELL2FROM,SELL2TO,SELLPROFIT);
   FileWriteString(lh,"<td style=\"text-align:center;\">\r\n<ul>\r\n<li>"+t+"</li>\r\n</ul>\r\n</td>\r\n");
   FileWriteString(lh,"</tr>\r\n</tbody>\r\n</table>\r\n");
   FileWriteString(lh,"<H2>"+"Tester Result"+"</H2>\r\n");
   FileWriteString(lh,"<table border=\"1\" width=\"100%\" cellspacing=\"0\" cellpadding=\"5\">\r\n");
   FileWriteString(lh,"<thead>\r\n<th>Num.</th>\r\n<th>Type</th>\r\n<th>WPR(P1/P2)</th>\r\n<th>Time(Begin/End/Length)</th>\r\n<th>Drawdown/<br/>Profit</th>\r\n<th>Pair Profit</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n");

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void PushWpr(double wpr) 
  {
   dWpr[2] = dWpr[1]; dWpr[1] = dWpr[0];
   dWpr[0] = wpr;
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void Stat() 
  {

   double d=0;
   for(int i=0; i<LG; i++) 
     {
      PositionSelectByTicket(Ticket[i]);
      d+=PositionGetDouble(POSITION_PROFIT);
     }
   if(d<Drw) Drw=d;
   if(Drw<mDrw) 
     {
      mDrw=Drw;
      TimeParam[2]=TimeCurrent();
     }
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
   if(bstate!=BCLOSE) 
     {
      Stat();
     }
   if(IsNewCandle()) 
     {
      double res=GetValue1(0);
      PushWpr(res);
      if(dWpr[1]!=EMPTY_VALUE) 
        {
         if(bstate==BBUY && (dWpr[0]>=BUYPROFIT )) 
           {
            CloseAllPos();
            bstate=BCLOSE;
           }
         if(bstate==BSELL && (dWpr[0]<=SELLPROFIT )) 
           {
            CloseAllPos();
            bstate=BCLOSE;
           }
         if(bstate==BCLOSE && dWpr[0]<=SELL2FROM && dWpr[0]>=SELL2TO && dWpr[1]>=SELL1LIMIT) 
           {
            EnterSell(0.01);
            bstate=BSELL;
            TimeParam[0]=TimeCurrent();
            TradeCurrency=0;
            Drw=1000000;
            iTradeCount++;
            sLog=StringFormat("<tr>\r\n<td>%d</td>\r\n<td>SELL</td>\r\n<td>%.2f/<br/>%.2f</td>\r\n<td>%s/<br/>",iTradeCount,dWpr[1],dWpr[0],TimeToString(TimeCurrent()));
            return;
           }
         if(bstate==BCLOSE && dWpr[0]>=BUY2FROM && dWpr[0]<=BUY2TO && dWpr[1]<=BUY1LIMIT) 
           {
            EnterBuy(0.01);
            bstate=BBUY;
            TimeParam[0]=TimeCurrent();
            TradeCurrency=0;
            Drw=1000000;
            iTradeCount++;
            sLog=StringFormat("<tr>\r\n<td>%d</td>\r\n<td>BUY</td>\r\n<td>%.2f/<br/>%.2f</td>\r\n<td>%s/<br/>",iTradeCount,dWpr[1],dWpr[0],TimeToString(TimeCurrent()));
            return;
           }
        }//if (stc.Pick(1) != EMPTY_VALUE)
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void CloseAllPos() 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   TimeParam[1]=TimeCurrent();
   string p="<td>";
   for(int i=0; i<LG; i++) 
     {
      TradeResult[i]=PositionGetDouble(POSITION_PROFIT)+PositionGetDouble(POSITION_SWAP);
      p+=StringFormat("%s = %.2f<br/>",pair[i],TradeResult[i]);
      TradeCurrency       += TradeResult[i];
      TradeTotalResult[i] += TradeResult[i];
      Trade.PositionClose(Ticket[i]);
     }
   p+="</td>\r\n";
   TradeTotalCurrency+=TradeCurrency;
   sLog += StringFormat("%s/<br/>%s</td>\r\n<td>%.2f/<br/>%.2f</td>\r\n",TimeToString(TimeParam[1]), TimeIntervalToStr(TimeParam[0], TimeParam[1]), Drw, TradeCurrency );
   sLog += p;
   FileWriteString(lh,sLog);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EnterBuy(double lot) 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {
      if(bDirect[i]) 
        { //send buy
         Trade.Buy(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
      else 
        { //send sell
         Trade.Sell(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void EnterSell(double lot) 
  {

   CTrade Trade;
   Trade.LogLevel(LOG_LEVEL_NO);

   for(int i=0; i<LG; i++) 
     {
      if(bDirect[i]) 
        { //send sell
         Trade.Sell(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
      else 
        { //send buy
         Trade.Buy(lot,pair[i]);
         Ticket[i]=Trade.ResultDeal();
        }
     }
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   EventKillTimer();

   FileWriteString(lh,"</tbody>\r\n</table>\r\n");
   FileWriteString(lh,"<H2>Total Result</H2>\r\n");
   FileWriteString(lh,"<table border=\"1\" width=\"100%\" cellspacing=\"0\" cellpadding=\"5\">\r\n");
   FileWriteString(lh,"<thead>\r\n<tr>\r\n<th>Deal's<br/>Count</th>\r\n<th>Profit</th>\r\n<th>Max.Drawdown</th>\r\n<th>Pair's Profit</th>\r\n</tr>\r\n</thead>\r\n<tbody>\r\n");
   string p = StringFormat("<tr><td>%d</td>\r\n<td>%.2f</td>\r\n<td>%.2f at<br/>%s</td>\r\n<td>",iTradeCount,TradeTotalCurrency,mDrw,TimeToString(TimeParam[2]));
   for(int i=0; i<LG; i++)
     {
      if(h1[i]!=INVALID_HANDLE) IndicatorRelease(h1[i]);
      p+=StringFormat("%s = %.2f<br/>",pair[i],TradeTotalResult[i]);
     }
   p+="</td>\r\n</tr>\r\n";
   FileWriteString(lh,p);
   FileWriteString(lh,"</tbody>\r\n</table>\r\n");
   FileWrite(lh,"</body>\r\n</html>"); //End log
   FileClose(lh);
  }
//+------------------------------------------------------------------+

bool IsNewCandle() 
  {

   static int candle=-1;

   int t1=0;
   switch(_Period)
     {
      case PERIOD_H1:  t1 = Hour();   break;
      case PERIOD_H4:  t1 = Hour4();  break;
      case PERIOD_D1:  t1 = Day();    break;
     }
   if(t1!=candle) {candle=t1; return(true);}
   return (false);
  }
int Hour4(){return((int)Hour()/4);}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Day()
  {
   MqlDateTime tm;
   TimeCurrent(tm);
   return(tm.day);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int Hour()
  {
   MqlDateTime tm;
   TimeCurrent(tm);
   return(tm.hour);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string TimeIntervalToStr(datetime dt1,datetime dt2) 
  {
   string tm;
   if(dt1 >= dt2)   tm = TimeToString(dt1 - dt2);
   else tm = TimeToString(dt2 - dt1,TIME_DATE|TIME_MINUTES|TIME_SECONDS);
   string ta[],ta1[];
   StringSplit(tm,StringGetCharacter(" ",0),ta);
   StringSplit(ta[0],StringGetCharacter(".",0),ta1);
   ta1[0] = IntegerToString( StringToInteger(ta1[0]) - 1970);
   ta1[1] = IntegerToString( StringToInteger(ta1[1]) - 1);
   ta1[2] = IntegerToString( StringToInteger(ta1[2]) - 1);
   return (ta1[0] + "." + ta1[1] + "." + ta1[2] + " " + ta[1]);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string TimeFrameToShortString(ENUM_TIMEFRAMES period)
  {
   switch(period)
     {
      case PERIOD_H1:  return ("H1");
      case PERIOD_H4:  return ("H4");
      case PERIOD_D1:  return ("D1");
     }
   return ("");
  }
//+------------------------------------------------------------------+

La primera versión del asesor para la simulación se puede encontrar también en el archivo anexo testBasket.mq5. En el propio algoritmo no hay nada especial, pero se centra mucha atención en las formas del informe. Vamos a aclarar el sentido de los parámetros de entrada del asesor:

  • SELLPROFIT. Cuando el indicador del WPR combinado alcanza este valor, cerramos todas las posiciones abiertas para la venta de la cesta. Por defecto, este valor es 0%.
  • SELL1LIMIT. Se trata del valor mínimo del WPR combinado para el punto №1 (ver la imagen más arriba) para comenzar la identificación del patrón de venta de la cesta. Por defecto es 70%.
  • SELL2FROM. Valor máximo del WPR combinado para el punto №2 para la identificación del patrón de venta de la cesta. Por defecto, 60% es el nivel de sobrecompra.
  • SELL2TO. Valor mínimo del WPR combinado para el punto №2 para la identificación final del patrón de venta de la cesta. Por defecto es 50%.
  • BUYPROFIT. Cuando el indicador del WPR combinado alcanza este valor, cerramos todas las posiciones abiertas para la compra de la cesta. Por defecto es 5%.
  • BUY1LIMIT. Es el valor máximo del WPR combinado para el punto №1 para comenzar la identificación del patrón de compra de la cesta. Por defecto es 70%.
  • BUY2FROM. Valor mínimo del WPR combinado para el punto №2 para la identificación del patrón de compra de la cesta. Por defecto, -60% es el nivel de sobreventa.
  • BUY2TO. Valor máximo del WPR combinado para el punto №2 para la identificación final del patrón de compra de la cesta. Por defecto es -50%.
  • WPR. Periodo del indicador técnico estándar WPR. Por defecto es 20.

A continuación, ponemos a prueba el asesor en el Simulador, comenzando por enero del año 2016. La fecha de simulación elegida depende de la calidad de la historia. Vamos a analizar dos formas de patrón. La primera se describe más arriba y se establece por defecto. La segunda está desplazada con respecto a la primera de la forma siguiente:

  • SELLPROFIT. Cuando el indicador del WPR combinado alcanza este valor, cerramos todas las posiciones abiertas para la venta de la cesta. Este valor es 0%.
  • SELL1LIMIT. Se trata del valor mínimo del WPR combinado para el punto №1 (ver la imagen más arriba) para comenzar la identificación del patrón de venta de la cesta. Este valor es 80%.
  • SELL2FROM. Valor máximo del WPR combinado para el punto №2 para la identificación del patrón de venta de la cesta. Este valor es 70%, nivel de sobrecompra.
  • SELL2TO. Valor mínimo del WPR combinado para el punto №2 para la identificación final del patrón de venta de la cesta. Este valor es 50%.
  • BUYPROFIT. Cuando el indicador del WPR combinado alcanza este valor, cerramos todas las posiciones abiertas para la compra de la cesta. Este valor es 0%.
  • BUY1LIMIT. Es el valor máximo del WPR combinado para el punto №1 para comenzar la identificación del patrón de compra de la cesta. Este valor es -80%.
  • BUY2FROM. Valor mínimo del WPR combinado para el punto №2 para la identificación del patrón de compra de la cesta. Este valor es -70%, nivel de sobreventa.
  • BUY2TO. Valor máximo del WPR combinado para el punto №2 para la identificación final del patrón de compra de la cesta. Este valor es -50%.

Los resultados se encuentran en los informes en html.

Forma de los informes del asesor.

No resulta en absoluto complicado descifrar los informes del asesor, vamos a ver la estructura de los informes usando como ejemplo el informe de la cesta EUR.

La primera línea representa el encabezamiento con el nombre del gráfico y el marco temporal en el que ha trabajado el asesor.

A continuación, van los parámetros del patrón con los que ha trabajado el asesor por separado para las cestas de compra y de venta: Point 1 — es la localización del punto №1: SELL1LIMIT (BUY1LIMIT). Point 2 from: ... to: ... —  es la localización del punto №2: SELL2FROM (BUY2FROM) y SELL2TO (BUY2TO). Close at — es la localización del punto de cierre del patrón SELLPROFIT (BUYPROFIT):

EURUSD H4

Pattern Params:

BUY SELL
  • Point 1: -80 Point 2 from: -70 to: -50 Close at: 0
  • Point 1: 80 Point 2 from: 70 to: 50 Close at: 0

Después viene el recuadro "Tester Result" con la información sobre cada transacción durante el periodo de simulación en el siguiente orden:

  • Num. — número del índice
  • Type — tipo de transacción: venta o compra de la cesta
  • WPR(P1/P2) — datos sobre el WPR combinado en el formato Punto №1 / Punto №2, usado para entrar en el mercado
  • Time(Begin/End/Length) — información sobre la hora de la transacción: Hora de entrada en el mercado / Hora de salida / Duración de la transacción
  • Drawdown/Profit — reducción máxima durante el tiempo de la transacción / beneficio total. Datos en la divisa del depósito.
  • Pair Profit — beneficio de las parejas individuales de las que consta la cesta de divisas. Datos en la divisa del depósito.

Aquí tenemos un fragmento de este recuadro. Podemos ver que la primera transacción se ha prolongado ocho horas y ha traído unas pérdidas de 16.34 USD. Concretamente, la orden abierta de EURUSD se ha cerrado con unas pérdidas de 2.55 USD:

Num. Type WPR(P1/P2) Time(Begin/End/Length) Drawdown/
Profit
Pair Profit
1 SELL 86.26/
67.15
2016.03.23 20:00/
2016.03.24 04:00/
0.0.0 08:00:00
-21.70/
-16.34
EURUSD = -2.55
GBPUSD = -1.58
AUDUSD = -2.02
NZDUSD = -3.66
USDCAD = -2.15
USDCHF = -2.97
USDJPY = -1.41


En último lugar va el recuadro "Total Result" con un resumen de los datos del periodo de simualción en el siguiente orden:

  • Deal's Count — número de transacciones durante todo el periodo de simulación.
  • Profit — beneficio obtenido durante todo el periodo de simulación. Datos en la divisa del depósito.
  • Max.Drawdown — reducción máxima y en qué momento fue detectada. Datos en la divisa del depósito y fecha.
  • Pair's Profit — beneficio total de cada pareja de divisas que compone la cesta. Datos en la divisa del depósito.

Aquí está el recuadro directamente del informe:

Deal's
Count
Profit Max.Drawdown Pair's Profit
22 189.06 -52.37 at
2016.05.02 19:53
EURUSD = 52.43
GBPUSD = 24.50
AUDUSD = 45.88
NZDUSD = 13.94
USDCAD = 15.73
USDCHF = 12.26
USDJPY = 24.32


Los informes obtenidos se encuentran en el fichero anexo DocUSD.zip.

Llama la atención que en el marco temporal D1 haya inesperadamente pocas transacciones. Pero también hay señales esperanzadoras:

  • En los marcos temporales H4 y H1 el asesor ha mostrado resultados positivos, además, sin ningún esfuerzo por nuestra parte.

De este material, aunque sea tan limitado, se pueden sacar ciertas conclusiones preliminares que posteriormente se podrán concretar.

  1. El patrón se observa muy rara vez en el marco temporal de un día. Lo más probable es que esta tendencia se conserve también en los marcos temporales superiores a D1.
  2. El nivel de sobrecompra / sobreventa se encuentra en el diapasón 60% — 70%, si habalamos de la sobrecompra, y de un -60% — -70%, si hablamos de la sobreventa. Por encima del 70% y por debajo del -70% hay muy pocas transacciones. Para que el patrón pueda ser identificado en este caso, el punto №1 deberá encontrarse por encima del 90%, o bien por debajo del -90%, y esta es una situación bastante rara. Por debajo del 60% y por encima del -60% el punto №2 resulta estar cerca del 40% o -40% y se aproxima a la zona de posible comienzo del movimiento lateral. Para esta zona es característica, además, una alta volatilidad en las indicaciones del indicador y, como consecuencia, multitud de señales de entrada falsas.

Vamos a perfeccionar un tanto el asesor, para ello, continuaremos con la siguiente pareja de la cesta: NZD. Primero debemos introducir cambios en la forma de informe, para ser más exactos, mostraremos el valor "reducción positiva". Vamos a aclarar este concepto. La cesta no se cierra por un valor de beneficio concreto, ni tampoco conforme a ciertos niveles comerciales, sino según las lecturas del indicador. Hasta el momento del cierre, las órdenes de la cesta de pedidos pueden encontrarse en reducción, cuya magnitud monitorea el asesor. Pero estas órdenes, igualmente, pueden experimentar un beneficio considerable que no será registrado, puesto que el indicador aún no ha alcanzado los valores necesarios para el cierre. Esta magnitud se llama "reducción positiva", y vamos a mostrar sus valores máximos en el informe. Ahora estaremos al tanto del beneficio potencial y la habilidad de la cesta para moverse hacia el lado positivo.

Vamos a añadir este valor a la penúltima columna del recuadro "Tester Result". La columna que se llamaba "Drawdown/Profit", ahora se llamará Drawdown/+Drawdown/Profit y los datos en cada celda de esta columna irán en el siguiente orden: Reducción / Reducción positiva / Beneficio. Todos los datos estarán en la divisa del depósito.

Además, vamos a mostrar el valor máximo de la reducción positiva en el recuadro "Total Result". Vamos a introducir una penúltima columna adicional "Max.+Drawdown". En ella mostraremos la reducción positiva máxima en todo el periodo de simulación y cuándo esta reducción ha sido fijada.

El código fuente de esta siguiente versión del asesor se encuentra en el archivo testBasket1.mq5.

Los informes obtenidos de la cesta NZD se encuentran en el fichero DocNZD.zip. Las conclusiones por el momento son las siguientes:

  • Se confirma la suposición hecha anteriormente sobre la localización de los niveles de sobrecompra y sobreventa. Al fichero se le ha añadido el informe NZDUSD_H1_1.html con los niveles próximos a la zona de posible comienzo del movimiento lateral con un gran número de entradas falsas. Las consecuencias son bastante obvias.
  • Se confirma que hay muy pocas transacciones de este patrón en el marco temporal D1.
  • Hemos obtenido un resultado decepcionante en el marco temporal H1. Podemos suponer que el nivel de ruido del marco temporal constituye una suma de los ruidos de todas las parejas de divisas de la cesta, y como resultado de ello, recibimos señales falsas.

Vamos a finalizar la investigación usando las divisas restantes de la cesta: AUD, EUR, GBP, CAD, JPY, CHF. Los informes de estas divisas se pueden encontrar en el fichero anexo Doc.zip. En cuanto a nosostros, ya es hora de hacer balance del trabajo realizado:

Conclusiones

  • El nivel de sobrecompra realmente se encuentra en el diapasón 60% - 70%, y el de sobreventa, entre -60% y -70%. Los informes obtenidos dan buena fe de ello, así como la localización del nivel correspondiente en el indicador WPR estándar.
  • La comprobación se ha realizado con tres marcos temporales y con las ocho cestas conocidas. Se han investigado dos formas de patrón de ruptura de las líneas de sobrecompra / sobreventa:
    1. El punto №1 del patrón está por encima del 80%. El nivel de sobreventa, en el 70%. El punto №2 se encuentra entre el 70% y el 50%. La cesta se cierra cuando el indicador ≤ 0%. Aquí se muestra la forma del patrón para la entrada en el mercado para vender la cesta. La forma para la entrada para comprar es simétrica con un signo menos.
    2. El punto №1 del patrón está por encima del 70%. El nivel de sobreventa, en el 60%. El punto №2 se encuentra entre el 60% y el 50%. La cesta se cierra cuando el indicador ≤ 0%. Aquí se muestra la forma del patrón para la entrada en el mercado para vender la cesta. La forma para la entrada en el mercado para comprar la cesta es simétrica con el signo menos.
  • Insistimos una vez más en que las transacciones en el marco temporal D1 son muy escasas, no vamos a volver a recurrir a él en este artículo. Vamos a tomar los datos del recuadro "Total Result" de todos los informes y crear sobre su base los recuadros finales sobre los demás marcos temporales. En los recuadros se muestran los resultados del comercio del asesor en la divisa del depósito para cada cesta de divisas y para ambas formas del patrón, que fueron descritas en el punto anterior:

     

    Marco temporal H1
      AUD EUR USD GBP NZD CAD CHF JPY
    Patrón  №1 -590 90 -37 -991 -141 -80 -118 -514
    Patrón  №2 -259 -67 328 -714 -352 -446 -118 -272

     

    Marco temporal H4
      AUD EUR USD GBP NZD CAD CHF JPY
    Patrón №1 286 -72 189 -400 104 60 -209 120
    Patrón №2 -208 25 40 80 172 10 -69 -176

     

    Prestemos atención a los terribles resultados en el marco temporal H1. Probablemente sean consecuencia del nivel de ruido de las parejas de divisas en este marco temporal.
  • Pero en el marco temporal H4 hemos obtenido un resultado muy digno. En lo sucesivo, prestaremos a este marco temporal especial atención.

Los resultados obtenidos no permiten elegir de manera razonable entre dos formas de un patrón, por eso nos vemos obligados a trabajar con ambos. Desde mi punto de vista, la segunda forma parece tener mejores perspectivas, pero podría resultar una opinión subjetiva. Tomaremos una decisión sobre este punto más tarde.

¿Debemos completar el trabajo con el marco temporal H1? ¡De ninguna manera! No en vano hemos introducido en el artículo la "reducción positiva". Echando un vistazo a estos datos y a los datos sobre la reducción convencional, podemos ver que:

  • La idea inicial sobre el cierre de la cesta según las lecturas del WPR combinado (cuando su valor llegue a cero) es insuficiente. Tampoco se ha solucionado la cuestión de la limitación de las pérdidas. Ya que nos vemos obligados a tratar con la cesta de órdenes, sería lógico establecer el stop-loss en la divisa del depósito y realizar el trailing del beneficio también en la divisa del depósito. Esto nos prevendría de sufrir pérdidas instantáneas mientras nos encontramos en beneficio y, por otra parte, nos permitiría limitar pérdidas potenciales de una manera razonable. Esta metodología podría dar un resultado positivo en H1 y aumentar el beneficio en H4. Ahora esto no entra en nuestros planes, pero como solución técnica, será útil en el futuro.

Conclusión

La primera etapa de la simulación de patrones ha finalizado. Los resultados obtenidos exigen de una reflexión cuidadosa por nuestra parte. En lo sucesivo, apoyándonos en los datos obtenidos, analizaremos las cuestiones referentes al filtrado de señales y a las señales adicionales de otros patrones conocidos. Esto nos permitirá no solo conseguir nueva información, sino también precisar la ya obtenida.

Programas usados en el artículo:

 # Nombre
Tipo
 Descripción
1 Pair.zip Fichero
Resultados del cálculo del número de transacciones posibles de todas las divisas de la cesta según los tres marcos temporales elegidos.
2
testBasket.mq5 Asesor Experto
Asesor para la simulación.
3
DocUSD.zip Fichero Informes en el formato html sobre la operación del asesor testBasket.mq5 con la cesta de USD.
 4 DocNZD.zip Fichero Informes en el formato html sobre la operación del asesor testBasket1.mq5 con la cesta de NZD.
5
testBasket1.mq5 Asesor Experto Asesor para la simulación - próxima versión.
 6  Doc.zip Fichero
Informes en el formato html sobre la operación del asesor testBasket1.mq5 con el resto de cestas.
7test.zip
 Fichero Fichero con los indicadores testIndexZig-Zag1.mq5 y testWPReur.mq5



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

Archivos adjuntos |
testBasket.mq5 (26.57 KB)
DocUSD.zip (14.3 KB)
DocNZD.zip (27.8 KB)
testBasket1.mq5 (27.74 KB)
Doc.zip (99.72 KB)
test.zip (3.82 KB)
Pair.zip (7.92 KB)
Asesor Experto multiplataforma: Filtros temporales Asesor Experto multiplataforma: Filtros temporales

En este artículo se analiza la implementación de diferentes métodos de la filtración temporal en el Asesor Experto multiplataforma. Las clases de los filtros temporales se ocupan de verificar la correspondencia de un determinado momento de tiempo a un determinado período definido en los ajustes.

El patrón Bandera El patrón Bandera

En el artículo se estudiarán los patrones de Bandera, Banderín, Cuña, Formación en Rectángulo, Triángulo decreciente, Triángulo creciente. Se analizarán sus semejanzas y diferencias, se crearán indicadores para su búsqueda en el gráfico y un indicador-probador para evaluar rápidamente su efectividad.

Interfaces gráficas XI: Campos de edición y combobox en las celdas de la tabla (build 15) Interfaces gráficas XI: Campos de edición y combobox en las celdas de la tabla (build 15)

En esta actualización de la librería, el control «Tabla» (clase CTable) será completado con nuevas opciones. Vamos a ampliar la gama de los controles en las celdas de la tabla, completándola esta vez con los campos de edición y los combobox. Como adición, a esta actualización ha sido añadida la posibilidad que permite al usuario de la aplicación MQL controlar los tamaños de la ventana durante su ejecución.

Interfaces gráficas XI: Integración de la librería gráfica estándar (build 16) Interfaces gráficas XI: Integración de la librería gráfica estándar (build 16)

Desde hace poco tiempo, fue presentada la nueva versión de la librería gráfica para el diseño de los gráficos científicos (clase CGraphic). En esta actualización de la librería para la creación de las interfaces gráficas será presentada la versión con nuevo control para crear los gráficos. Ahora, será aún más fácil visualizar los datos de diferentes tipos.