Generate code in 3 minutes
Enter your idea and AI generates runnable code.
To save the state of your Expert Advisor (EA) so that data persists across terminal restarts, timeframe changes, or re-initializations, the most efficient method in MQL4 is using Global Variables of the Client Terminal.
These variables are stored on your hard drive by the MetaTrader 4 terminal and remain available until they are explicitly deleted or expire (after 4 weeks of no access).
This method is best for saving integers or floating-point numbers, such as a "Strategy Step", "Trade Counter", or "Last Order Ticket".
Here is a complete, robust implementation. It generates a unique name for the variable based on the Symbol and Magic Number to prevent conflicts if you run the EA on multiple charts.
//+------------------------------------------------------------------+
//| StatePreservation.mq4 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"
#property strict
//--- Input Parameters
input int MagicNumber = 12345;
//--- Global scope variables (internal to the EA)
int currentStep = 0;
int tradeCounter = 0;
//--- Helper variable to store the unique name
string gv_StepName;
string gv_CountName;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// 1. Create unique names for the Global Variables
// Format: EA_Name + Symbol + MagicNumber + VariableName
string prefix = "MyEA_" + Symbol() + "_" + IntegerToString(MagicNumber) + "_";
gv_StepName = prefix + "Step";
gv_CountName = prefix + "Counter";
// 2. Load the state from the terminal
LoadState();
Print("EA Initialized. Current Step: ", currentStep, " | Counter: ", tradeCounter);
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
// Optional: Save state on exit (though we usually save immediately on change)
SaveState();
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// --- SIMULATION OF STRATEGY LOGIC ---
// Example: Advance step logic
if(currentStep == 0)
{
// Do logic for step 0...
Print("Processing Step 0...");
// Move to next step and increment counter
currentStep = 1;
tradeCounter++;
// CRITICAL: Save state immediately after changing it
SaveState();
}
else if(currentStep == 1)
{
// Do logic for step 1...
Print("Processing Step 1...");
// Reset for demo purposes
currentStep = 0;
tradeCounter++;
SaveState();
}
}
//+------------------------------------------------------------------+
//| Custom Function: Save State to Terminal Global Variables |
//+------------------------------------------------------------------+
void SaveState()
{
// GlobalVariableSet creates the variable if it doesn't exist,
// or updates it if it does.
// Note: Global Variables only store type 'double'.
GlobalVariableSet(gv_StepName, (double)currentStep);
GlobalVariableSet(gv_CountName, (double)tradeCounter);
// Optional: Force flush to disk immediately (good for crash safety)
GlobalVariablesFlush();
}
//+------------------------------------------------------------------+
//| Custom Function: Load State from Terminal Global Variables |
//+------------------------------------------------------------------+
void LoadState()
{
// Check if the variable exists in the terminal
if(GlobalVariableCheck(gv_StepName))
{
// Retrieve and cast back to int
currentStep = (int)GlobalVariableGet(gv_StepName);
}
else
{
// If it doesn't exist (first run), initialize it
currentStep = 0;
GlobalVariableSet(gv_StepName, 0);
}
if(GlobalVariableCheck(gv_CountName))
{
tradeCounter = (int)GlobalVariableGet(gv_CountName);
}
else
{
tradeCounter = 0;
GlobalVariableSet(gv_CountName, 0);
}
}
//+------------------------------------------------------------------+
If you need to save arrays, strings, or complex structures (which Global Variables cannot handle), you should use binary files.
Here is how to save and load a custom structure containing your strategy state:
//+------------------------------------------------------------------+
//| Define a structure to hold your data |
//+------------------------------------------------------------------+
struct StrategyState
{
int currentStep;
int counter;
double lastPrice;
datetime lastTradeTime;
};
StrategyState myState;
string fileName = "MyEA_State_" + Symbol() + ".bin";
//+------------------------------------------------------------------+
//| Save State to File |
//+------------------------------------------------------------------+
void SaveStateToFile()
{
// Open file for writing (Binary mode)
int handle = FileOpen(fileName, FILE_WRITE|FILE_BIN);
if(handle != INVALID_HANDLE)
{
// Write the structure directly to the file
FileWriteStruct(handle, myState);
FileClose(handle);
}
else
{
Print("Error saving state: ", GetLastError());
}
}
//+------------------------------------------------------------------+
//| Load State from File |
//+------------------------------------------------------------------+
void LoadStateFromFile()
{
// Check if file exists
if(FileIsExist(fileName))
{
int handle = FileOpen(fileName, FILE_READ|FILE_BIN);
if(handle != INVALID_HANDLE)
{
// Read the data back into the structure
FileReadStruct(handle, myState);
FileClose(handle);
Print("State loaded. Step: ", myState.currentStep);
}
}
else
{
// Initialize defaults if file doesn't exist
myState.currentStep = 0;
myState.counter = 0;
}
}
Global Variables (Method 1):
double), limited to 63 characters for the name.File Operations (Method 2):
MQL4/Files folder.Q: Where can I see the Global Variables in the terminal?
A: Press F3 in MetaTrader 4, or go to Tools -> Global Variables. You will see your variables listed there with their current values.
Q: What happens if I change the Magic Number?
A: In the code provided in Method 1, the variable name includes the Magic Number. If you change it, the EA will treat it as a fresh instance and create new variables (starting from 0), preserving the state of the previous Magic Number separately.
Q: Do Global Variables survive a computer reboot?
A: Yes. MetaTrader 4 saves these variables to a file on your hard drive. They persist even if the computer is turned off.