EAs do not have the same problem. I reported this indicator problem to MetaQuotes as a bug, but got the response that it was working as designed.
This "design feature" also prevents use of the Account Server name with indicators, something I often want when storing indicator data that can be different for different brokers.
So I developed the following workaround, which after 4 versions to cope with additional quirks, seems to be working well. The workaround involves:
- splitting OnInit() into two parts, a part with nothing critical in it that kicks off a one second timer, and the main initialisation code in OwnInit() or whatever.
- start() being prevented from running until the timer gives the all clear
- the timer code checks for Empty4 being ready, and scrolls the chart backwards to download more history if required. Once all is ok the timer code runs OwnInit(), and allows start() to run.
Note: This workaround can only be used with an indicator which uses start() rather than OnCalculate() if weekend (market closed) running is required.
I started on this workaround at Build 722 time. At the time of posting I am using it with Build 752.
The code required is:
Code: Select all
// Globals
bool BootingB, // Empty4 startup workaround in progress
AutoScrollB; // To remember the chart's auto scroll setting as it is set to off while the Empty4 startup workaround is in progress
int EnoughBars; // Bars sufficient for the indicator to run, allowing the Empty4 indicator booting problem workaround to exit
datetime InitTickT; // TST of the last tick at initialisation time
int OnInit() {
... anything which will not error on lack of account info or history can go here as usual e.g. buffer and indicator function calls.
// Start of workaround
BootingB = true;
InitTickT = TimeCurrent();
EnoughBars = ... as requited by the indicator for the current period
AutoScrollB = ChartGetInteger(0, CHART_AUTOSCROLL);
if (AutoScrollB) ChartSetInteger(0, CHART_AUTOSCROLL, false); // turn off auto scroll if on
if (EventSetTimer(1))
Print("1 second timer started");
else
return InitError("EventSetTimer() failed"); // this will abort
// Everything else is done in OwnInit() called from OnTimer() once the timer has determined that the history is ok
return INIT_SUCCEEDED;
}
// bool OwnInit()
// -------
// Initialisation function called from OnTimer() once Empty4 booting is complete
bool OwnInit() {
// All the stuff which the indicator wants to do during initialisation which involves use of account info and history.
...
}
void OnTimer() {
if (BootingB) {
static int sPrevBars, sScrollsAtLastBarsChange, sScrolls, sNumNoConnection;
if (!IsConnected()) {
// Test for connectivity with comment to show what is happening rather than let the following code handle it with potentially a lot of log messages.
// On the first time here on an Empty4 boot after closedown with the indi loaded the IsConnected() call gives false even when connected.
Comment("Waiting for internet connection");
return;
}
Comment("");
PrintFormat("Empty4 indicator start workaround: Enough Bars %d, Acct# %d, Bars %d, Prev Bars %d, Scrolling %d", EnoughBars, AccountNumber(), Bars, sPrevBars, sScrolls);
if (!AccountNumber() || Bars>sPrevBars || ((!EnoughBars || Bars<=EnoughBars) && (sScrolls-sScrollsAtLastBarsChange<3))) {
// Login not available (AccountNumber() serving as a check for all account info) || Bars still increasing || (not enough bars && scroll back attempt in progress)
// Empty4 booting not complete yet
if (AccountNumber() && Bars == sPrevBars) {
// Login available and Bars have stopped increasing but EnoughBars haven't been reached or are still in a scroll back attempt, so scroll back in order to try to download more history
ChartNavigate(0, CHART_BEGIN, -2000); // only does the number of bars visible on screen so this must be repeated
sScrolls++;
}else
sScrollsAtLastBarsChange = sScrolls; // Used because it seemed that more than 1 second is needed to complete downloading a screen's worth of bars. 3 times was enough for all brokers I have tested this with.
sPrevBars = Bars;
return; // Empty4 booting not complete yet
}
// Empty4 booting appears to be complete
BootingB = false;
ChartSetInteger(0, CHART_AUTOSCROLL, AutoScrollB); // restore the auto scroll setting
ChartNavigate(0, CHART_END, Bars); // navigate to the end of the chart
if (!OwnInit()) return;
if (TimeCurrent() == InitTickT) start(); // No tick has arrived since startup so call start() like Empty4 does for an indicator after running OnInit() to give weekend output
}
... anything else to be done by the timer
}
void start() {
if (BootingB) return; // Part of working around the Empty4 design fault of calling OnInit() for an indicator before history updating is complete or account information is available.
... rest of start() as usual
}