Техническое задание
General description
I need an MQL4 function
bool poi_detect(int timeframe, int limit)
which should fill up multiple global arrays created for different parameters for a list of POIs (point of interest) for the specified timeframe and limit in price points. For every parameter there is one array for long direction and another one for short. In this specification, by default we consider finding POIs for opening long (buy) positions if we don’t notice other explicitly. For short positions the function must do everything in the same way but for the opposite direction.
The list of POIs which should be detected by the function:
1. Imbalance (IM).
2. Inversion imbalance (II).
3. Order block (OB).
4. Breaker block (BB).
Definition for each of them is provided in the following sections.
The function will be run at the very beginning of every new candle of the corresponding timeframe. So, the previous completely closed candle is taken as a start point to detect all the POIs. The current incomplete bar is taken as a zero point to determine shifts from it.
Once started, the function should go down from the start point to find all the valid long POIs, and then go up from the start point to find all the valid short POIs, and save them in the corresponding arrays. The whole detailed process will be shown the corresponding section at the end.
Imbalance (IM)
3 close candles are taken to determine an imbalance (IM). It doesn’t matter if they are inside bars.
The requirement is only one – the Low of the candle 1 must be higher than the High of candle 3. The difference between them is the width of the formed IM. Candle 1 is considered as the candle where the IM is formed.
The following parameters should be saved by the function in the corresponding arrays:
· im_long_price_low[] / im_short_price_low[] - IM price low – the High of candle 3.
· im_long_price_high[] / im_short_price_high[] - IM price high – the Low of candle 1.
· im_long_shift[] / im_short_shift[] - Shift from the current bar (shift=0) to bar 1 (bar where the IM is formed).
The arrays index is an ID of the found IM. The order of long IMs should be based on “IM price high” – the higher price the lower ID. The order of short IMs should be based on “IM price low” – the lower price the lower ID.
Inversion imbalance (II)
If there is an IM detected, we should also check if there is an IM on the opposite side within the range of the current IM. If it is so, then there is an inversion imbalance (II) formed where two imbalances intersect. It doesn’t matter if the current IM is intersected completely or partially, as it is shown in the pictures below.
The following parameters should be saved by the function in the corresponding arrays:
· ii_long_price_low[] / ii_short_price_low[] - II price low – the low level of the intersecting IMs area.
· ii_long_price_high[] / ii_short_price_high[] - II price high – the high level of the intersecting IMs area.
· ii_long_shift[] / ii_short_shift[] - Shift from the current bar (shift=0) to bar 1 (bar where the II is formed)
· ii_long_dist1[] / ii_short_dist1[] - Dist1 – a distance from bar 1 till bar 2 where the IM on the opposite side is formed within the range of the current IM
The arrays index is an ID of the found II. The order of long IIs should be based on “II price high” – the higher price the lower ID. The order of short IIs should be based on “II price low” – the lower price the lower ID.
Order block (OB)
For determining OBs we will take into account 3 breakout types:
1. Breakout type 1.
3 candles are taken here. If the Low of candle 2 is lower than the Low of candle 1 and 3, then it is the long breakout of type 1. It doesn’t matter what direction each candle has.
2. Breakout type 2.
If the Low of last candle 2 is lower than the Low of previous candle 1, and the Close of candle 2 is higher than the High of candle 1, then the long breakout of type 2 is detected.
3. Breakout type 3.
If we take 3 close candles, breakout type 1 or 2 is not formed here. But in this case the direction of 2 first candles and the last one is important. Candle 1 must be long (Open price is lower than Close) while candle 2 – short (Open price is higher than Close). What is the next bar is not important here, it can be short inside bar as it is shown in the picture. But finally the breakout is formed when the price closes higher the High of the short candle 2.
The important moment that we always should take the Close price of the previous candle as the Open price for the current one in order to handle gaps properly. It is actual for all POIs.
If there is a breakout (type 1, 2, 3), there can be formed OB of a certain type from the lowest candle or from the whole movement of multiple bars if the price closes higher than the whole movement. It is shown in the following sections. If the price goes lower than the breakout, then this breakout gets invalid and another long breakout may be formed or not.
1. OB type 1.
2. OB type 2.
3. OB type 3.
4. OB type 4.
5. OB type 5.
6. OB type 6.
The following parameters should be saved by the function in the corresponding arrays:
· ob_long_type[] / ob_short_type[] - OB type (1-6)
· ob_long_price_low[] / ob_short_price_low[] - OB price low – the Low of candle 2.
· ob_long_price_high[] / ob_short_price_high[] - OB price high – the High of candle 3.
· ob_long_shift[] / ob_short_shift[] - Shift from the current bar (shift=0) to bar 1 (bar where the OB is formed)
· ob_long_dist1[] / ob_short_dist1[] - Dist1 - a distance from bar 1 till bar 2 - a lowest bar in the setup where the “OB price low” (“OB price high” for ob_short[]) is taken
· ob_long_dist2[] / ob_short_dist2[] - Dist2 - a distance from bar 1 till bar 3 - a bar where the “OB price high” (“OB price low” for ob_short[]) is taken
The arrays index is an ID of the found OB. The order of long OBs should be based on “OB price high” – the higher price the lower ID. The order of short OBs should be based on “OB price low” – the lower price the lower ID.
7. Combinations of multiple OB types.
The function should find every OB (and every other POI) independently. This way, multiple OBs may be detected on the latest candle. Here are some examples of such combinations for better understanding but actually it doesn’t affect anyhow the logic of detecting every single OB there.
Breaker block (BB)
If a valid OB is crossed by the price without forming a breakout of any type, i.e. all the crossing bars are long (a long BB is formed in this case from a short OB) and the High of each candle inside the OB is higher than the High of the previous candle, and the price finally closes higher than high level of the OB, then a BB is formed at this bar.
Here are some other examples of valid BBs:
If a breakout is formed while the price crosses the OB, we should check what part of OB is left after the High of the breakout. If the remaining part is more than 50% of the initial OB width, then this part should be taken to form a valid BB. Otherwise this OB should be ignored for forming a BB.
If an OB was already tested before the final crossing by price, it doesn’t matter. The main requirement that the remaining part must be more than 50%.
The following parameters should be saved by the function in the corresponding arrays:
· bb_long_price_low[] / bb_short_price_low[] - BB price low - “OB price low” of the short OB on the base of which the BB is formed if the whole OB is used to from the BB, or the low level of the remaining part of the short OB if it was tested or there is a breakout, as it was shown in the pictures.
· bb_long_price_high[] / bb_short_price_high[] - BB price high - “OB price high” of the short OB on the base of which the BB is formed.
· bb_long_shift[] / bb_short_shift[] - Shift from the current bar (shift=0) to bar 1 (bar where the BB is formed)
· bb_long_dist1[] / bb_short_dist1[] - Dist1 – a distance from bar 1 till bar 2 - a bar where the price enters the valid OB
· bb_long_dist2[] / bb_short_dist2[] - Dist2 – a distance from bar 1 till bar 3 - a bar where the OB is formed
At the same time, the function must copy the parameters from the OB which forms the BB to the following arrays:
· bb_ob_long_type[] / bb_ob_short_type[] - OB type (1-6)
· bb_ob_long_price_low[] / bb_ob_short_price_low[] - OB price low
· bb_ob_long_price_high[] / bb_ob_short_price_high[] - OB price high
· bb_ob_long_shift[] / bb_ob_short_shift[] - Shift from the current bar (shift=0) to bar 1 (bar where the OB is formed)
· bb_ob_long_dist1[] / bb_ob_short_dist1[] - Dist1 - a distance from bar 1 till bar 2 - a lowest bar in the setup where the “OB price low” (“OB price high” for ob_short[]) is taken
· bb_ob_long_dist2[] / bb_ob_short_dist2[] - Dist2 - a distance from bar 1 till bar 3 - a bar where the “OB price high” (“OB price low” for ob_short[]) is taken
The arrays index is an ID of the found BB. The order of long BBs should be based on “BB price high” – the higher price the lower ID. The order of short BBs should be based on “BB price low” – the lower price the lower ID.
Tested POI
If the price enters into the POI (IM, II, OB or BB) and then exits from it, then POI becomes tested, and some additional parameters should be saved for this POI in the corresponding arrays.
Here we review testing of OB but it works the same way for the other POIs (IM, II, BB). And in this case we take for example a short OB, not a long one as it was before in this document. For a long OB it is similar.
In the previous example the OB is tested only once. But it is possible that a POI is tested multiple times until it is completely overlapped by the price. In this case parameters for every test should be written to the corresponding parameters of the POI. Here is the example with 3 tests of a short OB:
As there could be multiple tests of the same POI, the function should save the parameters for every test in 2-dimensional arrays where the first dimension is the ID of the POI, and the second dimension is the ID of the test of this POI.
Once the candle which enters the POI is closed, the function should save only Dist3 - a distance from bar 1 till bar 4 – a bar where the price enters into the IM. The other parameters are still kept empty until the price exits from the POI. It allows to determine that the price is inside the POI for now.
Every test is considered completed and all the parameters are filled up only when the price exits from the POI as it shown on the pictures.
1. Additional arrays for tested imbalances (IM):
· im_long_price_test[][] / im_short_price_test[][] - IM price tested – the highest price during the IM testing which is taken to form the remaining part of the tested IM
· im_long_dist3[][] / im_short_dist3[][] – Dist3 - a distance from bar 1 till bar 4 – a bar where the price enters into the IM, i.e. the IM gets tested
· im_long_dist4[][] / im_short_dist4[][] – Dist4 - a distance from bar 1 till bar 5 – a bar where the price exits from the IM, i.e. OCLH of minimum one candle gets outside of the IM
2. Additional arrays for tested inversion imbalances (II):
· ii_long_price_test[][] / ii_short_price_test[][] - II price tested – the highest price during the II testing which is taken to form the remaining part of the tested II
· ii_long_dist3[][] / ii_short_dist3[][] – Dist3 - a distance from bar 1 till bar 4 – a bar where the price enters into the II, i.e. the II gets tested
· ii_long_dist4[][] / ii_short_dist4[][] – Dist4 - a distance from bar 1 till bar 5 – a bar where the price exits from the II, i.e. OCLH of minimum one candle gets outside of the II
3. Additional arrays for tested order blocks (OB):
· ob_long_price_test[][] / ob_short_price_test[][] - OB price tested – the highest price during the OB testing which is taken to form the remaining part of the tested OB
· ob_long_dist3[][] / ob_short_dist3[][] – Dist3 - a distance from bar 1 till bar 4 – a bar where the price enters into the OB, i.e. the OB gets tested
· ob_long_dist4[][] / ob_short_dist4[][] – Dist4 - a distance from bar 1 till bar 5 – a bar where the price exits from the OB, i.e. OCLH of minimum one candle gets outside of the OB
4. Additional arrays for tested breaker blocks (BB):
· bb_long_price_test[][] / bb_short_price_test[][] - BB price tested – the highest price during the BB testing which is taken to form the remaining part of the tested BB
· bb_long_dist3[][] / bb_short_dist3[][] – Dist3 - a distance from bar 1 till bar 4 – a bar where the price enters into the BB, i.e. the BB gets tested
· bb_long_dist4[][] / bb_short_dist4[][] – Dist4 - a distance from bar 1 till bar 5 – a bar where the price exits from the BB, i.e. OCLH of minimum one candle gets outside of the BB
Parameters that are copied from the test OB which forms the BB:
· bb_ob_long_price_test[][] / bb_ob_short_price_test[][] - OB price tested – the highest price during the OB testing which is taken to form the remaining part of the tested OB
· bb_ob_long_dist3[][] / bb_ob_short_dist3[][] – Dist3 - a distance from bar 1 till bar 4 – a bar where the price enters into the OB, i.e. the OB gets tested
· bb_ob_long_dist4[][] / bb_ob_short_dist4[][] – Dist4 - a distance from bar 1 till bar 5 – a bar where the price exits from the OB, i.e. OCLH of minimum one candle gets outside of the OB
Process of detecting POIs
The function will be run at the very beginning of every new candle of the corresponding timeframe. So, the previous completely closed candle is taken as a start point to detect all the POIs. The current incomplete bar is taken as a zero point to determine shifts from it.
The function goes up and down until the specified price limit in points. If the limit is reached, the process of POI detecting is stopped. So, there are 2 variables for the function: timeframe and limit in points.
1. IM and II detecting.
The function goes down from the start point to find every long IM one by one. Once an IM is detected, the function finds its “IM price high” (“IM price low” of short IM) and goes back to the start point on the timeline to find all the tests of the IM if they happen. Then the function goes down further to find the following IMs.
There is a similar process for detecting short IMs when the function goes up from the start point.
The process of detecting IIs is also shown on this picture. The difference is that if there is an IM detected, the function looks at the opposite side to find out whether there is another IM to form the II. If it is so, the II is detected and its parameters are saved in the corresponding II arrays. The test for IIs are found the same way as for IMs.
2. OB detecting.
The function goes down from the start point to find every long breakout one by one (type 1,2,3). Once a breakout is detected, the function determines all the long OBs which are based on this breakout. Taking “OB price high” (“OB price low” of short OB) of each OB, the function goes back to the start point on the timeline to find all the tests of the OB if they happen. Then the function goes down further to find the following breakouts and OBs. There is a similar process for detecting short OBs when the function goes up from the start point.
In the picture below 12 long and 4 short OBs are detected. So, there will be arrays ob_long…[11] and ob_short…[4].

3. BB detecting.
The function goes down from the start point to find every long breakout one by one (type 1,2,3). Once a breakout is detected, the function goes up till the Close price of the candle 0 to find all short breakouts on the opposite side within the range. Found short breakouts are used then to determine short OBs the same way as it is described in “OB detecting”. Finally, the found short OBs are used to determine corresponding long BBs.
Taking “BB price high” (“BB price low” of short BB) of each BB, the function goes back to the start point on the timeline to find all the tests of the BB if they happen. Then the function goes down further to find a following long breakout. Once a new long breakout is detected, the function goes up finding all short breakouts on the opposite side until the first short breakout found higher than the Low of the previous long breakout. If this first short breakout higher than the Low of the previous long breakout was already used to determine OBs on the previous step, then it is skipped.
Then everything is repeated while the price limit is not reached.
There is a similar process for detecting short BBs when the function goes up from the start point.
In the picture below 4 long BBs are detected. So, there will be arrays ob_long…[3].
