Today I am going to teach you how to code a simple indicator in MQL4 that plots a buy arrow when the high of the last bar is broken, and a sell arrow when the low of the last bar is broken. This indicator is the simplest of indicators that can be coded in Metatrader4.
Creating a new file
Let’s begin using the MetaEditor Wizard to create a new source code file with the basic structure already laid out for us. Using the wizard makes sure the structure of our indicator is correct.
-
- Create a new Indicator
- Select “Custom Indicator” from the wizard
- Set “Indicators\Indicator101” as name
- Select “OnCalculate(…,open, high, low, close)” and click [Next >]
- Ignore the next screen and click on [Finish]
- Create a new Indicator
The Metaeditor is opened and we are ready to code. The complete source code of our project is below. Feel free to copy and paste the code into the Editor, replacing all the generated code. The basic structure is the same as the generated one.
//---- File Properties #property copyright "Arthur Lopez" #property link "http://www.pointzero-trading.com" #property description "Sample indicator that plots breakout arrows." #property version "1.0" #property strict //---- Indicator drawing and buffers #property indicator_chart_window #property indicator_buffers 2 //---- Colors and sizes for buffers #property indicator_color1 clrDodgerBlue #property indicator_color2 clrTomato #property indicator_width1 2 #property indicator_width2 2 //---- Buffer Arrays double ExtMapBuffer1[]; double ExtMapBuffer2[]; //+------------------------------------------ //| Custom indicator initialization function //+------------------------------------------ int init() { // First buffer SetIndexBuffer(0, ExtMapBuffer1); // Assign buffer array SetIndexStyle(0, DRAW_ARROW); // Style to arrow SetIndexArrow(0, 233); // Arrow code //Second buffer SetIndexBuffer(1, ExtMapBuffer2); // Assign buffer array SetIndexStyle(1, DRAW_ARROW); // Style to arrow SetIndexArrow(1, 234); // Arrow code // Exit return(0); } //+------------------------------------- //| Custom indicator iteration function //+------------------------------------ int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { // Start and limit int start = 1; int limit; // Bars counted so far int counted_bars = IndicatorCounted(); // No more bars? if(counted_bars < 0) return(-1); // Do not check repeated bars limit = Bars - 1 - counted_bars; // Iterate bars from past to present for(int i = limit; i >= start; i--) { // If not enough data... if(i > Bars-2) continue; // Check buy signal if(Close[i] > High[i+1]) { ExtMapBuffer1[i] = Low[i]; } // Sell check signal if(Close[i] < Low[i+1]) { ExtMapBuffer2[i] = High[i]; } } // Exit return(rates_total); }
Now save the file and click on compile in MetaEditor. The compilation process will generate the indicator binary which we can load to the chart. Make sure the compilation raises no errors.
Now we are ready to load the indicator to the chart. The indicator will be listed in the Indicators menu in the Navigator. If the Navigator is hidden, go to View -> Navigator -> Indicators.
Load the Indicator101 Indicator to the chart, et voilà.
Understanding the indicator
The anatomy of our custom indicator is the following:
-
- The initial properties describe author, website, indicator description and indicator version, which are displayed in the indicator loading window.
- The buffer properties describe buffer number, colors and sizes.
- The OnInit() function is executed when the indicator loads. In this function, we define our buffer arrays and styles, which are later used to plot arrows on the chart.
- The OnCalculate() function is executed every tick. It iterates the bars in the chart and evaluates the entry strategy. If our conditions are met, it saves the signal on the buffer array, which causes the indicator to draw an arrow on the chart.
- Inside OnCalculate(), our code iterates bars from past to present and purposely ignores the unclosed bar to avoid repainting. The shift of the current bar is zero, and our loop ends at 1.
- A buffer is always linked to a previously defined array.
- The HLOC data is available in the OnCalculate() function as four arrays: High[…], Low[…], Open[…] and Close[…]. Other information is available to us such as Volume[…] and Time[…].
Making changes
Once the indicator is working, we can edit the buy/sell conditions to meet other, more complex criteria. For example, we can filter out breakouts which are preceded by a previous breakout in the same direction changing the OnCalculate(…) function like follows.
//+------------------------------------- //| Custom indicator iteration function //+------------------------------------- int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) { // Start and limit int start = 1; int limit; // Bars counted so far int counted_bars = IndicatorCounted(); // No more bars? if(counted_bars < 0) return(-1); // Do not check repeated bars limit = Bars - 1 - counted_bars; // Iterate bars from past to present for(int i = limit; i >= start; i--) { // If not enough data... if(i > Bars-3) continue; // Check buy signal and apply filter if(Close[i] > High[i+1] && !(Close[i+1] > High[i+2])) { ExtMapBuffer1[i] = Low[i]; } // Sell check signal and apply filter if(Close[i] < Low[i+1] && !(Close[i+1] < Low[i+2])) { ExtMapBuffer2[i] = High[i]; } } // Exit return(rates_total); }
Once edited, save the file, compile it again and load the indicator to the chart.
As you can see the result is very different: consecutive breakouts are no longer displayed and the trading frequency has decreased. We could keep adding conditions using HLOC data to find a particular price pattern that we’d like to trade, or read from custom indicators to apply a filter to our trades. The possibilities are almost endless.
I hope this served as an useful introduction to coding your own custom indicators. In the next post, I’ll teach you how to implement filters using native indicators applied to any timeframe.
Feel free to post your comments or questions below. Thank you.
Glad to see you writing tutorials 🙂 Well done!
Thanks Rimantas. You are the boss at that 😉 I wanted to do a larger post but let’s start small.
WOW this is great Arthur. Thank you!
OMG. This is very helpful! Thank you for this!
To you.
This is great initiative sir. Waiting for more. Thank you.
Thanks, Arun.
Great piece! One little issue. You said, “load” the indicator. But you didn’t describe how. I’m sure with some effort, I’ll find how. But it’ll complete this great tutorial.
Load an indicator by dragging it from the Navigator to the price chart.
@lopez.just a quick question…in term of editing the code.where can i find the time of signal”meaning is giving me late signals”just need to adjust it.
HI Mr. Arthur Lopez.. Do U – re-code & – Modify MT4 Indicators & – What’s the Cost??
Hi sir, please stoploss and takeprofit custom indicator simple cord for mql4 platform.