Discussing the article: "Developing Advanced ICT Trading Systems: Implementing Order Blocks in an Indicator"

 

Check out the new article: Developing Advanced ICT Trading Systems: Implementing Order Blocks in an Indicator.

In this article, we will learn how to create an indicator that detects, draws, and alerts on the mitigation of order blocks. We will also take a detailed look at how to identify these blocks on the chart, set accurate alerts, and visualize their position using rectangles to better understand the price action. This indicator will serve as a key tool for traders who follow the Smart Money Concepts and the Inner Circle Trader methodology.

Order Blocks are zones on the chart where pending orders are likely waiting to be filled.

This typically occurs when a large market participant, such as a financial institution, wants to enter a significant position but lacks sufficient liquidity to execute the entire order at once without impacting the market. According to the basic laws of supply and demand, executing a portion of the order drives the price higher (in the case of a buy) in an aggressive search for sellers who can provide the liquidity needed to complete the trade.

Because the institutional participant cannot execute the full order in one go without causing a substantial price shift, they break the order into smaller parts. This allows them to complete the trade without the price moving significantly before they've fully entered their position.

From this concept, we can identify these zones on a price chart as areas of strong imbalance between supply and demand (whether for buying or selling). Below, we'll explore three ways to identify these zones and how to implement them in code.


Author: Niquel Mendoza

 

Good day Mendoza

Thank you for this effort.

my question is ; since we are using OnCalculate function

int OnCalculate(const int rates_total,

                const int prev_calculated,

                const datetime &time[],// TimeSeries of Open times

                const double &open[], // TimeSeries of Open Prices

                const double &high[],// TimeSeries of High Prices

                const double &low[],// TimeSeries of Low Prices

                const double &close[],// TimeSeries of Close Prices

                const long &tick_volume[],// TimeSeries of tick volume

                const long &volume[],// TimeSeries of Bar Prices

                const int &spread[])// 


Why should we create new arrays and rearrange them ?

 
Ahmed Fouad Abdellatief #:

Good day Mendoza

Thank you for this effort.

my question is ; since we are using OnCalculate function

int OnCalculate(const int rates_total,

                const int prev_calculated,

                const datetime &time[],// TimeSeries of Open times

                const double &open[], // TimeSeries of Open Prices

                const double &high[],// TimeSeries of High Prices

                const double &low[],// TimeSeries of Low Prices

                const double &close[],// TimeSeries of Close Prices

                const long &tick_volume[],// TimeSeries of tick volume

                const long &volume[],// TimeSeries of Bar Prices

                const int &spread[])// 


Why should we create new arrays and rearrange them ?

Hello Ahmed, thank you very much for your comment. You're right. There's no need to create new arrays, because the OnCalculate function already gives us all the data ready to use. I did it out of habit at the time, but it's best to work directly with the data that's already there. By the way, if you want the most up-to-date code, I'll leave it here for you. In this new code, the arrays that already come by default are used, the logic for detecting the order blocks is the same.
 
Niquel Mendoza #:
datetime  mitigados_alcsitas(double price, const double &lowArray[], const  datetime &Time[], datetime start, datetime end)
 {
  int startIndex = iBarShift(_Symbol, PERIOD_CURRENT, start);
  int endIndex = iBarShift(_Symbol, PERIOD_CURRENT, end);

  NormalizeDouble(price, _Digits);
  for(int i = startIndex - 2 ; i >= endIndex + 1 ; i--)
   {
    if(price > lowArray[i])
     {
      return Time[i]; //si encuentra que si hubo retorna el tiempo de la vela donde hubo la mitigacion
      Print("el orderblock tuvo mitigaciones", TimeToString(end));
     }
   }

  return 0; //En caso no se haya encontrado niguna mitigacion retorna 0
 }

And so on in four neighbouring functions.

 
trader6_1 #:

And so on in four neighbouring functions.

Hi, you're absolutely right. I was wrong about thinking NormalizeDouble worked by reference. It actually returns a rounded value, and for a variable to take that value, you have to explicitly assign it to it. Sorry about that; I think I learned it that way when I wrote that code and that's how it stuck. I'm really sorry. I'm using NormalizeDouble here more as a precaution, although I don't think it has a significant impact on checking whether a bullish order block was mitigated (based on my testing). Thanks for pointing that out. We could choose to assign "price = NormalizeDouble(price, _Digits)" directly, or delete that line, since normalization doesn't seem to significantly affect the review.

 
Thank you so much, thank you for sharing. Go ahead with the next part.