Hi,
I have this sample code for the MTF RSI indicator.
The first thing we check in onCalculate is whether the number of bars calculated by the RSI handle matches the number of bars in the selected timeframe. If they don’t match, the function returns zero. This works well in the open market, and after a few ticks, we eventually calculate the RSI values.
However, in a closed market, onCalculate only runs once and does not calculate the historical values of the RSI.
Does anyone have a solution for this problem so that it works well in a closed market too?Yes, but it doesn't make any difference because, as long as the RSI is supposed to be calculated for timeframes higher than the chart's timeframe, the first call to oncalculate will almost always encounter a return(0) .
Since oncalculate is only called once at closed markets, the indicator doesn't display any value.
A potential solution could involve introducing some kind of delay in oninit , but the sleep function doesn't work for indicators.Yes, but it doesn't make any difference because, as long as the RSI is supposed to be calculated for timeframes higher than the chart's timeframe, the first call to oncalculate will almost always encounter a return(0) .
Since oncalculate is only called once at closed markets, the indicator doesn't display any value.
A potential solution could involve introducing some kind of delay in oninit , but the sleep function doesn't work for indicators.I'm thinking that you can mimic Sleep() with:
Forum on trading, automated trading systems and testing trading strategies
gordon, 2010.11.18 21:03
Sleep() is 'skipped' in the Tester. From the article 'Testing Features and Limits in MetaTrader 4':
Technically it's impossible to simulate Sleep(), since the Tester's time is quantized as opposed to being continuous (as in Live/Demo). U can simulate Sleep() to some degree by skipping ticks, but that only enables sleeping the amount of time between ticks. That time is determined by the specific bar's volume value, since the Tester produces as many ticks in a bar as the volume in that bar (in 'Every Tick' mode).
So for example if you are Testing on M1 and a certain bar has a volume of 20, u will only be able to skip 60/20=3 sec at a time, so u will only be able to simulate sleeping for 3 secs. Depending on what u are trying to achieve this might be good enough for u.
As to how to technically do it:
int start() { static int wait = 0; if ( ... ) // condition for sleeping wait = TimeCurrent() + 5; // sleeping for at least 5 seconds if ( TimeCurrent() < wait ) return(0); // skiping to next tick // main program code here... return(0); }
Note that this will make it "sleep" for at least 5 seconds (but maybe much more than that)... Also, the following will NOT work in the Tester (although it will work in Live/Demo):
int start() { int wait = 0; if ( ... ) // condition for sleeping wait = TimeCurrent() + 5; // sleeping for at least 5 seconds while ( TimeCurrent() < wait ) {} // this will NOT work in the Tester, it would cause it to loop endlessly... // main program code here... return(0); }
But maybe replace TimeCurrent() with TimeLocal() to force MT5 to read your pc time which is running while the market is closed.
"I managed to fix this issue.
To do this, the chart first needed to be refreshed programmatically, and in fact,
ChartRedraw() doesn’t accomplish this—instead, ChartSetSymbolPeriod(0, _Symbol, PERIOD_CURRENT); must be used.
The second problem was related to how similar values were being filled in candles that are subsets of higher-timeframe candles. Using the previous buffer value caused the entire buffer to be filled with incorrect data (this issue doesn’t occur in live markets) .
As a result, by modifying the code I shared in the first post, the problem was resolved, and the indicator now works correctly even in closed markets."
#property indicator_minimum 0.0 #property indicator_maximum 100.0 #property indicator_separate_window #property indicator_buffers 1 #property indicator_plots 1 #property indicator_label1 "RSI 1" #property indicator_type1 DRAW_LINE #property indicator_color1 clrFuchsia #property indicator_style1 STYLE_SOLID #property indicator_width1 1 //INPUTS input int Inp_RSI_Period = 2; //RSI PERIOD input ENUM_TIMEFRAMES Inp_TF = PERIOD_CURRENT; //TIME FRAME input int Inp_LineSize = 1; //RSI 1 LINE SIZE input int Inp_NumberOfBars = 500; //BARS TO CALCULATE //GLOBALS int Handle_RSI; ENUM_TIMEFRAMES Time_Frame; //BUFFERS double Buffer_RSI[]; //+------------------------------------------------------------------+ // OnInit //+------------------------------------------------------------------+ int OnInit() { //-global init Time_Frame = Inp_TF; //--- //set buffers SetIndexBuffer(0,Buffer_RSI,INDICATOR_DATA); PlotIndexSetInteger(0,PLOT_LINE_WIDTH,Inp_LineSize); //-INIT RSI HANDLES //RSI 1 ResetLastError(); Handle_RSI = iRSI(_Symbol,Time_Frame,Inp_RSI_Period,PRICE_CLOSE); if(Handle_RSI == INVALID_HANDLE) { Print("RSI HANDLE DOES NOT CREATED. ERROR :", GetLastError()); return INIT_FAILED; } //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ // OnDeInit //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //FREE UP RSI HANDLES IndicatorRelease(Handle_RSI); } //+------------------------------------------------------------------+ // OnCalculate //+------------------------------------------------------------------+ 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[]) { //check if RSIs data is available int bar_count = Bars(NULL,Time_Frame); if(BarsCalculated(Handle_RSI)<bar_count) return(0); //--- //-refreshing the chart if( prev_calculated == 0) ChartSetSymbolPeriod(0, _Symbol, PERIOD_CURRENT); //--- //-main loop int begin = prev_calculated-1; if(begin<rates_total-Inp_NumberOfBars) begin = rates_total-Inp_NumberOfBars; if(begin<0)begin = 0; for(int i = begin; i<rates_total ; i++) { int Shift1 = iBarShift(NULL, Time_Frame, time[i], false); if(Shift1 < 0 ) return 0; else { Buffer_RSI[i] = copy_value(Handle_RSI,Shift1); } if(i==rates_total-1) { for(int s=i ; s>=0; s--) { if(iBarShift(NULL, Time_Frame, time[s], false)==1 ||iBarShift(NULL, Time_Frame, time[s], false)==-1) break; else { Buffer_RSI[s] = Buffer_RSI[i]; } } } } //-end main loop return(rates_total); } //-------------------------------------------------------- //functions //-------------------------------------------------------- double copy_value(int handle, int shift) { double value[1]; CopyBuffer(handle,0,shift,1,value); return value[0]; }

- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi,
I have this sample code for the MTF RSI indicator.
The first thing we check in onCalculate is whether the number of bars calculated by the RSI handle matches the number of bars in the selected timeframe. If they don’t match, the function returns zero. This works well in the open market, and after a few ticks, we eventually calculate the RSI values.
However, in a closed market, onCalculate only runs once and does not calculate the historical values of the RSI.
Does anyone have a solution for this problem so that it works well in a closed market too?