Permanent files in tester mode - possible?

Chris70  
Doerk Hilger:

Is there a way to create files in tester mode which will survive a restart?

Global variables don't seem to work either.

Why shouldn't they survive? A restart per se doesn't delete any files, regardless if in live mode, tester (edit/correction: as long as the FILE_COMMON flag is used) or optimizer. The question is what the EA does later after restart and what exactly you want it to do.

If you reopen a preexisting file (=same filename) by default the pointer will be at the beginning of the file, so

  • if you want to add more data to the end of the old file use FileSeek(filehandle,0,SEEK_END) once after opening
  • if you want to overwrite the file and you expect the new file to have the same amount of bytes: just write the data like if the file has not even existed before
  • if you want to overwrite the file and you expect the new file to have a different amount of bytes: use FileDelete(), then write a new file (=to avoid left-over non-sense bytes at the end of the file in case the new file has less bytes)
  • of course overwriting doesn't mean you can't read the data once (e.g. after restart) and then overwrite it later
  • if you want a new file every time: simply chose a new filename (like Keith Watford says)

What do you mean by "global variables don't seem to work either"?

Of course, the values of global variables are lost after a restart. But if you write them to a file, of course you can read and reassign those values (usually in OnInit). Actually, most EAs should have such a function, because otherwise with simple things like changing the chart timeframe (=which forces a restart) means you get all your global variables reinitialized.

Here is an example for recovery of some global variables after restart (adapt it to work with the needs of your own EAs and remove the if (!MQLInfoInteger(MQL_TESTER)...) condition if you want the recovery also for the tester and not only in live trading (call the load_reboot_recovery once at the end of OnInit and the saving function in OnDeinit and maybe also regularly every few minutes or so):

// +------------------------------------------------------------------+
// | save reboot recovery file                                        |
// +------------------------------------------------------------------+
void save_reboot_recovery()
  {
   if(!MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_OPTIMIZATION))
     {
      // save program data
      main.advise("saving EA specific variables...",level_low);
      if (!FolderCreate("EA trade statistics",FILE_COMMON)){main.advise("unable to create 'EA trade statistics' group folder in '../Metaquotes/Terminal/Common/Files/'",level_medium);}
      string path="EA trade statistics\\magic_id_"+IntegerToString(main.magic_id)+"\\";
      if (!FolderCreate(path,FILE_COMMON)){main.advise("unable to create magic ID subfolder in '../Metaquotes/Terminal/Common/Files/EA trade statistics/' parent directory",level_medium);}
      string filename="EA_reboot_recovery.bin";
      if (FileIsExist(path+filename,FILE_COMMON)){FileDelete(path+filename,FILE_COMMON);} //=delete old versions
      int data_handle=FileOpen(path+filename,FILE_WRITE|FILE_BIN|FILE_COMMON); 
      if (data_handle==INVALID_HANDLE)
        {main.advise("invalid EA data file handle",level_critical);}
      else
        {
         FileSeek(data_handle,0,SEEK_SET);
         FileWriteDouble(data_handle,trailing_sl_long_price);
         FileWriteDouble(data_handle,trailing_sl_short_price);
         FileWriteLong(data_handle,(long)trailing_sl_long_time);
         FileWriteLong(data_handle,(long)trailing_sl_short_time);
         FileWriteDouble(data_handle,tp_long_price);
         FileWriteDouble(data_handle,tp_short_price);
         FileWriteLong(data_handle,(long)tp_long_time);
         FileWriteLong(data_handle,(long)tp_short_time);
         FileWriteDouble(data_handle,entry_price_long);
         FileWriteDouble(data_handle,entry_price_short);    
         FileWriteDouble(data_handle,entry_trigger); 
         FileWriteDouble(data_handle,sl_base);
         FileClose(data_handle);             
        }     
     }  
  }
  
// +------------------------------------------------------------------+
// | load reboot recovery file                                        |
// +------------------------------------------------------------------+
void load_reboot_recovery()
  {
   if (!MQLInfoInteger(MQL_TESTER) && !MQLInfoInteger(MQL_OPTIMIZATION))
     {
      main.statistics_load();   
      string path="EA trade statistics\\magic_id_"+IntegerToString(main.magic_id)+"\\"; 
      if (FileIsExist(path+"EA_reboot_recovery.bin"))
        {
         int data_handle=FileOpen(path+"EA_reboot_recovery.bin",FILE_READ|FILE_BIN|FILE_COMMON);
         if (data_handle==INVALID_HANDLE)
           {main.advise("invalid EA data file handle",level_critical);}
         else
           {
            FileSeek(data_handle,0,SEEK_SET);
            trailing_sl_long_price=FileReadDouble(data_handle);
            trailing_sl_short_price=FileReadDouble(data_handle);
            trailing_sl_long_time=(datetime)FileReadLong(data_handle);
            trailing_sl_short_time=(datetime)FileReadLong(data_handle);
            tp_long_price=FileReadDouble(data_handle);
            tp_short_price=FileReadDouble(data_handle);
            tp_long_time=(datetime)FileReadLong(data_handle);
            tp_short_time=(datetime)FileReadLong(data_handle);
            entry_price_long=FileReadDouble(data_handle);
            entry_price_short=FileReadDouble(data_handle); 
            entry_trigger=FileReadDouble(data_handle); 
            sl_base=FileReadDouble(data_handle);
            FileClose(data_handle);                   
           }  
        }
     }
  }  
Doerk Hilger  

Well, when I create a file in tester, its saved here

and when the tester ends, the file is gone. 

Chris70  
Doerk Hilger:

Ok, found the answer by myself. Files survive only when the common folder is used. 

But regarding global variables, I can neither read nor store such with build 2280 in tester. 

I cannot reproduce the problem. I tried this example with both builds 2190 and 2280 without any problems:

int global_variable=123456789;

void OnInit() 
  {
   if (!FileIsExist("test.bin",FILE_COMMON))
     {
      Print("before tester restart: trying to write some data to a file");
      int handle=FileOpen("test.bin",FILE_COMMON|FILE_WRITE|FILE_BIN);
      if (handle==INVALID_HANDLE){Print("invalid file handle error");return;}
      FileWriteInteger(handle,global_variable,INT_VALUE);
      FileClose(handle);
     }
   else
     {
      Print("after restart: trying to recover data from file");
      int handle=FileOpen("test.bin",FILE_COMMON|FILE_READ|FILE_BIN);
      if (handle==INVALID_HANDLE){Print("invalid file handle error");return;}
      Print ("result:",FileReadInteger(handle,INT_VALUE));
      FileClose(handle);      
     }
  }
  
void OnTick(){ExpertRemove();}

Did you set the correct flags for FILE_READ and FILE_WRITE? Please show the code that doesn't save the data correctly.

Doerk Hilger  

Chris, thank you for you effort. But you seem to ignore my answer ;) 

You are using the common-file-folder by FILE_COMMON, and of course it works with this flag ;) 

Chris70  
Doerk Hilger:

Chris, thank you for you effort. But you seem to ignore my answer ;) 

You are using the common-file-folder by FILE_COMMON, and of course it works with this flag ;) 

No idea what you have against the common files folder (which also wasn't part of your initial question) ... actually it makes many things a lot easier (and the differences between how files are handled in the tester are also not new with the latest builds).

But if you insist for whatever reason, you can use #property tester_file --> this also works without the FILE_COMMON flag:

#property tester_file "test.bin"

int global_variable=123456789;

void OnInit() 
  {
   if (!FileIsExist("test.bin"))
     {
      Print("before tester restart: trying to write some data to a file");
      int handle=FileOpen("test.bin",FILE_WRITE|FILE_BIN);
      if (handle==INVALID_HANDLE){Print("invalid file handle error");return;}
      FileWriteInteger(handle,global_variable,INT_VALUE);
      FileClose(handle);
     }
   else
     {
      Print("after restart: trying to recover data from file");
      int handle=FileOpen("test.bin",FILE_READ|FILE_BIN);
      if (handle==INVALID_HANDLE){Print("invalid file handle error");return;}
      Print ("result:",FileReadInteger(handle,INT_VALUE));
      FileClose(handle);      
     }
  }
  
void OnTick(){ExpertRemove();}

edit: oops, you are right! I stand corrected; property tester_file doesn't solve it for whatever reason!

Maybe you find something useful here (see section: "files in the tester"): https://www.mql5.com/en/articles/2720#z20

MQL5 Programming Basics: Files
MQL5 Programming Basics: Files
  • www.mql5.com
Like many other programming languages, MQL5 features the functions for working with files. Although working with files is not a very common task when developing MQL5 Expert Advisors and indicators, each developer faces it sooner or later. The range of issues that require working with files is wide enough. It includes generating a custom trading...
Chris70  

Puh.. I guess then we're all good ;-) 

Sorry for the misunderstanding; I'm just so used to ALWAYS put my files in subfolders of the common folder (exactly because of such trouble) that it didn't even come to my mind that anybody wouldn't to use this flag).

If your problem is now solved, that's all that counts.

Doerk Hilger  
Thanks for helping :) Enjoy the Sunday :) 
Reason: