Freezing charts - Error 4203

 

Hi,

its frequently that we have to deal with frozen charts. Any function like ObjectGetInteger(), even ObjectName() or similar, then needs seconds to return and the error code is always 4203. 

The error code makes no sense at all, since ObjectGetInteger() uses OBJ_TYPE with an existing object, and ObjectName() just tries to obtain the name of an existing object within an enumeration, like:


           //--- Add new objects   
            int cnt=ObjectsTotal(m_chart_id,0);
            ResetLastError();
            for (int i=0;i<cnt;i++)
               {
               string name=ObjectName(m_chart_id,i,0);
               int e=GetLastError();
               if (e!=0)
                  {
                  Print("Error during collecting objects E:"+(string)e);
                  return false;
                  }
               }

We tried several examples to provoke this with a simple code, but its not that easy reproducable as it seems. Nonetheless: This error cannot be return with existing objects and none of such functions should never need up to 30 seconds to return. And of course, already one such occurence freezes the whole chart immediately, whereby also no candles move anymore. 

Does anyone have an idea? This happens since build 3802.

 
Doerk Hilger:
ObjectName

Error 4203 = ERR_OBJECT_WRONG_PROPERTY (Wrong ID of a graphical object property)

You are missing one object property, object type.

Likewise with ObjectsTotal, missing one object property, object type.

string name=ObjectName(m_chart_id,i,0); ???
string name=ObjectName(m_chart_id,i,0,???);

https://www.mql5.com/en/docs/objects/objectname

https://www.mql5.com/en/docs/objects/objectstotal

Documentation on MQL5: Object Functions / ObjectName
Documentation on MQL5: Object Functions / ObjectName
  • www.mql5.com
ObjectName - Object Functions - MQL5 Reference - Reference on algorithmic/automated trading language for MetaTrader 5
 
Roberto Jacobs #:

Error 4203 = ERR_OBJECT_WRONG_PROPERTY (Wrong ID of a graphical object property)

You are missing one object property, object type.

Likewise with ObjectsTotal, missing one object property, object type.

https://www.mql5.com/en/docs/objects/objectname

https://www.mql5.com/en/docs/objects/objectstotal

I dont miss anything. It is a general problem with ALL functions which access the chart. ALL, means any function like ObjectGetInteger, ObjectGetString etc. as well as ChartGetInteger, ChartGetDouble .... ALL such functions do not return properly.

 
Roberto Jacobs #: You are missing one object property, object type.
No, the [object type] parameter is optional and it defaults to -1, meaning "all types".
 

Anyway, this is cleary a bug of MetaTrader, not a simple mistake in the code. If not, then the code would not work at all. But it works, until those functions dont return anymore, which happens just like that after some hours. 

There is no reasonable reason why a function like such could need seconds or even minutes to return. If a parameter would be wrong, the function should report this within microseconds. 

100% an MT5 Bug!

And since MetaQuotes almost never fixes any bugs and does not care at all about nothing, the question is just, where it comes from and how to avoid it. 
 
Doerk Hilger #: Anyway, this is cleary a bug of MetaTrader, not a simple mistake in the code. If not, then the code would not work at all. But it works, until those functions dont return anymore, which happens just like that after some hours. 

I don't know if it is plausible to do this for your project, but have you ever considered using a "canvas" as a work-around, with your own "virtual graphic objects"?

It may not resolve the issue completely, but it may simplify and reduce the "graphical object" load.

 
Doerk Hilger #:

Anyway, this is cleary a bug of MetaTrader, not a simple mistake in the code. If not, then the code would not work at all. But it works, until those functions dont return anymore, which happens just like that after some hours. 

There is no reasonable reason why a function like such could need seconds or even minutes to return. If a parameter would be wrong, the function should report this within microseconds. 

100% an MT5 Bug!

And since MetaQuotes almost never fixes any bugs and does not care at all about nothing, the question is just, where it comes from and how to avoid it. 

Is it related to the number of objects on a chart ?

Are there several thread accessing the objects at the same time (concurrency issue ?) ? Is it happening while accessing the objects of the same chart as the running code ?

" happens just like that after some hours ", what is done with objects during these "some hours" ? You need to find a way to reproduce it, then you can hope to understand the issue and work around it.

 
Doerk Hilger:

Hi,

its frequently that we have to deal with frozen charts. Any function like ObjectGetInteger(), even ObjectName() or similar, then needs seconds to return and the error code is always 4203. 

The error code makes no sense at all, since ObjectGetInteger() uses OBJ_TYPE with an existing object, and ObjectName() just tries to obtain the name of an existing object within an enumeration, like:


We tried several examples to provoke this with a simple code, but its not that easy reproducable as it seems. Nonetheless: This error cannot be return with existing objects and none of such functions should never need up to 30 seconds to return. And of course, already one such occurence freezes the whole chart immediately, whereby also no candles move anymore. 

Does anyone have an idea? This happens since build 3802.

which operations are you performing in your code ?

Maybe a bruteforce test is possible where the code will attempt all possible combinations of adjusting something and then looking for an object .

Also from a "DOM" perspective what Fernando suggested is worth looking into . If something is editing the object it must "render" the object inaccessible for a bit.
 

i tried this concurrent editing test , all i got was 4022 and 5035 on recompilation (build 4040)

#property version   "1.00"
enum _purpose{
creator=0,//create
edit=1//editor
};
input _purpose purpose=creator;//purpose : 
input int objects=1000;//total objects
input double W=100.0;//wiggle points

double _point=0.0;
int _digits=0;
long creator_id=-1;
int OnInit()
  {
  creator_id=-1;
  ObjectsDeleteAll(ChartID(),"TEST_");
  EventSetMillisecondTimer(44);
  return(INIT_SUCCEEDED);
  }

void OnTimer(){

  if(purpose==creator){
    if(creator_id==-1){
    creator_id=ChartID();
    int f=FileOpen("test.txt",FILE_WRITE|FILE_BIN);
    if(f!=INVALID_HANDLE){
    FileWriteLong(f,ChartID());
    FileWriteDouble(f,_Point);
    FileWriteInteger(f,_Digits,INT_VALUE);
    FileClose(f);
    }
    for(int i=0;i<objects;i++){
    ObjectCreate(ChartID(),"TEST_"+IntegerToString(i),OBJ_TREND,0,iTime(_Symbol,_Period,i-20),iHigh(_Symbol,_Period,i-20),iTime(_Symbol,_Period,i),iLow(_Symbol,_Period,i));
    }
    }else{
    ChartRedraw(ChartID());
    }
  }else{
  if(creator_id==-1){
    int f=FileOpen("test.txt",FILE_READ|FILE_BIN);
    if(f!=INVALID_HANDLE){
    creator_id=(long)FileReadLong(f);
    _point=(double)FileReadDouble(f);
    _digits=(int)FileReadInteger(f,INT_VALUE);
    FileClose(f);
    }
    }else{
    int total=ObjectsTotal(creator_id,0);
    ResetLastError();
    for(int i=0;i<total;i++){
       string name=ObjectName(creator_id,i,0);
       int e=GetLastError();
       if(e==0){
         //
         if(StringFind(name,"TEST_",0)!=-1){
           double price1=(double)ObjectGetDouble(creator_id,name,OBJPROP_PRICE,0);
           double price2=(double)ObjectGetDouble(creator_id,name,OBJPROP_PRICE,1);
           double wiggle=NormalizeDouble((((double)rand())/((double)32767.0)-0.5)*(W*_point),_digits);
           price1+=wiggle;
           price2-=wiggle;
           ObjectSetDouble(creator_id,name,OBJPROP_PRICE,0,price1);
           ObjectSetDouble(creator_id,name,OBJPROP_PRICE,1,price2);
           }
         //
         }else{
         Print("Error reading object ("+IntegerToString(i)+") #"+IntegerToString(e));
         }
       }
       ChartRedraw(creator_id);
    }
     
  }
}

void OnDeinit(const int reason)
  {
  ObjectsDeleteAll(ChartID(),"TEST_");
  }

void OnTick()
  {

  }

void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam)
  {

  }
 
Fernando Carreiro #:

I don't know if it is plausible to do this for your project, but have you ever considered using a "canvas" as a work-around, with your own "virtual graphic objects"?

It may not resolve the issue completely, but it may simplify and reduce the "graphical object" load.

Thats what I just implemented. I reduced the number of accesses to a minimum.

I catch CHARTEVENT_OBJECT_CREATE and CHARTEVENT_OBJECT_DELETE, (Change, Drag etc) obtain all the infos one time and store them into classes and arrays. This way I dont need to access the objects all the time, since the information is in the code. 

The situation is better, but still not solved entirely. 

 
Alain Verleyen #:

Is it related to the number of objects on a chart ?

Are there several thread accessing the objects at the same time (concurrency issue ?) ? Is it happening while accessing the objects of the same chart as the running code ?

" happens just like that after some hours ", what is done with objects during these "some hours" ? You need to find a way to reproduce it, then you can hope to understand the issue and work around it.

If its related is not sure. I just can guess so, since it happens mainly but not only, whit an indicator of mine. This indicator collects all user objects and manages profiles in files. It saves the object data as well as loads them into the chart. Usually its just <>1.000 objects. I also implemented async loading, so that it steps out after some milliseconds and continues later, to not block the thread. This indicator worked well for years, but recently not anymore. 

After some hours ... well, in between it might happen that the chart changes, and since the chart metrics is also buffered due to the same issue, the chart data is obtained and stored into a struct frequently. 

Furhtermore, ever 50 ms the chart width and scale is checked, since MetaTrader still doesn´t create a CHARTEVENT_CHART_CHANGED when these value change. I mean, MetaQuotes knows this only since some years, that´s not really long ... and why fixing bugs ;)

And, which seems to worsen it, is the volume profile. I implemented such a profile which is accessing bars data, the profile is recalculated every hour, and the last one (intraday) is updated every minute. 

When I provoke the freeze in the debugger, it also hangs at those functions like ChartGetInteger() or similar, within the timer. 

Several threads: Yes, indicator and EA access the same chart objects frequently.
Reason: