MQL4 Price Data: Open, High, Low, Close
Investing in assets such as stocks, bonds, cryptocurrencies, futures, options, and CFDs involves considerable risks. CFDs are especially risky with 74-89% of retail accounts losing money due to high leverage and complexity. Cryptocurrencies and options exhibit extreme volatility, while futures can also lead to significant losses. Even stocks and bonds can depreciate quickly during market downturns, and total loss can ensure if the issuing company fails. Furthermore, the stability of your broker matters; in case of bankruptcy, the presence of an effective investor compensation scheme is crucial for protecting your assets. It's vital to align these investments with your financial goals and if needed, consult with financial professionals to navigate complex financial markets.
We earn commissions from some affiliate partners at no extra cost to users (partners are listed on our ‘About Us’ page in the ‘Partners’ section). Despite these affiliations, our content remains unbiased and independent. We generate revenue through banner advertising and affiliate partnerships, which do not influence our impartial reviews or content integrity. Our editorial and marketing teams operate independently, ensuring the accuracy and objectivity of our financial insights.
Data is continually updated by our staff and systems.
Last updated: 14/04/2020
Often when developing an EA you will work with bar price data of a particular bar. Learn in this complete MQL4 Price Data article how to code a fully functioning Expert Advisor using the four levels of price data, Open, High, Low, Close, to help you program your trading EA.
Level | Price Data Constants / Functions | Functionality |
---|---|---|
1 | High, Low, Open, Close, also: Bid, Ask | The simplest level. The price data refers to the current data price of the chart symbol, chart time frame, and current bar. |
2 | High[], Low[], Open[], Close[] | The next level above. The price data refers to the current data price of the chat symbol, chart time frame, but it is more flexible as to which historical bar it can refer to. The number in brackets refers to the historical bar it can refer to. Example: Close[0] = close of current bar, Close[1] = close of previous bar. |
3 | iHigh(), iLow(), iOpen(),iClose() | A very flexible level of functionality. The price data function refers to the price data of a customizable symbol and/or time frame and/or historical bar. Example #1: iClose(NULL,0,0) = close of chart symbol, time frame, current bar. Note: this use of it differs little from Close or Bid or even iClose[0]. Example #2: iClose (“EURUSD”,30,1) = close of EURUSD symbol, of 30 minute time frame, of previous bar. Note: this use of it is a threefold increase in functionality than the previous price data functions. |
4 | iHighest(), iLowest(), | Price data function to find the maximum price data values over a period range. Good for finding the highest or lowest data values of a specific range. Example: Low[iLowest(Symbol(), 0, MODE_LOW, 3, 1)] = lowest bar of the last three bars. |
Let us go over each of these four levels of price data.
Level 1 Price Data: The Price Data Limited to the Chart Symbol, Chart Time Frame and Current Bar.
If you simply want to refer to the price data of the current bar of the current chart and time frame, you can use any of the following price data methods: High, Low, Open, Close, Bid, Ask.
Keep in mind all must have an initial capital letter to be read by the program (Bid is valid, bid is not). If you want to refer to the current close price, you can use Close, but you can also use Bid, because the MT4 closing prices are defaulted as Bid prices. For instance, if you wanted your EA to look for a condition whereby the current closing price must be greater than the 200 period moving average, you can state it with:
or, alternatively, as:
Note: Keep in mind that this simple level of price data can only be used for the chart symbol, chart time frame, and current bar. If you want to have the flexibility of working with different bars, you must turn to level 2 or level 3 price data. If you want to have the flexibility of working with different chart symbols, or different time frames, as well as different bars, you must work with level 3 price data.
Level 2 Price Data: The Price Data Flexible Enough to Work with Different Bars
If you want to work with price data for the current chart, but you want to be in control of the bar you are referring to, you can use the predefined series arrays: High[], Low[], Open[], and Close[].
An array is a variable that stores multiple values. They act like the list tables, wherein you can group items in the table and access them by row number, called Indexes. The numbered rows or indexes start from from 0, then proceed to 1, 2, 3 etc. These numbered indexes are contained in the brackets, and in the particular case above, each numbered index refers to a particular bar in time and changing the number changes the bar in time you want to refer to. For example, Close [0] is the open price of the current bar, where 0 is the index, and by changing it, we can get the close price of other bars: Close [1] refers to the bar previous to the current bar, Close [2] refers to the bar 2 bars back from the current, etc.
In most of the EAs we create we will be using either the current bar or the previous bar’s price values. However, if you desire even greater flexibility of working with price data of not only different historical bars, but also different symbols other than your current chart, or different time frames other than your current chart, then you must turn to level 3 Price data.
Level 3 Price Data: The Most Flexible Price Data using a Function that Works with Customizable Symbols, Customizable Time Frames, and Customizable Historical Bars.
If you want to work with price data (high, low, open, close) for a symbol other than the current chart, or if you need price data for a period other than the current chart period, you can use the following price data functions: iHigh(), iLow(), iOpen(), and iClose(). These will give you the price data value over a single period or bar.
The table below illustrates the syntax of the iClose() function:
Parameters | Description |
---|---|
Symbol | The Symbol of the currency pair in use |
Timeframe | Timeframe. Can be any Timeframe enumeration values.Choose (0) to display the current timeframe displayed on OR choose one of the following: (1, 5, 15, 30, 60, 240, 1440, 10080, 43200) {all in MINUTES} |
Shift | The backward shift, relative to current bar |
For instance, say for instance you have open a 1 hour chart but you want to check the close of the price of the previous bar on a daily chart.
Here is yesterday’s highest high and lowest low sample:
double low = iLow(NULL, PERIOD_D1, 1);
The Parameters signify:
- NULL = current chart symbol.
- PERIOD_D1 = D1 or daily chart period, also could be 1440.
- 1 = shift, 1 standing for previous bar.
Note: The iHigh() and iLow() functions gives you the shift of the maximum value of a single bar. If you want the shift of the maximum value over a range of bars, you must use the iHighest() and iLowest() functions, discussed further below.
Timeframe Enumeration Table
There are two ways to put in time frames: one by period constants and one by integer values, as in the example below.
double high = iClose (NULL, 1440,1);
You see that PERIOD_D1 can be substituted with 1440 — the minutes comprising the day period.
Here is a full table of the constant values and their integer equivalents:
Constant | Value | Description |
---|---|---|
PERIOD_M1 | 1 | 1 minute |
PERIOD_M5 | 5 | 5 minutes |
PERIOD_M30 | 30 | 30 minute |
PERIOD_H1 | 60 | 1 hour |
PERIOD_H4 | 240 | 4 hour |
PERIOD_D1 | 1440 | Daily |
PERIOD_W1 | 10080 | Weekly |
PERIOD_MN1 | 43200 | Monthly |
0 (zero) | 0 | Timeframe of chart |
These minute value substitutions are easy enough to remember, and once memorized, I find them easier to type into their designated parameter box than constants. I also find that these integers can be more readily used with extern variables. For instance, what if we wanted to refer to a previous Close different from our own H1 chart but we did not know exactly which time frame to use. We can then can construct the timeframe parameter as an extern variable, as in the example below:
// put in extern variables section
extern int TimeFrame = 30;
// placed somewhere within your code
double PreviousClose = iClose (NULL, TimeFrame, 1);
TimeFrame is my identifier that refers to the timeframe parameter, and my default value is 30, which refers to the previous M30 bar. I know it is the previous bar because I put in a 1 in the shift parameter. If I want to refer to a current M5 close, I simply put in 5 in the second parameter, and if I wanted to refer to the current bar I simply put in 0 in the third parameter.
Now you have an easy way of making your EA reference multiple time frames, and you can even set the strategy tester to optimize between the timeframes if you so wanted.
Alternative Currency Substitution Methodology
What is cool is that, not only can you easily reference multiple time frames, you can also easily reference multiple currency pairs. NULL stands for the symbol of the current chart, but it can be replaced with any currency symbol, even the currency outside the EA’s own chart. To do so is simple: you just replace NULL with the symbol you want to use (it must appear in your market window) and wrap it in quotation markets.
Sample if you wanted to reference EURUSD symbol:
Moreover, you have the flexibility of constructing an extern variable for this parameter, as in the example below:
// put in extern variables section
extern string CurrencyName = “EURUSD”;
extern int TimeFrame = 30;
// placed somewhere within your code
double PreviousClose = iClose (CurrencyName, TimeFrame, 0);
As you can see we substituted NULL with an extern string variable, we identified as CurrencyName, and we defaulted to “EURUSD” (though it could be any currency pair that you can see in your market window, so long as you put it within quotation marks). Also note that all currency names that you want to attach to an extern variable must use the extern string variable.
Why would you need to refer to a currency pair that is not the same as your chart?
I can think of many reasons, but the foremost that comes to mind is when you are trading by means of correlation. For instance, suppose that you are trading the GBPUSD, but that you consider EURUSD as a leader currency for most of the majors, and thus you want to first check to see the trend direction of the EURUSD as a prior condition for opening up trades on the GBPUSD.
Level 4 Price Data: The Function that Works with Maximum Price Data Values Over Period Ranges
In addition to working with price data functions like iHigh() and iLow of a single period, there is the ability to work with price data functions of maximum value over a range of periods: iHighest() and iLowest(). With each of these functions, you can work with the h/l of a number of bars in a range.
These two functions have their own parameter set:
Parameters | Description |
---|---|
Symbol | The symbol used. NULL= current chart |
TimeFrame | Timeframe. It can be any timeframe innumeration. 0= current timeframe |
Type | Series array identifier. It can be any of the Series array identifier enumeration values |
Bar Count | Number of bars you want to test, in direction from the start bar to the back one on which the calculation is carried out. |
Start Bar | Shift showing the bar, relative to the current bar, that the data should be taken from. |
Series array identifier table:
Constant | Value | Description |
---|---|---|
MODE_OPEN | 0 | Open Price |
MODE_LOW | 1 | Low Price |
MODE_HIGH | 2 | High Price |
MODE_CLOSE | 3 | Close Price |
MODE_VOLUME | 4 | Volume, used in iLowest() and iHighest() functions. |
MODE_TIME | 5 | Bar open time, used in ArrayCopySeries() function. |
Note: It appears as if you have the option to use any Type above, but in general practice, you will be using MODE_HIGH with iHighest() and MODE_LOW with iLowest().
Sample of lowest low and highest high of the last 3 bars for a stop loss:
if(dir == OP_BUY)
{
stopLoss = Low[iLowest(Symbol(), 0, MODE_LOW, 3, 1)];
}else if(dir == OP_SELL)
{
stopLoss = High[iHighest(Symbol(), 0, MODE_HIGH, 3, 1)];
}
The above is a clever technique of using a different type of stop than the regular one.
What if you wanted to get the lowest value between bars 10 to 20?
// from the 10th to the 19th index inclusive on the current chart
double val=Low[iLowest(NULL,0,MODE_LOW,10,10)];