Help with MQL4 to MQL5 Conversion (Rectangle Extender)

 

I found this simple code that extends any box drawn to the right edge of the screen.

Can someone kind enough please help me convert it to mql5.


Much Appreciated.


//+------------------------------------------------------------------+
//|                                           Rectangle Extender.mq4 |
//|                                      Copyright @ 2022, samsha786 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright @ 2022, samsha786"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window

input color LineColour = White;

datetime bars = -1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
   ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
   
   //---
   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[])
{
   //---
   if (bars != Bars)
   {
      for (int r = 0; r < ObjectsTotal(); r++)
      {
         string name = ObjectName(r);
         if ((ObjectType(name) == OBJ_RECTANGLE && StringFind(name, "Rectangle ") >= 0)
          || (ObjectType(name) == OBJ_RECTANGLE && StringFind(name, "LineRectangle ") >= 0))
               ObjectSet(name, OBJPROP_TIME2, Time[0]);
      }
      bars = Bars;
   }
   
   //--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
//| Custom indicator on chart event function                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{ 
   //--- Check the event belongs to the user events
   if (id == CHARTEVENT_OBJECT_CREATE)
   {
      if (ObjectType(sparam) == OBJ_RECTANGLE && StringFind(sparam, "Rectangle ") >= 0)
      {
         ObjectSet(sparam, OBJPROP_TIME2, Time[0]);
         datetime t1 = (datetime)ObjectGet(sparam, OBJPROP_TIME1);
         datetime t2 = (datetime)ObjectGet(sparam, OBJPROP_TIME2);
         double p1 = ObjectGet(sparam, OBJPROP_PRICE1);
         double p2 = ObjectGet(sparam, OBJPROP_PRICE2);
         double line = (p1 + p2) / 2.0;
         
         string name = "Line" + sparam;
         ObjectCreate(name, OBJ_RECTANGLE, 0, t1, line, t2, line);
         ObjectSet(name, OBJPROP_STYLE, STYLE_SOLID);
         ObjectSet(name, OBJPROP_COLOR, LineColour);
         ObjectSet(name, OBJPROP_BACK, false);
      }
   }
   else if (id == CHARTEVENT_OBJECT_DELETE)
   {
      if (ObjectType(sparam) == OBJ_RECTANGLE && StringFind(sparam, "Rectangle ") >= 0)
         ObjectDelete(0, "Line" + sparam);
   }
}
//+------------------------------------------------------------------+
Files:
 
Muhammad Shamsuddeen Muhammad: Can someone kind enough please help me convert it

Help you with what? You haven't stated a problem, you stated a want. Show us your attempt (using the CODE button) and state the nature of your difficulty.
          No free help (2017)

Or pay someone. Top of every page is the link Freelance.
          Hiring to write script - General - MQL5 programming forum (2018)

We're not going to code it for you (although it could happen if you are lucky or the problem is interesting).
          No free help (2017)

 
William Roeder #:

Help you with what? You haven't stated a problem, you stated a want. Show us your attempt (using the CODE button) and state the nature of your difficulty.
          No free help (2017)

Or pay someone. Top of every page is the link Freelance.
          Hiring to write script - General - MQL5 programming forum (2018)

We're not going to code it for you (although it could happen if you are lucky or the problem is interesting).
          No free help (2017)

Ok I understand,


Attached below is the conversion attempt.

//+------------------------------------------------------------------+
//|                                           Rectangle Extender.mq4 |
//|                                      Copyright @ 2022, samsha786 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright @ 2022, samsha786"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_plots 0

input color LineColour = Black;

datetime bars = -1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   EventSetMillisecondTimer(100);
   ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
   ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
   
   //---
   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[])
{
   
   //--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
void OnTimer()
 {
      for (int r = 0; r < ObjectsTotal(0); r++)
      {
         string name = ObjectName(0,r,0);
         string name_line = name+"Line";
         if (ObjectGetInteger(0,name,OBJPROP_TYPE) == OBJ_RECTANGLE)
          {
         long t1 = ObjectGetInteger(0,name, OBJPROP_TIME);
         long t2 = ObjectGetInteger(0,name, OBJPROP_TIME,1);
         double p1 = ObjectGetDouble(0,name, OBJPROP_PRICE);
         double p2 = ObjectGetDouble(0,name, OBJPROP_PRICE,1);
         double line = (p1 + p2) / 2.0; 
         ObjectSetInteger(0,name, OBJPROP_COLOR, LineColour);
         ObjectSetInteger(0,name, OBJPROP_BACK, false);
         ObjectSetInteger(0,name, OBJPROP_TIME,1,iTime(_Symbol,_Period,0));
         if(ObjectFind(0,name_line)<0)
         ObjectCreate(0,name_line, OBJ_TREND, 0, 0, 0);
         ObjectSetInteger(0,name_line, OBJPROP_TIME, t1);
         ObjectSetInteger(0,name_line, OBJPROP_TIME,1, t2);
         ObjectSetDouble(0,name_line, OBJPROP_PRICE, line);
         ObjectSetDouble(0,name_line, OBJPROP_PRICE,1, line);
         ObjectSetInteger(0,name_line, OBJPROP_STYLE, STYLE_SOLID);
         ObjectSetInteger(0,name_line, OBJPROP_COLOR, LineColour);
         ObjectSetInteger(0,name_line, OBJPROP_BACK, false);
         ObjectSetInteger(0,name_line, OBJPROP_TIME,1,iTime(_Symbol,_Period,0));
          }    
      }
 }
//+------------------------------------------------------------------+
//| Custom indicator on chart event function                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{ 
   //--- Check the event belongs to the user events
   if (id == CHARTEVENT_OBJECT_CREATE)
   {
      if (ObjectGetInteger(0,sparam,OBJPROP_TYPE) == OBJ_RECTANGLE)
      {
         ObjectSetInteger(0,sparam, OBJPROP_TIME,1,iTime(_Symbol,_Period,0));
      }
   }
   else if (id == CHARTEVENT_OBJECT_CLICK)
   {
      if (ObjectGetInteger(0,sparam,OBJPROP_TYPE) == OBJ_RECTANGLE&&ObjectGetInteger(0,sparam,OBJPROP_SELECTED) == true)
       {
         ObjectDelete(0,sparam);
         ObjectDelete(0,sparam+"Line");
       }
   }
}
//+------------------------------------------------------------------+


The rectangle drawn right now is very buggy as it:

1) shifts a few candles forward from where it was initially drawn

2) when drawn, the rectangle is visible when selected, but disappears when unselected

3) doesn't remove itself completely when deleted. and

4) interferes with other boxes or indicators that display boxes. 

Files:
 
Muhammad Shamsuddeen Muhammad #: The rectangle drawn right now is very buggy as it:

1) shifts a few candles forward from where it was initially drawn

2) when drawn, the rectangle is visible when selected, but disappears when unselected

3) doesn't remove itself completely when deleted. and

4) interferes with other boxes or indicators that display boxes. 

  1. The code only modifies the second coordinate. You will get a different result drawing the rectangle left to right vs. right to left. Same as the original.
  2. The original created the line when the rectangle was created and delete it when the rectangle was deleted. Your code deletes both when you select any rectangle.
  3. The original created the line when the rectangle was created and delete it when the rectangle was deleted. Your code deletes both when you select any rectangle.
  4. The original created the line when the rectangle was created and delete it when the rectangle was deleted. Your code deletes both when you select any rectangle and modifies all rectangles.
  5. The original only extended them at the start of a new bar. Why are you doing it ten (10) times per second? Very CPU intensive for no reason.
 
William Roeder #:
  1. The code only modifies the second coordinate. You will get a different result drawing the rectangle left to right vs. right to left. Same as the original.
  2. The original created the line when the rectangle was created and delete it when the rectangle was deleted. Your code deletes both when you select any rectangle.
  3. The original created the line when the rectangle was created and delete it when the rectangle was deleted. Your code deletes both when you select any rectangle.
  4. The original created the line when the rectangle was created and delete it when the rectangle was deleted. Your code deletes both when you select any rectangle and modifies all rectangles.
  5. The original only extended them at the start of a new bar. Why are you doing it ten (10) times per second? Very CPU intensive for no reason.

Ok the code has now been modified.


1. The code still modifies second co-ordinate, can you help me fix this so that I can draw it normally.

2. The code still affects other boxes that already exist on the chart, is there a way to avoid this?

3. I believe the disapearing box when unselected has now been fixed.

4. Can you also assist me with extending the bow further into the future, as it is now, it only extends to the current candle. I would prefer it to go further by at least five more 'candle' spaces for instance.

5. I have also removed the code from OnTimer and transferred it to OnCalculate, I am not sure if this is a good way to prevent it from being CPU intensive.

Pls have a look over the code and give me any feedback, thanks,


//+------------------------------------------------------------------+
//|                                           Rectangle Extender.mq4 |
//|                                      Copyright @ 2022, samsha786 |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright @ 2022, samsha786"
#property link      ""
#property version   "2.00"
#property strict
#property indicator_chart_window
#property indicator_plots 0

enum ENUM_PLOT_TYPE
  {
   Rect=0,       // Plot Rectangle
   Rect_Line=1,   // Plot Rectangle + Mid Line
  };
  
input ENUM_PLOT_TYPE  Plot_What = Rect;
input bool  Rectangle_Fill = false;
input color Rectangle_Color = clrBlack;
input color Line_Color = White;


datetime bars = -1;
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   //EventSetMillisecondTimer(10000);
   ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,true);
   ChartSetInteger(0,CHART_EVENT_OBJECT_DELETE,true);
   
   //---
   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[])
{
   for (int r = 0; r < ObjectsTotal(0); r++)
      {
         string name = ObjectName(0,r,0);
         if (ObjectGetInteger(0,name,OBJPROP_TYPE) == OBJ_RECTANGLE)
          {
         double p1 = ObjectGetDouble(0,name, OBJPROP_PRICE);
         double p2 = ObjectGetDouble(0,name, OBJPROP_PRICE,1);
         ObjectSetInteger(0,name, OBJPROP_FILL, Rectangle_Fill);
         ObjectSetInteger(0,name, OBJPROP_COLOR, Rectangle_Color);
         ObjectSetInteger(0,name, OBJPROP_TIME,1,iTime(_Symbol,_Period,0));
         ObjectSetString(0,name,OBJPROP_TEXT,DoubleToString(MathAbs(p1-p2)/_Point,0));
          } 
         if(Plot_What==Rect_Line&&ObjectFind(0,name)==0)
          {
         long t1 = ObjectGetInteger(0,name, OBJPROP_TIME);
         long t2 = ObjectGetInteger(0,name, OBJPROP_TIME,1);
         double p1 = ObjectGetDouble(0,name, OBJPROP_PRICE);
         double p2 = ObjectGetDouble(0,name, OBJPROP_PRICE,1);
         double line = (p1 + p2) / 2.0; 
         ObjectSetInteger(0,name+"Line", OBJPROP_TIME, t1);
         ObjectSetInteger(0,name+"Line", OBJPROP_TIME,1, t2);
         ObjectSetDouble(0,name+"Line", OBJPROP_PRICE, line);
         ObjectSetDouble(0,name+"Line", OBJPROP_PRICE,1, line);
         ObjectSetInteger(0,name+"Line", OBJPROP_STYLE, STYLE_SOLID);
         ObjectSetInteger(0,name+"Line", OBJPROP_COLOR, Line_Color);
         ObjectSetInteger(0,name+"Line", OBJPROP_BACK, false);
         ObjectSetInteger(0,name+"Line", OBJPROP_TIME,1,iTime(_Symbol,_Period,0));
          }   
      }
   
   //--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| Custom indicator on chart event function                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{ 
   //--- Check the event belongs to the user events
  if (id == CHARTEVENT_OBJECT_CREATE)
   {
      if(ObjectGetInteger(0,sparam,OBJPROP_TYPE)==OBJ_RECTANGLE)
       {
         if(Plot_What==Rect_Line)
          {
         long t1 = ObjectGetInteger(0,sparam, OBJPROP_TIME);
         long t2 = ObjectGetInteger(0,sparam, OBJPROP_TIME,1);
         double p1 = ObjectGetDouble(0,sparam, OBJPROP_PRICE);
         double p2 = ObjectGetDouble(0,sparam, OBJPROP_PRICE,1);
         double line = (p1 + p2) / 2.0; 
          if(ObjectFind(0,sparam+"Line")<0)
           {
         ObjectCreate(0,sparam+"Line", OBJ_TREND, 0, 0, 0);
           }
         ObjectSetInteger(0,sparam+"Line", OBJPROP_TIME, t1);
         ObjectSetInteger(0,sparam+"Line", OBJPROP_TIME,1, t2);
         ObjectSetDouble(0,sparam+"Line", OBJPROP_PRICE, line);
         ObjectSetDouble(0,sparam+"Line", OBJPROP_PRICE,1, line);
         ObjectSetInteger(0,sparam+"Line", OBJPROP_STYLE, STYLE_SOLID);
         ObjectSetInteger(0,sparam+"Line", OBJPROP_COLOR, Line_Color);
         ObjectSetInteger(0,sparam+"Line", OBJPROP_BACK, false);
         ObjectSetInteger(0,sparam+"Line", OBJPROP_TIME,1,iTime(_Symbol,_Period,0));
          }
       }
     }
      else 
  if (id == CHARTEVENT_OBJECT_DELETE)
   {
      if (StringSubstr(ObjectGetString(0,sparam,OBJPROP_NAME),StringLen(sparam)-4)=="Line")
       {
         ObjectDelete(0,sparam);
         string name_line = StringSubstr(sparam,0,StringLen(sparam)-4);
         ObjectDelete(0,name_line);
       }
   }
}
//+------------------------------------------------------------------+
 
  1. Muhammad Shamsuddeen Muhammad #: 1. The code still modifies second co-ordinate, can you help me fix this so that I can draw it normally.

    Help you with what? You haven't stated a problem, you stated a want. Show us your attempt (using the CODE button) and state the nature of your difficulty.
              No free help (2017)

    Find out which co-ordinate is the later one and modify that one.

  2. Muhammad Shamsuddeen Muhammad #: 2. The code still affects other boxes that already exist on the chart, is there a way to avoid this?

    Code it that way. Compare the original code that only modified objects named "Rectangle" with yours that modifies all rectangles.

  3. Muhammad Shamsuddeen Muhammad #: 3. I believe the disapearing box when unselected has now been fixed.

    Ok.

  4. Muhammad Shamsuddeen Muhammad #: 4. Can you also assist me with extending the bow further into the future, as it is now, it only extends to the current candle. I would prefer it to go further by at least five more 'candle' spaces for instance.

    "The bow?" You mean rectangles and lines. Set the time to the future. Time₀+5*PeriodSecond().

  5. Muhammad Shamsuddeen Muhammad #: 5. I have also removed the code from OnTimer and transferred it to OnCalculate, I am not sure if this is a good way to prevent it from being CPU 

    Instead of 10 times per second, you do it once per tick; slightly better. What part of "the original only extended them at the start of a new bar," was unclear?

    For a new bar test, Bars is unreliable (a refresh/reconnect can change number of bars on chart), volume is unreliable (miss ticks), Price is unreliable (duplicate prices and The == operand. - MQL4 programming forum.) Always use time.
              MT4: New candle - MQL4 programming forum #3 (2014)
              MT5: Accessing variables - MQL4 programming forum #3 (2022)

    I disagree with making a new bar function, because it can only be called once per tick (second call returns false). A variable can be tested multiple times.
              Running EA once at the start of each bar - MQL4 programming forum (2011)


  6. Muhammad Shamsuddeen Muhammad #: Pls have a look over the code and give me any feedback, thanks,
             string name = ObjectName(0,r,0);
             ⋮
             if(Plot_What==Rect_Line&&ObjectFind(0,name)==0)

    Name obviously exists; you got it from the loop. The ObjectFind is always true.

  7.   if (id == CHARTEVENT_OBJECT_CREATE)
       {
          if(ObjectGetInteger(0,sparam,OBJPROP_TYPE)==OBJ_RECTANGLE)
    1. You found some rectangle has been created. Don't you only want to process "rectangle"'s?

    2. You create the corresponding line. Don't you also want to exend the rectangle?

  8.       if (StringSubstr(ObjectGetString(0,sparam,OBJPROP_NAME),StringLen(sparam)-4)=="Line")
    
    The object sparam has been deleted.
    1. Getting the name of a deleted object fails; it no longer exists. You already have the name.
    2. Then you see if the deleted object ends in "Line". Why are you trying to delete it again?
    3. Then you get the name without "Line". If it is the rectangle, why are you storeing it in a variable called name_line?
    4. What do you do, when the rectangle is deleted (the line)? What do you do, when some other object is deleted?
 
William Roeder #:
  1. Help you with what? You haven't stated a problem, you stated a want. Show us your attempt (using the CODE button) and state the nature of your difficulty.
              No free help (2017)

    Find out which co-ordinate is the later one and modify that one.


//+------------------------------------------------------------------+
//|                                     Billy Rectangle Extender.mq4 |
//|                                    Copyright @ 2022, Billyenaire |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright @ 2022, Billyenaire"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_plots 0

int TFMigrate(int tf)
  {
   switch(tf)
     {
      case 0: return(0);
      case 1: return(1);
      case 5: return(5);
      case 15: return(15);
      case 30: return(30);
      case 60: return(60);
      case 240: return(240);
      case 1440: return(1440);
      case 10080: return(10080);
      case 43200: return(43200);
      
      case 2: return(2);
      case 3: return(3);
      case 4: return(4);      
      case 6: return(6);
      case 10: return(10);
      case 12: return(12);
      case 16385: return(60);
      case 16386: return(120);
      case 16387: return(180);
      case 16388: return(240);
      case 16390: return(360);
      case 16392: return(480);
      case 16396: return(720);
      case 16408: return(1440);
      case 32769: return(10080);
      case 49153: return(43200);      
      default: return(PERIOD_CURRENT);
     }
  }

input bool  Rectangle_Fill = false;
input color Rectangle_Color = clrBlack;
input int   Right_Offset = 13;

datetime bars = -1;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
   //--- indicator buffers mapping
   ChartSetInteger(0,CHART_EVENT_OBJECT_CREATE,true);
   
   //---
   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[])
{
   for (int r = 0; r < ObjectsTotal(0); r++)
      {
         string name = ObjectName(0,r,0);
         if (StringFind(name,"Rectangle")>0&&ObjectGetInteger(0,name,OBJPROP_TYPE) == OBJ_RECTANGLE)
          {
         ObjectSetInteger(0,name, OBJPROP_TIME,1,iTime(_Symbol,_Period,0)+Right_Offset*TFMigrate(_Period)*60);
          }   
      }
   
   //--- return value of prev_calculated for next call
   return(rates_total);
}
//+------------------------------------------------------------------+
//| Custom indicator on chart event function                         |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
{ 
   //--- Check the event belongs to the user events
  if (id == CHARTEVENT_OBJECT_CREATE)
   {
      if(StringFind(sparam,"Rectangle")>0&&ObjectGetInteger(0,sparam,OBJPROP_TYPE)==OBJ_RECTANGLE)
       {
         ObjectSetInteger(0,sparam, OBJPROP_FILL, Rectangle_Fill);
         ObjectSetInteger(0,sparam, OBJPROP_COLOR, Rectangle_Color);
         ObjectSetInteger(0,sparam, OBJPROP_TIME,1,iTime(_Symbol,_Period,0)+Right_Offset*TFMigrate(_Period)*60);
       }
     }
}
//+------------------------------------------------------------------+


 


I have pretty much now made progress on most of the issues I had, but alas it still remains the co-ordinates?


I have gone thru MQL5 documentation regarding ObjectSetInterger() functions and its variables. But I cant figure out how to modify the second co-ordinate so that when I draw the rectangle from left to right, the right side will auto extend into the future, and not the left side, like it does now.


See my code attempt above. 

Reason: