0% found this document useful (0 votes)
166 views39 pages

Indexing Direction in Arrays

coding in MQL4

Uploaded by

anto joseph
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
166 views39 pages

Indexing Direction in Arrays

coding in MQL4

Uploaded by

anto joseph
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as DOCX, PDF, TXT or read online on Scribd
You are on page 1/ 39

Indexing Direction in Arrays, Buffers and Timeseries

The default indexing of all arrays and indicator buffers is left to right. The index of the first
element is always equal to zero. Thus, the very first element of an array or indicator buffer
with index 0 is by default on the extreme left position, while the last element is on the
extreme right position.
An indicator buffer is a dynamic array of type double, whose size is managed by the client
terminals, so that it always corresponds to the number of bars the indicator is calculated on.
A usual dynamic array of type double is assigned as an indicator buffer using the
SetIndexBuffer() function. Indicator buffers do not require setting of their size using function
ArrayResize() - this will be done by the executing system of the terminal.
Timeseries are arrays with reverse indexing, i.e. the first element of a timeseries is in the
extreme right position, and the last element is in the extreme left position. Timeseries being
used for storing history price data and contain the time information, we can say that the
newest data are placed in the extreme right position of the timeseries, while the oldest data
are in the extreme left position.
So the timeseries element with index 0 contains the information about the latest quote of a
symbol. If a timeseries contains data on a daily timeframe, data of the current yet
uncompleted day are located on the zero position, and the position with index 1 contains
yesterday data.
Changing the Indexing Direction

Function ArraySetAsSeries() allows changing the method of accessing elements of a dynamic


array; the physical order of data storing in the computer memory is not changed at that. This
function simply changes the method of addressing array elements, so when copying one array
to another using function ArrayCopy(), the contents of the recipient array will not depend on
the indexing direction in the source array.
Direction of indexing cannot be changed for statically distributed arrays. Even if an array was
passed as a parameter to a function, attempts to change the indexing direction inside this
function will bring no effect.
For indicator buffers, like for usual arrays, indexing direction can also be set as backward (like
in timeseries), i.e. reference to the zero position in the indicator buffer will mean reference to
the last value on the corresponding indicator buffer and this will correspond to the value of
the indicator on the latest bar. Still, the physical location of indicator bars will be unchanged.
Receiving Price Data in Indicators

Each custom indicator must necessarily contain the OnCalculate() function, to which price
data required for calculating values in indicator buffers are passed. Indexing direction in these
passed arrays can be found out using function ArrayGetAsSeries().
Arrays passed to the function reflect price data, i.e. these arrays have the sign of a timeseries
and function ArrayIsSeries() will return true when checking these arrays. However, in any
case indexing direction should be checked only by function ArrayGetAsSeries().
In order not to be dependent on default values, ArraySetAsSeries() should be unconditionally
called for the arrays you are going to work with, and set the required direction.
Receiving Price Data and Indicator Values

Default indexing direction of all arrays in Expert Advisors, indicators and scripts is left-to-right.
If necessary, in any mql4 program you can request timeseries values on any symbol and
timeframe, as well as values of indicators calculated on any symbol and timeframe.
Use functions Copy...() for these purposes:
CopyRates — copy price history to an array of structures MqlRates;
CopyTime — copy Time values to an array of datetime type;
CopyOpen — copy Open values to an array of double type;
CopyHigh — copy High values to an array of double type;
CopyLow — copy Low values to an array of double type;
CopyClose — copy Close values to an array of double type;
CopyTickVolume — copy tick volumes to an array of long type;

All these functions work in a similar way. Let's consider the data obtaining mechanism on the
example of CopyOpen(). It is implied that the indexing direction of requested data is that of
timeseries, and the position with index 0 (zero) stores data of the current yet uncompleted
bar. In order to get access to these data we need to copy the necessary volume of data into
the recipient array, e.g. into array buffer.

When copying we need to specify the starting position in the source array, starting from
which data will be copied to the recipient array. In case of success, the specified number of
elements will be copied to the recipient array from the source array (from the indicator buffer
in this case). Irrespective of the indexing value set in the recipient array, copying is always
performed as is shown in the above figure.
Organizing Data Access

In this section questions connected with obtaining, storing and requesting price data
(timeseries) are considered.
Receiving Data from a Trade Server

Before price data become available in the MetaTrader 4 terminal, they must be received
and processed. To receive data, connection to the MetaTrader 4 trade server must be
established. Data are received in the form of packed blocks of minute bars from the server
upon the request of a terminal.
The mechanism of server reference for data doesn't depend on how the request has been
initiated - by a user when navigating in a chart or in a program way in the MQL4 language.
Storing Intermediate Data

Data received from a server are automatically unpacked and saved in the HCC intermediate
format. Data on each symbol are written into a separate folder: terminal_directory\bases\
server_name\history\symbol_name. For example, data on EURUSD received from the
MetaQuotes-Demo server will be stored in terminal_directory\bases\MetaQuotes-Demo\
history\EURUSD\.
Data are written into files with .hcc extension. Each file stores data of minute bars for one
year. For example, the file named 2009.hcc in the EURUSD folder contains minute bars of
EURUSD for year 2009. These files are used for preparing price data for all timeframes and
are not intended for direct access.
Obtaining Data on a Necessary Timeframe out of Intermediate Data

Intermediate HCC files are used as the data source for building price data for requested
timeframes in the HC format. Data of HC format are timeseries that are maximally prepared
for a quick access. They are created upon a request of a chart or a MQL4 program. The
volume of data should not exceed the value of the "Max bars in charts" parameter. Data
are stored for further using in files with hc extension.
To save resources, data on a timeframe are stored and saved in RAM only if necessary. If
not called for a long time, they are released from RAM and saved into a file. For each
timeframe, data are prepared regardless of whether there are ready data for other
timeframes or not. Rules of forming and accessing data are the same for all timeframes.
I.e., despite the fact that the unit data stored in HCC is one minute (M1), the availability of
HCC data doesn't mean the availability of data on M1 timeframe as HC in the same volume.
Receipt of new data from a server calls automatic update of used price data in HC format of
all timeframes. It also leads to the recalculation of all indicators that implicitly use them as
input data for calculations.
Parameter "Max bars in chart"

The "Max bars in charts" parameter restricts number of bars in HC format available to
charts, indicators and mql45 programs. This is valid for all available timeframes and serves,
first of all, to save computer resources.
When setting a large value of this parameter, it should be remembered, that if deep history
price data for small timeframes are available, memory used for storing timeseries and
indicator buffers can become hundreds of megabytes and reach the RAM restriction for the
client terminal program (2Gb for 32-bit applications of MS Windows).
Change of the "Max bars in charts" comes into effect after the client terminal is restarted.
Change of this parameter causes neither automatic referring to a server for additional data,
nor forming of additional bars of timeseries. Additional price data are requested from the
server, and timeseries are updated taking into account the new limitation, in case of either
chart scroll to the area with no data, or when data are requested by mql4 program.
Volume of data requested from the server corresponds to the required number of bars of
this timeframe with the "Max bars in charts" parameter taken into account. The restriction
set by this parameter is not strict, and in some cases the number of available bars for a
timeframe can be a little more than the current parameter value.
Data Availability

Presence of data on HCC format or even in the prepared for using HC format does not
always denote the absolute availability if these data to be shown in a chart or used in mql4
programs.
When accessing to price data or indicator values from a mql4 program it should be
remembered that their availability in a certain moment of time or starting from a certain
moment of time is not guaranteed. It is connected with the fact that with the purpose of
saving resources, the full copy of data necessary for a mql4 program isn't stored in
MetaTrader 4; only direct access to the terminal data base is given.
The price history for all timeframes is built from common data of HCC format, and any
update of data from a server leads to the update of data for all timeframes and to the
recalculation of indicators. Due to this access to data can be closed, even if these data were
available a moment ago.
Synchronization of the Terminal Data and Server Data

Since a mql4 program can call data fro any symbol and timeframe, there is a possibility that
data of a necessary timeseries are not formed yet in the terminal or the necessary price
data aren't synchronized with the trade server. In this case it's hard to predict the latency
time.
Algorithms using "do-nothing" loops are not the best solution. The only exception in this
case are scripts, because they do not have any alternative algorithm choice due to not
having event handling. For custom indicators such algorithms, as well as any other "do-
nothing" loops are strongly not recommended, because they lead to termination of
calculation of all indicators and any other handling of price data of the symbol.
For Expert Advisors and indicators, it is better to use the even model of handling. If during
handling of OnTick() or OnCalculate() event, data receipt for the required timeseries failed,
you should exit the event handler, relying on the access availability during the next call of
the handler.
SeriesInfoInteger

Returns information about the state of historical data. There are 2 variants of function calls.
Directly returns the property value.
long SeriesInfoInteger(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
ENUM_SERIES_INFO_INTEGER prop_id // property identifier
);

Returns true or false depending on the success of the function run.


bool SeriesInfoInteger(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
ENUM_SERIES_INFO_INTEGER prop_id, // property ID
long& long_var // variable for getting info
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
prop_id
[in] Identifier of the requested property, value of the ENUM_SERIES_INFO_INTEGER
enumeration.
long_var
[out] Variable to which the value of the requested property is placed.
Return Value
In the first case, it returns value of the long type.
For the second case, it returns true, if the specified property is available and its value has
been placed into long_var variable, otherwise it returns false. For more details about an
error, call GetLastError().
Example:
void OnStart()
{
//---
Print("Total number of bars for the symbol-period at this moment = ",
SeriesInfoInteger(Symbol(),0,SERIES_BARS_COUNT));

Print("The first date for the symbol-period at this moment = ",


(datetime)SeriesInfoInteger(Symbol(),0,SERIES_FIRSTDATE));

Print("The first date in the history for the symbol-period on the server = ",
(datetime)SeriesInfoInteger(Symbol(),0,SERIES_SERVER_FIRSTDATE));
}
RefreshRates

Refreshing of data in pre-defined variables and series arrays.


bool RefreshRates();
Parameters
None.
Returned value
True if the data updated, otherwise false.
Note
This function is used when Expert Advisor has been calculating for a long time and needs
data refreshing. Returns true if data are refreshed, otherwise returns false. The only reason
for data cannot be refreshed is that they are the current data of the client terminal.
Expert Advisors and scripts operate with their own copy of history data. Data of the current
symbol are copied at the first launch of the expert or script. At each subsequent launch of
the expert (remember that script is executed only once and does not depend on incoming
ticks), the initial copy will be updated. One or more new ticks can income while the Expert
Advisor or script is operating, and data can become out of date.
Example:
int ticket;
while(true)
{
ticket=OrderSend(Symbol(),OP_BUY,1.0,Ask,3,0,0,"expert comment",255,0,CLR_N
ONE);
if(ticket<=0)
{
int error=GetLastError();
//---- not enough money
if(error==134) break;
//---- 10 seconds wait
Sleep(10000);
//---- refresh price data
RefreshRates();
break;
}
else
{
OrderSelect(ticket,SELECT_BY_TICKET);
OrderPrint();
break;
}
}
CopyRates

Gets history data of MqlRates structure of a specified symbol-period in specified quantity into
the rates_array array. The elements ordering of the copied data is from present to the past,
i.e., starting position of 0 means the current bar.
When copying the yet unknown amount of data, it is recommended to use dynamic array as a
target array, because if the requested data count is less (or more) than the length of the
target array, function tries to reallocate the memory so that the requested data fit entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyRates(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
MqlRates rates_array[] // target array to copy
);

Call by the start date and the number of required elements


int CopyRates(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
MqlRates rates_array[] // target array to copy
);

Call by the start and end dates of a required time interval


int CopyRates(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // end date and time
MqlRates rates_array[] // target array to copy
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_time
[in] Bar time for the first element to copy.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
stop_time
[in] Bar time, corresponding to the last element to copy.
rates_array[]
[out] Array of MqlRates type.
Return Value
Returns the number of copied elements or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on the
chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices Open,
High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return 0,
because the open time on a week timeframe is always Sunday, but one week bar does not
fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use the
first form of call specifying start_pos=0 and count=1.
Example:
void OnStart()
{
//---
MqlRates rates[];
ArraySetAsSeries(rates,true);
int copied=CopyRates(Symbol(),0,0,100,rates);
if(copied>0)
{
Print("Bars copied: "+copied);
string format="open = %G, high = %G, low = %G, close = %G, volume = %d";
string out;
int size=fmin(copied,10);
for(int i=0;i<size;i++)
{
out=i+":"+TimeToString(rates[i].time);
out=out+" "+StringFormat(format,
rates[i].open,
rates[i].high,
rates[i].low,
rates[i].close,
rates[i].tick_volume);
Print(out);
}
}
else Print("Failed to get history data for the symbol ",Symbol());
}
CopyTime

The function gets to time_array history data of bar opening time for the specified symbol-
period pair in the specified quantity. It should be noted that elements ordering is from
present to past, i.e., starting position of 0 means the current bar.
When copying the yet unknown amount of data, it is recommended to use dynamic array
as a target array, because if the requested data count is less (or more) than the length of
the target array, function tries to reallocate the memory so that the requested data fit
entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyTime(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
datetime time_array[] // target array to copy open times
);

Call by the start date and the number of required elements


int CopyTime(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
datetime time_array[] // target array to copy open times
);

Call by the start and end dates of a required time interval


int CopyTime(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // stop date and time
datetime time_array[] // target array to copy open times
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
start_time
[in] The start time for the first element to copy.
stop_time
[in] Bar time corresponding to the last element to copy.
time_array[]
[out] Array of datetime type.
Return Value
Returns the copied data count or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on
the chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices
Open, High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return
0, because the open time on a week timeframe is always Sunday, but one week bar does
not fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use
the first form of call specifying start_pos=0 and count=1.
See a detailed example of requesting history data in section Methods of Object Binding. The
script available in that section shows how to get the values of indicator iFractals on the last
1000 bars and how to display the last 10 up and 10 down fractals on the chart. A similar
technique can be used for all indicators that have missing data and that are usually drawn
using the following styles:
DRAW_SECTION,
DRAW_ARROW,
DRAW_ZIGZAG,
DRAW_COLOR_SECTION,
DRAW_COLOR_ARROW,
DRAW_COLOR_ZIGZAG.
CopyOpen

The function gets into open_array the history data of bar open prices for the selected symbol-
period pair in the specified quantity. It should be noted that elements ordering is from
present to past, i.e., starting position of 0 means the current bar.
When copying the yet unknown amount of data, it is recommended to use dynamic array as a
target array, because if the requested data count is less (or more) than the length of the
target array, function tries to reallocate the memory so that the requested data fit entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyOpen(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
double open_array[] // target array to copy open prices
);

Call by the start date and the number of required elements


int CopyOpen(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
double open_array[] // target array for bar open prices
);

Call by the start and end dates of a required time interval


int CopyOpen(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // stop date and time
double open_array[] // target array for bar open values
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
start_time
[in] The start time for the first element to copy.
stop_time
[in] The start time for the last element to copy.
open_array[]
[out] Array of double type.
Return Value
Returns the number of element in the array or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on the
chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices Open,
High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return 0,
because the open time on a week timeframe is always Sunday, but one week bar does not
fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use the
first form of call specifying start_pos=0 and count=1.
CopyHigh

The function gets into high_array the history data of highest bar prices for the selected
symbol-period pair in the specified quantity. It should be noted that elements ordering is from
present to past, i.e., starting position of 0 means the current bar.
When copying the yet unknown amount of data, it is recommended to use dynamic array as a
target array, because if the requested data count is less (or more) than the length of the
target array, function tries to reallocate the memory so that the requested data fit entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyHigh(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
double high_array[] // target array to copy
);

Call by the start date and the number of required elements


int CopyHigh(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
double high_array[] // target array to copy
);

Call by the start and end dates of a required time interval


int CopyHigh(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // stop date and time
double high_array[] // target array to copy
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
start_time
[in] The start time for the first element to copy.
stop_time
[in] Bar time, corresponding to the last element to copy.
high_array[]
[out] Array of double type.
Return Value
Returns the copied data count or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on the
chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices Open,
High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return 0,
because the open time on a week timeframe is always Sunday, but one week bar does not
fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use the
first form of call specifying start_pos=0 and count=1.
Example:
#property copyright "2009, MetaQuotes Software Corp."
#property link "https://www.mql5.com"
#property version "1.00"

#property description "An example for output of the High[i] and Low[i]"
#property description "for a random chosen bars"

double High[],Low[];
//+------------------------------------------------------------------+
//| Get Low for specified bar index |
//+------------------------------------------------------------------+
double iLow(string symbol,ENUM_TIMEFRAMES timeframe,int index)
{
double low=0;
ArraySetAsSeries(Low,true);
int copied=CopyLow(symbol,timeframe,0,Bars(symbol,timeframe),Low);
if(copied>0 && index<copied) low=Low[index];
return(low);
}
//+------------------------------------------------------------------+
//| Get the High for specified bar index |
//+------------------------------------------------------------------+
double iHigh(string symbol,ENUM_TIMEFRAMES timeframe,int index)
{
double high=0;
ArraySetAsSeries(High,true);
int copied=CopyHigh(symbol,timeframe,0,Bars(symbol,timeframe),High);
if(copied>0 && index<copied) high=High[index];
return(high);
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
//--- on every tick we output the High and Low values for the bar with index,
//--- that is equal to the second, on which tick arrived
datetime t=TimeCurrent();
int sec=t%60;
printf("High[%d] = %G Low[%d] = %G",
sec,iHigh(Symbol(),0,sec),
sec,iLow(Symbol(),0,sec));
}
CopyLow

The function gets into low_array the history data of minimal bar prices for the selected
symbol-period pair in the specified quantity. It should be noted that elements ordering is from
present to past, i.e., starting position of 0 means the current bar.
When copying the yet unknown amount of data, it is recommended to use dynamic array as a
target array, because if the requested data count is less (or more) than the length of the
target array, function tries to reallocate the memory so that the requested data fit entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyLow(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
double low_array[] // target array to copy
);

Call by the start date and the number of required elements


int CopyLow(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
double low_array[] // target array to copy
);

Call by the start and end dates of a required time interval


int CopyLow(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // stop date and time
double low_array[] // target array to copy
);

Parameters
symbol_name
[in] Symbol.
timeframe
[in] Period.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
start_time
[in] Bar time, corresponding to the first element to copy.
stop_time
[in] Bar time, corresponding to the last element to copy.
low_array[]
[out] Array of double type.
Return Value
Returns the copied data count or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on the
chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices Open,
High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return 0,
because the open time on a week timeframe is always Sunday, but one week bar does not
fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use the
first form of call specifying start_pos=0 and count=1.
CopyClose

The function gets into close_array the history data of bar close prices for the selected symbol-
period pair in the specified quantity. It should be noted that elements ordering is from
present to past, i.e., starting position of 0 means the current bar.

When copying the yet unknown amount of data, it is recommended to use dynamic array as a
target array, because if the requested data count is less (or more) than the length of the
target array, function tries to reallocate the memory so that the requested data fit entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyClose(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
double close_array[] // target array to copy
);

Call by the start date and the number of required elements


int CopyClose(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
double close_array[] // target array to copy
);

Call by the start and end dates of a required time interval


int CopyClose(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // stop date and time
double close_array[] // target array to copy
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
start_time
[in] The start time for the first element to copy.
stop_time
[in] Bar time, corresponding to the last element to copy.
close_array[]
[out] Array of double type.
Return Value
Returns the copied data count or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on the
chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices Open,
High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return 0,
because the open time on a week timeframe is always Sunday, but one week bar does not
fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use the
first form of call specifying start_pos=0 and count=1.
CopyTickVolume

The function gets into volume_array the history data of tick volumes for the selected symbol-
period pair in the specified quantity. It should be noted that elements ordering is from
present to past, i.e., starting position of 0 means the current bar.

When copying the yet unknown amount of data, it is recommended to use dynamic array as a
target array, because if the requested data count is less (or more) than the length of the
target array, function tries to reallocate the memory so that the requested data fit entirely.
If you know the amount of data you need to copy, it should better be done to a statically
allocated buffer, in order to prevent the allocation of excessive memory.
No matter what is the property of the target array - as_series=true or as_series=false. Data
will be copied so that the oldest element will be located at the start of the physical memory
allocated for the array. There are 3 variants of function calls.
Call by the first position and the number of required elements
int CopyTickVolume(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
int start_pos, // start position
int count, // data count to copy
long volume_array[] // target array for tick volumes
);

Call by the start date and the number of required elements


int CopyTickVolume(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
int count, // data count to copy
long volume_array[] // target array for tick volumes
);

Call by the start and end dates of a required time interval


int CopyTickVolume(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time, // stop date and time
long volume_array[] // target array for tick volumes
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_pos
[in] The start position for the first element to copy.
count
[in] Data count to copy.
start_time
[in] The start time for the first element to copy.
stop_time
[in] Bar time, corresponding to the last element to copy.
volume_array[]
[out] Array of long type.
Return Value
Returns the copied data count or -1 in case of an error.
Note
If the whole interval of requested data is out of the available data on the server, the
function returns -1. If data outside TERMINAL_MAXBARS (maximal number of bars on the
chart) is requested, the function will also return -1.
If requested timeseries are not yet built or they need to be downloaded from the server,
the function will immediately return -1.
When requesting data by the start date and the number of required elements, only data
whose date is less than (earlier) or equal to the date specified will be returned. It means,
the open time of any bar, for which value is returned (volume, spread, value on the
indicator buffer, prices Open, High, Low, Close or open time Time) is always less or equal
to the specified one.
When requesting data in a specified range of dates, only data from this interval will be
returned. The interval is set and counted up to seconds. It means, the open time of any
bar, for which value is returned (volume, spread, value on the indicator buffer, prices Open,
High, Low, Close or open time Time) is always within the requested interval.
Thus, if the current day is Saturday, at the attempt to copy data on a week timeframe
specifying start_time=Last_Tuesday and stop_time=Last_Friday the function will return 0,
because the open time on a week timeframe is always Sunday, but one week bar does not
fall into the specified interval.
If you need to return value corresponding to the current uncompleted bar, you can use the
first form of call specifying start_pos=0 and count=1.
Example:
#property strict
#property indicator_separate_window
#property indicator_buffers 1
//---- plot TickVolume
#property indicator_label1 "TickVolume"
#property indicator_type1 DRAW_HISTOGRAM
#property indicator_color1 C'143,188,139'
#property indicator_style1 STYLE_SOLID
#property indicator_width1 1
//--- input parameters
input int bars=3000;
//--- indicator buffers
double TickVolumeBuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
void OnInit()
{
//--- indicator buffers mapping
SetIndexBuffer(0,TickVolumeBuffer,INDICATOR_DATA);
IndicatorSetInteger(INDICATOR_DIGITS,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[])
{
//---
if(prev_calculated==0)
{
long timeseries[];
ArraySetAsSeries(timeseries,true);
int copied=CopyTickVolume(Symbol(),0,0,bars,timeseries);
for(int i=rates_total-copied-1;i>copied-1;i--) TickVolumeBuffer[i]=0.0;
for(int i=0;i<copied;i++) TickVolumeBuffer[i]=(double)timeseries[i];
Print("We have received the following number of TickVolume values: "+
(string)copied);
}
else
{
long timeseries[];
int copied=CopyTickVolume(Symbol(),0,0,1,timeseries);
TickVolumeBuffer[0]=(double)timeseries[0];
}
//--- return value of prev_calculated for next call
return(rates_total);
}
Bars

Returns the number of bars count in the history for a specified symbol and period. There are
2 variants of functions calls.
Request all of the history bars
int Bars(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe // period
);

Request the history bars for the selected time interval


int Bars(
string symbol_name, // symbol name
ENUM_TIMEFRAMES timeframe, // period
datetime start_time, // start date and time
datetime stop_time // end date and time
);

Parameters
symbol_name
[in] Symbol name.
timeframe
[in] Period.
start_time
[in] Bar time corresponding to the first element.
stop_time
[in] Bar time corresponding to the last element.
Return Value
If the start_time and stop_time parameters are defined, the function returns the number of
bars in the specified time interval, otherwise it returns the total number of bars.
Note
If data for the timeseries with specified parameters are not formed in the terminal by the
time of the Bars() function call, or data of the timeseries are not synchronized with a trade
server by the moment of the function call, the function returns a zero value.
iBars

Returns the number of bars on the specified chart.


int iBars(
string symbol, // symbol
int timeframe // timeframe
);

Parameters
symbol
[in] Symbol the data of which should be used to calculate indicator. NULL means the
current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
Returned value
The number of bars on the specified chart.
Note
For the current chart, the information about the amount of bars is in the Bars predefined
variable.
Example:
Print("Bar count on the 'EURUSD,H1' is ",iBars("EURUSD",PERIOD_H1));

iBarShift
Search for a bar by its time. The function returns the index of the bar which covers the
specified time.
int iBarShift(
string symbol, // symbol
int timeframe, // timeframe
datetime time, // time
bool exact=false // mode
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
time
[in] Time value for searching.
exact=false
[in] Return mode when the bar is not found (false - iBarShift returns the nearest, true -
iBarShift returns -1).
Returned value
Index of the bar which covers the specified time. If there is no bar for the specified time
(history "gap"), the function will return -1 or the nearest bar index (depending on exact
parameter).
Example:
datetime some_time=D'2004.03.21 12:00';
int shift=iBarShift("EURUSD",PERIOD_M1,some_time);
Print("index of the bar for the time ",TimeToStr(some_time)," is ",shift);

iClose
Returns Close price value for the bar of specified symbol with timeframe and shift.
double iClose(
string symbol, // symbol
int timeframe, // timeframe
int shift // shift
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
shift
[in] Index of the value taken from the indicator buffer (shift relative to the current bar
the given amount of periods ago).
Returned value
Close price value for the bar of specified symbol with timeframe and shift. If local history is
empty (not loaded), function returns 0. To check errors, one has to call the GetLastError()
function.
Note
For the current chart, the information about close prices is in the Close[] predefined array.
Example:
Print("Current bar for USDCHF H1: ",iTime("USDCHF",PERIOD_H1,0),", ", iOpen("U
SDCHF",PERIOD_H1,0),", ",
iHigh("USDCHF",PERIOD_H1,0),", ", iLow("US
DCHF",PERIOD_H1,0),", ",
iClose("USDCHF",PERIOD_H1,0),", ", iVolume(
"USDCHF",PERIOD_H1,0));

iHigh
Returns High price value for the bar of specified symbol with timeframe and shift.
double iHigh(
string symbol, // symbol
int timeframe, // timeframe
int shift // shift
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
shift
[in] Index of the value taken from the indicator buffer (shift relative to the current bar
the given amount of periods ago).
Returned value
High value for the bar of specified symbol with timeframe and shift. If local history is
empty (not loaded), function returns 0. To check errors, one has to call the GetLastError()
function.
Note
For the current chart, the information about high prices is in the High[] predefined array.
Example:
Print("Current bar for USDCHF H1: ",iTime("USDCHF",PERIOD_H1,0),", ", iOpen("U
SDCHF",PERIOD_H1,0),", ",
iHigh("USDCHF",PERIOD_H1,0),", ", iLow("US
DCHF",PERIOD_H1,0),", ",
iClose("USDCHF",PERIOD_H1,0),", ", iVolume(
"USDCHF",PERIOD_H1,0));
iHighest
Returns the shift of the maximum value over a specific number of bars depending on type.
int iHighest(
string symbol, // symbol
int timeframe, // timeframe
int type, // timeseries
int count, // cont
int start // start
);

Parameters
symbol
[in] Symbol the data of which should be used for search. NULL means the current
symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
type
[in] Series array identifier. It can be any of the Series array identifier enumeration
values.
count=WHOLE_ARRAY
[in] Number of bars (in direction from the start bar to the back one) on which the
search is carried out.
start=0
[in] Shift showing the bar, relative to the current bar, that the data should be taken
from.
Returned value
The shift of the maximum value over a specific number of bars or -1 if error. To check
errors, one has to call the GetLastError() function.
Example:
double val;
//--- calculating the highest value on the 20 consecutive bars in the range
//--- from the 4th to the 23rd index inclusive on the current chart
int val_index=iHighest(NULL,0,MODE_HIGH,20,4);
if(val_index!=-1) val=High[val_index];
else PrintFormat("Error in call iHighest. Error code=%d",GetLastError());
iLow

Returns Low price value for the bar of indicated symbol with timeframe and shift.
double iLow(
string symbol, // symbol
int timeframe, // timeframe
int shift // shift
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
shift
[in] Index of the value taken from the indicator buffer (shift relative to the current bar
the given amount of periods ago).
Returned value
Low price value for the bar of specified symbol with timeframe and shift. If local history is
empty (not loaded), function returns 0. To check errors, one has to call the GetLastError()
function.
Note
For the current chart, the information about low prices is in the Low[] predefined array.
Example:
Print("Current bar for USDCHF H1: ",iTime("USDCHF",PERIOD_H1,0),", ", iOpen("U
SDCHF",PERIOD_H1,0),", ",
iHigh("USDCHF",PERIOD_H1,0),", ", iLow("US
DCHF",PERIOD_H1,0),", ",
iClose("USDCHF",PERIOD_H1,0),", ", iVolume(
"USDCHF",PERIOD_H1,0));

iLowest
Returns the shift of the lowest value over a specific number of bars depending on type.
int iLowest(
string symbol, // symbol
int timeframe, // timeframe
int type, // timeseries id
int count, // count
int start // starting index
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
type
[in] Series array identifier. It can be any of the Series array identifier enumeration
values.
count=WHOLE_ARRAY
[in] Number of bars (in direction from the start bar to the back one) on which the
search is carried out.
start=0
[in] Shift showing the bar, relative to the current bar, that the data should be taken
from.
Returned value
The shift of the lowest value over a specific number of bars or -1 if error. To check errors,
one has to call the GetLastError() function.
Example:
double val;
//--- calculating the lowest value on the 10 consequtive bars in the range
//--- from the 10th to the 19th index inclusive on the current chart
int val_index=iLowest(NULL,0,MODE_LOW,10,10);
if(val_index!=-1) val=Low[val_index];
else PrintFormat("Error in iLowest. Error code=%d",GetLastError());
iOpen

Returns Open price value for the bar of specified symbol with timeframe and shift.
double iOpen(
string symbol, // symbol
int timeframe, // timeframe
int shift // shift
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
shift
[in] Index of the value taken from the indicator buffer (shift relative to the current bar
the given amount of periods ago).
Returned value
Open price value for the bar of specified symbol with timeframe and shift or 0 if error. To
check errors, one has to call the GetLastError() function.
Note
For the current chart, the information about open prices is in the Open[] predefined array.
Example:
Print("Current bar for USDCHF H1: ",iTime("USDCHF",PERIOD_H1,0),", ", iOpen("U
SDCHF",PERIOD_H1,0),", ",
iHigh("USDCHF",PERIOD_H1,0),", ", iLow("US
DCHF",PERIOD_H1,0),", ",
iClose("USDCHF",PERIOD_H1,0),", ", iVolume(
"USDCHF",PERIOD_H1,0));

iTime
Returns Time value for the bar of specified symbol with timeframe and shift.
datetime iTime(
string symbol, // symbol
int timeframe, // timeframe
int shift // shift
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
shift
[in] Index of the value taken from the indicator buffer (shift relative to the current bar
the given amount of periods ago).
Returned value
Time value for the bar of specified symbol with timeframe and shift. If local history is
empty (not loaded), function returns 0. To check errors, one has to call the GetLastError()
function.
Note
For the current chart, the information about open bar times is in the Time[] predefined
array.
Example:
Print("Current bar for USDCHF H1: ",iTime("USDCHF",PERIOD_H1,0),", ", iOpen("U
SDCHF",PERIOD_H1,0),", ",
iHigh("USDCHF",PERIOD_H1,0),", ", iLow("US
DCHF",PERIOD_H1,0),", ",
iClose("USDCHF",PERIOD_H1,0),", ", iVolume(
"USDCHF",PERIOD_H1,0));

iVolume
Returns Tick Volume value for the bar of specified symbol with timeframe and shift.
long iVolume(
string symbol, // symbol
int timeframe, // timeframe
int shift // shift
);

Parameters
symbol
[in] Symbol name. NULL means the current symbol.
timeframe
[in] Timeframe. It can be any of ENUM_TIMEFRAMES enumeration values. 0 means the
current chart timeframe.
shift
[in] Index of the value taken from the indicator buffer (shift relative to the current bar
the given amount of periods ago).
Returned value
Tick volume value for the bar of specified symbol with timeframe and shift. If local history
is empty (not loaded), function returns 0. To check errors, one has to call the
GetLastError() function.
Note
For the current chart, the information about bars tick volumes is in the Volume[] predefined
array.
Example:
Print("Current bar for USDCHF H1: ",iTime("USDCHF",PERIOD_H1,0),", ", iOpen("U
SDCHF",PERIOD_H1,0),", ",
iHigh("USDCHF",PERIOD_H1,0),", ", iLow("US
DCHF",PERIOD_H1,0),", ",
iClose("USDCHF",PERIOD_H1,0),", ", iVolume(
"USDCHF",PERIOD_H1,0));

FileFindFirst
The function starts the search of files or subdirectories in a directory in accordance with the
specified filter.
long FileFindFirst(
const string file_filter, // String - search filter
string& returned_filename, // Name of the file or subdirectory found
int common_flag=0 // Defines the search
);

Parameters
file_filter
[in] Search filter. A subdirectory (or sequence of nested subdirectories) relative to the \
Files directory, in which files should be searched for, can be specified in the filter.
returned_filename
[out] The returned parameter, where, in case of success, the name of the first found file
or subdirectory is placed. Only the file name is returned (including the extension), the
directories and subdirectories are not included no matter if they are specified or not in the
search filter.
common_flag
[in] Flag determining the location of the file. If common_flag = FILE_COMMON, then the
file is located in a shared folder for all client terminals \Terminal\Common\Files.
Otherwise, the file is located in a local folder.
Return Value
Returns handle of the object searched, which should be used for further sorting of files and
subdirectories by the FileFindNext() function, or INVALID_HANDLE when there is no file
and subdirectory corresponding to the filter (in the particular case - when the directory is
empty). After searching, the handle must be closed using the FileFindClose() function.
Note
For security reasons, work with files is strictly controlled in the MQL4 language. Files with
which file operations are conducted using MQL4 means, cannot be outside the file sandbox.
Example:
//--- display the window of input parameters when launching the script
#property script_show_inputs
//--- filter
input string InpFilter="Dir1\\*";
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
string file_name;
string int_dir="";
int i=1,pos=0,last_pos=-1;
//--- search for the last backslash
while(!IsStopped())
{
pos=StringFind(InpFilter,"\\",pos+1);
if(pos>=0)
last_pos=pos;
else
break;
}
//--- the filter contains the folder name
if(last_pos>=0)
int_dir=StringSubstr(InpFilter,0,last_pos+1);
//--- get the search handle in the root of the local folder
long search_handle=FileFindFirst(InpFilter,file_name);
//--- check if the FileFindFirst() is executed successfully
if(search_handle!=INVALID_HANDLE)
{
//--- in a loop, check if the passed strings are the names of files or dire
ctories
do
{
ResetLastError();
//--- if it's a file, the function returns true, and if it's a directory
, it returns error ERR_FILE_IS_DIRECTORY
FileIsExist(int_dir+file_name);
PrintFormat("%d : %s name = %s",i,GetLastError()==ERR_FILE_IS_DIRECTORY
? "Directory" : "File",file_name);
i++;
}
while(FileFindNext(search_handle,file_name));
//--- close the search handle
FileFindClose(search_handle);
}
else
Print("Files not found!");
}

FileFindNext
The function continues the search started by FileFindFirst().
bool FileFindNext(
long search_handle, // Search handle
string& returned_filename // Name of the file or subdirectory found
);

Parameters
search_handle
[in] Search handle, retrieved by FileFindFirst().
returned_filename
[out] The name of the next file or subdirectory found. Only the file name is returned
(including the extension), the directories and subdirectories are not included no matter if
they are specified or not in the search filter.
Return Value
If successful returns true, otherwise false.
Example:
//--- display the window of input parameters when launching the script
#property script_show_inputs
//--- filter
input string InpFilter="*";
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
string file_name;
int i=1;
//--- receive search handle in local folder's root
long search_handle=FileFindFirst(InpFilter,file_name);
//--- check if FileFindFirst() function executed successfully
if(search_handle!=INVALID_HANDLE)
{
//--- check if the passed strings are file or directory names in the loop
do
{
ResetLastError();
//--- if this is a file, the function will return true, if it is a direc
tory, the function will generate error ERR_FILE_IS_DIRECTORY
FileIsExist(file_name);
PrintFormat("%d : %s name = %s",i,GetLastError()==ERR_FILE_IS_DIRECTORY
? "Directory" : "File",file_name);
i++;
}
while(FileFindNext(search_handle,file_name));
//--- close search handle
FileFindClose(search_handle);
}
else
Print("Files not found!");
}

FileFindClose
The function closes the search handle.
void FileFindClose(
long search_handle // Search handle
);

Parameters
search_handle
[in] Search handle, retrieved by FileFindFirst().
Return Value
No value returned.
Note
Function must be called to free up system resources.
Example:
//--- display the window of input parameters when launching the script
#property script_show_inputs
//--- filter
input string InpFilter="*";
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
string file_name;
int i=1;
//--- receive search handle in local folder's root
long search_handle=FileFindFirst(InpFilter,file_name);
//--- check if FileFindFirst() function executed successfully
if(search_handle!=INVALID_HANDLE)
{
//--- check if the passed strings are file or directory names in the loop
do
{
ResetLastError();
//--- if this is a file, the function will return true, if it is a direc
tory, the function will generate error 5018
FileIsExist(file_name);
PrintFormat("%d : %s name = %s",i,GetLastError()==5018 ? "Directory" : "
File",file_name);
i++;
}
while(FileFindNext(search_handle,file_name));
//--- close search handle
FileFindClose(search_handle);
}
else
Print("Files not found!");
}

FileIsExist
Checks the existence of a file.
bool FileIsExist(
const string file_name, // File name
int common_flag=0 // Search area
);

Parameters
file_name
[in] The name of the file being checked
common_flag=0
[in] Flag determining the location of the file. If common_flag = FILE_COMMON, then
the file is located in a shared folder for all client terminals \Terminal\Common\Files.
Otherwise, the file is located in a local folder.
Return Value
Returns true, if the specified file exists.
Note
Checked file can turn out to be a subdirectory. In this case, FileIsExist() function will
return false, while error 5019 will be logged in _LastError variable - "This is a directory,
not a file" (see example for FileFindFirst() function).
For security reasons, work with files is strictly controlled in the MQL4 language. Files with
which file operations are conducted using MQL4 means, cannot be outside the file
sandbox.
If common_flag = FILE_COMMON, then the function looks for the file in a shared folder
for all client terminals \Terminal\Common\Files, otherwise the function looks for a file in a
local folder (MQL4\Files or MQL4\Tester\Files in the case of testing).
Example:
//--- show the window of input parameters when launching the script
#property script_show_inputs
//--- date for old files
input datetime InpFilesDate=D'2013.01.01 00:00';
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
string file_name; // variable for storing file names
string filter="*.txt"; // filter for searching the files
datetime create_date; // file creation date
string files[]; // list of file names
int def_size=25; // array size by default
int size=0; // number of files
//--- allocate memory for the array
ArrayResize(files,def_size);
//--- receive the search handle in the local folder's root
long search_handle=FileFindFirst(filter,file_name);
//--- check if FileFindFirst() executed successfully
if(search_handle!=INVALID_HANDLE)
{
//--- searching files in the loop
do
{
files[size]=file_name;
//--- increase the array size
size++;
if(size==def_size)
{
def_size+=25;
ArrayResize(files,def_size);
}
//--- reset the error value
ResetLastError();
//--- receive the file creation date
create_date=(datetime)FileGetInteger(file_name,FILE_CREATE_DATE,false);
//--- check if the file is old
if(create_date<InpFilesDate)
{
PrintFormat("%s file deleted!",file_name);
//--- delete the old file
FileDelete(file_name);
}
}
while(FileFindNext(search_handle,file_name));
//--- close the search handle
FileFindClose(search_handle);
}
else
{
Print("Files not found!");
return;
}
//--- check what files have remained
PrintFormat("Results:");
for(int i=0;i<size;i++)
{
if(FileIsExist(files[i]))
PrintFormat("%s file exists!",files[i]);
else
PrintFormat("%s file deleted!",files[i]);
}
}
FileOpen
The function opens the file with the specified name and flag.
int FileOpen(
string file_name, // File name
int open_flags, // Combination of flags
short delimiter=';', // Delimiter
uint codepage=CP_ACP // Code page
);

Parameters
file_name
[in] The name of the file can contain subfolders. If the file is opened for writing, these
subfolders will be created if there are no such ones.
open_flags
[in] combination of flags determining the operation mode for the file. The flags are
defined as follows:
FILE_READ file is opened for reading
FILE_WRITE file is opened for writing
FILE_BIN binary read-write mode (no conversion from a string and to a string)
FILE_CSV file of csv type (all recorded items are converted to the strings of unicode or
ansi type, and are separated by a delimiter)
FILE_TXT a simple text file (the same as csv, but the delimiter is not taken into
account)
FILE_ANSI lines of ANSI type (single-byte symbols)
FILE_UNICODE lines of UNICODE type (double-byte characters)
FILE_SHARE_READ shared reading from several programs
FILE_SHARE_WRITE shared writing from several programs
FILE_COMMON location of the file in a shared folder for all client terminals \Terminal\
Common\Files
delimiter=';'
[in] value to be used as a separator in txt or csv-file. If the csv-file delimiter is not
specified, the default delimiter is ";". If the txt-file delimiter is not specified, then no
separator is used. If the separator is clearly set to 0, then no separator is used.
codepage=CP_ACP
[in] Optional parameter. The value of the code page. For the most-used code pages
provide appropriate constants.
Return Value
If a file has been opened successfully, the function returns the file handle, which is then
used to access the file data. In case of failure returns INVALID_HANDLE.
Note
For security reasons, work with files is strictly controlled in the MQL4 language. Files with
which file operations are conducted using MQL4 means, cannot be outside the file
sandbox.
The file is opened in the folder of the client terminal in the subfolder MQL4\files (or
Tester\Files in case of testing). If FILE_COMMON is specified among flags, the file is
opened in a shared folder for all MetaTrader 4 client terminals.
"Named pipes" can be opened according to the following rules:
Pipe name is a string, which should have the following look: "\\servername\pipe\
pipename", where servername - server name in the network, while pipename is a pipe
name. If the pipes are used on the same computer, the server name can be omitted but
a point should be inserted instead of it: "\\.\pipe\pipename". A client trying to connect
the pipe should know its name.
FileFlush() and FileSeek() should be called to the beginning of a file between sequential
operations of reading from the pipe and writing to it.
A special symbol '\' is used in shown strings. Therefore, '\' should be doubled when
writing a name in MQL4 application. It means that the above example should have the
following look in the code: "\\\\servername\\pipe\\pipename".
More information about working with named pipes can be found in the article
"Communicating With MetaTrader 5 Using Named Pipes Without Using DLLs".
Example:
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- incorrect file opening method
string terminal_data_path=TerminalInfoString(TERMINAL_DATA_PATH);
string filename=terminal_data_path+"\\MQL4\\Files\\"+"fractals.csv";
int filehandle=FileOpen(filename,FILE_WRITE|FILE_CSV);
if(filehandle<0)
{
Print("Failed to open the file by the absolute path ");
Print("Error code ",GetLastError());
}
//--- correct way of working in the "file sandbox"
ResetLastError();
filehandle=FileOpen("fractals.csv",FILE_WRITE|FILE_CSV);
if(filehandle!=INVALID_HANDLE)
{
FileWrite(filehandle,TimeCurrent(),Symbol(), EnumToString(ENUM_TIMEFRAMES(_
Period)));
FileClose(filehandle);
Print("FileOpen OK");
}
else Print("Operation FileOpen failed, error ",GetLastError());
//--- another example with the creation of an enclosed directory in MQL4\Files\
string subfolder="Research";
filehandle=FileOpen(subfolder+"\\fractals.txt",FILE_WRITE|FILE_CSV);
if(filehandle!=INVALID_HANDLE)
{
FileWrite(filehandle,TimeCurrent(),Symbol(), EnumToString(ENUM_TIMEFRAMES(_
Period)));
FileClose(filehandle);
Print("The file most be created in the folder "+terminal_data_path+"\\"+sub
folder);
}
else Print("File open failed, error ",GetLastError());
}

FileClose
Close the file previously opened by FileOpen().
void FileClose(
int file_handle // File handle
);

Parameters
file_handle
[in] File descriptor returned by FileOpen().
Return Value
No value returned.
Example:
//--- show the window of input parameters when launching the script
#property script_show_inputs
//--- input parameters
input string InpFileName="file.txt"; // file name
input string InpDirectoryName="Data"; // directory name
input int InpEncodingType=FILE_ANSI; // ANSI=32 or UNICODE=64
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- print the path to the file we are going to use
PrintFormat("Working %s\\Files\\ folder
",TerminalInfoString(TERMINAL_DATA_PATH));
//--- reset the error value
ResetLastError();
//--- open the file for reading (if the file does not exist, the error will occur
)
int file_handle=FileOpen(InpDirectoryName+"//"+InpFileName,FILE_READ|FILE_TXT|
InpEncodingType);
if(file_handle!=INVALID_HANDLE)
{
//--- print the file contents
while(!FileIsEnding(file_handle))
Print(FileReadString(file_handle));
//--- close the file
FileClose(file_handle);
}
else
PrintFormat("Error, code = %d",GetLastError());
}

FileCopy
The function copies the original file from a local or shared folder to another file.
bool FileCopy(
const string src_file_name, // Name of a source file
int common_flag, // Location
const string dst_file_name, // Name of the destination file
int mode_flags // Access mode
);

Parameters
src_file_name
[in] File name to copy.
common_flag
[in] Flag determining the location of the file. If common_flag = FILE_COMMON, then
the file is located in a shared folder for all client terminals \Terminal\Common\Files.
Otherwise, the file is located in a local folder (for example, common_flag=0).
dst_file_name
[in] Result file name.
mode_flags
[in] Access flags. The parameter can contain only 2 flags: FILE_REWRITE and/or
FILE_COMMON - other flags are ignored. If the file already exists, and the
FILE_REWRITE flag hasn't been specified, then the file will not be rewritten, and the
function will return false.
Return Value
In case of failure the function returns false.
Note
For security reasons, work with files is strictly controlled in the MQL4 language. Files with
which file operations are conducted using MQL4 means, cannot be outside the file
sandbox.
If the new file already exists, the copy will be made depending on the availability of the
FILE_REWRITE flag in the mode_flags parameter.
Example:
//--- display the window of input parameters when launching the script
#property script_show_inputs
//--- input parameters
input string InpSrc="source.txt"; // source
input string InpDst="destination.txt"; // copy
input int InpEncodingType=FILE_ANSI; // ANSI=32 or UNICODE=64
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- display the source contents (it must exist)
if(!FileDisplay(InpSrc))
return;
//--- check if the copy file already exists (may not be created)
if(!FileDisplay(InpDst))
{
//--- the copy file does not exist, copying without FILE_REWRITE flag (corr
ect copying)
if(FileCopy(InpSrc,0,InpDst,0))
Print("File is copied!");
else
Print("File is not copied!");
}
else
{
//--- the copy file already exists, try to copy without FILE_REWRITE flag (
incorrect copying)
if(FileCopy(InpSrc,0,InpDst,0))
Print("File is copied!");
else
Print("File is not copied!");
//--- InpDst file's contents remains the same
FileDisplay(InpDst);
//--- copy once more with FILE_REWRITE flag (correct copying if the file ex
ists)
if(FileCopy(InpSrc,0,InpDst,FILE_REWRITE))
Print("File is copied!");
else
Print("File is not copied!");
}
//--- receive InpSrc file copy
FileDisplay(InpDst);
}
//+------------------------------------------------------------------+
//| Read the file contents |
//+------------------------------------------------------------------+
bool FileDisplay(const string file_name)
{
//--- reset the error value
ResetLastError();
//--- open the file
int file_handle=FileOpen(file_name,FILE_READ|FILE_TXT|InpEncodingType);
if(file_handle!=INVALID_HANDLE)
{
//--- display the file contents in the loop
Print("+---------------------+");
PrintFormat("File name = %s",file_name);
while(!FileIsEnding(file_handle))
Print(FileReadString(file_handle));
Print("+---------------------+");
//--- close the file
FileClose(file_handle);
return(true);
}
//--- failed to open the file
PrintFormat("%s is not opened, error = %d",file_name,GetLastError());
return(false);
}

Common questions

Powered by AI

The timeframe parameter in functions like iVolume determines the granularity of the data retrieved, such as hourly, daily, or weekly bars. It is essential for aligning data retrieval with the analysis requirements, ensuring that the data's temporal resolution matches the intended analytical goals .

The GetLastError function is invaluable for debugging financial data processing systems in MQL4 by offering detailed error codes for operations that fail. This facilitates targeted debugging, allowing developers to identify and address specific issues, thereby enhancing the system's reliability and performance .

The CopyHigh function retrieves high prices of bars based on a specified symbol and period, where the data can be fetched by start position and count, start date and count, or start and end dates. When data with unknown size needs to be handled, using a dynamic array is recommended to automatically adjust to the required size, avoiding memory allocation issues. For known amounts, a statically allocated buffer prevents excessive memory allocation .

Correct use of ENUM_TIMEFRAMES values in MQL4 functions ensures that data is extracted with the appropriate temporal resolution, matching the analysis needs precisely. This flexibility supports different analysis scopes, from intraday to long-term trends, by allowing developers to toggle between various timeframes efficiently .

The GetLastError function is crucial for identifying errors in data retrieval processes in MQL4. After executing a function like iHighest or iLow, GetLastError can be called to determine whether the function executed successfully or returned an error code. This helps in diagnosing and handling errors, ensuring robust data processing .

When handling large datasets with FileFind functions, it's recommended to use a systematic approach—such as iterating through files using FileFindFirst and FileFindNext—while ensuring that file handles are closed with FileFindClose. This approach helps manage system resources efficiently and prevents memory leaks, crucial for maintaining performance in large data operations .

The shift parameter in the iHighest and iLow functions defines the period offset from the current bar for which the maximum or minimum value should be retrieved. It effectively alters the reference point for the data series, ensuring the function retrieves values relative to a specified position rather than the current bar .

A dynamic array in MQL4 reallocates its memory automatically to fit the requested data size, making it ideal for when the data count is unknown beforehand. In contrast, a statically allocated array has a fixed size, making it more efficient for known data sizes, as it avoids unnecessary memory allocation and deallocation overhead .

Time series identifiers define the type of data (e.g., prices, volumes) that the iHighest and iLowest functions will operate on. These identifiers allow the functions to specify which data series should be analyzed to find the highest or lowest value, influencing both the function's scope and outcome .

When using the CopyHigh function for a weekly timeframe, one must ensure the specified start and stop times align with the entire timeframe. For instance, a weekly bar begins on a Sunday, so a time interval from Tuesday to Friday does not encompass any full weekly bars, causing the function to return 0 .

You might also like