Price Action. Automatización de la estrategia de la barra interna (Inside Bar)

Dmitry Iglakov | 10 mayo, 2016

Introducción

Todos los traders en Forex habrán utilizado la técnica Price Action (Comportamiento del precio) en algún momento. Esto no es una simple técnica de análisis de gráficos, sino todo un sistema para determinar la posible dirección del movimiento del precio en el futuro. En este artículo, veremos el patrón de la barra interna (Inside Bar) en detalle y desarrollaremos un Asesor Experto para hacer el seguimiento de la barra interna y llevar a cabo operaciones en base al patrón.


Acerca de Price Action

Price Action es un método de detección del movimiento del precio que no se basa en los indicadores y que usa patrones sencillos o complejos, además otras herramientas gráficas (líneas horizontales, verticales y de tendencia, niveles de Fibonacci, niveles de soporte y resistencia, etc).

A primera vista, el método puede parecer muy complicado, pero en realidad no lo es. Este método es cada vez más popular, ya que sus ventajas son obvias, por ejemplo, en comparación con los métodos que implican los indicadores técnicos.


La barra interna (Inside Bar)

La barra interna es una barra cuyo cuerpo y sombras están completamente contenidos en la barra anterior (madre). El máximo de la barra interna es inferior al máximo de la barra anterior y el mínimo es superior al mínimo de la barra anterior. La barra madre y la barra interna forman un patrón considerado como una posible señal de entrada.

Es un patrón con dos opciones, ya que puede indicar una inversión o una continuidad de la tendencia.

Fig. 1 Barra interna (Inside Bar)

Fig. 1 Barra interna (Inside Bar)


Fig. 2 Representación del patrón de la barra interna

Fig. 2 Representación del patrón de la barra interna

Reglas de la barra interna:
  • El patrón de la barra interna tiene más sentido en los períodos de tiempo mayores, como H4 y D1.
  • El patrón puede sugerir una inversión o una continuidad de la tendencia.
  • Se puede obtener una señal de entrada más clara mediante el uso de herramientas adicionales del análisis gráfico, incluyendo las líneas de tendencia, los niveles de soporte y resistencia, los niveles de Fibonacci, otros patrones Price Action, etc.
  • Para evitar las entradas prematuras o erróneas al mercado, hay que utilizar las órdenes pendientes.
  • No se deben utilizar las barras internas repetidas como señales de entrada en un mercado plano.

Fig. 3 Determinar la barra interna real en GBPUSD D1

Fig. 3 Determinar la barra interna real en GBPUSD D1

En base a todo lo anterior, vamos a tratar de definir una barra interna real. En el gráfico anterior, podemos observar que se formó una barra alcista después de un fuerte movimiento bajista. No obstante, la barra está completamente contenida en los límites de la barra anterior. Se confirma el patrón por el hecho de estar formado en el nivel de soporte. La otra prueba es la ausencia de una zona plana. Puesto que el patrón cumple con las condiciones, se puede considerar que es real.


Definir los puntos de entrada y establecer las órdenes Stop

Así que hemos encontrado una barra interna real en el gráfico (figura 3). ¿Cómo tenemos que entrar al mercado y dónde tenemos que establecer nuestras órdenes Stop? Examinemos la figura 4.

Fig. 4 Establecimiento de las órdenes Buy Stop y Stop Loss

Fig. 4 Establecimiento de las órdenes Buy Stop y Stop Loss

En primer lugar, hay que tener en cuenta las reglas para establecer los niveles Stop mediante el ejemplo anterior:

  1. Establecemos una orden pendiente Buy Stop ligeramente por encima del máximo de la barra madre (algunos puntos por encima, para asegurarnos).
  2. Establecemos el nivel Stop Loss por debajo del nivel de soporte y del mínimo de la barra madre. Esto proporciona una protección adicional en caso de activar una orden pendiente y el precio rebota y alcanza el nivel de soporte antes de volver a la dirección correcta.
  3. Establecemos el nivel Take Profit ligeramente por debajo del nivel de resistencia más cercano.
No hay que olvidar que la barra interna puede ir seguida de una inversión o continuidad de la tendencia, lo que quiere decir que necesitamos también una orden Sell Stop.

Fig. 5 Establecimiento de las órdenes Sell Stop y Stop Loss

Fig. 5 Establecimiento de las órdenes Sell Stop y Stop Loss

En primer lugar, hay que tener en cuenta las reglas para establecer los niveles Stop mediante el ejemplo anterior:

  1. Establecemos una orden pendiente Sell Stop ligeramente por debajo del mínimo de la barra madre (algunos puntos por debajo, para asegurarnos).
  2. Establecemos el nivel Stop Loss por encima del máximo de la barra madre.
  3. Establecemos el nivel Take Profit ligeramente por encima del nivel de soporte más cercano.


Desarrollo de un Asesor Experto basado en el Trading con la barra interna

Ahora que conocemos todas las reglas necesarias para definir una barra interna, entrar al mercado y establecer las órdenes Stop, podemos por fin implementar el Asesor Experto adecuado para operar mediante el patrón de la barra interna.

Abrimos MetaEditor a partir del terminal de MetaTrader 4 y creamos un nuevo Asesor Experto (no voy a entrar en los detalles de cómo crear Asesores Expertos, ya que hay bastante información sobre este tema en el sitio web). De momento, se dejan todos los parámetros en blanco. Puede poner el nombre que quiera. Este sería el código:

//+------------------------------------------------------------------+
//|                                                    InsideBar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---

//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

  }
//+------------------------------------------------------------------+

Convertir el patrón en un algoritmo MQL4

Después de haber creado el Asesor Experto, tenemos que definir una barra interna al cerrarse una vela. Para ello, introducimos nuevas variables y les asignamos unos valores. Véase el siguiente código:

//+------------------------------------------------------------------+
//|                                                    InsideBar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict

double   open1,//first candle Open price
open2,    //second candle Open price
close1,   //first candle Close price
close2,   //second candle Close price
low1,     //first candle Low price
low2,     //second candle Low price
high1,    //first candle High price
high2;    //second candle High price
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//--- define prices of the necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
  }
//+------------------------------------------------------------------+

Como ejemplo, vamos a considerar que la barra madre es bajista (barra 2), mientras que la barra interna es alcista (barra 1). Vamos a añadir unas condiciones al código de la función OnTick():

void OnTick()
  {
//--- define prices of the necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
//--- if the second bar is bearish, while the first one is bullish
   if(open2>close2 && //the second bar is bullish
      close1>open1 && //the first bar is bearish
      high2>high1 &&  //the bar 2 High exceeds the first one's High
      open2>close1 && //the second bar's Open exceeds the first bar's Close
      low2<low1)      //the second bar's Low is lower than the first bar's Low
     {
      //--- we have listed all the conditions defining that the first bar is completely within the second one
     }
  }
  • Creamos unas variables personalizables: órdenes Stop, deslizamiento (slippage), tiempo de expiración de órdenes, número mágico del Asesor Experto, lote del trading. Se puede omitir Stop Loss, puesto que se establece de acuerdo con las reglas de la barra interna.
  • Introducimos las variables locales para normalizar el formato de las variables.
  • Se establecen las órdenes Stop a cierta distancia de los valores del precio de la barra. Para ello, añadimos la variable Interval que se encarga del intervalo entre los precios máximo/mínimo de las barras y de los niveles de las órdenes Stop, además de los niveles de las órdenes pendientes.
  • Añadimos la variable timeBarInside para evitar la reapertura de órdenes en este patrón.
  • Añadimos la variable bar2size para asegurarnos de que la barra madre es bastante grande, lo que indica que el mercado actual no es plano.

Como resultado, obtenemos el siguiente código:

//+------------------------------------------------------------------+
//|                                                    InsideBar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict

extern int     interval          = 20;                               //Interval
extern double  lot               = 0.1;                              //Lot Size
extern int     TP                = 300;                              //Take Profit
extern int     magic             = 555124;                           //Magic number
extern int     slippage          = 2;                                //Slippage
extern int     ExpDate           = 48;                               //Expiration Hour Order
extern int     bar2size          = 800;                              //Bar 2 Size

