Introduction
In our last lesson, we explored the OnStart() event handler and established its role as the single entry point for an MQL5 script. You learned that OnStart() is a special, pre-defined function that MetaTrader runs once when you launch a script. This was your first step into understanding how code is structured and organized.
Today, we're going to take a major leap forward. Instead of only using functions provided by the system, you will learn how to build your own. This lesson focuses on defining custom functions that can accept input information, perform a specific task, and return a result. Mastering this skill is fundamental to programming, as it allows you to create modular, reusable, and much more readable code—an essential practice for building the sophisticated trading bots you're aiming for.
Why Create Your Own Functions?
Imagine you need to perform the same calculation—like figuring out the right lot size based on your risk—at several different points in your trading bot's logic. You could copy and paste the same lines of code over and over, but this is inefficient and prone to errors. If you need to update the calculation, you'd have to find and change every single copy.
A function solves this problem. You write the code for the calculation once, give it a name, and then you can "call" that function by its name whenever you need it. This principle is often called DRY (Don't Repeat Yourself).
A function is like a specialized machine in a factory. It takes in some raw materials (inputs), processes them according to a set of instructions, and produces a finished product (an output).

This "factory" concept makes our code cleaner, more organized, and easier to debug.
Understanding functions in MQL5 with applications - MQL5 Articles
This article provides an excellent overview of why functions are so important in programming.
Read the introductory section, starting from the beginning and ending just before "Function structure". Focus on the list of benefits, especially the DRY principle and how functions make code more readable.
The Anatomy of a Custom Function
To build our own function, we need to follow a specific syntax. Let's break down its structure.
// (1) (2) (3)
// return_type function_name(parameter_type parameter_name)
// {
// (4)
// // Function body: code to perform the task
//
// (5)
// return value;
// }
- Return Type: This declares what type of data the function will send back as its result (e.g.,
int,double,string). If the function performs an action but doesn't return a value, we use the keywordvoid. - Function Name: This is the unique name you give your function. It should be descriptive of what the function does (e.g.,
CalculateSpread,CheckForNewBar). - Parameters (Inputs): These are the variables that hold the input data your function needs to work. They are declared inside the parentheses
(), each with its own type and name. A function can have zero, one, or many parameters. - Function Body: The code that does the actual work is placed inside the curly braces
{}. returnStatement: This keyword sends the final result back to the part of the code that called the function. The type of the value youreturnmust match the Return Type you declared in step 1.
This structure might seem a bit abstract, so let's see it in action.
LEARN MQL5 TUTORIAL BASICS - 10 HOW TO CODE A SIMPLE CUSTOM FUNCTION
This video provides a very clear, step-by-step demonstration of creating a simple custom function in MQL5.
Watch how the presenter defines a new function. Pay close attention to these parts: Defining the function: Notice how he specifies the return type (int), the function name (DoubleTheValue), and the input parameter (int CounterValue). The function body and return: He writes the logic to double the input value and then uses the return keyword to send the result back. Testing the function: See how the Strategy Tester visually confirms that the function is working correctly on every tick.
Building a Practical Trading Function
Now, let's apply this to a task directly related to your goal of building a trading bot: calculating the correct position size (lot size) for a trade. This is a perfect task for a custom function because it involves a specific, repeatable calculation.
Our function will take two inputs:
- The percentage of our account we are willing to risk (
risk_percent). - The size of our stop loss in pips (
stop_loss_pips).
It will then calculate and return the appropriate lot size as a double.
The article below contains a complete script for this, but we will focus only on building and understanding the function itself.
Understanding functions in MQL5 with applications - MQL5 Articles
This article includes a practical example of a lot size calculator. We will use it as a guide to build our own.
Find the section titled "Lotsize calc App". We are interested in the first function defined, OptimalLotSize. Read through the code and the author's explanation of each step, from getting account equity to the final lot size calculation. Don't worry about the second "overloading" function for now; we are focusing on the primary one.
Let's create this function together. Open MetaEditor and create a new script named LotSizeCalculator.
First, define the function signature. It needs to return a double (the lot size) and accept two double parameters for risk and stop loss. Place this code below the OnStart() function's closing brace }.
double CalculateLotSize(double riskPercent, double stopLossPips)
{
// Calculation logic will go here
}
Next, let's add the logic inside the function body. The calculation involves a few steps:
- Get the current account balance.
- Calculate the risk amount in your account's currency.
- Calculate the value of 1 pip for a full lot.
- Calculate the total value of the stop loss in currency.
- Finally, determine the lot size.
Here is the complete function. Add this code inside the CalculateLotSize function you just created.
double CalculateLotSize(double riskPercent, double stopLossPips)
{
// 1. Get account balance
double accountBalance = AccountInfoDouble(ACCOUNT_EQUITY);
// 2. Calculate risk amount in account currency
double riskAmount = accountBalance * (riskPercent / 100.0);
// 3. Get the value of one tick and the tick size
double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
double tickSize = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_SIZE);
// If tick_size is zero, we can't divide by it. Return 0 to be safe.
if(tickSize == 0) return 0.0;
// 4. Calculate the value of the stop loss for one lot
double stopLossValue = stopLossPips * (tickValue / tickSize);
// If stop_loss_value is zero, we can't divide by it.
if(stopLossValue == 0) return 0.0;
// 5. Calculate the final lot size
double lotSize = riskAmount / stopLossValue;
// We should also normalize the lot size to broker rules, but for now, we'll just return it.
return lotSize;
}
Note: AccountInfoDouble and SymbolInfoDouble are powerful built-in MQL5 functions for retrieving market and account data. We will cover them in detail in a future module.
Calling Your Custom Function
Now that you've defined your function, you can use it. Go back up to your OnStart() function and add the following code inside its curly braces {}. This code will call your new CalculateLotSize function with a 1% risk and a 20-pip stop loss, then print the result.
void OnStart()
{
// --- Call our custom function ---
// Risk 1% of the account, with a 20 pip stop loss
double myLotSize = CalculateLotSize(1.0, 20.0);
// --- Print the result ---
// The 'DoubleToString' function helps format the number nicely for printing
Print("Calculated Lot Size: ", DoubleToString(myLotSize, 2));
}
Now, compile your script (F7) and run it on a chart in MetaTrader. Check the "Experts" tab. You should see the calculated lot size printed out, based on your demo account's balance and the current symbol's properties. You have successfully created a reusable tool for your trading arsenal!
Conclusion
In this lesson, we moved beyond using only system-defined functions and learned how to create our own. This is a massive step in your journey as a programmer.
Key Takeaways:
- Custom functions are reusable blocks of code that perform a specific task, helping you adhere to the DRY (Don't Repeat Yourself) principle.
- A function is defined with a return type, a unique name, and optional input parameters.
- The logic of the function resides in its body, enclosed in curly braces
{}. - The
returnkeyword is used to send a value back from the function to the code that called it. - You can create practical, trading-related tools, like a
CalculateLotSizefunction, to make your code more modular and powerful.
You are now equipped to break down complex problems into smaller, manageable pieces. In our next lesson, we will explore an important concept related to functions: the difference between local and global variables, which governs where your data can be accessed within your program.