Problem Description
Solution
To create a separate file for common functions in MQL4, the standard approach is to use Include files (extension .mqh).
This method allows you to write your logic once and import it into any Expert Advisor (EA), Script, or Indicator. When you compile the EA, the compiler takes the code from the .mqh file and inserts it into the EA, creating a single executable.
Here is the step-by-step implementation.
Step 1: Create the Include File (.mqh)
- Open MetaEditor.
- In the Navigator, right-click the Include folder and select New File.
- Select Include (*.mqh), click Next, name it
MyCommonLib, and click Finish. - Paste the following code. This library contains a function to handle 4/5 digit brokers and a risk-based lot size calculator.
File Path: MQL4\Include\MyCommonLib.mqh
//+------------------------------------------------------------------+
//| MyCommonLib.mqh |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Your Name"
#property link "https://www.yourwebsite.com"
#property strict
//+------------------------------------------------------------------+
//| Helper: Adjust points for 3/5 digit brokers |
//+------------------------------------------------------------------+
double GetPipMultiplier()
{
if(Digits == 3 || Digits == 5) return(10.0);
return(1.0);
}
//+------------------------------------------------------------------+
//| Common: Calculate Lot Size based on Risk Percentage |
//+------------------------------------------------------------------+
double CalculateRiskLots(double riskPercent, double stopLossPips)
{
// Prevent division by zero
if(stopLossPips <= 0)
{
Print("Error: StopLoss is 0, cannot calculate risk.");
return(0.0);
}
double accountEquity = AccountEquity();
double riskAmount = accountEquity * (riskPercent / 100.0);
double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
// Adjust tick value if it returns 0 (rare server error protection)
if(tickValue == 0) tickValue = Point;
// Calculate raw lot size
// Formula: Risk / (SL_Points * TickValue)
// Note: We convert pips to points using the multiplier
double points = stopLossPips * GetPipMultiplier();
double lotSize = riskAmount / (points * tickValue);
// Normalize to broker's step requirements
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double step = MarketInfo(Symbol(), MODE_LOTSTEP);
// Round down to nearest step
lotSize = MathFloor(lotSize / step) * step;
// Cap limits
if(lotSize < minLot) lotSize = minLot;
if(lotSize > maxLot) lotSize = maxLot;
return(lotSize);
}
//+------------------------------------------------------------------+
//| Common: Print formatted error message |
//+------------------------------------------------------------------+
void LogError(string functionName, string message)
{
int err = GetLastError();
if(err > 0)
{
PrintFormat("Error in %s: %s | Code: %d", functionName, message, err);
}
else
{
PrintFormat("Log %s: %s", functionName, message);
}
}
Step 2: Use the Include File in an EA
To use the functions created above, you must use the #include directive at the top of your Expert Advisor.
File Path: MQL4\Experts\MyTradingRobot.mq4
//+------------------------------------------------------------------+
//| MyTradingRobot.mq4 |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, Your Name"
#property link "https://www.yourwebsite.com"
#property version "1.00"
#property strict
// --- IMPORT THE COMMON LIBRARY ---
// The < > brackets tell the compiler to look in the MQL4/Include folder
#include <MyCommonLib.mqh>
// --- Inputs ---
input double RiskPerTrade = 2.0; // Risk in %
input int StopLossPips = 50; // Stop Loss in Pips
input int MagicNumber = 123456;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
// We can use functions from the library immediately
LogError("OnInit", "EA Initialized successfully.");
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
// Example logic: Open a trade if no orders exist
if(OrdersTotal() == 0)
{
// 1. Use the library function to calculate lots
double lots = CalculateRiskLots(RiskPerTrade, StopLossPips);
// 2. Use the library function to get point multiplier for SL calculation
double pipMult = GetPipMultiplier();
double slPrice = Ask - (StopLossPips * Point * pipMult);
double tpPrice = Ask + (StopLossPips * Point * pipMult); // 1:1 RR
// Send Order
int ticket = OrderSend(Symbol(), OP_BUY, lots, Ask, 3, slPrice, tpPrice, "My Trade", MagicNumber, 0, clrGreen);
if(ticket < 0)
{
// 3. Use the library function to log errors
LogError("OnTick", "OrderSend failed");
}
else
{
Print("Buy Order Opened. Ticket: ", ticket, " Lots: ", lots);
}
}
}
Key Mechanics Explained
#include <Filename.mqh>:- Using angle brackets
< >tells the compiler to look specifically in theMQL4\Include\directory. - Using quotes
"Filename.mqh"tells the compiler to look in the same folder as the current source file (e.g.,MQL4\Experts\).
- Using angle brackets
- Compilation: When you compile
MyTradingRobot.mq4, the compiler literally copies the text fromMyCommonLib.mqhand pastes it into the EA code in memory before generating the.ex4file. You do not need to send the.mqhfile to other users; only the compiled.ex4EA file is required for trading. - Organization: You can create subfolders. If you save your file in
MQL4\Include\MyStrategies\Risk.mqh, you would import it like this:
#include <MyStrategies\Risk.mqh>
Q&A
Q: Can I include multiple .mqh files in one EA?
A: Yes, you can include as many files as you need. It is common practice to have separate files for RiskManagement.mqh, SignalLogic.mqh, and OrderExecution.mqh.
Q: What happens if I declare a variable with the same name in the EA and the .mqh file?
A: This will cause a compilation error (variable redefinition) or a warning (variable hiding), depending on the scope. It is best practice to prefix global variables in your library (e.g., Lib_RiskPercent) or encapsulate your library code inside a class to avoid naming conflicts.
Q: Do I need to recompile the .mqh file if I change it?
A: No, you cannot compile an .mqh file directly. However, after modifying an .mqh file, you must recompile every EA that uses it for the changes to take effect in those EAs.
Q: Can I use .ex4 libraries instead of .mqh files?
A: Yes, using #import. However, .ex4 libraries are harder to maintain because you must define the function headers in every EA that uses them. .mqh files are generally preferred for internal code reuse because the compiler can optimize the code better.