Content:
How to get a license for free!
More →
Crypto exchange
Imagine this situation: you're sitting in front of your monitor, watching the chart, and you see the price breaking through an important level. You want to enter a trade, but you need to make a quick decision, set a stop-loss and take-profit. What if you stepped away for a cup of coffee and missed the move? What if, at night while you're sleeping, a strong movement occurs that could have brought you profit?
This is exactly what trading robots (expert advisors) are for. They tirelessly monitor the market 24/7, know no fatigue or emotions, and act strictly according to the program embedded in them. Today, we will take the first step into the world of algorithmic trading and thoroughly analyze a trading robot named VR Breakdown Level.
We won't just read the code. We will understand the logic of the strategy, see how it is implemented in the two most popular languages for the MetaTrader platform — MQL4 and MQL5 — and compare these implementations. Don't be afraid if you've never programmed before! The article is written to be understandable even for those opening a code editor for the first time. Let's go!
Before writing code, we need to clearly understand what we want from the robot. The name of the strategy speaks for itself: VR Breakdown Level means "Breakout Levels".
The strategy is based on the classic idea of technical analysis: if the price breaks the High or Low of the previous period, it is a signal for the movement to continue. The period can be anything: 1 hour, 4 hours, 1 day. This is configurable.
How it works (logic for beginners):
High).Low).That's the whole strategy! Simple as a sledgehammer, and that's its beauty. Now let's see what this sledgehammer looks like in code for two different versions of MetaTrader.
MQL4 is the language in which thousands of expert advisors have been written over the last 15+ years. It's a bit older and simpler in some aspects. Let's break down the code piece by piece.
At the very beginning of the code, we see a "header" with information about the author and version. These are just comments for us; the program ignores them.
The most interesting part begins with the keyword input. These are the expert advisor settings that the user will see in the properties window when starting it.
iLots — this is the size of the first trade.iTimeFrame — the very period we talked about. You can choose H1, H4, D1, etc.iTakeProfit and iStopLoss — distances to targets in points (pips).iMagicNumber — a very important thing! This is a unique ID for our robot. Imagine several advisors running on one account. To prevent them from interfering with each other's orders and closing each other's trades, each has its own magic number. The robot only touches orders where this number matches its settings.Here we declare variables that will be visible in all functions of the robot.
lt — we will store the lot volume here, adjusted to the broker's requirements (more on this later).level_up and level_dw — our main characters. The breakout level prices will be stored here. They are zero until a new bar appears.OnInit() FunctionThis function is executed once, when we first attach the robot to the chart.
What's happening here? We are checking if we can trade with the volume entered by the user. Brokers often only allow trading in specific lot fractions (e.g., step 0.01). If the user entered 0.05, but the step is 0.03, we need to round to 0.03 or 0.06? The code adjusts the volume to the correct value. If, after rounding, the volume is less than the minimum allowed, we set lt to zero to prevent the robot from opening trades with an error.
OnTick() FunctionThis is the main function. It is called on every new tick (every slightest price change).
Step 1: Checking for a new bar
We call our own function NewBar(), which is written below. If it returns true (a new bar has appeared), we update our levels. iHigh(..., 1) is a standard MQL4 function that takes the High price of the bar with index 1, i.e., the previous (just closed) bar.
Step 2: Getting current prices
ASK — the price at which we can buy (it's always slightly above the market price).BID — the price at which we can sell (it's always slightly below the market price).Step 3: Checking conditions and opening trades
If the current ask price is greater than or equal to our upper level, and the level itself is not zero (we just updated it), then...
...we send a market order to buy! The OrderSend function is the "grandmother" of all trading functions in MQL4.
— immediately after opening, we reset the level to prevent further entries.
The logic is mirrored. If bid <= level_dw, we send an OP_SELL order.
Step 4: Managing stops for open positions
The most complex part of the MQL4 code. Here we loop through all open orders (for loop), look for "ours" (by symbol and magic number), and if necessary, modify their stop losses and take profits.
OrderSelect — a function that selects an order to work with.OrderModify — a function for changing order parameters (stop and take profit).The NewBar() Function
A simple yet ingenious function for detecting a new bar. It remembers the opening time of the current bar in the variable old_time. On the next tick, it compares the new time with the old one. If they differ, a new bar has appeared!
The CheckSL_TP Function
This function is a "checker". Brokers do not allow setting a stop-loss too close to the current price (there is usually a minimum distance, e.g., 20 points). This function checks if our new stop violates the broker's rules.
MQL5 is an evolution of the language. It's more powerful, stricter, but also a bit more complex for a beginner. The main difference is the shift from the concept of orders to the concept of positions. In MQL4, you could have pending orders and market orders "hanging" in the list. In MQL5, a market trade is a position that occupies a separate place in the positions list.
Because of this, special libraries (classes) appeared to simplify the programmer's life. Let's look at them.
At the very beginning, we see #include lines. This is like asking for help from senior comrades.
CTrade trade; — we create an object trade, which is an expert in executing trades. Instead of the long OrderSend() function, we simply say trade.Buy().CPositionInfo posit; — we create an object posit, which is an expert in getting information about open positions.The settings (input) look exactly the same as in MQL4. However, in OnInit(), we configure our new assistant trade.
We tell the trade object: "Remember our magic number" and "Here is the allowed slippage". This is very convenient: set it once and forget it.
OnTick() Function in MQL5The overall structure is the same, but the details have changed dramatically.
Step 1: Checking for a new bar and updating levels
Here, almost everything is the same, except the iHigh and iLow functions now require two colons :: before them. This means we are calling the "global" function of the language, not some other one.
Step 2: Opening trades
Now, this is the most beautiful difference!
We simply call the Buy method of our trade object and pass only the volume. That's it! The trade object knows the Ask price itself, remembers the magic number, and knows the slippage. This is incredibly elegant and concise.
— and we reset the level.
— analogously.
Step 3: Managing stops for open positions
Instead of looping through orders, we loop through positions (::PositionsTotal()). And we use our posit object to get information about each position.
Notice: for modification, we again use the trade object, calling its PositionModify method. It's all logical: posit for information, trade for actions.
We've analyzed two pieces of code that do the same thing. But how do they differ? Let's create a comparison table to clearly see the difference.
| Criterion | MQL4 | MQL5 |
|---|---|---|
| Main Approach | Procedural. All operations are done through functions (OrderSend, OrderSelect). |
Object-oriented. Helper classes are used (CTrade, CPositionInfo). |
| Opening a Trade | Long OrderSend function with many parameters. |
trade.Buy(volume). Concise and clear. |
| Trade Management | You constantly need to select an order (OrderSelect) before working with it. |
The position is selected once (posit.SelectByIndex), and we can directly query the posit object for its properties. |
| Code Readability | The code seems more "linear", but due to the abundance of functions, it can be confusing for a beginner. For example, to change a stop, you need to call OrderModify. |
The code is cleaner and more logical. posit handles data, trade handles actions. Easier to read and understand the programmer's intent. |
| Risk of Errors | Higher. Easy to mix up parameters in OrderSend or forget to call OrderSelect. |
Lower. Objects themselves monitor the correctness of calls. For example, trade.Buy() will automatically use the correct Ask price. |
| Relevance | Outdated. New platform features (e.g., order types) often appear only in MQL5. | Modern. This is the language of the future for MetaTrader 5. |
| Ease of Starting | Easier for a complete "zero" in programming, as it doesn't require understanding classes and objects. | Requires understanding the concept of objects (classes), but in the long run, it teaches you to write correct and beautiful code. |
The strategy description mentions an interesting point: "A similar way to implement the strategy is using pending orders BUY STOP and SELL STOP... The presence of pending orders shows the broker the prices at which we intend to enter the market. Using 'internal' levels hides this information from the broker."
What does this mean?
level_up and SELL STOP at the level_dw. If the price reaches the level, the order triggers. The downside is that the broker (or other market participants with access to the order book) can see these orders. Large players sometimes hunt for such clusters of stop orders, provoking false breakouts.Our code uses the second, more discreet approach. It's more complex to implement as it requires constant price monitoring in the OnTick() function, but it keeps our intentions hidden.
So, we've come a long way. We've analyzed a simple yet effective trading strategy based on level breakouts. We've seen how the same logic can be implemented in two different languages — MQL4 and modern MQL5.
What have we learned?
Why should you give it a try?
Writing your own robot is an incredibly exciting process. You're not just a trader; you become a creator. You can program any idea you have, any trading pattern you see on the chart. You can test your strategies on historical data (this is called backtesting) and instantly see if they are profitable or loss-making, without risking real money.
Start small. Copy the VR Breakdown Level code into MetaEditor (the built-in development environment in the MetaTrader terminal), compile it (press F7), and attach it to a chart on a demo account. Observe its work.
Change the settings: set the timeframe to H4, increase the stop-loss. See how the behavior changes. Then try changing something in the code. For example, add a condition so that the robot only opens a trade after two consecutive breakouts. Or make it close a trade not by take-profit, but by a reverse breakout.
Don't be afraid of errors! Error messages are not a punishment, but hints from the compiler that help you write correct code.
Programming trading robots is a blend of a trader's analytical thinking and a programmer's creativity. It's a fascinating journey that can not only automate your trading but also give you immense pleasure from the process of creating something of your own. Open the code editor and take the first step today! Your first trading robot is waiting for you.
Source codes of the trading strategy:
MetaTrader 4 : https://www.mql5.com/en/code/69562
MetaTrader 5 : https://www.mql5.com/en/code/69545
Telegram community
Comments