Price Action. Automating the Inside Bar Trading Strategy

Dmitry Iglakov | 3 August, 2015

Introduction

All Forex traders come across the Price Action at some point. This is not a mere chart analysis technique but the entire system for defining the possible future price movement direction. In this article, we will look at the Inside Bar pattern in details and develop an EA for tracking the Inside Bar and performing trades based on the pattern.


About Price Action

The Price Action is a non-indicator price movement detection method using simple and complex patterns, as well as auxiliary chart elements (horizontal, vertical and trend lines, Fibo levels, support/resistance levels, etc.).

At first glance, the method may seem rather complicated but actually this is not the case. The method is gaining popularity from year to year, since its advantages are evident, for example, when compared to the methods involving technical indicators.


Inside Bar

Inside Bar is a bar having its body and wicks contained entirely within the range of the previous (mother) bar. The inside bar's High lies lower and Low is located higher than the mother bar's ones. Mother and inside bars form a pattern considered to be a potential entry signal.

This is a two-sided pattern, since it may indicate either a reversal, or a trend continuation.

Fig. 1. Inside bar

Fig. 1. Inside bar


Fig. 2. Inside Bar pattern layout

Fig. 2. Inside Bar pattern layout

Inside bar rules:

  • The Inside Bar pattern is significant on higher timeframes, like H4 or D1.
  • The pattern can indicate either a trend reversal or a continuation.
  • Apply additional graphical analysis tools for more precise entry, including trend lines, support/resistance levels, Fibo levels, other Price Action patterns, etc.
  • Use pending orders to avoid premature or false market entries.
  • Do not use inside bars repeatedly occurring in the flat market as market entry signals.

Fig. 3. Defining the genuine inside bar on GBPUSD D1

Fig. 3. Defining the genuine inside bar on GBPUSD D1

Keeping all this in mind, let's try to define a genuine inside bar. On the above chart, we can see that a bullish bar was formed after the sharp downward movement. However, the bar lies completely within the boundaries of the previous one. The pattern is confirmed by the fact that it is formed at the support level. The third confirmation is the absence of flat. Since the pattern satisfies the rules, it can be considered genuine.


Defining Entry Points and Setting Stop Orders

So, we have found a genuine inside bar on the chart (Fig. 3). How should we enter the market and where should we set our stop orders? Let's examine the Figure 4.

Fig. 4. Setting Buy Stop and stop orders

Fig. 4. Setting Buy Stop and stop orders

First, we should consider the stop level setting rules using the example above:

  1. Set a Buy Stop pending order slightly higher than a mother bar's High price (only several points higher, for confirmation).
  2. Set a Stop Loss level below a support level, as well as a mother bar's Low price. This is an additional protection in case a pending order is triggered and the price reaches the support level just to bounce back and start moving in the right direction later on.
  3. Set a Take Profit level slightly lower than the nearest resistance level.
Do not forget that an inside bar may be followed either by a trend reversal or continuation meaning that we need a Sell Stop order as well.

Fig. 5. Setting Sell Stop and stop orders

Fig. 5. Setting Sell Stop and stop orders

First, we should consider the stop level setting rules using the example above:

  1. Set a Sell Stop pending order slightly lower than a mother bar's Low price (only several points lower, for confirmation).
  2. Set a Stop Loss level above a mother bar's High price.
  3. Set a Take Profit level slightly higher than the nearest support level.


Developing an Expert Advisor Based on Inside Bar Trading

Now that we know all the necessary rules of defining a genuine inside bar, entering the market and setting stop orders, we can finally implement the appropriate Expert Advisor that will trade using the Inside Bar pattern.

Open MetaEditor from the MetaTrader 4 terminal and create a new Expert Advisor (I believe, I do not have to dwell upon this, since the website provides plenty of information on how to create an Expert Advisor). All parameters are left blank at this stage. You can name them whatever you like. The resulting code will look as follows:

//+------------------------------------------------------------------+
//|                                                    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()
  {
//---

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


Converting the Pattern into MQL4 Algorithm

After we have created the EA, we need to define an inside bar after a candle is closed. To do this, we introduce new variables and assign values to them. See the code below:

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

As an example, let's consider that a mother bar is bearish (bar 2), while an inside one is bullish (bar 1). Let's add a number of conditions to the OnTick() function body:

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
     }
  }
  • Create customizable variables: stop orders, slippage, order expiration time, EA magic number, trading lot. Stop loss may be omitted, since it is to be defined according to the inside bar rules.
  • Enter local variables to normalize the look of the variables.
  • Stop orders are set at a certain distance from the bar price values. In order to implement that, add the Interval variable responsible for the interval between High/Low prices of bars and stop order levels, as well as pending order levels.
  • Add the timeBarInside variable to avoid order re-opening on this pattern.
  • Add the bar2size variable to ensure that a mother bar is big enough, which is a good sign that the current market is not flat.

As a result, we obtain the following code:

//+------------------------------------------------------------------+
//|                                                    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
     }
  }
//+------------------------------------------------------------------+


Defining Stop Order Levels

Now that all preparations are complete, we only have to define stop order levels and order prices. Also, do not forget about an order expiration time calculation.

Let's add the following code to the OnTick() function body:

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


Correction of Execution Errors

If you have ever engaged in the development of Expert Advisors, you probably know that errors often happen when closing and setting orders, including waiting time, incorrect stops, etc. To eliminate such errors, we should write a separate function with a small built-in handler of basic errors.

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

As a result, we obtain the following code:

//+------------------------------------------------------------------+
//|                                                    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
     }
  }
//+------------------------------------------------------------------+

Now, let's perform the compilation and check for error messages in the log.


Testing the Expert Advisor

It is time to test our Expert Advisor. Let's launch the strategy tester and set the input parameters. I have specified the parameters as follows:

Fig. 6. Input parameters for testing

Fig. 6. Input parameters for testing

  1. Select a symbol (it is CADJPY in my case).
  2. Be sure to set "Every tick" mode and define that testing is to be performed on history data. I have selected the entire year of 2014.
  3. Set D1 timeframe.
  4. Launch the test.
  5. After the test is complete, check the log. As we can see, no execution errors have occurred in the process.

Below is the EA testing journal:

Fig. 7. Expert Advisor testing journal

Fig. 7. Expert Advisor testing journal

Make sure there are no mistakes and optimize the EA.


Optimization

I have selected the following parameters for optimization:

Fig. 8. Optimization parameters

Fig. 8. Optimization parameters


Fig. 9. Optimization settings

Fig. 9. Optimization settings

Thus, we now have the ready-to-use robot.


Optimization and Test Results

Fig. 10. Test results

Fig. 10. Test results


Fig. 11. Test results graph

Fig. 11. Test results graph


Conclusion

  1. We have developed the ready-to-use Expert Advisor trading the Inside Bar pattern.
  2. We have made sure that Price Action patterns can work even with no additional market entry filters.
  3. No tricks (like Martingale or averaging) have been used.
  4. The drawdown has been minimized through the correct setting of the stop orders.
  5. No technical indicators have been used. The trading robot is based solely on reading a "bare" chart.

Thank you for reading! I hope this article has been helpful.