Identify Candlestick Patterns Using MQL5
Published: 2023-08-18 18:04:44


## Identify Candlestick Patterns
Identify the Marubozu, Hammer, Inverted Hammer, Hanging Man, Shooting Star Candlestick patterns.

The MQL5 programming language is based on the MetaTrader 5 platform.

## Program Description


![Program Output With Drawn Vertical Lines](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/u15gorze9twxbl2tet61.png)

The program will output a vertical line to identify a given candlestick pattern.

Bullish Marubozu will be identified using a red vertical line.

Bullish Hammer and Inverted Hammer will be identified using a blue and green line respectively.

Bearish Marubozu will be identified with yellow.
Bearish Hanging Man will be identified with orange.
Bearish Shooting Star will be identified with purple.

## Code Description

We will begin our project within the onTick function within the MQL editor.


![OnTick Function Description](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/ngk1blxjmyv4k8vi65xz.png)


The `OnTick()` function executes on every price change.
Within this function we will write our program logic.


Within the `OnTick()` Function we will initialize our price data array.

```
//Array To Store Price Data
MqlRates price_data_array[];
   
//Set The Most Recent Item To Index 0
ArraySetAsSeries(price_data_array, true);
   
//Copy Price Data To The Array
//Starting From 0 To 100 Price Data Items
CopyRates(_Symbol, _Period, 0, 100, price_data_array);
```

The first line initializes the array we will use to store price data.

`MqlRates price_data_array[];`


The `ArraySetAsSeries` function makes it so that index 0 in our `price_data_array` is the most recent price data.

This is an important function that if not included changes the functionality of the program.

`ArraySetAsSeries(price_data_array, true);`


The `CopyBuffer` function copies the price data of the current symbol, on the current timeframe to the `price_data_array[]`.

This allows us to access the date OHLCV data of the current symbol.

`CopyBuffer(_Symbol, _Period, 0, 100, price_data_array[]);`

We will copy data from index 0 to index 100.
Index 0 is the currently forming candle.
Index 1 is the most recently formed candle.
Index 100 is the 100th candle away from the most recent candle.


```
int candle_index = 1;

double curr_close_value = price_data_array[candle_index].close;
double curr_open_value = price_data_array[candle_index].open;
double curr_low_value = price_data_array[candle_index].low;
double curr_high_value = price_data_array[candle_index].high;
```

We will initialize variables to store our OHLC Data of the most recent candle.

`int candle_index=1;`
This variable stores the index of the candle whose candle pattern type we want.
Index 1 is the most recently completed candlestick.

Next we will begin calculating average candlestick values.
A candlestick will be considered long if it is greater than the average candle size.

```
int avg_range = 5; //Length Of Average

for(int i=candle_index;i<=avg_range;i++)
     {
      
      int val_index = i + 1;
      
      double open_value = price_data_array[val_index].open;
      
      double high_value = price_data_array[val_index].high;
      
      double low_value = price_data_array[val_index].low;
      
      double close_value = price_data_array[val_index].close;
      
      double body_size = MathAbs(open_value - close_value);
      
      double upper_size = 0;
      
      double lower_size = 0;
      
      //If The Currently Indexed Candle Is Bullish Or Bearish
      
      if(close_value > open_value)
        {
         
         upper_size = MathAbs(high_value - close_value);
         
         lower_size = MathAbs(open_value - low_value);
         
        }
      
      else
        {
         
         upper_size = MathAbs(high_value - open_value);
         
         lower_size = MathAbs(close_value - low_value);
         
        }
      
      avg_body_sum_value += body_size;
      
      avg_upper_sum_value += upper_size;
      
      avg_lower_sum_value += lower_size;
      
     }
   

   //Average Body, Upper, and Lower Wick Size Values
   
   double avg_body_size = avg_body_sum_value / avg_range;
   
   double avg_upper_size = avg_upper_sum_value / avg_range;
   
   double avg_lower_size = avg_lower_sum_value / avg_range;
```
In this code block we are calculating the average body size value, average upper wick size, and average lower wick size.

The Body Size is calculated by subtracting the candle open value with the candle close value.

The Upper Size is calculated by subtracting the candle high from the candle close if bullish, else if bearish we subtract candle high with candle open.

The Lower Size is calculated by subtracting the candle open with the candle low if bullish, else if bearish we subtract candle close with candle low.


The Average Candlestick Data is calculated at an average range of 5 items but this value may be easily changed.

The higher average range value the more candles will be used in the calculation.


Next we will calculate Candlestick Data (Body Size, Upper Wick Size, Lower Wick Size) using the most recent candle values.

```
double curr_body_size = MathAbs(curr_open_value - curr_close_value);
   
double curr_upper_size = 0;
   
double curr_lower_size = 0;
   
//Determine Whether The Current Candle Is Bullish Or Bearish
   
bool curr_candle_is_bullish = curr_close_value > curr_open_value;

bool curr_candle_is_bearish = curr_open_value > curr_close_value;
   

if(curr_candle_is_bullish)
  {
      
   curr_upper_size = MathAbs(curr_high_value - curr_close_value);
      
   curr_lower_size = MathAbs(curr_open_value - curr_low_value);
      
  }
   
else
  {
      
   curr_upper_size = MathAbs(curr_high_value - curr_open_value);
      
   curr_lower_size = MathAbs(curr_close_value - curr_low_value);
      
  }
```

In this code block we are calculating the Body Size, Upper Size, and Lower Size for the current candle.

A candle is bullish if the close is greater than the open, and is bearish if the open is greater than the close.

If a candle is bullish, the upper size is the difference between the high value and the close value, the lower size is the difference between the open value and the low value.

If a candle is bearish, the upper size is the difference between the high value and the open value, the lower size is the difference between the close value and the low value.


```
//Determine Whether The Candlestick Data Is Long Or Short

//Candle Data Is Long If It Is Greater Than 1.5 Times The Input

//The inp_val Will Typically Be The Average Value

bool Calculate_Is_Long(double curr_val, double inp_val){
   
   bool is_long = (curr_val >= (inp_val * 1.5));
   
   return(is_long);
   
}
```
At the top of our file we will create the `Calculate_Is_Long()` function, this function is used to determine if a value is long as compared to the average.

We will use the function to Calculate whether the Body Size, Upper Size, Lower Size is Long.

```
//Determine If The Body, Upper, Lower Wick Are Long
   
//A Value Is Long If It Is Greater Than The Average Value Times 1.5
   
bool body_is_long = Calculate_Is_Long(curr_body_size, avg_body_size);
   
bool upper_is_long = Calculate_Is_Long(curr_upper_size, avg_upper_size);
   
bool lower_is_long = Calculate_Is_Long(curr_lower_size, avg_lower_size);
```
Within the `OnTick()` function we will include the above code script.

We initialize variables that have the values of whether or not the current Body, Upper, or Lower value is Long.


```
//Calculate The Percentage Value

//Will Be Used To Calculate The Percentage Value Of
//The Body Size, Upper Wick, and Lower Wick Relative To
//The Total Candlestick Size

double Calculate_Percentage_Value(double curr_val, double total_val){
   
   double div_value = curr_val / total_val;
   
   double perc_value = div_value * 100;
   
   return(NormalizeDouble(perc_value, 5));
   
}


//Determine If Candle Data Is Significant

//If The Body, Upper Wick, or Lower Wick Size Is Significant
//It Means It Occupies Most Of The Candle

bool Calculate_Is_Significant(double perc_value){
   
   bool is_sig = (perc_value > 70);
   
   return(is_sig);
   
}
```
At the top of our file we will create two more functions.

The `Calculate_Percentage_Value()` function calculates the percentage value compared to the total value.

We will use this function to calculate the body, upper, and lower wick size compared to the total candle size.

The next function is `Calculate_Is_Significant()` function which calculates whether candle data occupies most of the candle.

```
double curr_candle_size = MathAbs(curr_high_value - curr_low_value);

//Calculating The Body, Upper, Lower Wick Percentage Values
   
//Determining The Percentage Value Of Candle Data Compared To The Candle Size
   
double curr_body_perc_value = Calculate_Percentage_Value(curr_body_size, curr_candle_size);
   
double curr_upper_perc_value = Calculate_Percentage_Value(curr_upper_size, curr_candle_size);
   
double curr_lower_perc_value = Calculate_Percentage_Value(curr_lower_size, curr_candle_size);
   
   
//Determine If Candle Data Is Significant
   
//Body, Upper, Lower Wick Values Are Significant If
//They Occupy Most Of The Candle Size
   
bool curr_body_is_significant = Calculate_Is_Significant(curr_body_perc_value);
   
bool curr_upper_is_significant = Calculate_Is_Significant(curr_upper_perc_value);
   
bool curr_lower_is_significant = Calculate_Is_Significant(curr_lower_perc_value);
```

Within the `OnTick()` function we will write the above code.

We will find the percentage value of the body size, upper size, and lower size.

Once we have the percentage values, we will determine whether or not the body size, upper, lower size values are significant in the candle.


```
//Determine If The Candle Is Of A Type

//If The Body, Upper Wick, or Lower Wick Is Both
//Long And Significant It Is A Type

bool Return_Is_Candle_Type(bool is_long, bool is_sig){
   
   bool is_type = is_long && is_sig;
   
   return(is_type);
   
}


//Date Time Index Of The Candle Stick Types

datetime bull_maru_index;

datetime bull_hammer_index;

datetime bull_inv_hammer_index;

datetime bear_maru_index;

datetime bear_hang_man_index;

datetime bear_shoot_star_idex;
```

At the top of our file we will add the last functions to determine the candlestick types.

`Return_Is_Candle_Type()` this function returns whether or not our candle data is a candle type.
A candle type has a long value and the value is significant.

The datetime indexes will be used to find the location of our candlestick pattern types.


```
//Determine Whether The Body, Upper, Or Lower Wick Are Long Types
   
//A Long Type Is Both Significant And Long(Greater Than The Average Value)
   
bool body_is_long_type = Return_Is_Candle_Type(body_is_long, curr_body_is_significant);
   
bool upper_is_long_type = Return_Is_Candle_Type(upper_is_long, curr_upper_is_significant);
   
bool lower_is_long_type = Return_Is_Candle_Type(lower_is_long, curr_lower_is_significant);
```

Within the `OnTick()` function we initialize variables to contain the values of whether or not our candle values are of the long type.

```
//Determine Marubozu Type Candles
   
//Is Bullish Marubozu If The Candle Is Bullish And The Body Is A Long Type
bool is_bull_maru = (curr_candle_is_bullish && body_is_long_type);
   
//Is Bearish Marubozu If The Candle Is Bearish And The Body Is A Long Type
bool is_bear_maru = (curr_candle_is_bearish && body_is_long_type);
   
   
//Determine Hammer And Inverted Hammer Type Candles
   
//Is Bullish Hammer If The Candle Is Bullish And The Lower Is A Long Type
bool is_bull_hammer = (curr_candle_is_bullish && lower_is_long_type);
   
//Is Bullish Inverted Hammer If The Candle Is Bullish And The Upper Is A Long Type
bool is_bull_inv_hammer = (curr_candle_is_bullish && upper_is_long_type);
   
   
//Determine Hanging Man And Shooting Star Type Candles
   
//Is Bearish Hanging Man If The Candle Is Bearish And The Lower Is A Long Type
bool is_bear_hang_man = (curr_candle_is_bearish && lower_is_long_type);
   
//Is Bearish Shooting Star If The Candle Is Bearish And The Upper Is A Long Type
bool is_bear_star = (curr_candle_is_bearish && upper_is_long_type);
```

The above code block identifies the individual bullish and bearish candle types.

A Bullish Marubozu has a long body type and the body is significant and the candle is bullish.

A Bullish Hammer has a long lower wick type and the lower wick is significant and the candle is bullish.

A Bullish Inverted Hammer has a long upper wick type and the upper wick is significant and the candle is bullish.

A Bearish Marubozu has a long body type, the body is significant, and the candle is bearish.

A Bearish Hanging Man Type has a long lower wick, the lower wick is significant, and the candle is bearish.

A Bearish Shooting Star has a long upper wick, the upper wick is significant, and the candle is bearish.


```
//Add Candle Type Indexes For Output
   
if(is_bull_maru)
  {
      
   bull_maru_index = price_data_array[candle_index].time;
      
  }
   
if(is_bull_hammer)
 {
      
  bull_hammer_index = price_data_array[candle_index].time;
      
 }
   
if(is_bull_inv_hammer)
 {
      
  bull_inv_hammer_index = price_data_array[candle_index].time;
      
 }
  
if(is_bear_maru)
 {
      
 bear_maru_index = price_data_array[candle_index].time;
      
 }
   
if(is_bear_hang_man)
 {
      
 bear_hang_man_index = price_data_array[candle_index].time;
      
}
   
if(is_bear_star)
  {
      
   bear_shoot_star_idex = price_data_array[candle_index].time;
      
  }
```
The code above initializes the candlestick pattern types to the datetime indexes of those candle types.

```
//Output Candle Type Data As A Vertical Line
   
//The Most Recent Candle Of Each Type Will Be Output
   
ObjectCreate(0, "Bullish Marubozu Index", OBJ_VLINE, 0, bull_maru_index, 0,0);
   
ObjectSetInteger(0, "Bullish Marubozu Index", OBJPROP_COLOR, clrRed);
   
   
ObjectCreate(0, "Bearish Marubozu Index", OBJ_VLINE, 0, bear_maru_index, 0,0);
   
ObjectSetInteger(0, "Bearish Marubozu Index", OBJPROP_COLOR, clrYellow);
   
   
ObjectCreate(0, "Hammer Index", OBJ_VLINE, 0, bull_hammer_index, 0,0);
   
ObjectSetInteger(0, "Hammer Index", OBJPROP_COLOR, clrBlue);
   
   
ObjectCreate(0, "Inverted Hammer Index", OBJ_VLINE, 0, bull_inv_hammer_index, 0,0);
   
ObjectSetInteger(0, "Inverted Hammer Index", OBJPROP_COLOR, clrGreen);
   
   
ObjectCreate(0, "Hanging Man Index", OBJ_VLINE, 0, bear_hang_man_index, 0,0);
   
ObjectSetInteger(0, "Hanging Man Index", OBJPROP_COLOR, clrOrange);
   
   
ObjectCreate(0, "Shooting Star Index", OBJ_VLINE, 0, bear_shoot_star_idex, 0,0);
   
ObjectSetInteger(0, "Shooting Star Index", OBJPROP_COLOR, clrPurple);
```

This final code block is what outputs the vertical lines corresponding to the individual candlestick pattern types.


A link to the full code: {% embed https://github.com/HloniTheCoder/Candle-Stick-Data %}