
How to use MQL5 to detect candlesticks patterns
Introduction
Candlesticks are a very helpful technical tool if we use them correctly, as we can find a potential movement based on their patterns. Candlesticks can form specific patterns on the chart and these patterns can be divided into two types single-candle patterns and blended candle patterns (more than one candle). In this article, we will learn how we can use MQL5 to detect some of these patterns automatically in the MetaTrader 5 trading terminal, we will cover that through the following topics:
I need to mention that it is very important to use these patterns accompanied by other technical tools to get significant signals. So, you need to understand the main idea of detecting mentioned patterns by MQL5 to be a part of your trading system to ease your trading and get good results.
Single candle pattern
In this part, we will see two examples of popular single-candle pattern which appears on the chart. You can see them in any time frame, it will be more significant when they come in its place relative to the price action. we will see the Doji and the Hammer patterns.
Doji pattern:
It is very popular among candlesticks patterns and it is the candle that has almost the same opening and closing price, we can see a very small body of the candle or a line on the chart for the same price with upper and lower body or even without these shadows. The following figure is for this candle:
This Doji candle indicates that there is a balance between buyers and sellers and no one controls the market to move the price higher or lower during the period when it appears at. It may signal a reversal or correction in the market if it appears at its suitable place on the chart before a correction or at the end of the trend and it will be more significant if it appears in the bigger time frame. There are many types and formations for this candle and everyone has a lot of information that can be used in our favor in trading like Dragonfly and Long-legged.
What we need to do is to inform the computer to detect the Doji pattern by defining the prices and time of the last candle and every tick we need the program to check and compare these values at this defined time and determine the positions of everyone. If the open is equal to the close we need the program to return a signal that this is a Doji candle pattern.
Now, we need to create a program that can detect this pattern and the following are steps of a method that can do that:
We will create a function for this Doji (getDoji) and we will call it in the OnTick() to check every tick searching for this pattern
void OnTick() { getDoji(); }
Create the (getDoji) function by creating it as an integer variable
int getDoji()
Defining this function by defining time, open, high, low, and close prices of the last candle
Using the iTime function which returns the opening time of the candle, the iOpen which returns the open price of the candle, the iHigh which returns the high price, the iLow which returns the low price, and the iClose which returns the close price of the candle. parameters are the same for all of them:
- symbol: to define the symbol name, we will use (_Symbol) for the current symbol.
- timeframe: to define the period or timeframe of the chart, we will use (PERIOD_CURRENT) for the current timeframe.
- shift: to define the index of the returned value, we will use (1) to define the last candle.
datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1);
Setting the condition of the Doji that we need to detect by using the if statement
if(open==close)
If this condition is true, we need the program to create an object based on the createObj function that we will create with the parameters of time, price, code of arrow, color, and the text that we need. Then terminate the function by returning 1.
if(open==close) { createObj(time,low,217, clrBlack,"Doji"); { return 1; } }
We will return 0 to terminate the function of getDoji
return 0;
Creating (createObj) function with the parameters of time, price, arrowcode, clr, and txt by using the void function
void createObj(datetime time, double price, int arrawCode, color clr, string txt)
Creating a string variable of (objName) assigned to (" ") value
string objName=" ";
Combining strings to assign them to the (objName) variable by using the (StringConcatenate) function which forms a string of passed parameters and returns the size of the formed string. Its parameters are:
- string_var: to define the string that will be formed after concatenation, we will use the (objName).
- argument1: to define the parameter of any simple type, we will use the text of "Signal at ".
- argument2: to define the time of the detected candle, we will use the time of the predetermined variable.
- argument3: we will set the text of " at ".
- argument4: we will set the text of the rounded price by using DoubleToString to convert the double type to string type.
- argument5: we will set the text of " (".
- argument6: we will assign a value for the predetermined integer variable (arrowcode) that we need. This code can be found by searching for the Wingdings in the mql5 reference.
- argument7: we will set the text of ")".
StringConcatenate(objName, "Signal at ",time, " at ",DoubleToString(price,_Digits)," (",arrawCode,")");
We will set a condition to be evaluated by using the if statement and the (ObjectCreate) function as an expression, the (ObjectCreate) function creates an object for us by using the predefined name (objName) and its parameters are:
- chart_id: to identify the chart, we will use 0 for the current chart.
- name: to define the object name, we will use the predefined name (objName).
- type: to define the object type, we will use (OBJ_ARROW).
- nwin: to define the number of the chart sub-window, we will use (0) for the main chart window.
- time1: to define the time of the anchor, we will use the predefined (time) variable.
- price1: to define the price of the anchor, we will use the predefined (price) variable.
if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price))
Once this condition is true by creating the object we need to set its properties its shape by determining the arrow code and its color by using the (ObjectSetInteger) function which sets the value of the object property. Its parameters are:
- chart_id: to identify the chart, we will use 0 for the current chart.
- name: to define the object name, we will use (objName).
- prop_id: to define the property of the object, we will use one of the ENUM_OBJECT_PROPERTY_INTEGER which will be the (OBJPROP_ARROWCODE) for the arrow code and (OBJPROP_COLOR) for the color.
- prop_value: to define the property value, we will use (arrawCode) for the arrow code and the predefined variable (clr) for the color.
ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr);
After that, we need to define the text that we need as a definition of the candle by creating a string variable for the (candleName) with an assignment of the predefined (objName) and (txt) variables
string candleName=objName+txt;
Creating and editing the text object by using the if statement and using (ObjectCreate) function as an expression and the operator will be (ObjectSetString) to set the string value of the object property and the (ObjectSetInteger) to set the color of the text object.
ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr);
Now, we can see the full code of this Expert Advisor the same as the following:
//+------------------------------------------------------------------+ //| Doji pattern detector.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ void OnTick() { getDoji(); } int getDoji() { datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); //Doji if(open==close) { createObj(time,low,217, clrBlack,"Doji"); { return 1; } } return 0; } void createObj(datetime time, double price, int arrawCode, color clr, string txt) { string objName=" "; StringConcatenate(objName, "Signal at ",time, " at ",DoubleToString(price,_Digits)," (",arrawCode,")"); if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price)) { ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr); } string candleName=objName+txt; if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price)) { ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr); } }
After compiling this code without errors, we can find it in the navigator window. By dragging it to be executed we can then get its signals detecting the Doji pattern and the following is an example from testing:
As we can see in the previous chart we have a black arrow object below the candle and the Doji text to define the candle pattern.
Hammer Pattern:
The hammer pattern is a very popular candlesticks pattern that we can see on the chart in many timeframes. Its name refers to its shape as it has a long shadow and a small body there are two types of Hammer patterns, Hammer and Inverted Hammer as per the position of the small body. If it has a long lower shadow and the body of the candle is above, it is a Hammer and it can be a bullish or bearish candle based on the opening and closing price, the following figures are examples of this Hammer patterns:
- Bullish Hammer
It indicates that the seller tried to push the price lower but the buyer controls the market and close higher than its opening which means strength for the buyer.
- Bearish Hammer
It indicates that the seller tried to push the price lower but the buyer appears to close at around the opening which means that the buyer is still in the game.
If the candle has a long upper shadow and its body is below, it is an Inverted Hammer pattern and it can be also bullish or bearish based on the position of open and close prices. The following figures are examples of this Inverted Hammer.
- Bullish Inverted Hammer
It indicates that the buyer tried to push prices higher but the seller appears to close the candle around the open and the low which means that the seller is still in the game although the strength of the buyer.
- Bearish Inverted Hammer
It indicates that the buyer tried to push the price lower but the seller controls the market and close lower than its opening which means strength for the seller.
This pattern also the same as all candlesticks patterns will be more meaningful and significant when it combined with other technical tools
Now, we need to create a program that can be used to detect this kind of pattern, so we will let this program find the candle prices, time, and candle size to be compared to the body and shadows of the candle and we need the program to continuously check and comparing them every tick to determine their positions. When the program detects one of the Hammer or Inverted Hammer (Bullish or Bearish), we need the program to return an object on the chart with its type name and arrows color green or red based and below or above the candle based on the color of the candle (bullish or bearish).
The following is the full code to create this type of program:
//+------------------------------------------------------------------+ //| Hammer pattern detector.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ void OnTick() { getHammer(0.07,0.7); } int getHammer(double smallShadowRatio, double longShadowRatio) { datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double candleSize=high-low; if(open<close) { if(high-close < candleSize*smallShadowRatio) { if(open-low>candleSize*longShadowRatio) createObj(time,low,217, clrGreen,"Hammer"); { return 1; } } } if(open>close) { if(high-open<candleSize*smallShadowRatio) { if(close-low>candleSize*longShadowRatio) createObj(time,high,218,clrRed,"Hammer"); { return 1; } } } if(open<close) { if(open-low < candleSize*smallShadowRatio) { if(high-close>candleSize*longShadowRatio) createObj(time,low,217, clrGreen,"Inverted Hammer"); { return -1; } } } if(open>close) { if(close-low < candleSize*smallShadowRatio) { if(high-open>candleSize*longShadowRatio) createObj(time,high,218, clrRed,"Inverted Hammer"); { return -1; } } } return 0; } void createObj(datetime time, double price, int arrawCode, color clr, string txt) { string objName=" "; StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")"); if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price)) { ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr); if(clr==clrGreen) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP); if(clr==clrRed) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM); } string candleName=objName+txt; if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price)) { ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr); } }
Differences in this code are the same as the following:
Calling the getHammer function in the OnTick() with determining desired parameters for the smallShadowRatio and longShadowRatio
void OnTick() { getHammer(0.07,0.7); }
Creating the (getHammer) function with parameters of two double variables (smallShadowRatio) and (longShadowRatio)
int getHammer(double smallShadowRatio, double longShadowRatio)
Creating a double variable for the (candleSize) to be compared to the ratio
double candleSize=high-low;
Conditions of the Hammer candle,
In the case of a Bullish Hammer (Open<Close), we need a last bullish candle, the upper shadow of the candle (high-close) is less than the ratio of small shadow which is 0.07, and the lower shadow (open-low) is greater than the long shadow ratio which is 0.7. Create a green arrow with the code (217) from Wingdings and the "Hammer" text object on the chart below the low of this Hammer candle, then terminate the function.
if(open<close) { if(high-close < candleSize*smallShadowRatio) { if(open-low>candleSize*longShadowRatio) createObj(time,low,217, clrGreen,"Hammer"); { return 1; } } }
In the case of a Bearish Hammer (open>close), we need a last bearish candle, the upper shadow of the candle (high-open) is less than the ratio of small shadow which is 0.07, and the lower shadow (close-low) is greater than the long shadow ratio which is 0.7. Create a red arrow with the code (218) from Wingdings and the "Hammer" text object on the chart above the high of this Hammer candle, then terminate the function.
if(open>close) { if(high-open<candleSize*smallShadowRatio) { if(close-low>candleSize*longShadowRatio) createObj(time,high,218,clrRed,"Hammer"); { return 1; } } }
In the case of a Bullish Inverted Hammer (open<close), we need a last bullish candle, the lower shadow of the candle (open-low) is less than the ratio of small shadow which is 0.07, and the upper shadow (high-close) is greater than the long shadow ratio which is 0.7. Create a green arrow with the code (217) from Wingdings and the "Inverted Hammer" text object on the chart below the low of this Hammer candle, then terminate the function.
if(open<close) { if(open-low < candleSize*smallShadowRatio) { if(high-close>candleSize*longShadowRatio) createObj(time,low,217, clrGreen,"Inverted Hammer"); { return -1; } } }
In the case of a Bearish Inverted Hammer (open>close), we need a last bearish candle, the lower shadow of the candle (close-low) is less than the ratio of small shadow which is 0.07, and the upper shadow (high-open) is greater than the long shadow ratio which is 0.7. Create a red arrow with the code (218) from Wingdings and the "Inverted Hammer" text object on the chart above the high of this candle, then terminate the function.
if(open>close) { if(close-low < candleSize*smallShadowRatio) { if(high-open>candleSize*longShadowRatio) createObj(time,high,218, clrRed,"Inverted Hammer"); { return -1; } } }
Let's edit the arrow position and color depending on the candle type using the 'if' operator. The expression will be the color, while the 'if' operator (if it is true) will be used as the arrow position with the help of the ObjectSetInteger function.
If green will be below the candle
if(clr==clrGreen) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP);
If red will be above the candle
if(clr==clrRed) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM);
After compiling this code without errors and executing it we can get our signal and the following are examples from testing:
- Bullish Hammer:
As we can see that we have a green arrow and the green "Hammer" text object on the chart below the low of the bullish Hammer candle.
- Bearish Hammer:
As we can see that we have a red arrow and the red "Hammer" text object on the chart above the high of the bearish Hammer candle.
- Bullish Inverted Hammer:
As we can see that we have a green arrow and the green "Inverted Hammer" text object on the chart below the low of the bullish Inverted Hammer candle.
- Bearish Inverted Hammer:
As we can see that we a red arrow and the red "Inverted Hammer" text object on the chart above the high of the bearish Inverted Hammer candle.
Dual candles pattern
In this part, we will see another type of candlesticks pattern that consists of two candles, we will see two popular patterns which are Engulfing (Bullish and Bearish) and the bullish Piercing line and its opposite bearish Dark Cloud patterns.
Engulfing pattern:
This candlestick pattern is also a very popular one on the chart and technical analysis that consists of two candles one of them engulfs the other one which means that it has a small candle followed by a larger one and this larger one covers the smaller one completely.
There are types of this Engulfing pattern based on the color or type of candles:
- The Bullish Engulfing:
It has a small bearish candle followed by a large bullish candle and this bullish one engulfs the smaller one and the following figure is for it:
Depending on its significance, it indicates that the buyer controls the market and the price may continue to rise after it.
- The Bearish Engulfing:
Depending on its significance, it indicates that the seller controls the market and the price may continue to decline after it.
Now, if we want to create a program that can be used to detect this pattern automatically, we need to define the time of the last candle and prices of the last two candles, we need the program to continuously check these values every tick and determine its positions related to each other to check if we have this type of Engulfing pattern or not. Once we have this Engulfing pattern, we need the program to return a specific signal which is a colored arrow and text object based on its type (Bullish or Bearish).
The following is the full code to create this program:
//+------------------------------------------------------------------+ //| Engulfing pattern detector.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ void OnTick() { getEngulfing(); } int getEngulfing() { datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double open2=iOpen(_Symbol,PERIOD_CURRENT,2); double high2=iHigh(_Symbol,PERIOD_CURRENT,2); double low2=iLow(_Symbol,PERIOD_CURRENT,2); double close2=iClose(_Symbol,PERIOD_CURRENT,2); if(open<close) { if(open2>close2) { if(high>high2&&low<low2) { if(close>open2&&open<close2) { createObj(time,low,217, clrGreen,"Bullish Engulfing"); { return 1; } } } } } if(open>close) { if(open2<close2) { if(high>high2&&low<low2) { if(close<open2&&open>close2) { createObj(time,high,218, clrRed,"Bearish Engulfing"); { return -1; } } } } } return 0; } void createObj(datetime time, double price, int arrawCode, color clr, string txt) { string objName=" "; StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")"); if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price)) { ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr); if(clr==clrGreen) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP); if(clr==clrRed) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM); } string candleName=objName+txt; if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price)) { ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr); } }
Differences in this code:
Creating double variables for time for the last candle and prices the last two candles in creating the function of (getEngulfing), time, open, high, low, and close are for the last candle and open2, high2, low2, and close2 are for the previous candle of the last one
datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double open2=iOpen(_Symbol,PERIOD_CURRENT,2); double high2=iHigh(_Symbol,PERIOD_CURRENT,2); double low2=iLow(_Symbol,PERIOD_CURRENT,2); double close2=iClose(_Symbol,PERIOD_CURRENT,2);
Conditions that define this type of candle pattern
In the case of Bullish Engulfing, The last candle is bullish (open<close), the previous of the last is bearish one (open2>close2), the high is greater than high2 and at the same low is lower than low2, the close greater than open2 and at the same time open is lower than close2. Once identifying it, create an object based on the created function (createObj) with the following parameters:
- time: it will be the time of the last candle which is the predefined variable.
- price: it will be the low of the last candle that we need the object below it.
- arrowCode: it will be 217 from the Wingdings.
- clr: it will be clrGreen.
- txt: it will be the "Bullish Engulfing".
Then terminate the function.
if(open<close) { if(open2>close2) { if(high>high2&&low<low2) { if(close>open2&&open<close2) { createObj(time,low,217, clrGreen,"Bullish Engulfing"); { return 1; } } } } }
In the case of Bearish Engulfing, The last candle is bearish (open>close), the previous of the last is bullish one (open2<close2), the high is greater than high2, and at the same low is lower than low2, the close lower than open2 and at the same time open is greater than close2. Once identifying it, create an object based on the created function (createObj) with the following parameters:
- time: it will be the time of the last candle which is the predefined variable.
- price: it will be the high of the last candle that we need the object above it.
- arrowCode: it will be 218 from the Wingdings.
- clr: it will be clrRed.
- txt: it will be the "Bearish Engulfing".
Then terminate the function.
if(open>close) { if(open2<close2) { if(high>high2&&low<low2) { if(close<open2&&open>close2) { createObj(time,high,218, clrRed,"Bearish Engulfing"); { return -1; } } } } }
After compiling this code without errors and executing its EA, we can get its signals the as the following examples from testing:
- The Bullish Engulfing:
The same as we can see on the previous chart we have a green arrow and Bullish Engulfing text below the low of the last candle in the pattern.
- The Bearish Engulfing:
The same as we can see on the previous chart we have a red arrow and Bearish Engulfing text above the high of the last candle in the pattern.
Piercing Line and Dark Cloud Cover pattern:
- Piercing Line Pattern:
It is a bullish candlestick and consists of two candles also as the first candle is bearish and followed by a bullish one with lower open than the bearish one then moves up and closes above the midpoint of the first bearish candle. The following figure is for a graph that describes it:
It indicates that the buyer becomes stronger and controls the market after the control from the seller. So, it refers to a shift from selling to buying power as the buyer was able to push the price above the midpoint of the previous bearish candle although there was a gap when opening.
- Dark Cloud Cover pattern:
It is the opposite form from the piercing patterns, as it is a bearish pattern that has two candles structure the first is bullish and is followed by a bearish candle with an opening gap and closes below the midpoint of the first bullish one. The following is a graph for it:
It indicates that the seller becomes stronger and controls the market after the control from the buyer. So, it refers to a shift from buying to selling power as the seller was able to push the price below the midpoint of the previous bullish candle although there was a gap when opening.
When we want to create a program that can be used to detect this type of pattern we will need to define the time and prices of the first candle (time, open, high, low, and close) and prices for the second candle (open2, high2, low2, and close2), candle size of the first candle (candleSize2), and the midpoint of the first candle (candleMidPoint2). we need the program to continuously check these values and determine their positions related to each other and return a specific signal based on specific conditions based on the bullishness or bearishness.
The following is the full code to create this program:
//+------------------------------------------------------------------+ //| Piercing && Dark Cloud pattern detector.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ void OnTick() { getPiercing(); } int getPiercing() { datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double open2=iOpen(_Symbol,PERIOD_CURRENT,2); double high2=iHigh(_Symbol,PERIOD_CURRENT,2); double low2=iLow(_Symbol,PERIOD_CURRENT,2); double close2=iClose(_Symbol,PERIOD_CURRENT,2); double candleSize2=high2-low2; double candleMidPoint2=high2-(candleSize2/2); if(open<close) { if(open2>close2) { if(open<low2) { if(close>candleMidPoint2&&close<high2) { createObj(time,low,217, clrGreen,"Piercing"); { return 1; } } } } } if(open>close) { if(open2<close2) { if(open>high2) { if(close<candleMidPoint2&&close>low2) { createObj(time,high,218, clrRed,"Dark Cloud"); { return -1; } } } } } return 0; } void createObj(datetime time, double price, int arrawCode, color clr, string txt) { string objName=" "; StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")"); if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price)) { ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr); if(clr==clrGreen) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP); if(clr==clrRed) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM); } string candleName=objName+txt; if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price)) { ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr); } }
Differences in this code
Defining candleSize2 and candleMidPoint2
double candleSize2=high2-low2; double candleMidPoint2=high2-(candleSize2/2);
Conditions of the pattern
In the case of the Piercing Line pattern:
If the last candle is bullish (open<close), and the open2 is greater than close2, open is lower than low2, and close is greater than candleMidPoint2 and at the same time close is lower than high2, we need the program to return an object on the chart with green arrow and the text of "Piercing" below the low of the pattern, then terminate the function.
if(open<close) { if(open2>close2) { if(open<low2) { if(close>candleMidPoint2&&close<high2) { createObj(time,low,217, clrGreen,"Piercing"); { return 1; } } } } }
In the case of the Dark Cloud Cover pattern:
If the last candle is bearish (open>close), and the open2 is lower than close2, open is greater than high2, and close is lower than candleMidPoint2 and at the same time close is greater than low2, we need the program to return an object on the chart with a red arrow and the text of "Dark Cloud" above the high of the pattern, then terminate the function.
if(open>close) { if(open2<close2) { if(open>high2) { if(close<candleMidPoint2&&close>low2) { createObj(time,high,218, clrRed,"Dark Cloud"); { return -1; } } } } }
After compiling this code and executing its EA, we can get the desired signals the same as the following examples from testing:
- Piercing Line pattern:
As we can see in the previous chart, we have our green arrow and piercing text below the low of the pattern the same as we need.
- Dark Cloud Cover pattern:
As we can see in the previous chart, we have a red arrow and Dark Cloud text above the high of the pattern the same as we need.
Three candles pattern
In this part, we will see two patterns from the blended patterns and they are the Star pattern (Morning, Evening) and the Three Inside Pattern (Up, Down).
Star Pattern:
- The Morning Star:
It is a three candles structure the same as we mentioned. It is formed by a small candle between two candles the first one is a long bearish and the second one is a long bullish one. The following is a graph for it:
Based on its significance, it indicates a shift in power from selling to buying as the buyer controls the market and pushes the price higher after a decline by seller control.
- Evening Star pattern:
Based on its significance, it indicates a shift in power from buying to selling as the seller controls the market and pushes the price lower after a rally by buyer control.
When we want to create a program that can be used to detect this kind of pattern, we need to define the time and price of the last candle and the price data of the previous two candles of the last one, candleSize of the last three candles and compare them to each other to determine their positions related to each other to get specific signals based on specific conditions.
The following is the full code to create this program:
//+------------------------------------------------------------------+ //| Star pattern detector.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" void OnTick() { getStar(0.5); } int getStar(double middleCandleRatio) { datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double open2=iOpen(_Symbol,PERIOD_CURRENT,2); double high2=iHigh(_Symbol,PERIOD_CURRENT,2); double low2=iLow(_Symbol,PERIOD_CURRENT,2); double close2=iClose(_Symbol,PERIOD_CURRENT,2); double open3=iOpen(_Symbol,PERIOD_CURRENT,3); double high3=iHigh(_Symbol,PERIOD_CURRENT,3); double low3=iLow(_Symbol,PERIOD_CURRENT,3); double close3=iClose(_Symbol,PERIOD_CURRENT,3); double candleSize=high-low; double candleSize2=high2-low2; double candleSize3=high3-low3; if(open<close) { if(open3>close3) { if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio) { createObj(time,low,217, clrGreen,"Morning Star"); { return 1; } } } } if(open>close) { if(open3<close3) { if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio) { createObj(time,high,218, clrRed,"Evening Star"); { return -1; } } } } return 0; } void createObj(datetime time, double price, int arrawCode, color clr, string txt) { string objName=" "; StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")"); if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price)) { ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr); if(clr==clrGreen) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP); if(clr==clrRed) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM); } string candleName=objName+txt; if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price)) { ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr); } }
Differences in this code
Creating the (getStar) with the parameter on middleCandleRatio
int getStar(double middleCandleRatio)
Creating variables of time for the last candle and the price data (open, high, low, close) and the candle size for the last three candles (candlesize, candleSize2, and candleSize3)
datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double open2=iOpen(_Symbol,PERIOD_CURRENT,2); double high2=iHigh(_Symbol,PERIOD_CURRENT,2); double low2=iLow(_Symbol,PERIOD_CURRENT,2); double close2=iClose(_Symbol,PERIOD_CURRENT,2); double open3=iOpen(_Symbol,PERIOD_CURRENT,3); double high3=iHigh(_Symbol,PERIOD_CURRENT,3); double low3=iLow(_Symbol,PERIOD_CURRENT,3); double close3=iClose(_Symbol,PERIOD_CURRENT,3); double candleSize=high-low; double candleSize2=high2-low2; double candleSize3=high3-low3;
Conditions of the pattern
In the case of the Morning Star pattern:
If the last candle is bullish (open<close), the third one is bearish (open3>close3), the candleSize2 is lower than the middleCandleRatio of the candleSize which is 0.5 and at the same time the candleSize2 is lower than the middleCandleRatio of the candleSize3, we need the program to return an object of green arrow and text of "Morning Star" below the low of the pattern, then terminate the function.
if(open<close) { if(open3>close3) { if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio) { createObj(time,low,217, clrGreen,"Morning Star"); { return 1; } } } }
In the case of the Evening Star:
If the last candle is bearish (open>close), the third one is bullish (open3<close3), the candleSize2 is lower than the middleCandleRatio of the candleSize which is 0.5 and at the same time the candleSize2 is lower than the middleCandleRatio of the candleSize3, we need the program to return an object of red arrow and text of "Evening Star" above the high of the pattern, then terminate the function.
if(open>close) { if(open3<close3) { if(candleSize2<candleSize*middleCandleRatio && candleSize2<candleSize3*middleCandleRatio) { createObj(time,high,218, clrRed,"Evening Star"); { return -1; } } } }
After compiling this code without errors and executing its EA, we can get signals the same as the following examples from testing:
- The Morning Star:
As we can see that we have the desired signal of the required object on the chart below the detected pattern.
- The Evening Star:
As we can see that we have the desired signal of the required object on the chart below the detected pattern.
As a note for the Star pattern, the identical pattern formation is having a gap with the middle small candle, you can add it as an additional condition in the code, if you want to get the identical pattern.
Three Inside pattern:
- Three Inside Up:
It is a three-candle pattern also, the first candle is a long bearish, the second one is a small bullish candle that is trading inside the first one, and the third one is a long bullish candle that closes above the high of the first one. The following is a graph of this pattern.
Based on its significance, it indicates a potential bullishness by the control of the buyer.
- Three Inside Down:
It is a three-candle pattern also, the first candle is a long bullish, the second one is a small bearish candle that is trading inside the first one, and the third one is a long bearish candle that closes below the low of the first one. The following is a graph of this pattern.
//+------------------------------------------------------------------+ //| Three inside pattern detector.mq5 | //| Copyright 2023, MetaQuotes Ltd. | //| https://www.mql5.com | //+------------------------------------------------------------------+ #property copyright "Copyright 2023, MetaQuotes Ltd." #property link "https://www.mql5.com" #property version "1.00" void OnTick() { getthreeInside(); } int getthreeInside() { datetime time=iTime(_Symbol,PERIOD_CURRENT,1); double open=iOpen(_Symbol,PERIOD_CURRENT,1); double high=iHigh(_Symbol,PERIOD_CURRENT,1); double low=iLow(_Symbol,PERIOD_CURRENT,1); double close=iClose(_Symbol,PERIOD_CURRENT,1); double open2=iOpen(_Symbol,PERIOD_CURRENT,2); double high2=iHigh(_Symbol,PERIOD_CURRENT,2); double low2=iLow(_Symbol,PERIOD_CURRENT,2); double close2=iClose(_Symbol,PERIOD_CURRENT,2); double open3=iOpen(_Symbol,PERIOD_CURRENT,3); double high3=iHigh(_Symbol,PERIOD_CURRENT,3); double low3=iLow(_Symbol,PERIOD_CURRENT,3); double close3=iClose(_Symbol,PERIOD_CURRENT,3); if(open3>close3) { if(open2<close2) { if(open2>low3&&close2<high3) { if(open<close&&open>open2&&open<close2) { if(close>high3) { createObj(time,low,217, clrGreen,"3 Inside Up"); { return 1; } } } } } } if(open3<close3) { if(open2>close2) { if(open2<high3&&close2>low3) { if(open>close&&open<open2&&open>close2) { if(close<low3) { createObj(time,high,218, clrRed,"3 Inside Down"); { return -1; } } } } } } return 0; } void createObj(datetime time, double price, int arrawCode, color clr, string txt) { string objName=" "; StringConcatenate(objName, "Signal@",time, "at",DoubleToString(price,_Digits),"(",arrawCode,")"); if(ObjectCreate(0,objName,OBJ_ARROW,0,time,price)) { ObjectSetInteger(0,objName,OBJPROP_ARROWCODE,arrawCode); ObjectSetInteger(0,objName,OBJPROP_COLOR,clr); if(clr==clrGreen) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_TOP); if(clr==clrRed) ObjectSetInteger(0,objName,OBJPROP_ANCHOR,ANCHOR_BOTTOM); } string candleName=objName+txt; if(ObjectCreate(0,candleName,OBJ_TEXT,0,time,price)) { ObjectSetString(0,candleName,OBJPROP_TEXT," "+txt); ObjectSetInteger(0,candleName,OBJPROP_COLOR,clr); } }
Differences in this code are conditions of the pattern
In the case of the Three Inside Up
if(open3>close3) { if(open2<close2) { if(open2>low3&&close2<high3) { if(open<close&&open>open2&&open<close2) { if(close>high3) { createObj(time,low,217, clrGreen,"3 Inside Up"); { return 1; } } } } } }
In the case of the Three Inside Down
if(open3<close3) { if(open2>close2) { if(open2<high3&&close2>low3) { if(open>close&&open<open2&&open>close2) { if(close<low3) { createObj(time,high,218, clrRed,"3 Inside Down"); { return -1; } } } } } }
After compiling this code without error and executing its EA, we can get signals the same as the following examples:
- Three Inside Up:
As we can see on the chart we have the desired signal of the Three Inside Up.
- Three Inside Down:
As we can see on the chart we have the desired signal of the Three Inside Down.
Conclusion
After the previous topics in this article, it is supposed that you got the idea of how to write the code to detect the candlesticks patterns in their different formations, single candle, dual candles, and three candles patterns:
- Signal candle patterns: we learned how to detect Doji and Hammer patterns.
- Dual candle patterns: we learn how to detect Engulfing, Piecing Line, and Dark Cloud Cover patterns.
- Three candles patterns: we learned how to create a program that can detect Star patterns and Three Inside patterns.
I hope that you find this article useful to help you get better insights.





- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Very helpful
Thanks for your comment.
I was wondering regarding detecting Engulfing candlesticks, you have used the condition
if(close>open2&&open<close2)
for Bullish Engulfing and conditionif(close<open2&&open>close2)
for Bearish engulfing. There condition that is true only when there is a gap. I mean how often does the gap occur? I was expecting use code it like thisif(close>open2&&open<=close2)
for Bullish Engulfing and conditionif(close<open2&&open>=close2)
for Bearish Engulfing. Because under the normal conditions the Open price of Bar 1 and Close price of Bar 2 is exactly the same. You code will detect the Engulfing pattern only when there is a market price gap.So my question is, do you think the pattern became invalid when the close and open prices of Bar 2 and Bar 1 is not the same.
Good stuff. thanks a lot .
What is the condition for both bullish and bearish Marubozu
What is the condition for both bullish and bearish Marubozu
Something like this: