Is "while(!IsStopped())" expected to work on Indicators?

 

Hi, the code "while(!IsStopped())" is not working on my Indicator. 

I have a code like this:

      while(!IsStopped()){
         copied = CopyTicks(_Symbol, ticks, COPY_TICKS_ALL, LAST_TICK_TIME, 1000000);
	 Print("COPIED: "+copied);
         if(copied>0){
            LAST_TICK_TIME = ticks[copied - 1].time_msc;
            handleTicks(ticks);
         }
         if(copied < ticks_to_copy ) break;
      } 

If i remove indicator from chart or close the chart, the operations inside "while" continue until the "break" is triggered (i can see it in logs).

Is it expected behaviour or a bug?

 
antony23:

Hi, the code "while(!IsStopped())" is not working on my Indicator. 

I have a code like this:

If i remove indicator from chart or close the chart, the operations inside "while" continue until the "break" is triggered (i can see it in logs).

Is it expected behaviour or a bug?

You have a loop that runs until it is complete. IsStopped() detects 3 seconds of inactivity when the code is running. in contrast, OnDeinit() detects when the indicator has been removed.

Expected. Not a bug.

 
Ryan L Johnson #:

You have a loop that runs until it is complete. IsStopped() detects 3 seconds of inactivity when the code is running. in contrast, OnDeinit() detects when the indicator has been removed.

Expected. Not a bug.

Thanks for the answer, but really don't understand it.

From doc about isStopped(): Returns true, if the _StopFlag system variable contains a value other than 0. A nonzero value is written into _StopFlag, if a mql5 program has been commanded to complete its operation. In this case, you must immediately terminate the program, otherwise the program will be completed forcibly from the outside after 3 seconds.

Abiout deinit, it is called after "while" operations and other onCalculate() operations are completed. And it happens more than 3 seconds after i close the chart.

Documentation on MQL5: _StopFlag / Predefined Variables
Documentation on MQL5: _StopFlag / Predefined Variables
  • www.mql5.com
The _StopFlag variable contains the mql5 program stop flag equal to 0 during normal operation. When the client terminal tries to stop the program...
 
antony23:

Hi, the code "while(!IsStopped())" is not working on my Indicator. 

I have a code like this:

If i remove indicator from chart or close the chart, the operations inside "while" continue until the "break" is triggered (i can see it in logs).

Is it expected behaviour or a bug?

You should never use such loop without a "Sleep". And sleep is not allowed in an indicator.

Fix your code.

 
Alain Verleyen #:

You should never use such loop without a "Sleep". And sleep is not allowed in an indicator.

Fix your code.

Any tip how to fix it?

I need, on first call of onCalculate(), iterate all ticks from a past date to current date to build history of the indicator. 

I tried recoding this way, but same problem.

do{
   copied = CopyTicks(_Symbol, ticks, COPY_TICKS_ALL, LAST_TICK_TIME, 1000000);
   Print("COPIED: "+copied);
   if(copied>0){
      LAST_TICK_TIME = ticks[copied - 1].time_msc;
      handleTicks(ticks);
   }
}while(copied == ticks_to_copy);
 

This is from an EA, but no Sleep() is used:

Forum on trading, automated trading systems and testing trading strategies

CopyTicks() Inconsistent Behavior

Lorentzos Roussos, 2022.08.22 18:08

Building a Point and figure chart ? :)

I was fighting with the ticks mechanism recently too so , there are some issues , on our end not MT5.

The system will querry the server for any date that is not in the downloaded tick data .

Try step loading small batches of ticks based on what the symbol has already (on its rates array ,on the native timeframe).

The following produces inverted ticks which you will need to sort based on time_msc and , it temporarily stores the batch on ticks[] which you then need to add to your 

collection array . It was done this way because i were developing an ask chart so i had to scrub any non TICK_FLAG_ASK ticks.

Now once the ticks you want are downloaded they will be almost instant to access from consecutive loads .

You can (should) also setup date limits (when reached stop loading) , and or tick amount limits .

int bars_step=400;//bars step
int step_timeout=2;//Step timeout in seconds
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
bool has_timer=false;
MqlTick ticks[];
datetime step_from,step_to;
int OnInit()
  {
//--- create timer
   //EventSetTimer(60);
   ArrayFree(ticks);
   step_from=0;step_to=0;
   has_timer=EventSetMillisecondTimer(300);
   if(!has_timer){return(INIT_FAILED);}
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//--- destroy timer
   //EventKillTimer();
   if(has_timer){EventKillTimer();}
   ArrayFree(ticks);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
  {
        /*
        okay so first download fails with 4401 
        then at some point when the range is ready its available
        */
//---
  EventKillTimer();
  //load ticks process 
    //copy ticks from the first bar 
      int barz_total=Bars(_Symbol,_Period);
      int maxbarsinchart=(int)TerminalInfoInteger(TERMINAL_MAXBARS);
      if(barz_total>maxbarsinchart){barz_total=maxbarsinchart;}
      //stepwise load
      if(barz_total>0){ 
      //first step 
        if(step_from==0&&step_to==0){
        step_to=iTime(_Symbol,_Period,0);
        step_from=(datetime)(step_to-bars_step*PeriodSeconds(_Period));
        }
      //request 
        ResetLastError();
        ArrayFree(ticks);
        //Print("Request "+TimeToString(step_from,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" - "+TimeToString(step_to,TIME_DATE|TIME_MINUTES|TIME_SECONDS));
        int ticks_total=CopyTicksRange(_Symbol,ticks,COPY_TICKS_INFO,((ulong)step_from*1000),((ulong)step_to*1000));
        //some delay occurs here 
          int error=GetLastError();
          //if not yet ready 
            if(error==4401&&ticks_total==-1){
            EventSetTimer(step_timeout);
            Print("wait for sync");
            }
          //if ready skip to next part
            else if(error==0&&ticks_total>=0){
            Print(TimeToString(step_from,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" - "+TimeToString(step_to,TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" ("+IntegerToString(ticks_total)+")ticks");
            step_to=step_from;
            step_from=(datetime)(step_to-bars_step*PeriodSeconds(_Period));
            if(ticks_total==0){
            Print("Finished ");ExpertRemove();
            }else{EventSetMillisecondTimer(40);}
            }
            else{Print("Unknown error "+IntegerToString(error)+" ticks("+IntegerToString(ticks_total)+")");ExpertRemove();}
      }else{Print("No bars in symbol");}
      
  }

 
Stop screwing this user. _StopFlag isnt working. Its a bug. I have reported this. Never got fixed.

Using Sleep() is not a solution. - Sleep() could be using a "noop" but who knows, right?

Documentation is clear on this. API is not behaving as documented -> Bug.
 
Dominik Egert #:
_StopFlag isnt working.

I recently downloaded an inefficient indicator code from the CodeBase, and MT5 threw an error that advised me to rewrite the source code because execution was too slow─it was in fact, over 3 seconds.

Is that the documented purpose of IsStopped()?

"Returns true, if the _StopFlag system variable contains a value other than 0. A nonzero value is written into _StopFlag, if a mql5 program has been commanded to complete its operation. In this case, you must immediately terminate the program, otherwise the program will be completed forcibly from the outside after 3 seconds."

Documentation on MQL5: IsStopped / Checkup
Documentation on MQL5: IsStopped / Checkup
  • www.mql5.com
Checks the forced shutdown of an mql5 program. Return Value Returns true, if the _StopFlag system variable contains a value other than 0. A nonzero...
 
antony23:
Hi, the code "while(!IsStopped())" is not working on my Indicator. 

while(!IsStopped()) is almost the same as while(true)

https://www.mql5.com/en/docs/runtime/running

It is strongly recommended not to use infinite loops to handle events. Possible exceptions are scripts and services handling a single Start event.

 
antony23 #:

Any tip how to fix it?

I need, on first call of onCalculate(), iterate all ticks from a past date to current date to build history of the indicator. 

I tried recoding this way, but same problem.

If you fail to get the required ticks on the first try, terminate OnCalculate() and try again the next time OnCalculate() is called.

If you want the indicator to work on weekends, you'll need a Timer (if you fail on the first Calculate event and there are no new Calculate events due to the weekend).

 
Vladislav Boyko #:

while(!IsStopped()) is almost the same as while(true)


I agree, almost the same.

Please see the example code on this page:


It shows examplatory usage of IsStopped() and documentation states you should use it to enable the Terminal to interrupt your codes loops.


Nether the less, it is not reliably doing such although clearly documented, adviced and empathized.

Resulting conclusion: Bug.

Anyone going to take this to the devs?