Find objects within a defined price range

 

Hello,

I have several horizontal lines and trendlines in a chart and I want to check if any of them is within a defined price range. Right now I check all objects in a loop if any of them is between my price levels.

Is there another/easier possibility to check this without controlling all objects in a loop?

 I only want to know if any of them is within my price range.

 
mar:

Hello,

I have several horizontal lines and trendlines in a chart and I want to check if any of them is within a defined price range. Right now I check all objects in a loop if any of them is between my price levels.

Is there another/easier possibility to check this without controlling all objects in a loop?

 I only want to know if any of them is within my price range.

No, I don't think.
 

Could you please have a look at my code? If you plot a horizontal line to your chart and move it slowly with your mouse from top to bottom you will see some rectangles. These rectangles highlight Pinbars according to a very simple definition. But of course you see that in the code.

My problem here is the following: It takes pretty much processor-time to do all that and I would like to optimize the code. Maybe you have an idea how I can modify it to run faster? Right now it's ok but if I use this indicator in many different chart windows and when I scan for more patterns it might slow the computer down.

Here is my code. I am thankful for any small improvement.

//+------------------------------------------------------------------+
//|                                                PinbarScanner.mq4 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MR"
#property link      "http://www.facebook.com/riemenschneider.marcus"
#property version   "1.00"
#property strict
#property indicator_chart_window

extern int  lineBuffer        = 5;

string ObjName;
double line;
int i, limit, end;
bool PBL, PBS, PriceAtZone = false;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   for (int j = ObjectsTotal(); j >= 0; j--) {
      string name = ObjectName(j);
      if (StringFind(name, "[PAS]", 0) == 0) ObjectDelete(name);
   }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---

   limit = WindowFirstVisibleBar();
   end = WindowBarsPerChart();
   end = (int)MathMin(limit, end);
   for(i=limit; i>=end; i--) {
   
      //--- Pinbars
      PBL   = MathMin(Open[i+1], Close[i+1]) - Low[i+1] >= 0.7*(High[i+1] - Low[i+1]);
      PBS   = High[i+1] - MathMax(Open[i+1], Close[i+1]) >= 0.7*(High[i+1] - Low[i+1]);
      
      if (PBL || PBS) {
         for (int j = ObjectsTotal(); j >= 0; j--) {
            string name = ObjectName(j);
            line = 0;
            if (ObjectType(name) == OBJ_HLINE || ObjectType(name) == OBJ_TREND) {
               if (ObjectType(name) == OBJ_HLINE) line = ObjectGet(name, OBJPROP_PRICE1);
               else line = ObjectGetValueByShift(name, 0);
               double ZoneHi = line + lineBuffer*10*Point;
               double ZoneLo = line - lineBuffer*10*Point;
               if ((MathMax(High[i+1], High[i+2]) > ZoneLo && MathMin(Low[i+1], Low[i+2]) < ZoneLo)
                  || (MathMax(High[i+1], High[i+2]) > ZoneHi && MathMin(Low[i+1], Low[i+2]) < ZoneHi)) {
                  PriceAtZone = true;
                  break;
               }
               else PriceAtZone = false;
            }  
         }
      }
      if (PBL && PriceAtZone) {
         ObjName = "[PAS] Pinbar Long" + (string)Time[i+1];
         ObjectCreate(0, ObjName, OBJ_RECTANGLE, 0, Time[i+2], High[i+1], Time[i], Low[i+1]);
         ObjectSet(ObjName, OBJPROP_COLOR, clrBlue);
         ObjectSet(ObjName, OBJPROP_BACK, false);
      }
      else ObjectDelete("[PAS] Pinbar Long" + (string)Time[i+1]);
      
      if (PBS && PriceAtZone) {
         ObjName = "[PAS] Pinbar Short" + (string)Time[i+1];
         ObjectCreate(0, ObjName, OBJ_RECTANGLE, 0, Time[i+2], High[i+1], Time[i], Low[i+1]);
         ObjectSet(ObjName, OBJPROP_COLOR, clrRed);
         ObjectSet(ObjName, OBJPROP_BACK, false);
      }
      else ObjectDelete("[PAS] Pinbar Short" + (string)Time[i+1]);
   }  
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
 
