I'm writing an indicator which displays (many) trendlines on the chart. When the indicator is removed from the chart I would like to delete the trendlines it has drawn, and do so without deleting other trendlines created by other indicators or drawn manually. For illustration one can just assume the following code, which draws many trendlines:
In order to delete the trendlines I implement the OnDeinit() procedure, search the list of chart objects for objects with the substring "My Trendline", and delete every one of those.
The problem is that it doesn't work, and the chart still contains the trendlines. If I delete the trendlines using the ObjectsDeleteAll() function, the trendlines are removed but so are also every other trendline. Also, if the chart does not contain too many trendlines it seems to work, but becomes a problem when several hundreds of trendlines are drawn by the indicator.
Does anyone know the problem, or a possible solution?
Yes
StringFind()
Is the incorrect approach.
Can use
ObjectFind()
Function.
Also
ObjectCreate(0, "My Trendline " + IntegerToString(i)
Yes
Is the incorrect approach.
Can use
I'm using the StringFind() in order to filter out the objects with the substring "My Trendline", as every actual trendline has a unique name such as "My Trendline 1", "My Trendline 2".
The ObjectFind() function only returns whether or not an object with the specified name actually exists in the chart, and so does not address the problem since the name is already given by ObjectName() function.
If I add print statements in the OnDeinit() procedure the output actually says that an object with the name has been found, and the ObjectDelete() function returns true, yet the trendlines remain in the chart.
Could you please post an example OnDeinit() procedure which deletes just the trendlines which begin their name with "My Trendline", if you know the problem?
PS: I tried changing the name using IntegerToString(i) but it still does not function.
I'm using the StringFind() in order to filter out the objects with the substring "My Trendline", as every actual trendline has a unique name such as "My Trendline 1", "My Trendline 2".
The ObjectFind() function only returns whether or not an object with the specified name actually exists in the chart, and so does not address the problem since the name is already given by ObjectName() function.
If I add print statements in the OnDeinit() procedure the output actually says that an object with the name has been found, and the ObjectDelete() function returns true, yet the trendlines remain in the chart.
Could you please post an example OnDeinit() procedure which deletes just the trendlines which begin their name with "My Trendline", if you know the problem?
PS: I tried changing the name using IntegerToString(i) but it still does not function.
Well you call the ObjectsTotal() function at every cycle in the loop but if the loop removes an object then this will affect that exact number of iterations... and hence int i, so instead you can do like so:
void OnDeinit(const int reason) { int objects=ObjectsTotal(0); for (int i = 0; i < objects; i++) { string name = ObjectName(0, i); if (StringFind(name, "My Trendline") != -1) { ObjectDelete(0, name); } } ObjectsDeleteAll(0, -1, OBJ_TREND); }
Well you call the ObjectsTotal() function at every cycle in the loop but if the loop removes an object then this will affect that exact number of iterations... and hence int i, so instead you can do like so:
Mhm, I too thought that was the problem, but after trying to put the ObjectsTotal() function outside the loop scope, somehow strangely the trendlines remain.
ObjectDelete()
Also watch the output log to see something like
4202 |
ERR_OBJECT_DOES_NOT_EXIST |
Object does not exist |
4203 |
ERR_UNKNOWN_OBJECT_TYPE |
Unknown object type |
4204 |
ERR_NO_OBJECT_NAME |
No object name |
Also
ObjectsTotal The function returns the number of objects in the specified chart, specified subwindow, of the specified type. int ObjectsTotal( long chart_id, // chart identifier int sub_window=-1, // window index int type=-1 // object type ); Parameters chart_id [in] Chart identifier. 0 means the current chart. sub_window=-1 [in] Number of the chart subwindow. 0 means the main chart window, -1 means all the subwindows of the chart, including the main window. type=-1 [in] Type of the object. The value can be one of the values of the ENUM_OBJECT enumeration. -1 means all types. Return Value The number of objects.
So that seemed to be the problem, that after deleting an object the chart's object list changes. The following procedure removed all the trendlines:
void OnDeinit(const int reason) { bool allDeleted = false; while (!allDeleted) { allDeleted = true; int objects=ObjectsTotal(0); for (int i = 0; i < objects; i++) { string name = ObjectName(0, i); if (StringFind(name, "My Trendline") != -1) { allDeleted = false; ObjectDelete(0, name); } } } //ObjectsDeleteAll(0, -1, OBJ_TREND); }
Kindof nice to know since I have seen the previous version in other indicators.
So that seemed to be the problem, that after deleting an object the chart's object list changes. The following procedure removed all the trendlines:
Kindof nice to know since I have seen the previous version in other indicators.
So
int objects=ObjectsTotal(-1,-1);
And the best approach would be to use i-- in stead of i++ in the loop.
This way it auto compensates so to speak.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
I'm writing an indicator which displays (many) trendlines on the chart. When the indicator is removed from the chart I would like to delete the trendlines it has drawn, and do so without deleting other trendlines created by other indicators or drawn manually. For illustration one can just assume the following code, which draws many trendlines:
In order to delete the trendlines I implement the OnDeinit() procedure, search the list of chart objects for objects with the substring "My Trendline", and delete every one of those.
void OnDeinit(const int reason) { /*for (int i = 0; i < ObjectsTotal(0); i++) { string name = ObjectName(0, i); if (StringFind(name, "My Trendline") != -1) { ObjectDelete(0, name); } }*/ ObjectsDeleteAll(0, -1, OBJ_TREND); }
The problem is that it doesn't work, and the chart still contains the trendlines. If I delete the trendlines using the ObjectsDeleteAll() function, the trendlines are removed but so are also every other trendline. Also, if the chart does not contain too many trendlines it seems to work, but becomes a problem when several hundreds of trendlines are drawn by the indicator.
Does anyone know the problem, or a possible solution?