Problem Description
Solution
To check if you have enough free margin to open a specific trade in MQL4, you should use the built-in function AccountFreeMarginCheck.
This function calculates the free margin that would remain after a specified order is opened. If the return value is greater than zero, you have sufficient funds. If it is less than or equal to zero, or if GetLastError() returns 134 (ERR_NOT_ENOUGH_MONEY), the trade cannot be placed.
Implementation
Here is a robust, reusable function and an example of how to implement it within an Expert Advisor.
//+------------------------------------------------------------------+
//| MarginCheck.mq4 |
//| Copyright 2023, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property strict
//+------------------------------------------------------------------+
//| Function to check if margin is sufficient for a specific trade |
//+------------------------------------------------------------------+
bool IsMarginSufficient(string symbol, int cmd, double volume)
{
// Reset the last error code before the check
ResetLastError();
// AccountFreeMarginCheck returns the free margin that remains AFTER the trade
double remainingMargin = AccountFreeMarginCheck(symbol, cmd, volume);
// Check for specific error code 134 (ERR_NOT_ENOUGH_MONEY)
if(GetLastError() == 134)
{
Print("Error: Not enough money to open trade.");
return(false);
}
// If the remaining margin is negative or zero, we cannot open the trade
if(remainingMargin <= 0)
{
Print("Margin Check Failed: Resulting free margin would be ", remainingMargin);
return(false);
}
// If we passed checks, margin is sufficient
return(true);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Example parameters
double lots = 0.1;
int orderType = OP_BUY;
// --- LOGIC FLOW ---
// 1. Check Margin BEFORE sending the order
if(IsMarginSufficient(Symbol(), orderType, lots))
{
// 2. If sufficient, proceed to send order
int ticket = OrderSend(Symbol(), orderType, lots, Ask, 3, 0, 0, "Margin Checked", 0, 0, clrGreen);
if(ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
else
{
Print("Order opened successfully. Ticket: ", ticket);
}
}
else
{
Print("Trade aborted due to insufficient margin.");
}
}
Key Functions Used
-
AccountFreeMarginCheck(symbol, cmd, volume):- symbol: The asset you want to trade (e.g.,
Symbol()or "EURUSD"). - cmd: The operation type (
OP_BUYorOP_SELL). This is important because margin requirements may differ for different directions depending on the broker's hedging settings. - volume: The lot size you intend to trade.
- Return: Returns the amount of free margin that will remain after the trade.
- symbol: The asset you want to trade (e.g.,
-
GetLastError():- It is crucial to check this immediately after
AccountFreeMarginCheck. Even if the function returns a value, the system might flag error 134 (ERR_NOT_ENOUGH_MONEY), indicating the calculation failed due to lack of funds.
- It is crucial to check this immediately after
Why this is important
Using OrderSend without checking margin first will result in the trade server rejecting the request. This generates error logs, wastes network resources, and can cause logic loops in poorly coded EAs that keep retrying a failed trade.
Q&A
Q: Does AccountFreeMarginCheck account for the spread?
A: It calculates the margin required based on the current price. While it doesn't explicitly "subtract" the spread cost from the balance immediately (as spread is realized PnL), it ensures you have the required collateral to open the position.
Q: Can I use AccountFreeMargin() instead?
A: AccountFreeMargin() only tells you what you have now. It does not calculate how much the new trade will cost. You would have to manually calculate the margin cost using MarketInfo(Symbol(), MODE_MARGINREQUIRED) and subtract it, which is more complex and prone to calculation errors compared to using AccountFreeMarginCheck.
Q: Does this work for pending orders?
A: Yes, you can pass OP_BUYLIMIT, OP_SELLSTOP, etc., into the cmd parameter, though usually, the margin check is most critical for immediate market execution (OP_BUY / OP_SELL).