mar: It takes pretty much processor-time to do all that and I would like to optimize the code.
  1. If there are N bars on chart (assuming not shifted) they are [limit .. limit - N+1] but you try to do [limit .. N]
    limit = WindowFirstVisibleBar();
    end = WindowBarsPerChart();
    end = (int)MathMin(limit, end);
    for(i=limit; i>=end; i--) {
    Do your limits right
    int iLeft, iRight, double top, double bot; GetChartLimits(iLeft, iRight, top, bot);
    for(i=iLeft; i >= iRight; --i) {
    :
    void     GetChartLimits(int&iLeft, int&iRight, double&top, double&bot,int iW=0){
       top      = WindowPriceMax(iW);   iLeft    = WindowFirstVisibleBar();
       bot      = WindowPriceMin(iW);   iRight   = iLeft-WindowBarsPerChart();
       if(top-bot < pips2dbl)  top    = bot+pips2dbl;     // Avoid scroll bug / div0
       if(iRight < 0)          iRight = 0;                // Chart is shifted.
    }  // GetChartLimits
  2. Why are you doing the above every tick? Nothing is changing on those bars.
    • Just do it once.
      int counted = IndicatorCounted();
      int lookback = 2; // Max lookback "... High[i+2]) > ZoneLo..."
      for(i=Bars - 1 - MathMax(counted,lookback); i >= 1; --i) { // Don't do bar zero
    • Or when a new bar forms
      int OnCalculate(...)
      {
         static datetime Time0;
         if(Time0 == Time[0]) return;
         Time0 == Time[0];
         :
    • Or once per minute, giving the human time to move the lines
    • Or when a line actually moves EventChartCustom - MQL4 Documentation
  3.     PBL   = MathMin(Open[i+1], Close[i+1]) - Low[i+1] >= 0.7*(High[i+1] - Low[i+1]);
    Why is everything i+1 or i+2? Do everything relative to i. You want to test if bar i is a PB
  4. else line = ObjectGetValueByShift(name, 0);
    You are testing bar i. Why are you getting the trendline location of bar zero?
  5. if ((MathMax(High[i+1], High[i+2]) > ZoneLo && MathMin(Low[i+1], Low[i+2]) < ZoneLo)
       || (MathMax(High[i+1], High[i+2]) > ZoneHi && MathMin(Low[i+1], Low[i+2]) < ZoneHi)) {
    
    These calculations are not changing per object. Do them once, above the object loop.
    double H2 = MathMax(High[i+1], High[i+2]);
    double L2 = MathMin(Low[i+1], Low[i+2]);
    for (int j = ObjectsTotal(); j >= 0; j--) {
       :
       if ((H2 > ZoneLo && L2 < ZoneLo)
          || (H2 > ZoneHi && L2 < ZoneHi)) {
    
  6. That if tests for a candle intersecting ZoneLo or ZoneHi. What if the candle is inside the zone, (doesn't touch either?) You want to test if a candle intersects ZoneLo .. ZoneHi, simplify
    bool isOutside = L2 > ZoneHi || H2 < ZoneLo;
    if(!isOutside) { // intersects.

 

Wow, a lot of great stuff... thank you very much for that! Some comments:

Generally I programmed this indicator because I am not interested in Pinbars, Outsidebars etc. when they are located somewhere in the chart. They are only important for me when appearing at a certain daily/weekly level.  Earlier I just used a normal line-alert-indicator but I recognized that this alert is not important at all because then I still have to wait for a price action signal to place a trade. By the way, this is the reason I made the error with the trendline location at bar 0 instead of i. I copied this part from my line-alert-indicator.

I learned i+1 to use because the current bar 0 shouldn't be calclulated and I never questioned that. Now it's so simple by using i >= 1 instead of i >= 0 like I used to do all the time.

The code to be executed with every tick was just a test. Normally the code should be executed only once a new bar is printed. But I had to test if a signal appears (and disappears) when moving the line across the chart. This is the reason why I execute it every tick.

Before I fix my indicator now with the help of your code-fragments I want to ask you what exactly the & means in your GetChartLimits() function. What is the difference between int test and int&test ?

Thank you! 

 

A last question.

What exactly is the difference between:

int counted = IndicatorCounted();
int lookback = 2; // Max lookback "... High[i+2]) > ZoneLo..."
for(i=Bars - 1 - MathMax(counted,lookback); i >= 1; --i) { // Don't do bar zero

 and

int OnCalculate(...)
{
   static datetime Time0;
   if(Time0 == Time[0]) return;
   Time0 == Time[0];
   :

 As far as I know it does practically the same. The first part with IndicatorCounted() executes the code once for all bars and then it waits for a new bar to appear to do the next loop-calculation with just that single new bar. Is that generally correct? And the second option only executes the following code if a new bar is printed.

Can I also use them both together? My goal is the indicator to run once at the start and after that only when a new bar is printed. So I don't need it running at every tick

 
mar: what exactly the & means in your GetChartLimits() function. What is the difference between int test and int&test ?

References: Modifier & and Keyword this - MQL4 Documentation You are returning a value to the caller.
 
Thanks!