Inserted Code
//+------------------------------------------------------------------+
//| MQL4 Expert Advisor Learning Module: Diagnosing and Fixing Error 134 |
//+------------------------------------------------------------------+
// Part 1: The Concept - What is Error 134?
/*
Error 134 in MQL4, defined as ERR_TRADE_NOT_ENOUGH_MONEY, occurs when an Expert Advisor (EA) attempts to open a trade but the account lacks sufficient free margin to cover the required margin for the position. This error is logged as, for example, "SendNewOrder::doAction Connot Send Order, error: 134," indicating that the trade request was rejected due to insufficient funds. In the MetaTrader 4 (MT4) environment, free margin is the portion of account equity not currently tied up in open positions, and this error signals that the available free margin is less than what the trade requires.
*/
// Part 2: The "Why" - Diagnosing the Root Causes
/*
Several scenarios can lead to Error 134:
- **Insufficient Free Margin**: The account's free margin is less than the margin required to open the new position. Free margin is calculated as AccountEquity() - AccountMargin(), representing the funds available for new trades.
- **Incorrect Lot Size Calculation**: If the EA uses a fixed or incorrectly calculated lot size that exceeds the account's capacity, it will trigger Error 134. For example, attempting to open a 1-lot trade on a $1,000 account with 1:100 leverage may require $1,000 margin, which could exceed available funds.
- **Leverage Impact**: Leverage determines the margin required per lot. For instance, with 1:100 leverage, a 1-lot trade on EURUSD (100,000 units) typically requires $1,000 margin in the account currency. Lower leverage (e.g., 1:50) doubles the margin requirement, increasing the likelihood of Error 134.
- **Dynamic Spreads & Slippage**: While spreads don’t directly affect margin requirements in standard forex trading, sudden spread widening during volatile market conditions can lead to execution issues, though this is less directly tied to Error 134.
- **Multiple Open Trades**: Each open position consumes margin, reducing the free margin available for new trades. If an EA opens multiple positions without accounting for cumulative margin use, it may exhaust the free margin, causing Error 134.
Understanding these causes is critical for diagnosing and preventing the error in your EA.
*/
// Part 3: The "How" - Proactive Solutions and Code
// Section 3.1: Calculating Required Margin
/*
The following function calculates the margin required for a trade on a given symbol with a specified lot size. It uses MarketInfo(symbol, MODE_MARGINREQUIRED) to obtain the margin needed for one lot and scales it by the desired lot size.
*/
double GetRequiredMargin(string symbol, double lots)
{
double margin_per_lot = MarketInfo(symbol, MODE_MARGINREQUIRED);
if (margin_per_lot == 0)
{
Print("Failed to get MODE_MARGINREQUIRED for ", symbol);
return -1; // Indicate an error
}
return margin_per_lot * lots;
}
// Section 3.2: Implementing the Safeguard
/*
To prevent Error 134, check the available margin before sending a trade order. MQL4 provides two effective methods:
1. **Using AccountFreeMarginCheck()**: This built-in function returns the free margin that would remain after opening a specified position. A positive value indicates sufficient margin to proceed with the trade.
Example usage:
*/
void CheckMarginWithFreeMarginCheck(string symbol, int cmd, double lots)
{
double free_margin_after = AccountFreeMarginCheck(symbol, cmd, lots);
if (free_margin_after > 0)
{
Print("Sufficient margin available. Free margin after trade: ", free_margin_after);
// Proceed with OrderSend
}
else
{
Print("Insufficient margin. Free margin after trade would be: ", free_margin_after);
}
}
/*
2. **Manual Margin Calculation**: Use the GetRequiredMargin() function to calculate the required margin and compare it with AccountFreeMargin().
Example usage:
*/
void CheckMarginManually(string symbol, double lots)
{
double required_margin = GetRequiredMargin(symbol, lots);
if (required_margin > 0 && AccountFreeMargin() > required_margin)
{
Print("Sufficient margin. Required: ", required_margin, " Available: ", AccountFreeMargin());
// Proceed with OrderSend
}
else
{
if (required_margin <= 0)
Print("Failed to calculate required margin for ", symbol);
else
Print("Insufficient margin. Required: ", required_margin, " Available: ", AccountFreeMargin());
}
}
// Section 3.3: Practical Code Transformation
/*
Below are "Before" and "After" code examples demonstrating how to transform a vulnerable EA into a robust one by incorporating margin checks.
**Before (Vulnerable Code)**:
This code attempts to open a buy order without checking available margin, risking Error 134.
*/
void VulnerableTradeExample()
{
double lots = 0.1;
string symbol = Symbol();
double ask = MarketInfo(symbol, MODE_ASK);
int ticket = OrderSend(symbol, OP_BUY, lots, ask, 3, 0, 0, "My EA", 0, 0, clrGreen);
if (ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
}
/*
**After (Robust Code with AccountFreeMarginCheck)**:
This version checks the margin using AccountFreeMarginCheck() before sending the order, preventing Error 134.
*/
void RobustTradeExampleWithFreeMarginCheck()
{
double lots = 0.1;
string symbol = Symbol();
double ask = MarketInfo(symbol, MODE_ASK);
int cmd = OP_BUY;
double free_margin_after = AccountFreeMarginCheck(symbol, cmd, lots);
if (free_margin_after > 0)
{
int ticket = OrderSend(symbol, cmd, lots, ask, 3, 0, 0, "My EA", 0, 0, clrGreen);
if (ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
else
{
Print("Trade opened successfully. Ticket: ", ticket);
}
}
else
{
Print("Not enough margin to open position. Free margin after trade would be: ", free_margin_after);
}
}
/*
**After (Robust Code with Manual Margin Calculation)**:
This version uses GetRequiredMargin() to calculate the required margin and compares it with AccountFreeMargin().
*/
void RobustTradeExampleWithManualCheck()
{
double lots = 0.1;
string symbol = Symbol();
double ask = MarketInfo(symbol, MODE_ASK);
int cmd = OP_BUY;
double required_margin = GetRequiredMargin(symbol, lots);
if (required_margin > 0 && AccountFreeMargin() > required_margin)
{
int ticket = OrderSend(symbol, cmd, lots, ask, 3, 0, 0, "My EA", 0, 0, clrGreen);
if (ticket < 0)
{
Print("OrderSend failed with error #", GetLastError());
}
else
{
Print("Trade opened successfully. Ticket: ", ticket);
}
}
else
{
if (required_margin <= 0)
Print("Failed to calculate required margin for ", symbol);
else
Print("Not enough margin. Required: ", required_margin, " Available: ", AccountFreeMargin());
}
}
// Part 4: Conclusion - Best Practices for Robust EAs
/*
To build reliable EAs that avoid Error 134, always perform pre-trade margin checks using either AccountFreeMarginCheck() or manual calculations with GetRequiredMargin(). These checks ensure that the EA only attempts trades within the account’s financial capacity, enhancing stability and preventing trade failures. Optionally, consider adding a margin buffer (e.g., requiring AccountFreeMarginCheck() > 100) to account for market volatility or spread changes, though this is typically unnecessary for standard forex trading. The key lesson is to "check before you trade," ensuring your EA operates robustly under varying market and account conditions.
For further reading, refer to the MQL4 documentation:
- AccountFreeMarginCheck: https://docs.mql4.com/account/accountfreemargincheck
- MarketInfo: https://docs.mql4.com/marketinformation/marketinfo
- Error Codes: https://docs.mql4.com/constants/errorswarnings/errorcodes
*/
// Example OnStart function to demonstrate usage
void OnStart()
{
// Example: Attempt to open a buy order with margin checks
Print("Testing Vulnerable Trade Example:");
VulnerableTradeExample();
Print("\nTesting Robust Trade Example with AccountFreeMarginCheck:");
RobustTradeExampleWithFreeMarginCheck();
Print("\nTesting Robust Trade Example with Manual Margin Check:");
RobustTradeExampleWithManualCheck();
}