The easiest is using GlobalVariables if you need to save numerical values or short text strings
The easiest is using GlobalVariables if you need to save numerical values or short text strings
I guess that Terminal Global Variables could only handle Double content...
If I wanted to transfer the state of my EA to a different machine, I would use some sort of file.
I might not use an .ini file, though. It depends upon the nature of the data being saved. INI files are useful for key,value pairs, but they're not as useful for arrays of data. For arrays of data I would use some sort of CSV. I notice in the example for the INI library that he stores order data in the .ini file—I would never do that.
As it pointed out above, GlobalVariables could be a simple way to save certain data. I personally wouldn't save EA state data there. I think of Terminal Global Variables as "shared memory" between EA's, indicators, and scripts. So to me, logically, it shouldn't go there. That's not to say it isn't possible, though.
As for what I currently use: I don't currently save state data. When my EA starts up, it pulls deal data using HistoryDealsTotal(), HistorySelect(), etc. Apart from that, my EA starts with a clean slate every time.
It depends on the application.
If i need to check if something already exists, for example a magic number, or i want to quickly reload some saved values i definitely use Global Vars.
I would probably not use it when i want to save larger amounts of data, for example when i generate CSV or HTML that's all written to file.
So i would say it depends on the amount of data you want to save.
I guess that Terminal Global Variables could only handle Double content...
I have on occasions used Terminal GVs to store strings as part of the GV's name
Pierre
Global variables can only handle doubles, and imho, the internal handling of global vars is based on SQL and not proper implemented. Since I dropped extensive usage of global variables, I have no more timeouts and no more crashes of MT4/MT5 at all.
Ini files, in view of speed, require a lot of string operations and by this lot of memory allocation - not a good idea.
I implemented a class for variable exchange, doubles and strings, in four different ways:
1. Exchange data between indicators/EA within a chart
2. Within the same MT4 instance
3. Between all MT4 instances
4. Between any MT4 and MT5 instance
The class also handles the lifetime of a variable automatically.
This is the description header. If you´re interested in the whole code, drop me a private message. The code is a part of a commercial product and may be used for free by anyone, no matter if you purchased the product or not, but I am not allowed to mention the name here. It´s not fully described in the documentation, but I am sure it´s not that hard to figure out how it works. One example:
For writing, just use:
__LocalVars.SetString("MyStrVar","Sample text");
__LocalVars.SetDouble("MyDblVar",1.234);
For reading:
Props:string text = __LocalVars.GetString("MyStrVar");
double n = __LocalVars.GetDouble("MyDblVar");
datetime d = __LocalVars.GetTC("MyStrVar");
bool b = __LocalVars.IsExist("MyStrVar");
Actually that´s it.
/*
Functions
---------
bool InitByChart (string prefix=NULL, CHART id=NULL, bool commonfolder=false)
bool Init (string filename, bool commonfolder)
bool SetDouble (string name, double value, bool permanent=false)
bool SetString (string name, string value, bool permanent=false)
double GetDouble(string name, bool reload=true)
string GetString(string name, bool reload=true)
bool IsDefined(string name, bool reload=true)
bool Delete(string name, bool reload=true)
bool DeleteAll(string prefix=NULL, bool reload=true)
bool Update()
datetime GetTC(string name)
Prop-Functions
--------------
bool AutoUpdate(bool flag) - default ON
bool AutoUpdate()
bool Display(bool flag) - default OFF
bool Display()
bool Prefix(string value=NULL) - If NULL, a unique prefix is used
string Prefix()
long GetUniqueId - Returns a unique identifier
Predefined objects
------------------
__ChartVars - database with variables in the sandbox of the chart
__LocalVars - database with variables limited to the current instance of MT4/MT5
__GlobalVars - global data, valid for all instances of either MT4 or MT5
__GlobalVarsMTX - global data, valid for all instances of any MT4 and MT5
Sample without initialization / direct usage
-----------------
__ChartVars.SetDouble("Value",1)
double v=__ChartVars.GetDouble("Value");
Architecture of var database
----------------------------
int - number of records (m_cnt)
SDBVarsData[] - main records 0-max (m_data[])
int[] - string index table (m_sx[])
string[] - string records 0-max
Comments
--------
The focus is performance. Therefore the main table in SDBVarsData[] is always compressed.
When a record is removed, the remaining records are shifted and on every access, the
main table is loaded at once into memory.
But, shifting strings would decrease speed due to too many disk accesses. Therefore
the strings are allocated via a string-index table. This way, a record of the main table
which points to a string, only has the index to the string and when it is shifted during
compression, the string itself remains at the same physical adress.
*/
Here's a simple and efficient way to save/load variables.
#property strict #include <Arrays\List.mqh> //+------------------------------------------------------------------+ class VariableData : public CObject { protected: string m_name; string m_value; public: VariableData(){} VariableData(string name):m_name(name){} template<typename T> void operator = (T value){ m_value=(string)value;} template<typename T> T value() { return (T)m_value; } string name() { return m_name; } virtual bool Save(const int file_handle) override{ if(file_handle==INVALID_HANDLE) return(false); int len_name = StringLen(m_name); int len_value = StringLen(m_value); if( FileWriteInteger(file_handle,len_name) != sizeof(int) || FileWriteString(file_handle, m_name, len_name) == 0 || FileWriteInteger(file_handle,len_value) != sizeof(int) || FileWriteString(file_handle, m_value, len_value) == 0 ) return false; return true; } virtual bool Load(const int file_handle) override{ if(file_handle==INVALID_HANDLE) return(false); m_name = FileReadString(file_handle, FileReadInteger(file_handle)); m_value = FileReadString(file_handle, FileReadInteger(file_handle)); return true; } }; //+------------------------------------------------------------------+ class VariableList : public CList { public: virtual CObject *CreateElement(void) { return new VariableData(); } }; //+------------------------------------------------------------------+ class PersistentVariables : public CObject { VariableList m_list; string m_file_name; public: PersistentVariables(string file_name):m_file_name(file_name){} VariableData *operator[](string name){ VariableData *vd = m_list.GetFirstNode(); for(;CheckPointer(vd); vd=vd.Next()) if(vd.name() == name) return vd; vd = new VariableData(name); m_list.Add(vd); return vd; } bool load(){ int h = FileOpen(m_file_name, FILE_READ|FILE_BIN); m_list.Clear(); bool res = m_list.Load(h); FileClose(h); return res; } bool save(){ int h = FileOpen(m_file_name, FILE_WRITE|FILE_BIN); bool res = m_list.Save(h); FileClose(h); return res; } }; //+------------------------------------------------------------------+ void OnStart() { PersistentVariables vars("saved_variables.bin"); int test_int = 444; double test_double = 44.4; string test_string = "Hello world!"; vars["test_int"] = test_int; vars["test_double"] = test_double; vars["test_string"] = test_string; if(vars.save()) Print("vars saved without errors."); if(vars.load()) Print("vars loaded without errors."); test_int = vars["test_int"].value<int>(); test_double = vars["test_double"].value<double>(); test_string = vars["test_string"].value<string>(); printf("results: int=%d, double=%.2f, string=%s", test_int, test_double, test_string); }
Here's a simple and efficient way to save/load variables.
Thank you so much.
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Thank you,
https://www.mql5.com/en/code/20842
https://www.mql5.com/en/docs/globals