Problem with a multi-chart-script

 

Hi coders,

I made two scipts. One changes the timeframe of all open charts to the timeframe where the script is dragged to. The other script changes the template of all open charts to a template named "test".

Both work fine. But now I added one chart which should not be affected by the scripts. Now I check the chart-symbol in the scripts. If the chart-symbol is USDHKD nothing should be done.

That works fine with the timeframe script. But if I run the template-change script, it always changes the template of the USDHKD chart too. Can somebody tell me why it works with the timeframe script and not with the template script? I have absolutely no idea because the logic is exactly the same...?!?!

Change timeframe:

void OnStart()
  {
   for (long chartID=ChartFirst(); chartID!=-1; chartID=ChartNext(chartID)) {
      if (ChartSymbol(chartID)!="USDHKD") ChartSetSymbolPeriod(chartID, ChartSymbol(chartID), ChartPeriod());
   }  
  }

Change template:

void OnStart()
  {
   for (long chartID=ChartFirst(); chartID!=-1; chartID=ChartNext(chartID)) {
      if (ChartSymbol(chartID)!="USDHKD") ChartApplyTemplate(chartID, "test");
   }
  }
 
Marcus Riemenschneider: it always changes the template of the USDHKD chart too.
If the naming pattern of your charts isn't exactly "BasQuo" then your code fails.
Broker's use a variety of naming patterns: EURUSD, EURUSDc, EURUSDct, EURUSDi, EURUSDm, EURUSDecn, EURUSDpro, "EUR.USD", "EUR/USD", "EURUSD.", "EURUSD..", "EURUSD.G", "EURUSD.SBe", "EURUSD.stp", "EURUSD+", "EURUSD-sb", etc. 
 
whroeder1:
If the naming pattern of your charts isn't exactly "BasQuo" then your code fails.
Broker's use a variety of naming patterns: EURUSD, EURUSDc, EURUSDct, EURUSDi, EURUSDm, EURUSDecn, EURUSDpro, "EUR.USD", "EUR/USD", "EURUSD.", "EURUSD..", "EURUSD.G", "EURUSD.SBe", "EURUSD.stp", "EURUSD+", "EURUSD-sb", etc. 

Yes, I know. But the symbol is 100% correct. As I mentioned above it works absolutely fine with the script which changes the timeframe.

 

For reasons unknown (to me), after the first ChartApplyTemplate() is called the subsequent calls to ChartSymbol() return null strings. Even though the chartIDs remain the same.

The same behaviour is not apparent with ChartSetSymbolPeriod().

A workaround: 

#property strict

void OnStart()
  {
   long ChartsToChange[];
   long chartID = ChartFirst();
   while(chartID >= 0)
     {
      if(ChartSymbol(chartID)!="USDHKD")
        {
         int arraysize = ArraySize(ChartsToChange);
         ArrayResize(ChartsToChange, arraysize+1);
         ChartsToChange[arraysize] = chartID;        
        }
      chartID = ChartNext(chartID);
     }
   int count=ArraySize(ChartsToChange);
   for(int i=0; i<count; i++) ChartApplyTemplate(ChartsToChange[i], "test");
  }
 
honest_knave:

For reasons unknown (to me), after the first ChartApplyTemplate() is called the subsequent calls to ChartSymbol() return null strings. Even though the chartIDs remain the same.

The same behaviour is not apparent with ChartSetSymbolPeriod().

A workaround: 

EDIT: ok I was able to replicate the bug... Here's another workaround. Same as knave's just a little bit different implementation.
#include <Arrays\ArrayLong.mqh>
void OnStart()
{
   CArrayLong charts;
   for(long ch=ChartFirst(); ch>=0; ch=ChartNext(ch)) 
      if(StringFind(ChartSymbol(ch),"USDJPY")<0) 
         charts.Add(ch);
   for(int i=0;i<charts.Total();i++)
      ChartApplyTemplate(charts[i],"ADX.tpl");
}
 
honest_knave:

For reasons unknown (to me), after the first ChartApplyTemplate() is called the subsequent calls to ChartSymbol() return null strings. Even though the chartIDs remain the same.

The same behaviour is not apparent with ChartSetSymbolPeriod().

A workaround: 

Because you are applying a template to the current chart where the script is running.

void OnStart()
  {
//---
   long thisID=ChartID();
   for(long chartID=ChartFirst(); chartID!=-1; chartID=ChartNext(chartID)) 
     {
      if(chartID!=thisID && ChartSymbol(chartID)!="AUDUSD") ChartApplyTemplate(chartID,"test");
     }
   ChartApplyTemplate(thisID,"test");
  }
 
Alain Verleyen:

Because you are applying a template to the current chart where the script is running.


Hi Alain,

I understand the general implications of running the template on the current chart.

But I still don't get why valid ChartID's would pull null values through ChartSymbol() in this situation.

The ChartApplyTemplate() call isn't changing the chartID's of the other charts.

It seems like there isn't any access to the other charts while ChartApplyTemplate() is waiting to be executed (returned empty string implies chart does not exist)


 
honest_knave:

Hi Alain,

I understand the general implications of running the template on the current chart.

But I still don't get why valid ChartID's would pull null values through ChartSymbol() in this situation.

The ChartApplyTemplate() call isn't changing the chartID's of the other charts.

It seems like there isn't any access to the other charts while ChartApplyTemplate() is waiting to be executed (returned empty string implies chart does not exist)


That doesn't matter. Only Metaquotes can answer about what is happening exactly.

By applying a template to current chart you remove the running script, don't expect a normal behaviour.

ChartSetSymbolPeriod() could do the same, but here it doesn't change anything on current chart.

 
Alain Verleyen:

That doesn't matter. Only Metaquotes can answer about what is happening exactly.

By applying a template to current chart you remove the running script, don't expect a normal behaviour.

ChartSetSymbolPeriod() could do the same, but here it doesn't change anything on current chart.


Thanks for all your help, guys!

Like Alain said, this seems to be an issue which only the coders of MT4 can understand... but anyway, I am happy that it works now.

Reason: