Download MetaTrader 5

Find objects within a defined price range

To add comments, please log in or register
Do you have questions on how to turn your idea into reality? Ask them on the Forum!
mar
1146
mar 2015.01.14 10:34 

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.

Alain Verleyen
Moderator
30727
Alain Verleyen 2015.01.14 11:51  
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.
mar
1146
mar 2015.01.15 09:04  

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);
  }
//+------------------------------------------------------------------+
whroeder1
14486
whroeder1 2015.01.15 13:08  
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.

mar
1146
mar 2015.01.15 17:19  

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! 

mar
1146
mar 2015.01.15 17:59  

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

whroeder1
14486
whroeder1 2015.01.15 17:59  
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.
mar
1146
mar 2015.01.15 18:12  
Thanks!
To add comments, please log in or register