What in gods name does clicking "Refresh" do? PLEASE HELP.

 

I have an indicator that uses multiple other indicators on multiple timeframes.

I have used SeriesInfoInteger(NULL, timeframe, SERIES_SYNCHRONIZED) to make sure all is synchronized, BarsCalculated() to make sure indicators are loaded, ChartRedraw() thinking maybe that is the same as refreshing the chart, and Bars() for each timeframe to load in OnInit(). 

Once the indicator is put on a new symbol it will fail to retrieve a certain bar on an alternate timeframe. Even removing the indicator and putting it back on does not work. Even clicking on other timeframes on the chart does not work.

The ONLY thing that works is right clicking and clicking "refresh". Indicator works as expected after that. I can even remove the indicator and put it back on. I can even close the chart and reopen it and reattach the indicator and it works.

Please tell me what EXACTLY "refresh" does to the chart so I can try replicate it from code.

 
A refresh isn't a solution, it is a reinitialization I think. If you return rates_total when a problem occurs, that could sometimes work as a refresh, but you shouldn't have an indicator that needs to be refreshed constantly. Most likely the problem is with the calculation loop in your indicator.
 

I was dealing with same issue these days.

The refresh will reload the data on the chart like if is the first time (for example, when you restart the terminal, or open a chart for a symbol and timeframe the first time). Then it will recalculate all the indicators. It won't call OnInit, but will call OnCalculate with prev_calculated equal 0.

To make it clear. For example you have set in your terminal options the maximum number of bars on a chart to 5000. So if the symbol and timeframe has more than that, let say 15000, the chart will be loaded with 5000 bars only and every time a new bar forms it will increase to 5001, 5002, etc. The issue lies on how your or many indicators are calculated, not using only the price or ohlc arrays from the parameters of the OnCalculate. For example making use of iTime, iOpen, iClose, etc. The issue is that these function only return values until the limit of maximum bars set in the terminal options. Because of that if your indicator try to calculate values using data from bar 5000, 5001, etc, it will fail or propagate the issue.

To solve this i'm using this approach. I'm still working on this also, but seems to work.

Regarding refresh, you make it programatically setting the symbol and timeframe with the same symbol and timeframe already loaded. By the ways the terminal reloads the data even if the parameters (symbol and timeframe) has not changed.

bool refreshing = false;
//+------------------------------------------------------------------+
//| 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(prev_calculated == 0 && rates_total > TerminalInfoInteger(TERMINAL_MAXBARS))
     {
      if(refreshing)
         return(0);
      
      refreshing = true;
      Print("Number of bars set in terminal options: ", (string)TerminalInfoInteger(TERMINAL_MAXBARS), ". There is already ", (string)rates_total," bars on the chart. Refreshing...");
      ChartSetSymbolPeriod(ChartID(), _Symbol, _Period);
      return(0);
     }
   
   refreshing = false;

   //--- make you calculations

   //--- return value of prev_calculated for next call
   return Calculate(rates_total, prev_calculated);
  }
 

Note that i'm using refresh only if previous calculated is 0. if it is not 0 then i assume that all bars already was calculated and i'll calculate only new bars not needing use data beyond the limit set in terminal settings anymore. Also becaue sometimes OnCalculate is called with prev_calculate = 0 for an unkown reason (maybe reconnection) after some time that the chart is open.

 

To be more precise Refresh() will reset all indicators on all charts for the considered symbol.

ChartSetSymbolPeriod(ChartID(), _Symbol, _Period);

This MQL code will do exactly the same, reset all indicators on all charts for the considered symbol, so running OnCalculate with prev_calculated=0, and that INDEPENDENTLY of the chartID parameter.

I recommend to avoid using this statement. Unfortunately there is no easy solution to replace it, only a custom solution is able to reset the current indicator.

 
Alain Verleyen #:

To be more precise Refresh() will reset all indicators on all charts for the considered symbol.

This MQL code will do exactly the same, reset all indicators on all charts for the considered symbol, so running OnCalculate with prev_calculated=0, and that INDEPENDENTLY of the chartID parameter.

I recommend to avoid using this statement. Unfortunately there is no easy solution to replace it, only a custom solution is able to reset the current indicator.

So, i was thinking on rewrite the logic of the indicators to limit the lookback to TerminalIndo Integer(TERMINAL MAXBARS). But it requires the rewrite of any indicator used as source by calling iCustom. If someone don't have the source code of an indicator, they would not be able to do that.

 
Samuel Manoel De Souza #:

So, i was thinking on rewrite the logic of the indicators to limit the lookback to TerminalIndo Integer(TERMINAL MAXBARS). But it requires the rewrite of any indicator used as source by calling iCustom. If someone don't have the source code of an indicator, they would not be able to do that.

Sorry but I don't get your point about TERMINAL MAXBARS ? (I have read your previous post explanation but it doesn't make it clearer to me).

 
Alain Verleyen #:

Sorry but I don't get your point about TERMINAL MAXBARS ? (I have read your previous post explanation but it doesn't make it clearer to me).

My specific case was due to try to access bars beyond TERMINAL MAXBARS. For example, MAXBARS is 5000, try using iClose(_Symbol,_Period, 5000) returns 0. If when prev_calculated is 0, i start the loop from 4999, it would be suficient for my use case.

For give more context, in some functions i use Bars function to get the amount of data and iClose, iOpen, etc to get OHLC and other datas, when i'm not working in (or with) OnCalculation.

 
Samuel Manoel De Souza #:

So, i was thinking on rewrite the logic of the indicators to limit the lookback to TerminalIndo Integer(TERMINAL MAXBARS). But it requires the rewrite of any indicator used as source by calling iCustom. If someone don't have the source code of an indicator, they would not be able to do that.

To be honest, applying surgery like this to a badly written indicator is never that nice to do. Could you instead get in touch with the author to obtain the source code or tell them to optimize it? or even just recreate the indicator?