double   buyPrice,//define BuyStop price
buyTP,      //Take Profit BuyStop
buySL,      //Stop Loss BuyStop
sellPrice,  //define SellStop price
sellTP,     //Take Profit SellStop
sellSL;     //Stop Loss SellStop

double   open1,//first candle Open price
open2,    //second candle Open price
close1,   //first candle Close price
close2,   //second candle Close price
low1,     //first candle Low price
low2,     //second candle Low price
high1,    //first candle High price
high2;    //second candle High price

datetime _ExpDate=0;          //local variable to define a pending order expiration time
double     _bar2size;
datetime timeBarInside;         //time of the bar, at which inside bar orders were opened, to avoid re-opening
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double   _bid     = NormalizeDouble(MarketInfo(Symbol(), MODE_BID), Digits); //define a lower price 
   double   _ask     = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK), Digits); //define an upper price
   double   _point   = MarketInfo(Symbol(), MODE_POINT);
//--- define prices of the necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
//---
   _bar2size=NormalizeDouble(((high2-low2)/_point),0);
//--- if the second bar is bearish, while the first one is bullish
   if(timeBarInside!=iTime(Symbol(),Period(),1) && //no orders have been opened at this pattern yet
      _bar2size>bar2size && //the second bar is big enough, so the market is not flat
      open2>close2 && //the second bar is bullish
      close1>open1 && //the first bar is bearish
      high2>high1 &&  //the bar 2 High exceeds the first one's High
      open2>close1 && //the second bar's Open exceeds the first one's Close
      low2<low1)      //the second bar's Low is lower than the first one's Low
     {
      //--- we have listed all the conditions defining that the first bar is completely within the second one
      timeBarInside=iTime(Symbol(),Period(),1); //indicate that orders are already placed on this pattern
     }
  }
//+------------------------------------------------------------------+


Determinar los niveles de las órdenes Stop

Ahora que está todo preparado, sólo nos falta determinar los niveles de las órdenes Stop y los precios de las órdenes. Además, no hay que olvidar calcular el tiempo de expiración de las órdenes.

Vamos a añadir el siguiente código a la función OnTick():

buyPrice=NormalizeDouble(high2+interval*_point,Digits);       //define an order price considering the interval
      buySL=NormalizeDouble(low2-interval*_point,Digits);     //define a stop loss considering the interval
      buyTP=NormalizeDouble(buyPrice+TP*_point,Digits);       //define a take profit
      _ExpDate=TimeCurrent()+ExpDate*60*60;                   //a pending order expiration time calculation
      sellPrice=NormalizeDouble(low2-interval*_point,Digits);
      sellSL=NormalizeDouble(high2+interval*_point,Digits);
      sellTP=NormalizeDouble(sellPrice-TP*_point,Digits);


Corrección de los errores de ejecución

Si ya ha desarrollado algunos Asesores Expertos, seguro que sabe que los errores ocurren a menudo al cerrar y establecer las órdenes, incluyendo el tiempo de espera, los valores erróneos, etc. Para eliminar estos errores tenemos que escribir una función por separado que incluye un pequeño procesador de errores básicos.

//+----------------------------------------------------------------------------------------------------------------------+
//| The function opens or sets an order                                                                                  |
//| symbol      - symbol, at which a deal is performed.                                                                  |
//| cmd         - a deal (may be equal to any of the deal values).                                                       |
//| volume      - amount of lots.                                                                                        |
//| price       - Open price.                                                                                            |
//| slippage    - maximum price deviation for market buy or sell orders.                                                 |
//| stoploss    - position close price when an unprofitability level is reached (0 if there is no unprofitability level).|
//| takeprofit  - position close price when a profitability level is reached (0 if there is no profitability level).     |
//| comment     - order comment. The last part of comment can be changed by the trade server.                            |
//| magic       - order magic number. It can be used as a user-defined ID.                                               |
//| expiration  - pending order expiration time.                                                                         |
//| arrow_color - open arrow color on a chart. If the parameter is absent or equal to CLR_NONE,                          |
//|               the open arrow is not displayed on a chart.                                                            |
//+----------------------------------------------------------------------------------------------------------------------+
int OrderOpenF(string     OO_symbol,
               int        OO_cmd,
               double     OO_volume,
               double     OO_price,
               int        OO_slippage,
               double     OO_stoploss,
               double     OO_takeprofit,
               string     OO_comment,
               int        OO_magic,
               datetime   OO_expiration,
               color      OO_arrow_color)
  {
   int      result      = -1;    //result of opening an order
   int      Error       = 0;     //error when opening an order
   int      attempt     = 0;     //amount of performed attempts
   int      attemptMax  = 3;     //maximum amount of attempts
   bool     exit_loop   = false; //exit the loop
   string   lang=TerminalInfoString(TERMINAL_LANGUAGE);  //trading terminal language, for defining the language of the messages
   double   stopllvl=NormalizeDouble(MarketInfo(OO_symbol,MODE_STOPLEVEL)*MarketInfo(OO_symbol,MODE_POINT),Digits);  //minimum stop loss/ take profit level, in points
                                                                                                                     //the module provides safe order opening. 
//--- check stop orders for buying
   if(OO_cmd==OP_BUY || OO_cmd==OP_BUYLIMIT || OO_cmd==OP_BUYSTOP)
     {
      double tp = (OO_takeprofit - OO_price)/MarketInfo(OO_symbol, MODE_POINT);
      double sl = (OO_price - OO_stoploss)/MarketInfo(OO_symbol, MODE_POINT);
      if(tp>0 && tp<=stopllvl)
        {
         OO_takeprofit=OO_price+stopllvl+2*MarketInfo(OO_symbol,MODE_POINT);
        }
      if(sl>0 && sl<=stopllvl)
        {
         OO_stoploss=OO_price -(stopllvl+2*MarketInfo(OO_symbol,MODE_POINT));
        }
     }
//--- check stop orders for selling
   if(OO_cmd==OP_SELL || OO_cmd==OP_SELLLIMIT || OO_cmd==OP_SELLSTOP)
     {
      double tp = (OO_price - OO_takeprofit)/MarketInfo(OO_symbol, MODE_POINT);
      double sl = (OO_stoploss - OO_price)/MarketInfo(OO_symbol, MODE_POINT);
      if(tp>0 && tp<=stopllvl)
        {
         OO_takeprofit=OO_price -(stopllvl+2*MarketInfo(OO_symbol,MODE_POINT));
        }
      if(sl>0 && sl<=stopllvl)
        {
         OO_stoploss=OO_price+stopllvl+2*MarketInfo(OO_symbol,MODE_POINT);
        }
     }
//--- while loop
   while(!exit_loop)
     {
      result=OrderSend(OO_symbol,OO_cmd,OO_volume,OO_price,OO_slippage,OO_stoploss,OO_takeprofit,OO_comment,OO_magic,OO_expiration,OO_arrow_color); //attempt to open an order using the specified parameters
      //--- if there is an error when opening an order
      if(result<0)
        {
         Error = GetLastError();                                     //assign a code to an error
         switch(Error)                                               //error enumeration
           {                                                         //order closing error enumeration and an attempt to fix them
            case  2:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(3000);                                       //3 seconds of delay
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;                                         //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case  3:
               RefreshRates();
               exit_loop = true;                                     //exit while
               break;                                                //exit switch   
            case  4:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(3000);                                       //3 seconds of delay
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case  5:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch   
            case  6:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(5000);                                       //3 seconds of delay
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case  8:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(7000);                                       //3 seconds of delay
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 64:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch
            case 65:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch
            case 128:
               Sleep(3000);
               RefreshRates();
               continue;                                             //exit switch
            case 129:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  Sleep(3000);                                       //3 seconds of delay
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //reset the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 130:
               exit_loop=true;                                       //exit while
               break;
            case 131:
               exit_loop = true;                                     //exit while
               break;                                                //exit switch
            case 132:
               Sleep(10000);                                         //sleep for 10 seconds
               RefreshRates();                                       //update data
               //exit_loop = true;                                   //exit while
               break;                                                //exit switch
            case 133:
               exit_loop=true;                                       //exit while
               break;                                                //exit switch
            case 134:
               exit_loop=true;                                       //exit while
               break;                                                //exit switch
            case 135:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //set the number of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 136:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;                                 //define one more attempt
                  RefreshRates();
                  break;                                             //exit switch
                 }
               if(attempt==attemptMax)
                 {
                  attempt = 0;                                       //set the amount of attempts to zero 
                  exit_loop = true;                                  //exit while
                  break;                                             //exit switch
                 }
            case 137:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  Sleep(2000);
                  RefreshRates();
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 138:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  Sleep(1000);
                  RefreshRates();
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 139:
               exit_loop=true;
               break;
            case 141:
               Sleep(5000);
               exit_loop=true;
               break;
            case 145:
               exit_loop=true;
               break;
            case 146:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  Sleep(2000);
                  RefreshRates();
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 147:
               if(attempt<attemptMax)
                 {
                  attempt=attempt+1;
                  OO_expiration=0;
                  break;
                 }
               if(attempt==attemptMax)
                 {
                  attempt=0;
                  exit_loop=true;
                  break;
                 }
            case 148:
               exit_loop=true;
               break;
            default:
               Print("Error: ",Error);
               exit_loop=true; //exit while 
               break;          //other options 
           }
        }
      //--- if no errors detected
      else
        {
         if(lang == "Russian") {Print("Ордер успешно открыт. ", result);}
         if(lang == "English") {Print("The order is successfully opened.", result);}
         Error = 0;                                //reset the error code to zero
         break;                                    //exit while
         //errorCount =0;                          //reset the amount of attempts to zero
        }
     }
   return(result);
  }
//+------------------------------------------------------------------+

Como resultado, obtenemos el siguiente código:

//+------------------------------------------------------------------+
//|                                                    InsideBar.mq4 |
//|                                  Copyright 2015, Iglakov Dmitry. |
//|                                               cjdmitri@gmail.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, Iglakov Dmitry."
#property link      "cjdmitri@gmail.com"
#property version   "1.00"
#property strict

extern int     interval          = 20;                               //Interval
extern double  lot               = 0.1;                              //Lot Size
extern int     TP                = 300;                              //Take Profit
extern int     magic             = 555124;                           //Magic number
extern int     slippage          = 2;                                //Slippage
extern int     ExpDate           = 48;                               //Expiration Hour Order
extern int     bar2size          = 800;                              //Bar 2 Size

double   buyPrice,//define BuyStop price
buyTP,      //Take Profit BuyStop
buySL,      //Stop Loss BuyStop
sellPrice,  //define SellStop price
sellTP,     //Take Profit SellStop
sellSL;     //Stop Loss SellStop

double   open1,//first candle Open price
open2,    //second candle Open price
close1,   //first candle Close price
close2,   //second candle Close price
low1,     //first candle Low price
low2,     //second candle Low price
high1,    //first candle High price
high2;    //second candle High price

datetime _ExpDate=0;          //local variable to define a pending order expiration time
double     _bar2size;
datetime timeBarInside;       //time of the bar, at which inside bar orders were opened, to avoid re-opening
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   double   _bid     = NormalizeDouble(MarketInfo(Symbol(), MODE_BID), Digits); //define a lower price 
   double   _ask     = NormalizeDouble(MarketInfo(Symbol(), MODE_ASK), Digits); //define an upper price
   double   _point   = MarketInfo(Symbol(), MODE_POINT);
//--- define prices of the necessary bars
   open1        = NormalizeDouble(iOpen(Symbol(), Period(), 1), Digits);
   open2        = NormalizeDouble(iOpen(Symbol(), Period(), 2), Digits);
   close1       = NormalizeDouble(iClose(Symbol(), Period(), 1), Digits);
   close2       = NormalizeDouble(iClose(Symbol(), Period(), 2), Digits);
   low1         = NormalizeDouble(iLow(Symbol(), Period(), 1), Digits);
   low2         = NormalizeDouble(iLow(Symbol(), Period(), 2), Digits);
   high1        = NormalizeDouble(iHigh(Symbol(), Period(), 1), Digits);
   high2        = NormalizeDouble(iHigh(Symbol(), Period(), 2), Digits);
//---
   _bar2size=NormalizeDouble(((high2-low2)/_point),0);
//--- if the second bar is bearish, while the first one is bullish
   if(timeBarInside!=iTime(Symbol(),Period(),1) && //no orders have been opened at this pattern yet
      _bar2size>bar2size && //the second bar is big enough, so the market is not flat
      open2>close2 && //the second bar is bullish
      close1>open1 && //the first bar is bearish
      high2>high1 &&  //the bar 2 High exceeds the first one's High
      open2>close1 && //the second bar's Open exceeds the first one's Close
      low2<low1)      //the second bar's Low is lower than the first one's Low
     {
      buyPrice=NormalizeDouble(high2+interval*_point,Digits); //define an order price considering the interval
      buySL=NormalizeDouble(low2-interval*_point,Digits);     //define a stop loss considering the interval
      buyTP=NormalizeDouble(buyPrice+TP*_point,Digits);       //define a take profit
      _ExpDate=TimeCurrent()+ExpDate*60*60;                   //pending order expiration time calculation
      sellPrice=NormalizeDouble(low2-interval*_point,Digits);
      sellSL=NormalizeDouble(high2+interval*_point,Digits);
      sellTP=NormalizeDouble(sellPrice-TP*_point,Digits);
      OrderOpenF(Symbol(),OP_BUYSTOP,lot,buyPrice,slippage,buySL,buyTP,NULL,magic,_ExpDate,Blue);
      OrderOpenF(Symbol(),OP_SELLSTOP,lot,sellPrice,slippage,sellSL,sellTP,NULL,magic,_ExpDate,Blue);
      //--- we have listed all the conditions defining that the first bar is completely within the second one
      timeBarInside=iTime(Symbol(),Period(),1); //indicate that orders are already placed on this pattern
     }
  }
//+------------------------------------------------------------------+

Vamos compilar el código y comprobar si hay mensajes de error en el registro.


Prueba del asesor experto

Es el momento de probar nuestro Asesor Experto. Vamos a ejecutar la prueba de estrategias y establecer los parámetros de entrada. He establecido los parámetros de la siguiente manera:

Fig. 6 Parámetros de entrada para la prueba

Fig. 6 Parámetros de entrada para la prueba

  1. Seleccionamos un símbolo (en este caso es CADJPY).
  2. Hay que asegurarse de elegir el modo "Cada tick" y seleccionar la casilla "Utilizar datos" para llevar a cabo la prueba. He seleccionado todo el año 2014.
  3. Establecemos el período de tiempo D1.
  4. Iniciamos la prueba.
  5. Una vez finalizada la prueba, comprobamos el diario. Como se puede observar, no se ha producido ningún error durante el proceso.

La siguiente figura muestra el diario de la prueba del Asesor Experto:

Fig. 7 Diario de la prueba del Asesor Experto

Fig. 7 Diario de la prueba del Asesor Experto

Nos aseguramos de que no hay ningún error y optimizamos el Asesor Experto


Optimización

He seleccionado los siguientes parámetros para la optimización:

Fig. 8 Parámetros de la optimización

Fig. 8 Parámetros de la optimización


Fig. 9 Ajustes de la optimización

Fig. 9 Ajustes de la optimización

Como resultado, obtenemos el Asesor Experto listo para su uso.


Resultados de la optimización y la prueba

Fig. 10 Resultados de la prueba

Fig. 10 Resultados de la prueba


Fig. 11. Gráfico de los resultados de la prueba

Fig. 11. Gráfico de los resultados de la prueba


Conclusión

  1. Hemos desarrollado un Asesor Experto para el trading con el patrón de la barra interna.
  2. Hemos visto que los patrones Price Action pueden funcionar incluso sin filtros adicionales para entrar al mercado.
  3. No hemos recurrido a ningún truco (tipo martingala o promediado).
  4. Al establecer correctamente las órdenes Stop, se ha reducido la disminución al mínimo.
  5. No se ha utilizado ningún indicador técnico. Se basa el Asesor Experto únicamente en la lectura del gráfico "básico".

¡Gracias por leer el artículo! Espero que le haya resultado útil.