Initial Commit.
This commit is contained in:
@@ -0,0 +1,31 @@
|
||||
# Group of Functions for Working with Arrays
|
||||
|
||||
[Arrays](/en/docs/basis/variables#array_define) are allowed to be maximum four-dimensional. Each dimension is indexed from 0 to dimension_size-1. In a particular case of a one-dimensional array of 50 elements, calling of the first element will appear as array[0], of the last one - as array[49].
|
||||
|
||||
| Function | Action |
|
||||
| --- | --- |
|
||||
| ArrayBsearch | Returns index of the first found element in the first array dimension |
|
||||
| ArrayCopy | Copies one array into another |
|
||||
| ArrayCompare | Returns the result of comparing two arrays of simple types or custom structures without complex objects |
|
||||
| ArrayFree | Frees up buffer of any dynamic array and sets the size of the zero dimension in 0. |
|
||||
| ArrayGetAsSeries | Checks direction of array indexing |
|
||||
| ArrayInitialize | Sets all elements of a numeric array into a single value |
|
||||
| ArrayFill | Fills an array with the specified value |
|
||||
| ArrayIsSeries | Checks whether an array is a timeseries |
|
||||
| ArrayIsDynamic | Checks whether an array is dynamic |
|
||||
| ArrayMaximum | Search for an element with the maximal value |
|
||||
| ArrayMinimum | Search for an element with the minimal value |
|
||||
| ArrayPrint | Prints an array of a simple type or a simple structure into journal |
|
||||
| ArrayRange | Returns the number of elements in the specified dimension of the array |
|
||||
| ArrayResize | Sets the new size in the first dimension of the array |
|
||||
| ArrayInsert | Inserts the specified number of elements from a source array to a receiving one starting from a specified index |
|
||||
| ArrayRemove | Removes the specified number of elements from the array starting with a specified index |
|
||||
| ArrayReverse | Reverses the specified number of elements in the array starting with a specified index |
|
||||
| ArraySetAsSeries | Sets the direction of array indexing |
|
||||
| ArraySize | Returns the number of elements in the array |
|
||||
| ArraySort | Sorting of numeric arrays by the first dimension |
|
||||
| ArraySwap | Swaps the contents of two dynamic arrays of the same type |
|
||||
| ArrayToFP16 | Copies an array of type float or double into an array of type ushort with the given format |
|
||||
| ArrayToFP8 | Copies an array of type float or double into an array of type uchar with the given format |
|
||||
| ArrayFromFP16 | Copies an array of type ushort into an array of float or double type with the given format |
|
||||
| ArrayFromFP8 | Copies an array of type uchar into an array of float or double type with the given format |
|
||||
@@ -0,0 +1,176 @@
|
||||
# ArrayBsearch
|
||||
|
||||
Searches for a specified value in a multidimensional numeric array [sorted](/en/docs/array/arraysort) ascending. Search is performed through the elements of the first dimension.
|
||||
|
||||
For searching in an array of double type
|
||||
|
||||
```
|
||||
int ArrayBsearch(
|
||||
const double& array[], // array for search
|
||||
double value // what is searched for
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For searching in an array of float type
|
||||
|
||||
```
|
||||
int ArrayBsearch(
|
||||
const float& array[], // array for search
|
||||
float value // what is searched for
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For searching in an array of long type
|
||||
|
||||
```
|
||||
int ArrayBsearch(
|
||||
const long& array[], // array for search
|
||||
long value // what is searched for
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For searching in an array of int type
|
||||
|
||||
```
|
||||
int ArrayBsearch(
|
||||
const int& array[], // array for search
|
||||
int value // what is searched for
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For searching in an array of short type
|
||||
|
||||
```
|
||||
int ArrayBsearch(
|
||||
const short& array[], // array for search
|
||||
short value // what is searched for
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For searching in an array of char type
|
||||
|
||||
```
|
||||
int ArrayBsearch(
|
||||
const char& array[], // array for search
|
||||
char value // what is searched for
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Numeric array for search.
|
||||
|
||||
value
|
||||
|
||||
[in] Value for search.
|
||||
|
||||
Return Value
|
||||
|
||||
The function returns index of a found element. If the wanted value isn't found, the function returns the index of an element nearest in value.
|
||||
|
||||
Note
|
||||
|
||||
Binary search processes only sorted arrays. To sort numeric arrays use the [ArraySort()](/en/docs/array/arraysort) function.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "Script based on RSI indicator data displays"
|
||||
#property description "how often the market was in"
|
||||
#property description "overbought and oversold areas in the specified time interval."
|
||||
//--- display the window of input parameters when launching the script
|
||||
#property script_show_inputs
|
||||
//--- input parameters
|
||||
input int InpMAPeriod=14; // Moving average period
|
||||
input ENUM_APPLIED_PRICE InpAppliedPrice=PRICE_CLOSE; // Price type
|
||||
input double InpOversoldValue=30.0; // Oversold level
|
||||
input double InpOverboughtValue=70.0; // Overbought level
|
||||
input datetime InpDateStart=D'2012.01.01 00:00'; // Analysis start date
|
||||
input datetime InpDateFinish=D'2013.01.01 00:00'; // Analysis finish date
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
double rsi_buff[]; // array of the indicator values
|
||||
int size=0; // array size
|
||||
//--- receive RSI indicator handle
|
||||
ResetLastError();
|
||||
int rsi_handle=iRSI(Symbol(),Period(),InpMAPeriod,InpAppliedPrice);
|
||||
if(rsi_handle==INVALID_HANDLE)
|
||||
{
|
||||
//--- failed to receive the indicator handle
|
||||
PrintFormat("Indicator handle receiving error. Error code = %d",GetLastError());
|
||||
return;
|
||||
}
|
||||
//--- being in the loop, until the indicator calculates all its values
|
||||
while(BarsCalculated(rsi_handle)==-1)
|
||||
{
|
||||
//--- exit if the indicator has forcedly completed the script's operation
|
||||
if(IsStopped())
|
||||
return;
|
||||
//--- a pause to allow the indicator to calculate all its values
|
||||
Sleep(10);
|
||||
}
|
||||
//--- copy the indicator values for a certain period of time
|
||||
ResetLastError();
|
||||
if(CopyBuffer(rsi_handle,0,InpDateStart,InpDateFinish,rsi_buff)==-1)
|
||||
{
|
||||
PrintFormat("Failed to copy the indicator values. Error code = %d",GetLastError());
|
||||
return;
|
||||
}
|
||||
//--- receive the array size
|
||||
size=ArraySize(rsi_buff);
|
||||
//--- sort out the array
|
||||
ArraySort(rsi_buff);
|
||||
//--- find out the time (in percentage terms) the market was in the oversold area
|
||||
double ovs=(double)ArrayBsearch(rsi_buff,InpOversoldValue)*100/(double)size;
|
||||
//--- find out the time (in percentage terms) the market was in the overbought area
|
||||
double ovb=(double)(size-ArrayBsearch(rsi_buff,InpOverboughtValue))*100/(double)size;
|
||||
//--- form the strings for displaying the data
|
||||
string str="From "+TimeToString(InpDateStart,TIME_DATE)+" to "
|
||||
+TimeToString(InpDateFinish,TIME_DATE)+" the market was:";
|
||||
string str_ovb="in overbought area "+DoubleToString(ovb,2)+"% of time";
|
||||
string str_ovs="in oversold area "+DoubleToString(ovs,2)+"% of time";
|
||||
//--- display the data on the chart
|
||||
CreateLabel("top",5,60,str,clrDodgerBlue);
|
||||
CreateLabel("overbought",5,35,str_ovb,clrDodgerBlue);
|
||||
CreateLabel("oversold",5,10,str_ovs,clrDodgerBlue);
|
||||
//--- redraw the chart
|
||||
ChartRedraw(0);
|
||||
//--- pause
|
||||
Sleep(10000);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Display comment in the bottom left corner of the chart |
|
||||
//+------------------------------------------------------------------+
|
||||
void CreateLabel(const string name,const int x,const int y,
|
||||
const string str,const color clr)
|
||||
{
|
||||
//--- create the label
|
||||
ObjectCreate(0,name,OBJ_LABEL,0,0,0);
|
||||
//--- bind the label to the bottom left corner
|
||||
ObjectSetInteger(0,name,OBJPROP_CORNER,CORNER_LEFT_LOWER);
|
||||
//--- change position of the anchor point
|
||||
ObjectSetInteger(0,name,OBJPROP_ANCHOR,ANCHOR_LEFT_LOWER);
|
||||
//--- distance from the anchor point in X-direction
|
||||
ObjectSetInteger(0,name,OBJPROP_XDISTANCE,x);
|
||||
//--- distance from the anchor point in Y-direction
|
||||
ObjectSetInteger(0,name,OBJPROP_YDISTANCE,y);
|
||||
//--- label text
|
||||
ObjectSetString(0,name,OBJPROP_TEXT,str);
|
||||
//--- text color
|
||||
ObjectSetInteger(0,name,OBJPROP_COLOR,clr);
|
||||
//--- text size
|
||||
ObjectSetInteger(0,name,OBJPROP_FONTSIZE,12);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,241 @@
|
||||
# ArrayCopy
|
||||
|
||||
It copies an array into another one.
|
||||
|
||||
```
|
||||
int ArrayCopy(
|
||||
void& dst_array[], // destination array
|
||||
const void& src_array[], // source array
|
||||
int dst_start=0, // index starting from which write into destination array
|
||||
int src_start=0, // first index of a source array
|
||||
int count=WHOLE_ARRAY // number of elements
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
dst_array[]
|
||||
|
||||
[out] Destination array
|
||||
|
||||
src_array[]
|
||||
|
||||
[in] Source array
|
||||
|
||||
dst_start=0
|
||||
|
||||
[in] Starting index from the destination array. By default, start index is 0.
|
||||
|
||||
src_start=0
|
||||
|
||||
[in] Starting index for the source array. By default, start index is 0.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of elements that should be copied. By default, the whole array is copied (count=[WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants)).
|
||||
|
||||
Return Value
|
||||
|
||||
It returns the number of copied elements.
|
||||
|
||||
Note
|
||||
|
||||
If count<0 or count>src_size-src_start, all the remaining array part is copied. Arrays are copied from left to right. For series arrays, the starting position is correctly defined adjusted for copying from left to right.
|
||||
|
||||
If arrays are of different types, during copying it tries to transform each element of a source array into the type of the destination array. A string array can be copied into a string array only. Array of [classes and structures](/en/docs/basis/types/classes) containing objects that require initialization aren't copied. An array of structures can be copied into an array of the same type only.
|
||||
|
||||
For dynamic arrays with indexing as in [timeseries](/en/docs/series/bufferdirection), the size of a destination array is automatically increased to the amount of copied data (if the latter exceeds the array size). The destination array size is not decreased automatically.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "The indicator highlights the candlesticks that are local"
|
||||
#property description "highs and lows. Interval length for finding"
|
||||
#property description "extreme values should be found using an input parameters."
|
||||
//--- indicator settings
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 5
|
||||
#property indicator_plots 1
|
||||
//---- plot
|
||||
#property indicator_label1 "Extremums"
|
||||
#property indicator_type1 DRAW_COLOR_CANDLES
|
||||
#property indicator_color1 clrLightSteelBlue,clrRed,clrBlue
|
||||
#property indicator_style1 STYLE_SOLID
|
||||
#property indicator_width1 1
|
||||
//--- predefined constant
|
||||
#define INDICATOR_EMPTY_VALUE 0.0
|
||||
//--- input parameters
|
||||
input int InpNum=4; // Half-interval length
|
||||
//--- indicator buffers
|
||||
double ExtOpen[];
|
||||
double ExtHigh[];
|
||||
double ExtLow[];
|
||||
double ExtClose[];
|
||||
double ExtColor[];
|
||||
//--- global variables
|
||||
int ExtStart=0; // index of the first candlestick that is not an extremum
|
||||
int ExtCount=0; // number of non-extremums in the interval
|
||||
//+------------------------------------------------------------------+
|
||||
//| Filling out non-extremum candlesticks |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillCandles(const double &open[],const double &high[],
|
||||
const double &low[],const double &close[])
|
||||
{
|
||||
//--- fill out the candlesticks
|
||||
ArrayCopy(ExtOpen,open,ExtStart,ExtStart,ExtCount);
|
||||
ArrayCopy(ExtHigh,high,ExtStart,ExtStart,ExtCount);
|
||||
ArrayCopy(ExtLow,low,ExtStart,ExtStart,ExtCount);
|
||||
ArrayCopy(ExtClose,close,ExtStart,ExtStart,ExtCount);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- indicator buffers mapping
|
||||
SetIndexBuffer(0,ExtOpen);
|
||||
SetIndexBuffer(1,ExtHigh);
|
||||
SetIndexBuffer(2,ExtLow);
|
||||
SetIndexBuffer(3,ExtClose);
|
||||
SetIndexBuffer(4,ExtColor,INDICATOR_COLOR_INDEX);
|
||||
//--- specify the value, which is not displayed
|
||||
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
|
||||
//--- specify the names of indicator buffers for displaying in the data window
|
||||
PlotIndexSetString(0,PLOT_LABEL,"Open;High;Low;Close");
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
//--- set straight indexing in time series
|
||||
ArraySetAsSeries(open,false);
|
||||
ArraySetAsSeries(high,false);
|
||||
ArraySetAsSeries(low,false);
|
||||
ArraySetAsSeries(close,false);
|
||||
//--- variable of the bar calculation start
|
||||
int start=prev_calculated;
|
||||
//--- calculation is not performed for the first InpNum*2 bars
|
||||
if(start==0)
|
||||
{
|
||||
start+=InpNum*2;
|
||||
ExtStart=0;
|
||||
ExtCount=0;
|
||||
}
|
||||
//--- if the bar has just formed, check the next potential extremum
|
||||
if(rates_total-start==1)
|
||||
start--;
|
||||
//--- bar index to be checked for the extremum
|
||||
int ext;
|
||||
//--- indicator value calculation loop
|
||||
for(int i=start;i<rates_total-1;i++)
|
||||
{
|
||||
//--- initially on i bar without drawing
|
||||
ExtOpen[i]=0;
|
||||
ExtHigh[i]=0;
|
||||
ExtLow[i]=0;
|
||||
ExtClose[i]=0;
|
||||
//--- extremum index for check
|
||||
ext=i-InpNum;
|
||||
//--- check for the local maximum
|
||||
if(IsMax(high,ext))
|
||||
{
|
||||
//--- highlight an extremum candlestick
|
||||
ExtOpen[ext]=open[ext];
|
||||
ExtHigh[ext]=high[ext];
|
||||
ExtLow[ext]=low[ext];
|
||||
ExtClose[ext]=close[ext];
|
||||
ExtColor[ext]=1;
|
||||
//--- highlight other candles up to the extremum with a neutral color
|
||||
FillCandles(open,high,low,close);
|
||||
//--- change the variable colors
|
||||
ExtStart=ext+1;
|
||||
ExtCount=0;
|
||||
//--- pass to the next iteration
|
||||
continue;
|
||||
}
|
||||
//--- check for the local minimum
|
||||
if(IsMin(low,ext))
|
||||
{
|
||||
//--- highlight an extremum candlestick
|
||||
ExtOpen[ext]=open[ext];
|
||||
ExtHigh[ext]=high[ext];
|
||||
ExtLow[ext]=low[ext];
|
||||
ExtClose[ext]=close[ext];
|
||||
ExtColor[ext]=2;
|
||||
//--- highlight other candles up to the extremum with a neutral color
|
||||
FillCandles(open,high,low,close);
|
||||
//--- change variable values
|
||||
ExtStart=ext+1;
|
||||
ExtCount=0;
|
||||
//--- pass to the next iteration
|
||||
continue;
|
||||
}
|
||||
//--- increase the number of non-extremums at the interval
|
||||
ExtCount++;
|
||||
}
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if the current array element is a local high |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsMax(const double &price[],const int ind)
|
||||
{
|
||||
//--- interval start variable
|
||||
int i=ind-InpNum;
|
||||
//--- interval end period
|
||||
int finish=ind+InpNum+1;
|
||||
//--- check for the first half of the interval
|
||||
for(;i<ind;i++)
|
||||
{
|
||||
if(price[ind]<=price[i])
|
||||
return(false);
|
||||
}
|
||||
//--- check for the second half of the interval
|
||||
for(i=ind+1;i<finish;i++)
|
||||
{
|
||||
if(price[ind]<=price[i])
|
||||
return(false);
|
||||
}
|
||||
//--- this is an extremum
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check if the current array element is a local low |
|
||||
//+------------------------------------------------------------------+
|
||||
bool IsMin(const double &price[],const int ind)
|
||||
{
|
||||
//--- interval start variable
|
||||
int i=ind-InpNum;
|
||||
//--- interval end variable
|
||||
int finish=ind+InpNum+1;
|
||||
//--- check for the first half of the interval
|
||||
for(;i<ind;i++)
|
||||
{
|
||||
if(price[ind]>=price[i])
|
||||
return(false);
|
||||
}
|
||||
//--- check for the second half of the interval
|
||||
for(i=ind+1;i<finish;i++)
|
||||
{
|
||||
if(price[ind]>=price[i])
|
||||
return(false);
|
||||
}
|
||||
//--- this is an extremum
|
||||
return(true);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,149 @@
|
||||
# ArrayCompare
|
||||
|
||||
The function returns the result of comparing two arrays of the same type. It can be used to compare arrays of [simple types](/en/docs/basis/types#base_types) or custom structures without [complex objects](/en/docs/basis/types#complex_types), that is the custom structures that do not contain [strings](/en/docs/basis/types/stringconst), [dynamic arrays](/en/docs/basis/types/dynamic_array), classes and other structures with complex objects.
|
||||
|
||||
```
|
||||
int ArrayCompare(
|
||||
const void& array1[], // first array
|
||||
const void& array2[], // second array
|
||||
int start1=0, // initial offset in the first array
|
||||
int start2=0, // initial offset in the second array
|
||||
int count=WHOLE_ARRAY // number of elements for comparison
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array1[]
|
||||
|
||||
[in] First array.
|
||||
|
||||
array2[]
|
||||
|
||||
[in] Second array.
|
||||
|
||||
start1=0
|
||||
|
||||
[in] The element's initial index in the first array, from which comparison starts. The default start index - 0.
|
||||
|
||||
start2=0
|
||||
|
||||
[in] The element's initial index in the second array, from which comparison starts. The default start index - 0.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of elements to be compared. All elements of both arrays participate in comparison by default (count=[WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants)).
|
||||
|
||||
Return Value
|
||||
|
||||
- -1, if array1[] less than array2[]
|
||||
- 0, if array1[] equal to array2[]
|
||||
- 1, if array1[] more than array2[]
|
||||
- -2, if an error occurs due to incompatibility of the types of compared arrays or if start1, start2 or count values lead to falling outside the array.
|
||||
|
||||
Note
|
||||
|
||||
The function will not return 0 (the arrays will not be considered equal) if the arrays differ in size and count=WHOLE_ARRAY for the case when one array is a faithful subset of another one. In this case, the result of comparing the sizes of that arrays will be returned: -1, if the size of array1[] is less than the size of array2[] , otherwise 1.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//--- global variables
|
||||
double ExtArrayFirst[];
|
||||
double ExtArraySecond[];
|
||||
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
//--- set the array sizes
|
||||
if(ArrayResize(ExtArrayFirst,10)!=10)
|
||||
{
|
||||
Print("ArrayResize() failed for ExtArrayFirst. Error code: ",GetLastError());
|
||||
return;
|
||||
}
|
||||
if(ArrayResize(ExtArraySecond,10)!=10)
|
||||
{
|
||||
Print("ArrayResize() failed for ExtArraySecond. Error code: ",GetLastError());
|
||||
return;
|
||||
}
|
||||
|
||||
//--- fill the arrays with the values of i and j indices in a loop
|
||||
int total=ArraySize(ExtArrayFirst);
|
||||
for(int i=0, j=total-1; i<total; i++,j--)
|
||||
{
|
||||
//--- fill the ExtArrayFirst array from left to right
|
||||
//--- fill the ExtArraySecond array from right to left
|
||||
ExtArrayFirst[i]=i;
|
||||
ExtArraySecond[i]=j;
|
||||
}
|
||||
//--- compare the arrays and print the result in the log
|
||||
ArrayComparePrint(ExtArrayFirst,ExtArraySecond);
|
||||
/*
|
||||
Result:
|
||||
ExtArrayFirst:
|
||||
0.00000 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000
|
||||
ExtArraySecond:
|
||||
9.00000 8.00000 7.00000 6.00000 5.00000 4.00000 3.00000 2.00000 1.00000 0.00000
|
||||
Result ArrayCompare(): ExtArrayFirst is smaller than ExtArraySecond (result = -1)
|
||||
*/
|
||||
|
||||
//--- now let's flip the arrays
|
||||
//--- fill the arrays with the values of i and j indices in a loop
|
||||
for(int i=0, j=total-1; i<total; i++,j--)
|
||||
{
|
||||
//--- fill the ExtArrayFirst array from right to left
|
||||
//--- fill the ExtArraySecond array from left to right
|
||||
ExtArrayFirst[i]=j;
|
||||
ExtArraySecond[i]=i;
|
||||
}
|
||||
//--- compare the arrays and print the result in the log
|
||||
ArrayComparePrint(ExtArrayFirst,ExtArraySecond);
|
||||
/*
|
||||
Result:
|
||||
ExtArrayFirst:
|
||||
9.00000 8.00000 7.00000 6.00000 5.00000 4.00000 3.00000 2.00000 1.00000 0.00000
|
||||
ExtArraySecond:
|
||||
0.00000 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000
|
||||
Result ArrayCompare(): ExtArrayFirst is larger than ExtArraySecond (result = 1)
|
||||
*/
|
||||
|
||||
//--- now let's fill the arrays in one direction
|
||||
//--- fill the arrays with the values of i index in a loop
|
||||
for(int i=0; i<total; i++)
|
||||
{
|
||||
//--- fill both arrays from left to right
|
||||
ExtArrayFirst[i]=i;
|
||||
ExtArraySecond[i]=i;
|
||||
}
|
||||
//--- compare the arrays and print the result in the log
|
||||
ArrayComparePrint(ExtArrayFirst,ExtArraySecond);
|
||||
/*
|
||||
Result:
|
||||
ExtArrayFirst:
|
||||
0.00000 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000
|
||||
ExtArraySecond:
|
||||
0.00000 1.00000 2.00000 3.00000 4.00000 5.00000 6.00000 7.00000 8.00000 9.00000
|
||||
Result ArrayCompare(): ExtArrayFirst and ExtArraySecond are equal (result = 0)
|
||||
*/
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Compare and display the result |
|
||||
//+------------------------------------------------------------------+
|
||||
void ArrayComparePrint(const double &array1[], const double &array2[])
|
||||
{
|
||||
//--- print the header and contents of the arrays
|
||||
Print("ExtArrayFirst:");
|
||||
ArrayPrint(array1);
|
||||
Print("ExtArraySecond:");
|
||||
ArrayPrint(array2);
|
||||
//--- compare the arrays and print the comparison result
|
||||
int res=ArrayCompare(array1,array2);
|
||||
string res_str=(res>0 ? "ExtArrayFirst is larger than ExtArraySecond" : res<0 ? "ExtArrayFirst is smaller than ExtArraySecond" : "ExtArrayFirst and ExtArraySecond are equal");
|
||||
PrintFormat("Result ArrayCompare(): %s (result = %d)\n",res_str,res);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
|
||||
```
|
||||
@@ -0,0 +1,406 @@
|
||||
# ArrayFree
|
||||
|
||||
It frees up a buffer of any dynamic array and sets the size of the zero dimension to 0.
|
||||
|
||||
```
|
||||
void ArrayFree(
|
||||
void& array[] // array
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Dynamic array.
|
||||
|
||||
Return Value
|
||||
|
||||
No return value.
|
||||
|
||||
Note
|
||||
|
||||
The need for using ArrayFree() function may not appear too often considering that all used memory is freed at once and main work with the arrays comprises the access to the indicator buffers. The sizes of the buffers are automatically managed by the terminal's executive subsystem.
|
||||
|
||||
In case it is necessary to manually manage the memory in complex dynamic environment of the application, ArrayFree() function allows users to free the memory occupied by the already unnecessary dynamic array explicitly and immediately.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#include <Controls\Dialog.mqh>
|
||||
#include <Controls\Button.mqh>
|
||||
#include <Controls\Label.mqh>
|
||||
#include <Controls\ComboBox.mqh>
|
||||
//--- predefined constants
|
||||
#define X_START 0
|
||||
#define Y_START 0
|
||||
#define X_SIZE 280
|
||||
#define Y_SIZE 300
|
||||
//+------------------------------------------------------------------+
|
||||
//| Dialog class for working with memory |
|
||||
//+------------------------------------------------------------------+
|
||||
class CMemoryControl : public CAppDialog
|
||||
{
|
||||
private:
|
||||
//--- array size
|
||||
int m_arr_size;
|
||||
//--- arrays
|
||||
char m_arr_char[];
|
||||
int m_arr_int[];
|
||||
float m_arr_float[];
|
||||
double m_arr_double[];
|
||||
long m_arr_long[];
|
||||
//--- labels
|
||||
CLabel m_lbl_memory_physical;
|
||||
CLabel m_lbl_memory_total;
|
||||
CLabel m_lbl_memory_available;
|
||||
CLabel m_lbl_memory_used;
|
||||
CLabel m_lbl_array_size;
|
||||
CLabel m_lbl_array_type;
|
||||
CLabel m_lbl_error;
|
||||
CLabel m_lbl_change_type;
|
||||
CLabel m_lbl_add_size;
|
||||
//--- buttons
|
||||
CButton m_button_add;
|
||||
CButton m_button_free;
|
||||
//--- combo boxes
|
||||
CComboBox m_combo_box_step;
|
||||
CComboBox m_combo_box_type;
|
||||
//--- current value of the array type from the combo box
|
||||
int m_combo_box_type_value;
|
||||
|
||||
public:
|
||||
CMemoryControl(void);
|
||||
~CMemoryControl(void);
|
||||
//--- class object creation method
|
||||
virtual bool Create(const long chart,const string name,const int subwin,const int x1,const int y1,const int x2,const int y2);
|
||||
//--- handler of chart events
|
||||
virtual bool OnEvent(const int id,const long &lparam,const double &dparam,const string &sparam);
|
||||
|
||||
protected:
|
||||
//--- create labels
|
||||
bool CreateLabel(CLabel &lbl,const string name,const int x,const int y,const string str,const int font_size,const int clr);
|
||||
//--- create control elements
|
||||
bool CreateButton(CButton &button,const string name,const int x,const int y,const string str,const int font_size,const int clr);
|
||||
bool CreateComboBoxStep(void);
|
||||
bool CreateComboBoxType(void);
|
||||
//--- event handlers
|
||||
void OnClickButtonAdd(void);
|
||||
void OnClickButtonFree(void);
|
||||
void OnChangeComboBoxType(void);
|
||||
//--- methods for working with the current array
|
||||
void CurrentArrayFree(void);
|
||||
bool CurrentArrayAdd(void);
|
||||
};
|
||||
//+------------------------------------------------------------------+
|
||||
//| Free memory of the current array |
|
||||
//+------------------------------------------------------------------+
|
||||
void CMemoryControl::CurrentArrayFree(void)
|
||||
{
|
||||
//--- reset array size
|
||||
m_arr_size=0;
|
||||
//--- free the array
|
||||
if(m_combo_box_type_value==0)
|
||||
ArrayFree(m_arr_char);
|
||||
if(m_combo_box_type_value==1)
|
||||
ArrayFree(m_arr_int);
|
||||
if(m_combo_box_type_value==2)
|
||||
ArrayFree(m_arr_float);
|
||||
if(m_combo_box_type_value==3)
|
||||
ArrayFree(m_arr_double);
|
||||
if(m_combo_box_type_value==4)
|
||||
ArrayFree(m_arr_long);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Attempt to add memory for the current array |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CMemoryControl::CurrentArrayAdd(void)
|
||||
{
|
||||
//--- exit if the size of the used memory exceeds the size of the physical memory
|
||||
if(TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)/TerminalInfoInteger(TERMINAL_MEMORY_USED)<2)
|
||||
return(false);
|
||||
//--- attempt to allocate memory according to the current type
|
||||
if(m_combo_box_type_value==0 && ArrayResize(m_arr_char,m_arr_size)==-1)
|
||||
return(false);
|
||||
if(m_combo_box_type_value==1 && ArrayResize(m_arr_int,m_arr_size)==-1)
|
||||
return(false);
|
||||
if(m_combo_box_type_value==2 && ArrayResize(m_arr_float,m_arr_size)==-1)
|
||||
return(false);
|
||||
if(m_combo_box_type_value==3 && ArrayResize(m_arr_double,m_arr_size)==-1)
|
||||
return(false);
|
||||
if(m_combo_box_type_value==4 && ArrayResize(m_arr_long,m_arr_size)==-1)
|
||||
return(false);
|
||||
//--- memory allocated
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handling events |
|
||||
//+------------------------------------------------------------------+
|
||||
EVENT_MAP_BEGIN(CMemoryControl)
|
||||
ON_EVENT(ON_CLICK,m_button_add,OnClickButtonAdd)
|
||||
ON_EVENT(ON_CLICK,m_button_free,OnClickButtonFree)
|
||||
ON_EVENT(ON_CHANGE,m_combo_box_type,OnChangeComboBoxType)
|
||||
EVENT_MAP_END(CAppDialog)
|
||||
//+------------------------------------------------------------------+
|
||||
//| Constructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CMemoryControl::CMemoryControl(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Destructor |
|
||||
//+------------------------------------------------------------------+
|
||||
CMemoryControl::~CMemoryControl(void)
|
||||
{
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Class object creation method |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CMemoryControl::Create(const long chart,const string name,const int subwin,
|
||||
const int x1,const int y1,const int x2,const int y2)
|
||||
{
|
||||
//--- create base class object
|
||||
if(!CAppDialog::Create(chart,name,subwin,x1,y1,x2,y2))
|
||||
return(false);
|
||||
//--- prepare strings for labels
|
||||
string str_physical="Memory physical = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_PHYSICAL)+" Mb";
|
||||
string str_total="Memory total = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_TOTAL)+" Mb";
|
||||
string str_available="Memory available = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)+" Mb";
|
||||
string str_used="Memory used = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED)+" Mb";
|
||||
//--- create labels
|
||||
if(!CreateLabel(m_lbl_memory_physical,"physical_label",X_START+10,Y_START+5,str_physical,12,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_memory_total,"total_label",X_START+10,Y_START+30,str_total,12,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_memory_available,"available_label",X_START+10,Y_START+55,str_available,12,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_memory_used,"used_label",X_START+10,Y_START+80,str_used,12,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_array_type,"type_label",X_START+10,Y_START+105,"Array type = double",12,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_array_size,"size_label",X_START+10,Y_START+130,"Array size = 0",12,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_error,"error_label",X_START+10,Y_START+155,"",12,clrRed))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_change_type,"change_type_label",X_START+10,Y_START+185,"Change type",10,clrBlack))
|
||||
return(false);
|
||||
if(!CreateLabel(m_lbl_add_size,"add_size_label",X_START+10,Y_START+210,"Add to array",10,clrBlack))
|
||||
return(false);
|
||||
//--- create control elements
|
||||
if(!CreateButton(m_button_add,"add_button",X_START+15,Y_START+245,"Add",12,clrBlue))
|
||||
return(false);
|
||||
if(!CreateButton(m_button_free,"free_button",X_START+75,Y_START+245,"Free",12,clrBlue))
|
||||
return(false);
|
||||
if(!CreateComboBoxType())
|
||||
return(false);
|
||||
if(!CreateComboBoxStep())
|
||||
return(false);
|
||||
//--- initialize the variable
|
||||
m_arr_size=0;
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create the button |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CMemoryControl::CreateButton(CButton &button,const string name,const int x,
|
||||
const int y,const string str,const int font_size,
|
||||
const int clr)
|
||||
{
|
||||
//--- create the button
|
||||
if(!button.Create(m_chart_id,name,m_subwin,x,y,x+50,y+20))
|
||||
return(false);
|
||||
//--- text
|
||||
if(!button.Text(str))
|
||||
return(false);
|
||||
//--- font size
|
||||
if(!button.FontSize(font_size))
|
||||
return(false);
|
||||
//--- label color
|
||||
if(!button.Color(clr))
|
||||
return(false);
|
||||
//--- add the button to the control elements
|
||||
if(!Add(button))
|
||||
return(false);
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a combo box for the array size |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CMemoryControl::CreateComboBoxStep(void)
|
||||
{
|
||||
//--- create the combo box
|
||||
if(!m_combo_box_step.Create(m_chart_id,"step_combobox",m_subwin,X_START+100,Y_START+185,X_START+200,Y_START+205))
|
||||
return(false);
|
||||
//--- add elements to the combo box
|
||||
if(!m_combo_box_step.ItemAdd("100 000",100000))
|
||||
return(false);
|
||||
if(!m_combo_box_step.ItemAdd("1 000 000",1000000))
|
||||
return(false);
|
||||
if(!m_combo_box_step.ItemAdd("10 000 000",10000000))
|
||||
return(false);
|
||||
if(!m_combo_box_step.ItemAdd("100 000 000",100000000))
|
||||
return(false);
|
||||
//--- set the current combo box element
|
||||
if(!m_combo_box_step.SelectByValue(1000000))
|
||||
return(false);
|
||||
//--- add the combo box to control elements
|
||||
if(!Add(m_combo_box_step))
|
||||
return(false);
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a combo box for the array type |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CMemoryControl::CreateComboBoxType(void)
|
||||
{
|
||||
//--- create the combo box
|
||||
if(!m_combo_box_type.Create(m_chart_id,"type_combobox",m_subwin,X_START+100,Y_START+210,X_START+200,Y_START+230))
|
||||
return(false);
|
||||
//--- add elements to the combo box
|
||||
if(!m_combo_box_type.ItemAdd("char",0))
|
||||
return(false);
|
||||
if(!m_combo_box_type.ItemAdd("int",1))
|
||||
return(false);
|
||||
if(!m_combo_box_type.ItemAdd("float",2))
|
||||
return(false);
|
||||
if(!m_combo_box_type.ItemAdd("double",3))
|
||||
return(false);
|
||||
if(!m_combo_box_type.ItemAdd("long",4))
|
||||
return(false);
|
||||
//--- set the current combo box element
|
||||
if(!m_combo_box_type.SelectByValue(3))
|
||||
return(false);
|
||||
//--- store the current combo box element
|
||||
m_combo_box_type_value=3;
|
||||
//--- add the combo box to control elements
|
||||
if(!Add(m_combo_box_type))
|
||||
return(false);
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Create a label |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CMemoryControl::CreateLabel(CLabel &lbl,const string name,const int x,
|
||||
const int y,const string str,const int font_size,
|
||||
const int clr)
|
||||
{
|
||||
//--- create a label
|
||||
if(!lbl.Create(m_chart_id,name,m_subwin,x,y,0,0))
|
||||
return(false);
|
||||
//--- text
|
||||
if(!lbl.Text(str))
|
||||
return(false);
|
||||
//--- font size
|
||||
if(!lbl.FontSize(font_size))
|
||||
return(false);
|
||||
//--- color
|
||||
if(!lbl.Color(clr))
|
||||
return(false);
|
||||
//--- add the label to control elements
|
||||
if(!Add(lbl))
|
||||
return(false);
|
||||
//--- succeed
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of clicking "Add" button event |
|
||||
//+------------------------------------------------------------------+
|
||||
void CMemoryControl::OnClickButtonAdd(void)
|
||||
{
|
||||
//--- increase the array size
|
||||
m_arr_size+=(int)m_combo_box_step.Value();
|
||||
//--- attempt to allocate memory for the current array
|
||||
if(CurrentArrayAdd())
|
||||
{
|
||||
//--- memory allocated, display the current status on the screen
|
||||
m_lbl_memory_available.Text("Memory available = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)+" Mb");
|
||||
m_lbl_memory_used.Text("Memory used = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED)+" Mb");
|
||||
m_lbl_array_size.Text("Array size = "+IntegerToString(m_arr_size));
|
||||
m_lbl_error.Text("");
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- failed to allocate memory, display the error message
|
||||
m_lbl_error.Text("Array is too large, error!");
|
||||
//--- return the previous array size
|
||||
m_arr_size-=(int)m_combo_box_step.Value();
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of clicking "Free" button event |
|
||||
//+------------------------------------------------------------------+
|
||||
void CMemoryControl::OnClickButtonFree(void)
|
||||
{
|
||||
//--- free the memory of the current array
|
||||
CurrentArrayFree();
|
||||
//--- display the current status on the screen
|
||||
m_lbl_memory_available.Text("Memory available = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_AVAILABLE)+" Mb");
|
||||
m_lbl_memory_used.Text("Memory used = "+(string)TerminalInfoInteger(TERMINAL_MEMORY_USED)+" Mb");
|
||||
m_lbl_array_size.Text("Array size = 0");
|
||||
m_lbl_error.Text("");
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Handler of the combo box change event |
|
||||
//+------------------------------------------------------------------+
|
||||
void CMemoryControl::OnChangeComboBoxType(void)
|
||||
{
|
||||
//--- check if the array's type has changed
|
||||
if(m_combo_box_type.Value()!=m_combo_box_type_value)
|
||||
{
|
||||
//--- free the memory of the current array
|
||||
OnClickButtonFree();
|
||||
//--- work with another array type
|
||||
m_combo_box_type_value=(int)m_combo_box_type.Value();
|
||||
//--- display the new array type on the screen
|
||||
if(m_combo_box_type_value==0)
|
||||
m_lbl_array_type.Text("Array type = char");
|
||||
if(m_combo_box_type_value==1)
|
||||
m_lbl_array_type.Text("Array type = int");
|
||||
if(m_combo_box_type_value==2)
|
||||
m_lbl_array_type.Text("Array type = float");
|
||||
if(m_combo_box_type_value==3)
|
||||
m_lbl_array_type.Text("Array type = double");
|
||||
if(m_combo_box_type_value==4)
|
||||
m_lbl_array_type.Text("Array type = long");
|
||||
}
|
||||
}
|
||||
//--- CMemoryControl class object
|
||||
CMemoryControl ExtDialog;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- create the dialog
|
||||
if(!ExtDialog.Create(0,"MemoryControl",0,X_START,Y_START,X_SIZE,Y_SIZE))
|
||||
return(INIT_FAILED);
|
||||
//--- launch
|
||||
ExtDialog.Run();
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert deinitialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnDeinit(const int reason)
|
||||
{
|
||||
//---
|
||||
ExtDialog.Destroy(reason);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Expert chart event function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnChartEvent(const int id,
|
||||
const long &lparam,
|
||||
const double &dparam,
|
||||
const string &sparam)
|
||||
{
|
||||
ExtDialog.ChartEvent(id,lparam,dparam,sparam);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,125 @@
|
||||
# ArrayGetAsSeries
|
||||
|
||||
It checks direction of an array index.
|
||||
|
||||
```
|
||||
bool ArrayGetAsSeries(
|
||||
const void& array[] // array for checking
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array
|
||||
|
||||
[in] Checked array.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns [true](/en/docs/basis/types/integer/boolconst), if the specified array has the AS_SERIES flag set, i.e. access to the array is performed back to front as in timeseries. A [timeseries](/en/docs/series) differs from a usual array in that the indexing of timeseries elements is performed from its end to beginning (from the newest data to old).
|
||||
|
||||
Note
|
||||
|
||||
To check whether an array belongs to timeseries, use the [ArrayIsSeries()](/en/docs/array/arrayisseries) function. Arrays of price data passed as input parameters into the [OnCalculate()](/en/docs/basis/function/events#oncalculate2) function do not obligatorily have the indexing direction the same as in timeseries. The necessary indexing direction can be set using the [ArraySetAsSeries()](/en/docs/array/arraysetasseries) function.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "Indicator calculates absolute values of the difference between"
|
||||
#property description "Open and Close or High and Low prices displaying them in a separate subwindow"
|
||||
#property description "as a histrogram."
|
||||
//--- indicator settings
|
||||
#property indicator_separate_window
|
||||
#property indicator_buffers 1
|
||||
#property indicator_plots 1
|
||||
//---- plot
|
||||
#property indicator_type1 DRAW_HISTOGRAM
|
||||
#property indicator_style1 STYLE_SOLID
|
||||
#property indicator_width1 3
|
||||
//--- input parameters
|
||||
input bool InpAsSeries=true; // Indexing direction in the indicator buffer
|
||||
input bool InpPrices=true; // Calculation prices (true - Open,Close; false - High,Low)
|
||||
//--- indicator buffer
|
||||
double ExtBuffer[];
|
||||
//+------------------------------------------------------------------+
|
||||
//| Calculating indicator values |
|
||||
//+------------------------------------------------------------------+
|
||||
void CandleSizeOnBuffer(const int rates_total,const int prev_calculated,
|
||||
const double &first[],const double &second[],double &buffer[])
|
||||
{
|
||||
//--- start variable for calculation of bars
|
||||
int start=prev_calculated;
|
||||
//--- work at the last bar if the indicator values have already been calculated at the previous tick
|
||||
if(prev_calculated>0)
|
||||
start--;
|
||||
//--- define indexing direction in arrays
|
||||
bool as_series_first=ArrayGetAsSeries(first);
|
||||
bool as_series_second=ArrayGetAsSeries(second);
|
||||
bool as_series_buffer=ArrayGetAsSeries(buffer);
|
||||
//--- replace indexing direction with direct one if necessary
|
||||
if(as_series_first)
|
||||
ArraySetAsSeries(first,false);
|
||||
if(as_series_second)
|
||||
ArraySetAsSeries(second,false);
|
||||
if(as_series_buffer)
|
||||
ArraySetAsSeries(buffer,false);
|
||||
//--- calculate indicator values
|
||||
for(int i=start;i<rates_total;i++)
|
||||
buffer[i]=MathAbs(first[i]-second[i]);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- bind indicator buffers
|
||||
SetIndexBuffer(0,ExtBuffer);
|
||||
//--- set indexing element in the indicator buffer
|
||||
ArraySetAsSeries(ExtBuffer,InpAsSeries);
|
||||
//--- check for what prices the indicator is calculated
|
||||
if(InpPrices)
|
||||
{
|
||||
//--- Open and Close prices
|
||||
PlotIndexSetString(0,PLOT_LABEL,"BodySize");
|
||||
//--- set the indicator color
|
||||
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrOrange);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- High and Low prices
|
||||
PlotIndexSetString(0,PLOT_LABEL,"ShadowSize");
|
||||
//--- set the indicator color
|
||||
PlotIndexSetInteger(0,PLOT_LINE_COLOR,clrDodgerBlue);
|
||||
}
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
//--- calculate the indicator according to the flag value
|
||||
if(InpPrices)
|
||||
CandleSizeOnBuffer(rates_total,prev_calculated,open,close,ExtBuffer);
|
||||
else
|
||||
CandleSizeOnBuffer(rates_total,prev_calculated,high,low,ExtBuffer);
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[Access to timeseries](/en/docs/series), [ArraySetAsSeries](/en/docs/array/arraysetasseries)
|
||||
@@ -0,0 +1,125 @@
|
||||
# ArrayInitialize
|
||||
|
||||
The function initializes a numeric array by a preset value.
|
||||
|
||||
For initialization of an array of char type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
char array[], // initialized array
|
||||
char value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of short type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
short array[], // initialized array
|
||||
short value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of int type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
int array[], // initialized array
|
||||
int value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of long type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
long array[], // initialized array
|
||||
long value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of float type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
float array[], // initialized array
|
||||
float value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of double type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
double array[], // initialized array
|
||||
double value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of bool type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
bool array[], // initialized array
|
||||
bool value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
For initialization of an array of uint type
|
||||
|
||||
```
|
||||
int ArrayInitialize(
|
||||
uint array[], // initialized array
|
||||
uint value // value that will be set
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[out] Numeric array that should be initialized.
|
||||
|
||||
value
|
||||
|
||||
[in] New value that should be set to all array elements.
|
||||
|
||||
Return Value
|
||||
|
||||
Number of initialized elements.
|
||||
|
||||
Note
|
||||
|
||||
The [ArrayResize()](/en/docs/array/arrayresize) function allows to set size of an array with a reserve for further expansion without the physical relocation of memory. It is implemented for the better performance, because the operations of memory relocation are reasonably slow.
|
||||
|
||||
Initialization of the array using ArrayInitialize(array, init_val) doesn't mean the initialization with the same value of reserve elements allocated for this array. At further expanding of the array using the ArrayResize() function, the elements will be added at the end of the array, their values will be undefined and in most cases will not be equal to init_value.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
void OnStart()
|
||||
{
|
||||
//--- dynamic array
|
||||
double array[];
|
||||
//--- let's set the array size for 100 elements and reserve a buffer for another 10 elements
|
||||
ArrayResize(array,100,10);
|
||||
//--- initialize the array elements with EMPTY_VALUE=DBL_MAX value
|
||||
ArrayInitialize(array,EMPTY_VALUE);
|
||||
Print("Values of 10 last elements after initialization");
|
||||
for(int i=90;i<100;i++) printf("array[%d] = %G",i,array[i]);
|
||||
//--- expand the array by 5 elements
|
||||
ArrayResize(array,105);
|
||||
Print("Values of 10 last elements after ArrayResize(array,105)");
|
||||
//--- values of 5 last elements are obtained from reserve buffer
|
||||
for(int i=95;i<105;i++) printf("array[%d] = %G",i,array[i]);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,60 @@
|
||||
# ArrayFill
|
||||
|
||||
The function fills an array with the specified value.
|
||||
|
||||
```
|
||||
void ArrayFill(
|
||||
void& array[], // array
|
||||
int start, // starting index
|
||||
int count, // number of elements to fill
|
||||
void value // value
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[out] Array of simple type ([char](/en/docs/basis/types/integer/integertypes), [uchar](/en/docs/basis/types/integer/integertypes), [short](/en/docs/basis/types/integer/integertypes), [ushort](/en/docs/basis/types/integer/integertypes), [int](/en/docs/basis/types/integer/integertypes), [uint](/en/docs/basis/types/integer/integertypes), [long](/en/docs/basis/types/integer/integertypes), [ulong](/en/docs/basis/types/integer/integertypes), [bool](/en/docs/basis/types/integer/boolconst), [color](/en/docs/basis/types/integer/color), [datetime](/en/docs/basis/types/integer/datetime), [float](/en/docs/basis/types/double), [double](/en/docs/basis/types/double)).
|
||||
|
||||
start
|
||||
|
||||
[in] Starting index. In such a case, specified [AS_SERIES flag](/en/docs/array/arraysetasseries) is ignored.
|
||||
|
||||
count
|
||||
|
||||
[in] Number of elements to fill.
|
||||
|
||||
value
|
||||
|
||||
[in] Value to fill the array with.
|
||||
|
||||
Return Value
|
||||
|
||||
No return value.
|
||||
|
||||
Note
|
||||
|
||||
When ArrayFill() function is called, normal indexation direction (from left to right) is always implied. It means that the change of the order of access to the array elements using [ArraySetAsSeries()](/en/docs/array/arraysetasseries) function is ignored.
|
||||
|
||||
A multidimensional array is shown as one-dimensional when processed by ArrayFill() function. For example, array[2][4] is processed as array[8]. Therefore, you may specify the initial element's index to be equal to 5 when working with this array. Thus, the call of ArrayFill(array, 5, 2, 3.14) for array[2][4] fills array[1][1] and array[1][2] elements with 3.14.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
void OnStart()
|
||||
{
|
||||
//--- declare dynamic array
|
||||
int a[];
|
||||
//--- set size
|
||||
ArrayResize(a,10);
|
||||
//--- fill first 5 elements with 123
|
||||
ArrayFill(a,0,5,123);
|
||||
//--- fill next 5 elements with 456
|
||||
ArrayFill(a,5,5,456);
|
||||
//--- show values
|
||||
for(int i=0;i<ArraySize(a);i++) printf("a[%d] = %d",i,a[i]);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,95 @@
|
||||
# ArrayIsDynamic
|
||||
|
||||
The function checks whether an array is dynamic.
|
||||
|
||||
```
|
||||
bool ArrayIsDynamic(
|
||||
const void& array[] // checked array
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Checked array.
|
||||
|
||||
Return Value
|
||||
|
||||
It returns true if the selected array is [dynamic](/en/docs/basis/types/dynamic_array), otherwise it returns false.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "This indicator does not calculate values. It makes a single attempt to"
|
||||
#property description "apply the call of ArrayFree() function to three arrays: dynamic one, static one and"
|
||||
#property description "an indicator buffer. Results are shown in Experts journal."
|
||||
//--- indicator settings
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 1
|
||||
#property indicator_plots 1
|
||||
//--- global variables
|
||||
double ExtDynamic[]; // dynamic array
|
||||
double ExtStatic[100]; // static array
|
||||
bool ExtFlag=true; // flag
|
||||
double ExtBuff[]; // indicator buffer
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- allocate memory for the array
|
||||
ArrayResize(ExtDynamic,100);
|
||||
//--- indicator buffers mapping
|
||||
SetIndexBuffer(0,ExtBuff);
|
||||
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,0);
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator iteration function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnCalculate(const int rates_total,
|
||||
const int prev_calculated,
|
||||
const int begin,
|
||||
const double &price[])
|
||||
{
|
||||
//--- perform a single analysis
|
||||
if(ExtFlag)
|
||||
{
|
||||
//--- attempt to free memory for arrays
|
||||
//--- 1. Dynamic array
|
||||
Print("+============================+");
|
||||
Print("1. Check dynamic array:");
|
||||
Print("Size before memory is freed = ",ArraySize(ExtDynamic));
|
||||
Print("Is this a dynamic array = ",ArrayIsDynamic(ExtDynamic) ? "Yes" : "No");
|
||||
//--- attempt to free array memory
|
||||
ArrayFree(ExtDynamic);
|
||||
Print("Size after memory is freed = ",ArraySize(ExtDynamic));
|
||||
//--- 2. Static array
|
||||
Print("2. Check static array:");
|
||||
Print("Size before memory is freed = ",ArraySize(ExtStatic));
|
||||
Print("Is this a dynamic array = ",ArrayIsDynamic(ExtStatic) ? "Yes" : "No");
|
||||
//--- attempt to free array memory
|
||||
ArrayFree(ExtStatic);
|
||||
Print("Size after memory is freed = ",ArraySize(ExtStatic));
|
||||
//--- 3. Indicator buffer
|
||||
Print("3. Check indicator buffer:");
|
||||
Print("Size before memory is freed = ",ArraySize(ExtBuff));
|
||||
Print("Is this a dynamic array = ",ArrayIsDynamic(ExtBuff) ? "Yes" : "No");
|
||||
//--- attempt to free array memory
|
||||
ArrayFree(ExtBuff);
|
||||
Print("Size after memory is freed = ",ArraySize(ExtBuff));
|
||||
//--- change the flag value
|
||||
ExtFlag=false;
|
||||
}
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[Access to timeseries and indicators](/en/docs/series)
|
||||
@@ -0,0 +1,72 @@
|
||||
# ArrayIsSeries
|
||||
|
||||
The function checks whether an array is a timeseries.
|
||||
|
||||
```
|
||||
bool ArrayIsSeries(
|
||||
const void& array[] // checked array
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Checked array.
|
||||
|
||||
Return Value
|
||||
|
||||
It returns true, if a checked array is an array timeseries, otherwise it returns false. Arrays passed as a parameter to the [OnCalculate()](/en/docs/basis/function/events#oncalculate2) function must be checked for the order of accessing the array elements by [ArrayGetAsSeries()](/en/docs/array/arraygetasseries).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 1
|
||||
#property indicator_plots 1
|
||||
//---- plot Label1
|
||||
#property indicator_label1 "Label1"
|
||||
#property indicator_type1 DRAW_LINE
|
||||
#property indicator_color1 clrRed
|
||||
#property indicator_style1 STYLE_SOLID
|
||||
#property indicator_width1 1
|
||||
//--- indicator buffers
|
||||
double Label1Buffer[];
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnInit()
|
||||
{
|
||||
//--- indicator buffers mapping
|
||||
SetIndexBuffer(0,Label1Buffer,INDICATOR_DATA);
|
||||
//---
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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(ArrayIsSeries(open))
|
||||
Print("open[] is timeseries");
|
||||
else
|
||||
Print("open[] is not timeseries!!!");
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[Access to timeseries and indicators](/en/docs/series)
|
||||
@@ -0,0 +1,542 @@
|
||||
# ArrayMaximum
|
||||
|
||||
Searches for the largest element in the first dimension of a multidimensional numeric array.
|
||||
|
||||
```
|
||||
int ArrayMaximum(
|
||||
const void& array[], // array for search
|
||||
int start=0, // index to start checking with
|
||||
int count=WHOLE_ARRAY // number of checked elements
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] A numeric array, in which search is made.
|
||||
|
||||
start=0
|
||||
|
||||
[in] Index to start checking with.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of elements for search. By default, searches in the entire array (count=[WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants)).
|
||||
|
||||
Return Value
|
||||
|
||||
The function returns an index of a found element taking into account the array [serial](/en/docs/array/arraygetasseries). In case of failure it returns -1.
|
||||
|
||||
Note
|
||||
|
||||
The [AS_SERIES](/en/docs/array/arraygetasseries) flag value is taken into account while searching for a maximum.
|
||||
|
||||
Functions ArrayMaximum and ArrayMinimum accept any-dimensional arrays as a parameter. However, searching is always applied to the first (zero) dimension.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "The indicator displays larger timeframe's candlesticks on the current one."
|
||||
//--- indicator settings
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 16
|
||||
#property indicator_plots 8
|
||||
//---- plot 1
|
||||
#property indicator_label1 "BearBody"
|
||||
#property indicator_color1 clrSeaGreen,clrSeaGreen
|
||||
//---- plot 2
|
||||
#property indicator_label2 "BearBodyEnd"
|
||||
#property indicator_color2 clrSeaGreen,clrSeaGreen
|
||||
//---- plot 3
|
||||
#property indicator_label3 "BearShadow"
|
||||
#property indicator_color3 clrSalmon,clrSalmon
|
||||
//---- plot 4
|
||||
#property indicator_label4 "BearShadowEnd"
|
||||
#property indicator_color4 clrSalmon,clrSalmon
|
||||
//---- plot 5
|
||||
#property indicator_label5 "BullBody"
|
||||
#property indicator_color5 clrOlive,clrOlive
|
||||
//---- plot 6
|
||||
#property indicator_label6 "BullBodyEnd"
|
||||
#property indicator_color6 clrOlive,clrOlive
|
||||
//---- plot 7
|
||||
#property indicator_label7 "BullShadow"
|
||||
#property indicator_color7 clrSkyBlue,clrSkyBlue
|
||||
//---- plot 8
|
||||
#property indicator_label8 "BullShadowEnd"
|
||||
#property indicator_color8 clrSkyBlue,clrSkyBlue
|
||||
//--- predefined constant
|
||||
#define INDICATOR_EMPTY_VALUE 0.0
|
||||
//--- input parameters
|
||||
input ENUM_TIMEFRAMES InpPeriod=PERIOD_H4; // Time frame for the indicator calculation
|
||||
input datetime InpDateStart=D'2013.01.01 00:00'; // Analysis start date
|
||||
//--- indicator buffers for bearish candlesticks
|
||||
double ExtBearBodyFirst[];
|
||||
double ExtBearBodySecond[];
|
||||
double ExtBearBodyEndFirst[];
|
||||
double ExtBearBodyEndSecond[];
|
||||
double ExtBearShadowFirst[];
|
||||
double ExtBearShadowSecond[];
|
||||
double ExtBearShadowEndFirst[];
|
||||
double ExtBearShadowEndSecond[];
|
||||
//--- indicator buffers for bullish candlesticks
|
||||
double ExtBullBodyFirst[];
|
||||
double ExtBullBodySecond[];
|
||||
double ExtBullBodyEndFirst[];
|
||||
double ExtBullBodyEndSecond[];
|
||||
double ExtBullShadowFirst[];
|
||||
double ExtBullShadowSecond[];
|
||||
double ExtBullShadowEndFirst[];
|
||||
double ExtBullShadowEndSecond[];
|
||||
//--- global variables
|
||||
datetime ExtTimeBuff[]; // larger time frame's time buffer
|
||||
int ExtSize=0; // time buffer size
|
||||
int ExtCount=0; // index inside time buffer
|
||||
int ExtStartPos=0; // initial position for the indicator calculation
|
||||
bool ExtStartFlag=true; // auxiliary flag for receiving the initial position
|
||||
datetime ExtCurrentTime[1]; // last time of the larger time frame's bar generation
|
||||
datetime ExtLastTime; // last time from the larger time frame, for which the calculation is performed
|
||||
bool ExtBearFlag=true; // flag for defining the order of writing the data to bearish indicator buffers
|
||||
bool ExtBullFlag=true; // flag for defining the order of writing the data to bullish indicator buffers
|
||||
int ExtIndexMax=0; // index of the maximum element in the array
|
||||
int ExtIndexMin=0; // index of the minimum element in the array
|
||||
int ExtDirectionFlag=0; // price movement direction for the current candlestick
|
||||
//--- shift between the candlestick's open and close price for correct drawing
|
||||
const double ExtEmptyBodySize=0.2*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
|
||||
//+------------------------------------------------------------------+
|
||||
//| Filling the basic part of the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillCandleMain(const double &open[],const double &close[],
|
||||
const double &high[],const double &low[],
|
||||
const int start,const int last,const int fill_index,
|
||||
int &index_max,int &index_min)
|
||||
{
|
||||
//--- find the index of the maximum and minimum elements in the arrays
|
||||
index_max=ArrayMaximum(high,ExtStartPos,last-start+1); // maximum in High
|
||||
index_min=ArrayMinimum(low,ExtStartPos,last-start+1); // minimum in Low
|
||||
//--- define how many bars from the current time frame are to be filled out
|
||||
int count=fill_index-start+1;
|
||||
//--- if the close price at the first bar exceeds the one at the last bar, the candlestick is bearish
|
||||
if(open[start]>close[last])
|
||||
{
|
||||
//--- if the candlestick has been bullish before that, clear the values of bullish indicator buffers
|
||||
if(ExtDirectionFlag!=-1)
|
||||
ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);
|
||||
//--- bearish candlestick
|
||||
ExtDirectionFlag=-1;
|
||||
//--- generate the candlestick
|
||||
FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],
|
||||
close[last],high[index_max],low[index_min],start,count,ExtBearFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if the close price at the first bar is less than the one at the last bar, the candlestick is bullish
|
||||
if(open[start]<close[last])
|
||||
{
|
||||
//--- if the candlestick has been bearish before that, clear the values of bearish indicator buffers
|
||||
if(ExtDirectionFlag!=1)
|
||||
ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,start,count);
|
||||
//--- bullish candlestick
|
||||
ExtDirectionFlag=1;
|
||||
//--- generate the candlestick
|
||||
FormCandleMain(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,close[last],
|
||||
open[start],high[index_max],low[index_min],start,count,ExtBullFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if you are in this part of the function, the open price at the first bar is equal to
|
||||
//--- the close price at the last bar; such candlestick is considered bearish
|
||||
//--- if the candlestick has been bullish before that, clear the values of bullish indicator buffers
|
||||
if(ExtDirectionFlag!=-1)
|
||||
ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);
|
||||
//--- bearish candlestick
|
||||
ExtDirectionFlag=-1;
|
||||
//--- if close and open prices are equal, use the shift for correct display
|
||||
if(high[index_max]!=low[index_min])
|
||||
FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],
|
||||
open[start]-ExtEmptyBodySize,high[index_max],low[index_min],start,count,ExtBearFlag);
|
||||
else
|
||||
FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,
|
||||
open[start],open[start]-ExtEmptyBodySize,high[index_max],
|
||||
high[index_max]-ExtEmptyBodySize,start,count,ExtBearFlag);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fill out the end of the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillCandleEnd(const double &open[],const double &close[],
|
||||
const double &high[],const double &low[],
|
||||
const int start,const int last,const int fill_index,
|
||||
const int index_max,const int index_min)
|
||||
{
|
||||
//--- do not draw in case of a single bar
|
||||
if(last-start==0)
|
||||
return;
|
||||
//--- if the close price at the first bar exceeds the one at the last bar, the candlestick is bearish
|
||||
if(open[start]>close[last])
|
||||
{
|
||||
//--- generate the end of the candlestick
|
||||
FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,
|
||||
open[start],close[last],high[index_max],low[index_min],fill_index,ExtBearFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if the close price at the first bar is less than the one at the last bar, the candlestick is bullish
|
||||
if(open[start]<close[last])
|
||||
{
|
||||
//--- generate the end of the candlestick
|
||||
FormCandleEnd(ExtBullBodyEndFirst,ExtBullBodyEndSecond,ExtBullShadowEndFirst,ExtBullShadowEndSecond,
|
||||
close[last],open[start],high[index_max],low[index_min],fill_index,ExtBullFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if you are in this part of the function, the open price at the first bar is equal to
|
||||
//--- the close price at the last bar; such candlestick is considered bearish
|
||||
//--- generate the end of the candlestick
|
||||
if(high[index_max]!=low[index_min])
|
||||
FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],
|
||||
open[start]-ExtEmptyBodySize,high[index_max],low[index_min],fill_index,ExtBearFlag);
|
||||
else
|
||||
FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],
|
||||
open[start]-ExtEmptyBodySize,high[index_max],high[index_max]-ExtEmptyBodySize,fill_index,ExtBearFlag);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- check the indicator period
|
||||
if(!CheckPeriod((int)Period(),(int)InpPeriod))
|
||||
return(INIT_PARAMETERS_INCORRECT);
|
||||
//--- display price data in the foreground
|
||||
ChartSetInteger(0,CHART_FOREGROUND,0,1);
|
||||
//--- binding indicator buffers
|
||||
SetIndexBuffer(0,ExtBearBodyFirst);
|
||||
SetIndexBuffer(1,ExtBearBodySecond);
|
||||
SetIndexBuffer(2,ExtBearBodyEndFirst);
|
||||
SetIndexBuffer(3,ExtBearBodyEndSecond);
|
||||
SetIndexBuffer(4,ExtBearShadowFirst);
|
||||
SetIndexBuffer(5,ExtBearShadowSecond);
|
||||
SetIndexBuffer(6,ExtBearShadowEndFirst);
|
||||
SetIndexBuffer(7,ExtBearShadowEndSecond);
|
||||
SetIndexBuffer(8,ExtBullBodyFirst);
|
||||
SetIndexBuffer(9,ExtBullBodySecond);
|
||||
SetIndexBuffer(10,ExtBullBodyEndFirst);
|
||||
SetIndexBuffer(11,ExtBullBodyEndSecond);
|
||||
SetIndexBuffer(12,ExtBullShadowFirst);
|
||||
SetIndexBuffer(13,ExtBullShadowSecond);
|
||||
SetIndexBuffer(14,ExtBullShadowEndFirst);
|
||||
SetIndexBuffer(15,ExtBullShadowEndSecond);
|
||||
//--- set some property values for creating the indicator
|
||||
for(int i=0;i<8;i++)
|
||||
{
|
||||
PlotIndexSetInteger(i,PLOT_DRAW_TYPE,DRAW_FILLING); // graphical construction type
|
||||
PlotIndexSetInteger(i,PLOT_LINE_STYLE,STYLE_SOLID); // drawing line style
|
||||
PlotIndexSetInteger(i,PLOT_LINE_WIDTH,1); // drawing line width
|
||||
}
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
//--- in case there are no calculated bars yet
|
||||
if(prev_calculated==0)
|
||||
{
|
||||
//--- receive larger time frame's bars arrival time
|
||||
if(!GetTimeData())
|
||||
return(0);
|
||||
}
|
||||
//--- set direct indexing
|
||||
ArraySetAsSeries(time,false);
|
||||
ArraySetAsSeries(high,false);
|
||||
ArraySetAsSeries(low,false);
|
||||
ArraySetAsSeries(open,false);
|
||||
ArraySetAsSeries(close,false);
|
||||
//--- start variable for calculation of bars
|
||||
int start=prev_calculated;
|
||||
//--- if the bar is generated, recalculate the indicator value on it
|
||||
if(start!=0 && start==rates_total)
|
||||
start--;
|
||||
//--- the loop for calculating the indicator values
|
||||
for(int i=start;i<rates_total;i++)
|
||||
{
|
||||
//--- fill i elements of the indicator buffers by empty values
|
||||
FillIndicatorBuffers(i);
|
||||
//--- perform calculation for bars starting from InpDateStart date
|
||||
if(time[i]>=InpDateStart)
|
||||
{
|
||||
//--- define position, from which the values are to be displayed, for the first time
|
||||
if(ExtStartFlag)
|
||||
{
|
||||
//--- store the number of the initial bar
|
||||
ExtStartPos=i;
|
||||
//--- define the first date from the larger time frame exceeding time[i]
|
||||
while(time[i]>=ExtTimeBuff[ExtCount])
|
||||
if(ExtCount<ExtSize-1)
|
||||
ExtCount++;
|
||||
//--- change the value of the flag in order not to run into this block again
|
||||
ExtStartFlag=false;
|
||||
}
|
||||
//--- check if there are still any elements in the array
|
||||
if(ExtCount<ExtSize)
|
||||
{
|
||||
//--- wait for the current time frame's value to reach the larger time frame's one
|
||||
if(time[i]>=ExtTimeBuff[ExtCount])
|
||||
{
|
||||
//--- draw the main part of the candlestick (without filling out the area between the last and penultimate bar)
|
||||
FillCandleMain(open,close,high,low,ExtStartPos,i-1,i-2,ExtIndexMax,ExtIndexMin);
|
||||
//--- fill out the end of the candlestick (the area between the last and the penultimate bar)
|
||||
FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);
|
||||
//--- shift the initial position for drawing the next candlestick
|
||||
ExtStartPos=i;
|
||||
//--- increase the array counter
|
||||
ExtCount++;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- reset the array values
|
||||
ResetLastError();
|
||||
//--- receive the last date from the larger time frame
|
||||
if(CopyTime(Symbol(),InpPeriod,0,1,ExtCurrentTime)==-1)
|
||||
{
|
||||
Print("Data copy error, code = ",GetLastError());
|
||||
return(0);
|
||||
}
|
||||
//--- if the new date is later, stop generating the candlestick
|
||||
if(ExtCurrentTime[0]>ExtLastTime)
|
||||
{
|
||||
//--- clear the area between the last and penultimate bars in the main indicator buffers
|
||||
ClearEndOfBodyMain(i-1);
|
||||
//--- fill out the area using auxiliary indicator buffers
|
||||
FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);
|
||||
//--- shift the initial position for drawing the next candlestick
|
||||
ExtStartPos=i;
|
||||
//--- reset price direction flag
|
||||
ExtDirectionFlag=0;
|
||||
//--- store the new last date
|
||||
ExtLastTime=ExtCurrentTime[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- generate the candlestick
|
||||
FillCandleMain(open,close,high,low,ExtStartPos,i,i,ExtIndexMax,ExtIndexMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check correctness of the specified indicator period |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPeriod(int current_period,int high_period)
|
||||
{
|
||||
//--- the indicator period should exceed the timeframe on which it is displayed
|
||||
if(current_period>=high_period)
|
||||
{
|
||||
Print("Error! The value of the indicator period should exceed the value of the current time frame!");
|
||||
return(false);
|
||||
}
|
||||
//--- if the indicator period is one week or month, the period is correct
|
||||
if(high_period>32768)
|
||||
return(true);
|
||||
//--- convert period values to minutes
|
||||
if(high_period>30)
|
||||
high_period=(high_period-16384)*60;
|
||||
if(current_period>30)
|
||||
current_period=(current_period-16384)*60;
|
||||
//--- the indicator period should be multiple of the time frame it is displayed on
|
||||
if(high_period%current_period!=0)
|
||||
{
|
||||
Print("Error! The value of the indicator period should be multiple of the value of the current time frame!");
|
||||
return(false);
|
||||
}
|
||||
//--- the indicator period should exceed the time frame it is displayed on 3 or more times
|
||||
if(high_period/current_period<3)
|
||||
{
|
||||
Print("Error! The indicator period should exceed the current time frame 3 or more times!");
|
||||
return(false);
|
||||
}
|
||||
//--- the indicator period is correct for the current time frame
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Receive time data from the larger time frame |
|
||||
//+------------------------------------------------------------------+
|
||||
bool GetTimeData(void)
|
||||
{
|
||||
//--- reset the error value
|
||||
ResetLastError();
|
||||
//--- copy all data for the current time
|
||||
if(CopyTime(Symbol(),InpPeriod,InpDateStart,TimeCurrent(),ExtTimeBuff)==-1)
|
||||
{
|
||||
//--- receive the error code
|
||||
int code=GetLastError();
|
||||
//--- print out the error message
|
||||
PrintFormat("Data copy error! %s",code==4401
|
||||
? "History is still being uploaded!"
|
||||
: "Code = "+IntegerToString(code));
|
||||
//--- return false to make a repeated attempt to download data
|
||||
return(false);
|
||||
}
|
||||
//--- receive the array size
|
||||
ExtSize=ArraySize(ExtTimeBuff);
|
||||
//--- set the loop index for the array to zero
|
||||
ExtCount=0;
|
||||
//--- set the current candlestick's position on the time frame to zero
|
||||
ExtStartPos=0;
|
||||
ExtStartFlag=true;
|
||||
//--- store the last time value from the larger time frame
|
||||
ExtLastTime=ExtTimeBuff[ExtSize-1];
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+--------------------------------------------------------------------------+
|
||||
//| Function forms the main part of the candlestick. Depending on the flag's |
|
||||
//| value, the function defines what data and arrays are |
|
||||
//| to be used for correct display. |
|
||||
//+--------------------------------------------------------------------------+
|
||||
void FormCandleMain(double &body_fst[],double &body_snd[],
|
||||
double &shadow_fst[],double &shadow_snd[],
|
||||
const double fst_value,const double snd_value,
|
||||
const double fst_extremum,const double snd_extremum,
|
||||
const int start,const int count,const bool flag)
|
||||
{
|
||||
//--- check the flag's value
|
||||
if(flag)
|
||||
{
|
||||
//--- generate the candlestick's body
|
||||
FormMain(body_fst,body_snd,fst_value,snd_value,start,count);
|
||||
//--- generate the candlestick's shadow
|
||||
FormMain(shadow_fst,shadow_snd,fst_extremum,snd_extremum,start,count);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- generate the candlestick's body
|
||||
FormMain(body_fst,body_snd,snd_value,fst_value,start,count);
|
||||
//--- generate the candlestick's shadow
|
||||
FormMain(shadow_fst,shadow_snd,snd_extremum,fst_extremum,start,count);
|
||||
}
|
||||
}
|
||||
//+-------------------------------------------------------------------------------+
|
||||
//| The function forms the end of the candlestick. Depending on the flag's value, |
|
||||
//| the function defines what data and arrays are |
|
||||
//| to be used for correct display. |
|
||||
//+-------------------------------------------------------------------------------+
|
||||
void FormCandleEnd(double &body_fst[],double &body_snd[],
|
||||
double &shadow_fst[],double &shadow_snd[],
|
||||
const double fst_value,const double snd_value,
|
||||
const double fst_extremum,const double snd_extremum,
|
||||
const int end,bool &flag)
|
||||
{
|
||||
//--- check the flag's value
|
||||
if(flag)
|
||||
{
|
||||
//--- generate the end of the candlestick's body
|
||||
FormEnd(body_fst,body_snd,fst_value,snd_value,end);
|
||||
//--- generate the end of the candlestick's shadow
|
||||
FormEnd(shadow_fst,shadow_snd,fst_extremum,snd_extremum,end);
|
||||
//--- change the flag's value to the opposite one
|
||||
flag=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- generate the end of the candlestick's body
|
||||
FormEnd(body_fst,body_snd,snd_value,fst_value,end);
|
||||
//--- generate the end of the candlestick's shadow
|
||||
FormEnd(shadow_fst,shadow_snd,snd_extremum,fst_extremum,end);
|
||||
//--- change the flag's value to the opposite one
|
||||
flag=true;
|
||||
}
|
||||
}
|
||||
//+---------------------------------------------------------------------------------+
|
||||
//| Clear the end of the candlestick (the area between the last and the penultimate |
|
||||
//| bar) |
|
||||
//+---------------------------------------------------------------------------------+
|
||||
void ClearEndOfBodyMain(const int ind)
|
||||
{
|
||||
ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,ind,1);
|
||||
ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,ind,1);
|
||||
}
|
||||
//+--------------------------------------------------------------------------+
|
||||
//| Clear the candlestick |
|
||||
//+--------------------------------------------------------------------------+
|
||||
void ClearCandle(double &body_fst[],double &body_snd[],double &shadow_fst[],
|
||||
double &shadow_snd[],const int start,const int count)
|
||||
{
|
||||
//--- check
|
||||
if(count!=0)
|
||||
{
|
||||
//--- fill indicator buffers with empty values
|
||||
ArrayFill(body_fst,start,count,INDICATOR_EMPTY_VALUE);
|
||||
ArrayFill(body_snd,start,count,INDICATOR_EMPTY_VALUE);
|
||||
ArrayFill(shadow_fst,start,count,INDICATOR_EMPTY_VALUE);
|
||||
ArrayFill(shadow_snd,start,count,INDICATOR_EMPTY_VALUE);
|
||||
}
|
||||
}
|
||||
//+--------------------------------------------------------------------------+
|
||||
//| Generate the main part of the candlestick |
|
||||
//+--------------------------------------------------------------------------+
|
||||
void FormMain(double &fst[],double &snd[],const double fst_value,
|
||||
const double snd_value,const int start,const int count)
|
||||
{
|
||||
//--- check
|
||||
if(count!=0)
|
||||
{
|
||||
//--- fill indicator buffers with values
|
||||
ArrayFill(fst,start,count,fst_value);
|
||||
ArrayFill(snd,start,count,snd_value);
|
||||
}
|
||||
}
|
||||
//+-----------------------------------------------------------------------------+
|
||||
//| Generate the end of the candlestick |
|
||||
//+-----------------------------------------------------------------------------+
|
||||
void FormEnd(double &fst[],double &snd[],const double fst_value,
|
||||
const double snd_value,const int last)
|
||||
{
|
||||
//--- fill indicator buffers with values
|
||||
ArrayFill(fst,last-1,2,fst_value);
|
||||
ArrayFill(snd,last-1,2,snd_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fill i element of the indicator buffers by empty values |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillIndicatorBuffers(const int i)
|
||||
{
|
||||
//--- set an empty value in the cell of the indicator buffers
|
||||
ExtBearBodyFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearBodySecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodyFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodySecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,542 @@
|
||||
# ArrayMinimum
|
||||
|
||||
Searches for the lowest element in the first dimension of a multidimensional numeric array.
|
||||
|
||||
```
|
||||
int ArrayMinimum(
|
||||
const void& array[], // array for search
|
||||
int start=0, // index to start checking with
|
||||
int count=WHOLE_ARRAY // number of checked elements
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] A numeric array, in which search is made.
|
||||
|
||||
start=0
|
||||
|
||||
[in] Index to start checking with.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of elements for search. By default, searches in the entire array (count=[WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants)).
|
||||
|
||||
Return Value
|
||||
|
||||
The function returns an index of a found element taking into account the array [serial](/en/docs/array/arraygetasseries). In case of failure it returns -1.
|
||||
|
||||
Note
|
||||
|
||||
The [AS_SERIES](/en/docs/array/arraygetasseries) flag value is taken into account while searching for a minimum.
|
||||
|
||||
Functions ArrayMaximum and ArrayMinimum accept any-dimensional arrays as a parameter. However, searching is always applied to the first (zero) dimension.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "The indicator displays larger timeframe's candlesticks on the current one."
|
||||
//--- indicator settings
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 16
|
||||
#property indicator_plots 8
|
||||
//---- plot 1
|
||||
#property indicator_label1 "BearBody"
|
||||
#property indicator_color1 clrSeaGreen,clrSeaGreen
|
||||
//---- plot 2
|
||||
#property indicator_label2 "BearBodyEnd"
|
||||
#property indicator_color2 clrSeaGreen,clrSeaGreen
|
||||
//---- plot 3
|
||||
#property indicator_label3 "BearShadow"
|
||||
#property indicator_color3 clrSalmon,clrSalmon
|
||||
//---- plot 4
|
||||
#property indicator_label4 "BearShadowEnd"
|
||||
#property indicator_color4 clrSalmon,clrSalmon
|
||||
//---- plot 5
|
||||
#property indicator_label5 "BullBody"
|
||||
#property indicator_color5 clrOlive,clrOlive
|
||||
//---- plot 6
|
||||
#property indicator_label6 "BullBodyEnd"
|
||||
#property indicator_color6 clrOlive,clrOlive
|
||||
//---- plot 7
|
||||
#property indicator_label7 "BullShadow"
|
||||
#property indicator_color7 clrSkyBlue,clrSkyBlue
|
||||
//---- plot 8
|
||||
#property indicator_label8 "BullShadowEnd"
|
||||
#property indicator_color8 clrSkyBlue,clrSkyBlue
|
||||
//--- predefined constant
|
||||
#define INDICATOR_EMPTY_VALUE 0.0
|
||||
//--- input parameters
|
||||
input ENUM_TIMEFRAMES InpPeriod=PERIOD_H4; // Time frame for the indicator calculation
|
||||
input datetime InpDateStart=D'2013.01.01 00:00'; // Analysis start date
|
||||
//--- indicator buffers for bearish candlesticks
|
||||
double ExtBearBodyFirst[];
|
||||
double ExtBearBodySecond[];
|
||||
double ExtBearBodyEndFirst[];
|
||||
double ExtBearBodyEndSecond[];
|
||||
double ExtBearShadowFirst[];
|
||||
double ExtBearShadowSecond[];
|
||||
double ExtBearShadowEndFirst[];
|
||||
double ExtBearShadowEndSecond[];
|
||||
//--- indicator buffers for bullish candlesticks
|
||||
double ExtBullBodyFirst[];
|
||||
double ExtBullBodySecond[];
|
||||
double ExtBullBodyEndFirst[];
|
||||
double ExtBullBodyEndSecond[];
|
||||
double ExtBullShadowFirst[];
|
||||
double ExtBullShadowSecond[];
|
||||
double ExtBullShadowEndFirst[];
|
||||
double ExtBullShadowEndSecond[];
|
||||
//--- global variables
|
||||
datetime ExtTimeBuff[]; // larger time frame's time buffer
|
||||
int ExtSize=0; // time buffer size
|
||||
int ExtCount=0; // index inside time buffer
|
||||
int ExtStartPos=0; // initial position for the indicator calculation
|
||||
bool ExtStartFlag=true; // auxiliary flag for receiving the initial position
|
||||
datetime ExtCurrentTime[1]; // last time of the larger time frame's bar generation
|
||||
datetime ExtLastTime; // last time from the larger time frame, for which the calculation is performed
|
||||
bool ExtBearFlag=true; // flag for defining the order of writing the data to bearish indicator buffers
|
||||
bool ExtBullFlag=true; // flag for defining the order of writing the data to bullish indicator buffers
|
||||
int ExtIndexMax=0; // index of the maximum element in the array
|
||||
int ExtIndexMin=0; // index of the minimum element in the array
|
||||
int ExtDirectionFlag=0; // price movement direction for the current candlestick
|
||||
//--- shift between the candlestick's open and close price for correct drawing
|
||||
const double ExtEmptyBodySize=0.2*SymbolInfoDouble(Symbol(),SYMBOL_POINT);
|
||||
//+------------------------------------------------------------------+
|
||||
//| Filling the basic part of the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillCandleMain(const double &open[],const double &close[],
|
||||
const double &high[],const double &low[],
|
||||
const int start,const int last,const int fill_index,
|
||||
int &index_max,int &index_min)
|
||||
{
|
||||
//--- find the index of the maximum and minimum elements in the arrays
|
||||
index_max=ArrayMaximum(high,ExtStartPos,last-start+1); // maximum in High
|
||||
index_min=ArrayMinimum(low,ExtStartPos,last-start+1); // minimum in Low
|
||||
//--- define how many bars from the current time frame are to be filled out
|
||||
int count=fill_index-start+1;
|
||||
//--- if the close price at the first bar exceeds the one at the last bar, the candlestick is bearish
|
||||
if(open[start]>close[last])
|
||||
{
|
||||
//--- if the candlestick has been bullish before that, clear the values of bullish indicator buffers
|
||||
if(ExtDirectionFlag!=-1)
|
||||
ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);
|
||||
//--- bearish candlestick
|
||||
ExtDirectionFlag=-1;
|
||||
//--- generate the candlestick
|
||||
FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],
|
||||
close[last],high[index_max],low[index_min],start,count,ExtBearFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if the close price at the first bar is less than the one at the last bar, the candlestick is bullish
|
||||
if(open[start]<close[last])
|
||||
{
|
||||
//--- if the candlestick has been bearish before that, clear the values of bearish indicator buffers
|
||||
if(ExtDirectionFlag!=1)
|
||||
ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,start,count);
|
||||
//--- bullish candlestick
|
||||
ExtDirectionFlag=1;
|
||||
//--- generate the candlestick
|
||||
FormCandleMain(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,close[last],
|
||||
open[start],high[index_max],low[index_min],start,count,ExtBullFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if you are in this part of the function, the open price at the first bar is equal to
|
||||
//--- the close price at the last bar; such candlestick is considered bearish
|
||||
//--- if the candlestick has been bullish before that, clear the values of bullish indicator buffers
|
||||
if(ExtDirectionFlag!=-1)
|
||||
ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,start,count);
|
||||
//--- bearish candlestick
|
||||
ExtDirectionFlag=-1;
|
||||
//--- if close and open prices are equal, use the shift for correct display
|
||||
if(high[index_max]!=low[index_min])
|
||||
FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,open[start],
|
||||
open[start]-ExtEmptyBodySize,high[index_max],low[index_min],start,count,ExtBearFlag);
|
||||
else
|
||||
FormCandleMain(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,
|
||||
open[start],open[start]-ExtEmptyBodySize,high[index_max],
|
||||
high[index_max]-ExtEmptyBodySize,start,count,ExtBearFlag);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fill out the end of the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillCandleEnd(const double &open[],const double &close[],
|
||||
const double &high[],const double &low[],
|
||||
const int start,const int last,const int fill_index,
|
||||
const int index_max,const int index_min)
|
||||
{
|
||||
//--- do not draw in case of a single bar
|
||||
if(last-start==0)
|
||||
return;
|
||||
//--- if the close price at the first bar exceeds the one at the last bar, the candlestick is bearish
|
||||
if(open[start]>close[last])
|
||||
{
|
||||
//--- generate the end of the candlestick
|
||||
FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,
|
||||
open[start],close[last],high[index_max],low[index_min],fill_index,ExtBearFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if the close price at the first bar is less than the one at the last bar, the candlestick is bullish
|
||||
if(open[start]<close[last])
|
||||
{
|
||||
//--- generate the end of the candlestick
|
||||
FormCandleEnd(ExtBullBodyEndFirst,ExtBullBodyEndSecond,ExtBullShadowEndFirst,ExtBullShadowEndSecond,
|
||||
close[last],open[start],high[index_max],low[index_min],fill_index,ExtBullFlag);
|
||||
//--- exit the function
|
||||
return;
|
||||
}
|
||||
//--- if you are in this part of the function, the open price at the first bar is equal to
|
||||
//--- the close price at the last bar; such candlestick is considered bearish
|
||||
//--- generate the end of the candlestick
|
||||
if(high[index_max]!=low[index_min])
|
||||
FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],
|
||||
open[start]-ExtEmptyBodySize,high[index_max],low[index_min],fill_index,ExtBearFlag);
|
||||
else
|
||||
FormCandleEnd(ExtBearBodyEndFirst,ExtBearBodyEndSecond,ExtBearShadowEndFirst,ExtBearShadowEndSecond,open[start],
|
||||
open[start]-ExtEmptyBodySize,high[index_max],high[index_max]-ExtEmptyBodySize,fill_index,ExtBearFlag);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- check the indicator period
|
||||
if(!CheckPeriod((int)Period(),(int)InpPeriod))
|
||||
return(INIT_PARAMETERS_INCORRECT);
|
||||
//--- display price data in the foreground
|
||||
ChartSetInteger(0,CHART_FOREGROUND,0,1);
|
||||
//--- binding indicator buffers
|
||||
SetIndexBuffer(0,ExtBearBodyFirst);
|
||||
SetIndexBuffer(1,ExtBearBodySecond);
|
||||
SetIndexBuffer(2,ExtBearBodyEndFirst);
|
||||
SetIndexBuffer(3,ExtBearBodyEndSecond);
|
||||
SetIndexBuffer(4,ExtBearShadowFirst);
|
||||
SetIndexBuffer(5,ExtBearShadowSecond);
|
||||
SetIndexBuffer(6,ExtBearShadowEndFirst);
|
||||
SetIndexBuffer(7,ExtBearShadowEndSecond);
|
||||
SetIndexBuffer(8,ExtBullBodyFirst);
|
||||
SetIndexBuffer(9,ExtBullBodySecond);
|
||||
SetIndexBuffer(10,ExtBullBodyEndFirst);
|
||||
SetIndexBuffer(11,ExtBullBodyEndSecond);
|
||||
SetIndexBuffer(12,ExtBullShadowFirst);
|
||||
SetIndexBuffer(13,ExtBullShadowSecond);
|
||||
SetIndexBuffer(14,ExtBullShadowEndFirst);
|
||||
SetIndexBuffer(15,ExtBullShadowEndSecond);
|
||||
//--- set some property values for creating the indicator
|
||||
for(int i=0;i<8;i++)
|
||||
{
|
||||
PlotIndexSetInteger(i,PLOT_DRAW_TYPE,DRAW_FILLING); // graphical construction type
|
||||
PlotIndexSetInteger(i,PLOT_LINE_STYLE,STYLE_SOLID); // drawing line style
|
||||
PlotIndexSetInteger(i,PLOT_LINE_WIDTH,1); // drawing line width
|
||||
}
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
//--- in case there are no calculated bars yet
|
||||
if(prev_calculated==0)
|
||||
{
|
||||
//--- receive larger time frame's bars arrival time
|
||||
if(!GetTimeData())
|
||||
return(0);
|
||||
}
|
||||
//--- set direct indexing
|
||||
ArraySetAsSeries(time,false);
|
||||
ArraySetAsSeries(high,false);
|
||||
ArraySetAsSeries(low,false);
|
||||
ArraySetAsSeries(open,false);
|
||||
ArraySetAsSeries(close,false);
|
||||
//--- start variable for calculation of bars
|
||||
int start=prev_calculated;
|
||||
//--- if the bar is generated, recalculate the indicator value on it
|
||||
if(start!=0 && start==rates_total)
|
||||
start--;
|
||||
//--- the loop for calculating the indicator values
|
||||
for(int i=start;i<rates_total;i++)
|
||||
{
|
||||
//--- fill i elements of the indicator buffers by empty values
|
||||
FillIndicatorBuffers(i);
|
||||
//--- perform calculation for bars starting from InpDateStart date
|
||||
if(time[i]>=InpDateStart)
|
||||
{
|
||||
//--- define position, from which the values are to be displayed, for the first time
|
||||
if(ExtStartFlag)
|
||||
{
|
||||
//--- store the number of the initial bar
|
||||
ExtStartPos=i;
|
||||
//--- define the first date from the larger time frame exceeding time[i]
|
||||
while(time[i]>=ExtTimeBuff[ExtCount])
|
||||
if(ExtCount<ExtSize-1)
|
||||
ExtCount++;
|
||||
//--- change the value of the flag in order not to run into this block again
|
||||
ExtStartFlag=false;
|
||||
}
|
||||
//--- check if there are still any elements in the array
|
||||
if(ExtCount<ExtSize)
|
||||
{
|
||||
//--- wait for the current time frame's value to reach the larger time frame's one
|
||||
if(time[i]>=ExtTimeBuff[ExtCount])
|
||||
{
|
||||
//--- draw the main part of the candlestick (without filling out the area between the last and penultimate bar)
|
||||
FillCandleMain(open,close,high,low,ExtStartPos,i-1,i-2,ExtIndexMax,ExtIndexMin);
|
||||
//--- fill out the end of the candlestick (the area between the last and the penultimate bar)
|
||||
FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);
|
||||
//--- shift the initial position for drawing the next candlestick
|
||||
ExtStartPos=i;
|
||||
//--- increase the array counter
|
||||
ExtCount++;
|
||||
}
|
||||
else
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- reset the array values
|
||||
ResetLastError();
|
||||
//--- receive the last date from the larger time frame
|
||||
if(CopyTime(Symbol(),InpPeriod,0,1,ExtCurrentTime)==-1)
|
||||
{
|
||||
Print("Data copy error, code = ",GetLastError());
|
||||
return(0);
|
||||
}
|
||||
//--- if the new date is later, stop generating the candlestick
|
||||
if(ExtCurrentTime[0]>ExtLastTime)
|
||||
{
|
||||
//--- clear the area between the last and penultimate bars in the main indicator buffers
|
||||
ClearEndOfBodyMain(i-1);
|
||||
//--- fill out the area using auxiliary indicator buffers
|
||||
FillCandleEnd(open,close,high,low,ExtStartPos,i-1,i-1,ExtIndexMax,ExtIndexMin);
|
||||
//--- shift the initial position for drawing the next candlestick
|
||||
ExtStartPos=i;
|
||||
//--- reset price direction flag
|
||||
ExtDirectionFlag=0;
|
||||
//--- store the new last date
|
||||
ExtLastTime=ExtCurrentTime[0];
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- generate the candlestick
|
||||
FillCandleMain(open,close,high,low,ExtStartPos,i,i,ExtIndexMax,ExtIndexMin);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Check correctness of the specified indicator period |
|
||||
//+------------------------------------------------------------------+
|
||||
bool CheckPeriod(int current_period,int high_period)
|
||||
{
|
||||
//--- the indicator period should exceed the timeframe on which it is displayed
|
||||
if(current_period>=high_period)
|
||||
{
|
||||
Print("Error! The value of the indicator period should exceed the value of the current time frame!");
|
||||
return(false);
|
||||
}
|
||||
//--- if the indicator period is one week or month, the period is correct
|
||||
if(high_period>32768)
|
||||
return(true);
|
||||
//--- convert period values to minutes
|
||||
if(high_period>30)
|
||||
high_period=(high_period-16384)*60;
|
||||
if(current_period>30)
|
||||
current_period=(current_period-16384)*60;
|
||||
//--- the indicator period should be multiple of the time frame it is displayed on
|
||||
if(high_period%current_period!=0)
|
||||
{
|
||||
Print("Error! The value of the indicator period should be multiple of the value of the current time frame!");
|
||||
return(false);
|
||||
}
|
||||
//--- the indicator period should exceed the time frame it is displayed on 3 or more times
|
||||
if(high_period/current_period<3)
|
||||
{
|
||||
Print("Error! The indicator period should exceed the current time frame 3 or more times!");
|
||||
return(false);
|
||||
}
|
||||
//--- the indicator period is correct for the current time frame
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Receive time data from the larger time frame |
|
||||
//+------------------------------------------------------------------+
|
||||
bool GetTimeData(void)
|
||||
{
|
||||
//--- reset the error value
|
||||
ResetLastError();
|
||||
//--- copy all data for the current time
|
||||
if(CopyTime(Symbol(),InpPeriod,InpDateStart,TimeCurrent(),ExtTimeBuff)==-1)
|
||||
{
|
||||
//--- receive the error code
|
||||
int code=GetLastError();
|
||||
//--- print out the error message
|
||||
PrintFormat("Data copy error! %s",code==4401
|
||||
? "History is still being uploaded!"
|
||||
: "Code = "+IntegerToString(code));
|
||||
//--- return false to make a repeated attempt to download data
|
||||
return(false);
|
||||
}
|
||||
//--- receive the array size
|
||||
ExtSize=ArraySize(ExtTimeBuff);
|
||||
//--- set the loop index for the array to zero
|
||||
ExtCount=0;
|
||||
//--- set the current candlestick's position on the time frame to zero
|
||||
ExtStartPos=0;
|
||||
ExtStartFlag=true;
|
||||
//--- store the last time value from the larger time frame
|
||||
ExtLastTime=ExtTimeBuff[ExtSize-1];
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+--------------------------------------------------------------------------+
|
||||
//| Function forms the main part of the candlestick. Depending on the flag's |
|
||||
//| value, the function defines what data and arrays are |
|
||||
//| to be used for correct display. |
|
||||
//+--------------------------------------------------------------------------+
|
||||
void FormCandleMain(double &body_fst[],double &body_snd[],
|
||||
double &shadow_fst[],double &shadow_snd[],
|
||||
const double fst_value,const double snd_value,
|
||||
const double fst_extremum,const double snd_extremum,
|
||||
const int start,const int count,const bool flag)
|
||||
{
|
||||
//--- check the flag's value
|
||||
if(flag)
|
||||
{
|
||||
//--- generate the candlestick's body
|
||||
FormMain(body_fst,body_snd,fst_value,snd_value,start,count);
|
||||
//--- generate the candlestick's shadow
|
||||
FormMain(shadow_fst,shadow_snd,fst_extremum,snd_extremum,start,count);
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- generate the candlestick's body
|
||||
FormMain(body_fst,body_snd,snd_value,fst_value,start,count);
|
||||
//--- generate the candlestick's shadow
|
||||
FormMain(shadow_fst,shadow_snd,snd_extremum,fst_extremum,start,count);
|
||||
}
|
||||
}
|
||||
//+--------------------------------------------------------------------------------+
|
||||
//| The function forms the end of the candlestick. Depending on the flag's value, |
|
||||
//| the function defines what data and arrays are |
|
||||
//| to be used for correct display. |
|
||||
//+--------------------------------------------------------------------------------+
|
||||
void FormCandleEnd(double &body_fst[],double &body_snd[],
|
||||
double &shadow_fst[],double &shadow_snd[],
|
||||
const double fst_value,const double snd_value,
|
||||
const double fst_extremum,const double snd_extremum,
|
||||
const int end,bool &flag)
|
||||
{
|
||||
//--- check the flag's value
|
||||
if(flag)
|
||||
{
|
||||
//--- generate the end of the candlestick's body
|
||||
FormEnd(body_fst,body_snd,fst_value,snd_value,end);
|
||||
//--- generate the end of the candlestick's shadow
|
||||
FormEnd(shadow_fst,shadow_snd,fst_extremum,snd_extremum,end);
|
||||
//--- change the flag's value to the opposite one
|
||||
flag=false;
|
||||
}
|
||||
else
|
||||
{
|
||||
//--- generate the end of the candlestick's body
|
||||
FormEnd(body_fst,body_snd,snd_value,fst_value,end);
|
||||
//--- generate the end of the candlestick's shadow
|
||||
FormEnd(shadow_fst,shadow_snd,snd_extremum,fst_extremum,end);
|
||||
//--- change the flag's value to the opposite one
|
||||
flag=true;
|
||||
}
|
||||
}
|
||||
//+-------------------------------------------------------------------------------------+
|
||||
//| Clear the end of the candlestick (the area between the last and the penultimate |
|
||||
//| bar) |
|
||||
//+-------------------------------------------------------------------------------------+
|
||||
void ClearEndOfBodyMain(const int ind)
|
||||
{
|
||||
ClearCandle(ExtBearBodyFirst,ExtBearBodySecond,ExtBearShadowFirst,ExtBearShadowSecond,ind,1);
|
||||
ClearCandle(ExtBullBodyFirst,ExtBullBodySecond,ExtBullShadowFirst,ExtBullShadowSecond,ind,1);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Clear the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void ClearCandle(double &body_fst[],double &body_snd[],double &shadow_fst[],
|
||||
double &shadow_snd[],const int start,const int count)
|
||||
{
|
||||
//--- check
|
||||
if(count!=0)
|
||||
{
|
||||
//--- fill indicator buffers with empty values
|
||||
ArrayFill(body_fst,start,count,INDICATOR_EMPTY_VALUE);
|
||||
ArrayFill(body_snd,start,count,INDICATOR_EMPTY_VALUE);
|
||||
ArrayFill(shadow_fst,start,count,INDICATOR_EMPTY_VALUE);
|
||||
ArrayFill(shadow_snd,start,count,INDICATOR_EMPTY_VALUE);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generate the main part of the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void FormMain(double &fst[],double &snd[],const double fst_value,
|
||||
const double snd_value,const int start,const int count)
|
||||
{
|
||||
//--- check
|
||||
if(count!=0)
|
||||
{
|
||||
//--- fill indicator buffers with values
|
||||
ArrayFill(fst,start,count,fst_value);
|
||||
ArrayFill(snd,start,count,snd_value);
|
||||
}
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Generate the end of the candlestick |
|
||||
//+------------------------------------------------------------------+
|
||||
void FormEnd(double &fst[],double &snd[],const double fst_value,
|
||||
const double snd_value,const int last)
|
||||
{
|
||||
//--- fill indicator buffers with values
|
||||
ArrayFill(fst,last-1,2,fst_value);
|
||||
ArrayFill(snd,last-1,2,snd_value);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Fill i element of the indicator buffers by empty values |
|
||||
//+------------------------------------------------------------------+
|
||||
void FillIndicatorBuffers(const int i)
|
||||
{
|
||||
//--- set an empty value in the cell of the indicator buffers
|
||||
ExtBearBodyFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearBodySecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBearShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodyFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodySecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodyEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullBodyEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowEndFirst[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtBullShadowEndSecond[i]=INDICATOR_EMPTY_VALUE;
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,109 @@
|
||||
# ArrayPrint
|
||||
|
||||
Prints an array of a simple type or a simple structure into journal.
|
||||
|
||||
```
|
||||
void ArrayPrint(
|
||||
const void& array[], // printed array
|
||||
uint digits=_Digits, // number of decimal places
|
||||
const string separator=NULL, // separator of the structure field values
|
||||
ulong start=0, // first printed element index
|
||||
ulong count=WHOLE_ARRAY, // number of printed elements
|
||||
ulong flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Array of a simple type or a [simple structure](/en/docs/basis/types/classes#simple_structure).
|
||||
|
||||
digits=_Digits
|
||||
|
||||
[in] The number of decimal places for real types. The default value is [_Digits](/en/docs/predefined/_digits).
|
||||
|
||||
separator=NULL
|
||||
|
||||
[in] Separator of the structure element field values. The default value [NULL](/en/docs/basis/types/void) means an empty line. A space is used as a separator in that case.
|
||||
|
||||
start=0
|
||||
|
||||
[in] The index of the first printed array element. It is printed from the zero index by default.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of the array elements to be printed. The entire array is displayed by default (count=[WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants)).
|
||||
|
||||
flags=ARRAYPRINT_HEADER|ARRAYPRINT_INDEX|ARRAYPRINT_LIMIT|ARRAYPRINT_ALIGN
|
||||
|
||||
[in] Combination of flags setting the output mode. All flags are enabled by default:
|
||||
|
||||
- ARRAYPRINT_HEADER – print headers for the structure array
|
||||
ARRAYPRINT_INDEX – print index at the left side
|
||||
ARRAYPRINT_LIMIT – print only the first 100 and the last 100 array elements. Use if you want to print only a part of a large array.
|
||||
ARRAYPRINT_ALIGN – enable alignment of the printed values – numbers are aligned to the right, while lines to the left.
|
||||
ARRAYPRINT_DATE – when printing datetime, print the date in the dd.mm.yyyy format
|
||||
ARRAYPRINT_MINUTES – when printing datetime, print the time in the HH:MM format
|
||||
ARRAYPRINT_SECONDS – when printing datetime, print the time in the HH:MM:SS format
|
||||
|
||||
Return Value
|
||||
|
||||
No
|
||||
|
||||
Note
|
||||
|
||||
ArrayPrint() does not print all structure array fields into journal – array and [object pointer](/en/docs/basis/types/object_pointers) fields are skipped. These columns are simply not printed for more convenient presentation. If you need to print all structure fields, you need to write your own mass print function with the desired formatting.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//--- print the values of the last 10 bars
|
||||
MqlRates rates[];
|
||||
if(CopyRates(_Symbol,_Period,1,10,rates))
|
||||
{
|
||||
ArrayPrint(rates);
|
||||
Print("Check\n[time]\t[open]\t[high]\t[low]\t[close]\t[tick_volume]\t[spread]\t[real_volume]");
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
PrintFormat("[%d]\t%s\t%G\t%G\t%G\t%G\t%G\t%G\t%I64d\t",i,
|
||||
TimeToString(rates[i].time,TIME_DATE|TIME_MINUTES|TIME_SECONDS),
|
||||
rates[i].open,rates[i].high,rates[i].low,rates[i].close,
|
||||
rates[i].tick_volume,rates[i].spread,rates[i].real_volume);
|
||||
}
|
||||
}
|
||||
else
|
||||
PrintFormat("CopyRates failed, error code=%d",GetLastError());
|
||||
//--- example of printing
|
||||
/*
|
||||
[time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume]
|
||||
[0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000
|
||||
[1] 2016.11.09 05:00:00 1.12296 1.12825 1.11930 1.12747 17829 9 15632176000
|
||||
[2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000
|
||||
[3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000
|
||||
[4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000
|
||||
[5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000
|
||||
[6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000
|
||||
[7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000
|
||||
[8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000
|
||||
[9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000
|
||||
Check
|
||||
[time] [open] [high] [low] [close] [tick_volume] [spread] [real_volume]
|
||||
[0] 2016.11.09 04:00:00 1.11242 1.12314 1.11187 1.12295 18110 10 17300175000
|
||||
[1] 2016.11.09 05:00:00 1.12296 1.12825 1.1193 1.12747 17829 9 15632176000
|
||||
[2] 2016.11.09 06:00:00 1.12747 1.12991 1.12586 1.12744 13458 10 9593492000
|
||||
[3] 2016.11.09 07:00:00 1.12743 1.12763 1.11988 1.12194 15362 9 12352245000
|
||||
[4] 2016.11.09 08:00:00 1.12194 1.12262 1.11058 1.11172 16833 9 12961333000
|
||||
[5] 2016.11.09 09:00:00 1.11173 1.11348 1.10803 1.11052 15933 8 10720384000
|
||||
[6] 2016.11.09 10:00:00 1.11052 1.11065 1.10289 1.10528 11888 9 8084811000
|
||||
[7] 2016.11.09 11:00:00 1.10512 1.11041 1.10472 1.10915 7284 10 5087113000
|
||||
[8] 2016.11.09 12:00:00 1.10915 1.11079 1.10892 1.10904 8710 9 6769629000
|
||||
[9] 2016.11.09 13:00:00 1.10904 1.10913 1.10223 1.10263 8956 7 7192138000
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[FileSave](/en/docs/files/filesave), [FileLoad](/en/docs/files/fileload)
|
||||
@@ -0,0 +1,56 @@
|
||||
# ArrayRange
|
||||
|
||||
The function returns the number of elements in a selected array dimension.
|
||||
|
||||
```
|
||||
int ArrayRange(
|
||||
const void& array[], // array for check
|
||||
int rank_index // index of dimension
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Checked array.
|
||||
|
||||
rank_index
|
||||
|
||||
[in] Index of dimension.
|
||||
|
||||
Return Value
|
||||
|
||||
Number of elements in a selected array dimension.
|
||||
|
||||
Note
|
||||
|
||||
Since indexes start at zero, the number of the array dimensions is one greater than the index of the last dimension.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
void OnStart()
|
||||
{
|
||||
//--- create four-dimensional array
|
||||
double array[][5][2][4];
|
||||
//--- set the size of the zero dimension
|
||||
ArrayResize(array,10,10);
|
||||
//--- print dimensions
|
||||
int temp;
|
||||
for(int i=0;i<4;i++)
|
||||
{
|
||||
//--- receive the size of i dimension
|
||||
temp=ArrayRange(array,i);
|
||||
//--- print
|
||||
PrintFormat("dim = %d, range = %d",i,temp);
|
||||
}
|
||||
//--- Result
|
||||
// dim = 0, range = 10
|
||||
// dim = 1, range = 5
|
||||
// dim = 2, range = 2
|
||||
// dim = 3, range = 4
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,119 @@
|
||||
# ArrayResize
|
||||
|
||||
The function sets a new size for the first dimension
|
||||
|
||||
```
|
||||
int ArrayResize(
|
||||
void& array[], // array passed by reference
|
||||
int new_size, // new array size
|
||||
int reserve_size=0 // reserve size value (excess)
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[out] Array for changing sizes.
|
||||
|
||||
new_size
|
||||
|
||||
[in] New size for the first dimension.
|
||||
|
||||
reserve_size=0
|
||||
|
||||
[in] Distributed size to get reserve.
|
||||
|
||||
Return Value
|
||||
|
||||
If executed successfully, it returns count of all elements contained in the array after resizing, otherwise, returns -1, and array is not resized.
|
||||
|
||||
If ArrayResize() is applied to a [static](/en/docs/basis/types/dynamic_array#static_array) array, a [timeseries](/en/docs/series/bufferdirection) or an [indicator buffer](/en/docs/customind/setindexbuffer), the array size remains the same – these arrays will not be reallocated. In this case, if new_size<=[ArraySize(](/en/docs/array/arraysize)array[)](/en/docs/array/arrayresize), the function will only return new_size; otherwise a value of -1 will be returned.
|
||||
|
||||
Note
|
||||
|
||||
The function can be applied only to [dynamic arrays](/en/docs/basis/types/dynamic_array). It should be noted that you cannot change the size of dynamic arrays assigned as indicator buffers by the [SetIndexBuffer()](/en/docs/customind/setindexbuffer) function. For indicator buffers, all operations of resizing are performed by the runtime subsystem of the terminal.
|
||||
|
||||
Total amount of elements in the array cannot exceed 2147483647.
|
||||
|
||||
With the frequent memory allocation, it is recommended to use a third parameter that sets a reserve to reduce the number of physical memory allocations. All the subsequent calls of ArrayResize do not lead to physical reallocation of memory, but only change the size of the first array dimension within the reserved memory. It should be remembered that the third parameter will be used only during physical memory allocation. For example:
|
||||
|
||||
```
|
||||
ArrayResize(arr,1000,1000);
|
||||
for(int i=1;i<3000;i++)
|
||||
ArrayResize(arr,i,1000);
|
||||
|
||||
```
|
||||
|
||||
In this case the memory will be reallocated twice, first before entering the 3000 iterations loop (the array size will be set to 1000), and the second time with i equal to 2000. If we skip the third parameter, there will be 2000 physical reallocations of memory, which will slow down the program.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
//--- Counters
|
||||
ulong start=GetTickCount();
|
||||
ulong now;
|
||||
int count=0;
|
||||
//--- An array for demonstration of a quick version
|
||||
double arr[];
|
||||
ArrayResize(arr,100000,100000);
|
||||
//--- Check how fast the variant with memory reservation works
|
||||
Print("--- Test Fast: ArrayResize(arr,100000,100000)");
|
||||
for(int i=1;i<=300000;i++)
|
||||
{
|
||||
//--- Set a new array size specifying the reserve of 100,000 elements!
|
||||
ArrayResize(arr,i,100000);
|
||||
//--- When reaching a round number, show the array size and the time spent
|
||||
if(ArraySize(arr)%100000==0)
|
||||
{
|
||||
now=GetTickCount();
|
||||
count++;
|
||||
PrintFormat("%d. ArraySize(arr)=%d Time=%d ms",count,ArraySize(arr),(now-start));
|
||||
start=now;
|
||||
}
|
||||
}
|
||||
//--- Now show, how slow the version without memory reservation is
|
||||
double slow[];
|
||||
ArrayResize(slow,100000,100000);
|
||||
//---
|
||||
count=0;
|
||||
start=GetTickCount();
|
||||
Print("---- Test Slow: ArrayResize(slow,100000)");
|
||||
//---
|
||||
for(int i=1;i<=300000;i++)
|
||||
{
|
||||
//--- Set a new array size, but without the additional reserve
|
||||
ArrayResize(slow,i);
|
||||
//--- When reaching a round number, show the array size and the time spent
|
||||
if(ArraySize(slow)%100000==0)
|
||||
{
|
||||
now=GetTickCount();
|
||||
count++;
|
||||
PrintFormat("%d. ArraySize(slow)=%d Time=%d ms",count,ArraySize(slow),(now-start));
|
||||
start=now;
|
||||
}
|
||||
}
|
||||
}
|
||||
//--- A sample result of the script
|
||||
/*
|
||||
Test_ArrayResize (EURUSD,H1) --- Test Fast: ArrayResize(arr,100000,100000)
|
||||
Test_ArrayResize (EURUSD,H1) 1. ArraySize(arr)=100000 Time=0 ms
|
||||
Test_ArrayResize (EURUSD,H1) 2. ArraySize(arr)=200000 Time=0 ms
|
||||
Test_ArrayResize (EURUSD,H1) 3. ArraySize(arr)=300000 Time=0 ms
|
||||
Test_ArrayResize (EURUSD,H1) ---- Test Slow: ArrayResize(slow,100000)
|
||||
Test_ArrayResize (EURUSD,H1) 1. ArraySize(slow)=100000 Time=0 ms
|
||||
Test_ArrayResize (EURUSD,H1) 2. ArraySize(slow)=200000 Time=0 ms
|
||||
Test_ArrayResize (EURUSD,H1) 3. ArraySize(slow)=300000 Time=228511 ms
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayInitialize](/en/docs/array/arrayinitialize)
|
||||
@@ -0,0 +1,96 @@
|
||||
# ArrayInsert
|
||||
|
||||
Inserts the specified number of elements from a source array to a receiving one starting from a specified index.
|
||||
|
||||
```
|
||||
bool ArrayInsert(
|
||||
void& dst_array[], // receiving array
|
||||
const void& src_array[], // source array
|
||||
uint dst_start, // receiver array index to be inserted
|
||||
uint src_start=0, // source array index to be copied
|
||||
uint count=WHOLE_ARRAY // number of elements to insert
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
dst_array[]
|
||||
|
||||
[in][out] Receiving array the elements should be added to.
|
||||
|
||||
src_array[]
|
||||
|
||||
[in] Source array the elements are to be added from.
|
||||
|
||||
dst_start
|
||||
|
||||
[in] Index in the receiving array for inserting elements from the source array.
|
||||
|
||||
src_start=0
|
||||
|
||||
[in] Index in the source array, starting from which the elements of the source array are taken for insertion.
|
||||
|
||||
count
|
||||
|
||||
[in] Number of elements to be added from the source array. The [WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants) means all elements from the specified index up to the end of the array.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful, otherwise - false. To get information about the error, call the [GetLastError()](/en/docs/check/getlasterror) function. Possible errors:
|
||||
|
||||
- 5052 – ERR_SMALL_ARRAY (the start and/or count parameters are set incorrectly or the src_array[] source array is empty),
|
||||
- 5056 – ERR_SERIES_ARRAY (the array cannot be changed, indicator buffer),
|
||||
- 4006 – ERR_INVALID_ARRAY (copying to oneself is not allowed, or the arrays are of different types, or there is a fixed-size array containing class objects or destructor structures),
|
||||
- 4005 - ERR_STRUCT_WITHOBJECTS_ORCLASS (the array contains no [POD structures](/en/docs/basis/types/classes#simple_structure) meaning a simple copying is impossible),
|
||||
- Errors occurred when changing the dst_array[] receiving array size are provided in the [ArrayRemove()](/en/docs/array/arrayremove) function description.
|
||||
|
||||
Note
|
||||
|
||||
If the function is used for a fixed-size array, the size of the dst_array[] receiving array itself does not change. Starting from the dst_start position, the elements of the receiving array are shifted to the right (the last counts of the elements "come off"), while the elements copied from the source array take their place.
|
||||
|
||||
You cannot insert the elements to the dynamic arrays designated as the indicator buffers by the [SetIndexBuffer()](/en/docs/customind/setindexbuffer) function. For indicator buffers, all size changing operations are performed by the terminal's executing subsystem.
|
||||
|
||||
In the source array, the elements are copied starting from the src_start index. The source array size remains unchanged. The elements to be added to the receiving array are not links to the source array elements. This means that subsequent changes of the elements in any of the two arrays are not reflected in the second one.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
//--- declare the fixed-size array and fill in the values
|
||||
int array_dest[10];
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
array_dest[i]=i;
|
||||
}
|
||||
//--- source array
|
||||
int array_source[10];
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
array_source[i]=10+i;
|
||||
}
|
||||
//--- display arrays before inserting the elements
|
||||
Print("Before calling ArrayInsert()");
|
||||
ArrayPrint(array_dest);
|
||||
ArrayPrint(array_source);
|
||||
//--- insert 3 elements from the source array and show the new set of the receiving array
|
||||
ArrayInsert(array_dest,array_source,4,0,3);
|
||||
Print("After calling ArrayInsert()");
|
||||
ArrayPrint(array_dest);
|
||||
/*
|
||||
Execution result
|
||||
Before calling ArrayInsert()
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
After calling ArrayInsert()
|
||||
0 1 2 3 10 11 12 7 8 9
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayRemove](/en/docs/array/arrayremove),[ ArrayCopy](/en/docs/array/arraycopy), [ArrayResize](/en/docs/array/arrayresize), [ArrayFree](/en/docs/array/arrayfree)
|
||||
@@ -0,0 +1,77 @@
|
||||
# ArrayRemove
|
||||
|
||||
Removes the specified number of elements from the array starting with a specified index.
|
||||
|
||||
```
|
||||
bool ArrayRemove(
|
||||
void& array[], // array of any type
|
||||
uint start, // index the removal starts from
|
||||
uint count=WHOLE_ARRAY // number of elements
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in][out] Array.
|
||||
|
||||
start
|
||||
|
||||
[in] Index, starting from which the array elements are removed.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of removed elements. The [WHOLE_ARRAY](/en/docs/constants/namedconstants/otherconstants) value means removing all elements from the specified index up the end of the array.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful, otherwise - false. To get information about the error, call the [GetLastError()](/en/docs/check/getlasterror) function. Possible errors:
|
||||
|
||||
- 5052 – ERR_SMALL_ARRAY (too big start value),
|
||||
- 5056 – ERR_SERIES_ARRAY (the array cannot be changed, indicator buffer),
|
||||
- 4003 – ERR_INVALID_PARAMETER (too big count value),
|
||||
- 4005 - ERR_STRUCT_WITHOBJECTS_ORCLASS (fixed-size array containing complex objects with the destructor),
|
||||
- 4006 - ERR_INVALID_ARRAY (fixed-size array containing structure or class objects with a destructor).
|
||||
|
||||
Note
|
||||
|
||||
If the function is used for a fixed-size array, the array size does not change: the remaining "tail" is physically copied to the start position. For accurate understanding of how the function works, see the example below. "Physical" copying means the copied objects are not created by calling the constructor or copying operator. Instead, the binary representation of an object is copied. For this reason, you cannot apply the ArrayRemove() function to the fixed-size array containing objects with the destructor (the ERR_INVALID_ARRAY or ERR_STRUCT_WITHOBJECTS_ORCLASS error is activated). When removing such an object, the destructor should be called twice – for the original object and its copy.
|
||||
|
||||
You cannot remove elements from dynamic arrays designated as the indicator buffers by the [SetIndexBuffer()](/en/docs/customind/setindexbuffer) function. This will result in the ERR_SERIES_ARRAY error. For indicator buffers, all size changing operations are performed by the terminal's executing subsystem.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
//--- declare the fixed-size array and fill in the values
|
||||
int array[10];
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
array[i]=i;
|
||||
}
|
||||
//--- display the array before removing the elements
|
||||
Print("Before calling ArrayRemove()");
|
||||
ArrayPrint(array);
|
||||
//--- delete 2 elements from the array and display the new set
|
||||
ArrayRemove(array,4,2);
|
||||
Print("After calling ArrayRemove()");
|
||||
ArrayPrint(array);
|
||||
/*
|
||||
Execution result:
|
||||
Before calling ArrayRemove()
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
After calling ArrayRemove()
|
||||
0 1 2 3 6 7 8 9 8 9
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayInsert](/en/docs/array/arrayinsert),[ ArrayCopy](/en/docs/array/arraycopy), [ArrayResize](/en/docs/array/arrayresize), [ArrayFree](/en/docs/array/arrayfree)
|
||||
@@ -0,0 +1,69 @@
|
||||
# ArrayReverse
|
||||
|
||||
Reverses the specified number of elements in the array starting with a specified index.
|
||||
|
||||
```
|
||||
bool ArrayReverse(
|
||||
void& array[], // array of any type
|
||||
uint start=0, // index to start reversing the array from
|
||||
uint count=WHOLE_ARRAY // number of elements
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in][out] Array.
|
||||
|
||||
start=0
|
||||
|
||||
[in] Index the array reversal starts from.
|
||||
|
||||
count=WHOLE_ARRAY
|
||||
|
||||
[in] Number of reversed elements. If WHOLE_ARRAY, then all array elements are moved in the inversed manner starting with the specified start index up to the end of the array.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful, otherwise - false.
|
||||
|
||||
Note
|
||||
|
||||
The [ArraySetAsSeries()](/en/docs/array/arraysetasseries) function does not move the array elements physically. Instead, it only changes the indexation direction backwards to arrange the access to the elements as in the [timeseries](/en/docs/series). The ArrayReverse() function physically moves the array elements so that the array is "reversed".
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
//--- declare the fixed-size array and fill in the values
|
||||
int array[10];
|
||||
for(int i=0;i<10;i++)
|
||||
{
|
||||
array[i]=i;
|
||||
}
|
||||
//--- display the array before reversing the elements
|
||||
Print("Before calling ArrayReverse()");
|
||||
ArrayPrint(array);
|
||||
//--- reverse 3 elements in the array and show the new set
|
||||
ArrayReverse(array,4,3);
|
||||
Print("After calling ArrayReverse()");
|
||||
ArrayPrint(array);
|
||||
/*
|
||||
Execution result:
|
||||
Before calling ArrayReverse()
|
||||
0 1 2 3 4 5 6 7 8 9
|
||||
After calling ArrayReverse()
|
||||
0 1 2 3 6 5 4 7 8 9
|
||||
*/
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayInsert](/en/docs/array/arrayinsert), [ArrayRemove](/en/docs/array/arrayremove), [ArrayCopy](/en/docs/array/arraycopy), [ArrayResize](/en/docs/array/arrayresize), [ArrayFree](/en/docs/array/arrayfree), [ArrayGetAsSeries](/en/docs/array/arraygetasseries), [ArraySetAsSeries](/en/docs/array/arraysetasseries)
|
||||
@@ -0,0 +1,94 @@
|
||||
# ArraySetAsSeries
|
||||
|
||||
The function sets the AS_SERIES flag to a selected [object of a dynamic array](/en/docs/basis/types/dynamic_array), and elements will be indexed like in [timeseries](/en/docs/series).
|
||||
|
||||
```
|
||||
bool ArraySetAsSeries(
|
||||
const void& array[], // array by reference
|
||||
bool flag // true denotes reverse order of indexing
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in][out] Numeric array to set.
|
||||
|
||||
flag
|
||||
|
||||
[in] Array indexing direction.
|
||||
|
||||
Return Value
|
||||
|
||||
The function returns true on success, otherwise - false.
|
||||
|
||||
Note
|
||||
|
||||
The [AS_SERIES](/en/docs/array/arraygetasseries) flag can't be set for multi-dimensional arrays or static arrays (arrays, whose size in square brackets is preset already on the compilation stage). Indexing in timeseries differs from a common array in that the elements of timeseries are indexed from the end towards the beginning (from the newest to oldest data).
|
||||
|
||||
Example: Indicator that shows bar number
|
||||
|
||||

|
||||
|
||||
```
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 1
|
||||
#property indicator_plots 1
|
||||
//---- plot Numeration
|
||||
#property indicator_label1 "Numeration"
|
||||
#property indicator_type1 DRAW_LINE
|
||||
#property indicator_color1 CLR_NONE
|
||||
//--- indicator buffers
|
||||
double NumerationBuffer[];
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- indicator buffers mapping
|
||||
SetIndexBuffer(0,NumerationBuffer,INDICATOR_DATA);
|
||||
//--- set indexing for the buffer like in timeseries
|
||||
ArraySetAsSeries(NumerationBuffer,true);
|
||||
//--- set accuracy of showing in DataWindow
|
||||
IndicatorSetInteger(INDICATOR_DIGITS,0);
|
||||
//--- how the name of the indicator array is displayed in DataWindow
|
||||
PlotIndexSetString(0,PLOT_LABEL,"Bar #");
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
//--- we'll store the time of the current zero bar opening
|
||||
static datetime currentBarTimeOpen=0;
|
||||
//--- revert access to array time[] - do it like in timeseries
|
||||
ArraySetAsSeries(time,true);
|
||||
//--- If time of zero bar differs from the stored one
|
||||
if(currentBarTimeOpen!=time[0])
|
||||
{
|
||||
//--- enumerate all bars from the current to the chart depth
|
||||
for(int i=rates_total-1;i>=0;i--) NumerationBuffer[i]=i;
|
||||
currentBarTimeOpen=time[0];
|
||||
}
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[Access to timeseries](/en/docs/series), [ArrayGetAsSeries](/en/docs/array/arraygetasseries)
|
||||
@@ -0,0 +1,71 @@
|
||||
# ArraySize
|
||||
|
||||
The function returns the number of elements of a selected array.
|
||||
|
||||
```
|
||||
int ArraySize(
|
||||
const void& array[] // checked array
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in] Array of any type.
|
||||
|
||||
Return Value
|
||||
|
||||
Value of [int](/en/docs/basis/types/integer/integertypes) type.
|
||||
|
||||
Note
|
||||
|
||||
For a one-dimensional array, the value to be returned by the ArraySize is equal to that of [ArrayRange](/en/docs/array/arrayrange)(array,0).
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
void OnStart()
|
||||
{
|
||||
//--- create arrays
|
||||
double one_dim[];
|
||||
double four_dim[][10][5][2];
|
||||
//--- sizes
|
||||
int one_dim_size=25;
|
||||
int reserve=20;
|
||||
int four_dim_size=5;
|
||||
//--- auxiliary variable
|
||||
int size;
|
||||
//--- allocate memory without backup
|
||||
ArrayResize(one_dim,one_dim_size);
|
||||
ArrayResize(four_dim,four_dim_size);
|
||||
//--- 1. one-dimensional array
|
||||
Print("+==========================================================+");
|
||||
Print("Array sizes:");
|
||||
Print("1. One-dimensional array");
|
||||
size=ArraySize(one_dim);
|
||||
PrintFormat("Zero dimension size = %d, Array size = %d",one_dim_size,size);
|
||||
//--- 2. multidimensional array
|
||||
Print("2. Multidimensional array");
|
||||
size=ArraySize(four_dim);
|
||||
PrintFormat("Zero dimension size = %d, Array size = %d",four_dim_size,size);
|
||||
//--- dimension sizes
|
||||
int d_1=ArrayRange(four_dim,1);
|
||||
int d_2=ArrayRange(four_dim,2);
|
||||
int d_3=ArrayRange(four_dim,3);
|
||||
Print("Check:");
|
||||
Print("Zero dimension = Array size / (First dimension * Second dimension * Third dimension)");
|
||||
PrintFormat("%d = %d / (%d * %d * %d)",size/(d_1*d_2*d_3),size,d_1,d_2,d_3);
|
||||
//--- 3. one-dimensional array with memory backup
|
||||
Print("3. One-dimensional array with memory backup");
|
||||
//--- double the value
|
||||
one_dim_size*=2;
|
||||
//--- allocate memory with backup
|
||||
ArrayResize(one_dim,one_dim_size,reserve);
|
||||
//--- print out the size
|
||||
size=ArraySize(one_dim);
|
||||
PrintFormat("Size with backup = %d, Actual array size = %d",one_dim_size+reserve,size);
|
||||
}
|
||||
|
||||
```
|
||||
@@ -0,0 +1,218 @@
|
||||
# ArraySort
|
||||
|
||||
Sorts the values in the first dimension of a multidimensional numeric array in the ascending order.
|
||||
|
||||
```
|
||||
bool ArraySort(
|
||||
void& array[] // array for sorting
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array[]
|
||||
|
||||
[in][out] Numeric array for sorting.
|
||||
|
||||
Return Value
|
||||
|
||||
The function returns true on success, otherwise - false.
|
||||
|
||||
Note
|
||||
|
||||
An array is always sorted in the ascending order irrespective of the [AS_SERIES](/en/docs/array/arraygetasseries) flag value.
|
||||
|
||||
Functions ArraySort and ArrayBSearch accept any-dimensional arrays as a parameter. However, searching and sorting are always applied to the first (zero) dimension.
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
#property description "The indicator analyzes data for the last month and draws all candlesticks with small"
|
||||
#property description "and large tick volumes. The tick volume array is sorted out"
|
||||
#property description "to define such candlesticks. The candlesticks having the volumes comprising the first InpSmallVolume"
|
||||
#property description "per cent of the array are considered small. The candlesticks having the tick volumes comprising "
|
||||
#property description "the last InpBigVolume per cent of the array are considered large."
|
||||
//--- indicator settings
|
||||
#property indicator_chart_window
|
||||
#property indicator_buffers 5
|
||||
#property indicator_plots 1
|
||||
//--- plot
|
||||
#property indicator_label1 "VolumeFactor"
|
||||
#property indicator_type1 DRAW_COLOR_CANDLES
|
||||
#property indicator_color1 clrDodgerBlue,clrOrange
|
||||
#property indicator_style1 STYLE_SOLID
|
||||
#property indicator_width1 2
|
||||
//--- predefined constant
|
||||
#define INDICATOR_EMPTY_VALUE 0.0
|
||||
//--- input parameters
|
||||
input int InpSmallVolume=15; // Percentage value of small volumes (<50)
|
||||
input int InpBigVolume=20; // Percentage value of large volumes (<50)
|
||||
//--- analysis start time (will be shifted)
|
||||
datetime ExtStartTime;
|
||||
//--- indicator buffers
|
||||
double ExtOpenBuff[];
|
||||
double ExtHighBuff[];
|
||||
double ExtLowBuff[];
|
||||
double ExtCloseBuff[];
|
||||
double ExtColorBuff[];
|
||||
//--- volume boundary values for displaying the candlesticks
|
||||
long ExtLeftBorder=0;
|
||||
long ExtRightBorder=0;
|
||||
//+------------------------------------------------------------------+
|
||||
//| Receive border values for tick volumes |
|
||||
//+------------------------------------------------------------------+
|
||||
bool GetVolumeBorders(void)
|
||||
{
|
||||
//--- variables
|
||||
datetime stop_time; // copy end time
|
||||
long buff[]; // buffer for copying
|
||||
//--- end time is the current one
|
||||
stop_time=TimeCurrent();
|
||||
//--- start time is one month earlier from the current one
|
||||
ExtStartTime=GetStartTime(stop_time);
|
||||
//--- receive the values of tick volumes
|
||||
ResetLastError();
|
||||
if(CopyTickVolume(Symbol(),Period(),ExtStartTime,stop_time,buff)==-1)
|
||||
{
|
||||
//--- failed to receive the data, return false to launch recalculation command
|
||||
PrintFormat("Failed to receive tick volume values. Error code = %d",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
//--- calculate array size
|
||||
int size=ArraySize(buff);
|
||||
//--- sort out the array
|
||||
ArraySort(buff);
|
||||
//--- define the values of the left and right border for tick volumes
|
||||
ExtLeftBorder=buff[size*InpSmallVolume/100];
|
||||
ExtRightBorder=buff[(size-1)*(100-InpBigVolume)/100];
|
||||
//--- successful execution
|
||||
return(true);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Receive the data that is one month less than the passed one |
|
||||
//+------------------------------------------------------------------+
|
||||
datetime GetStartTime(const datetime stop_time)
|
||||
{
|
||||
//--- convert end time into MqlDateTime type structure variable
|
||||
MqlDateTime temp;
|
||||
TimeToStruct(stop_time,temp);
|
||||
//--- receive the data that is one month less
|
||||
if(temp.mon>1)
|
||||
temp.mon-=1; // the current month is not the first one in the year, therefore, the number of the previous one is one less
|
||||
else
|
||||
{
|
||||
temp.mon=12; // the current month is the first in the year, therefore, the number of the previous one is 12,
|
||||
temp.year-=1; // while the year number is one less
|
||||
}
|
||||
//--- day number will not exceed 28
|
||||
if(temp.day>28)
|
||||
temp.day=28;
|
||||
//--- return the obtained date
|
||||
return(StructToTime(temp));
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| Custom indicator initialization function |
|
||||
//+------------------------------------------------------------------+
|
||||
int OnInit()
|
||||
{
|
||||
//--- check if input parameters satisfy the conditions
|
||||
if(InpSmallVolume<0 || InpSmallVolume>=50 || InpBigVolume<0 || InpBigVolume>=50)
|
||||
{
|
||||
Print("Incorrect input parameters");
|
||||
return(INIT_PARAMETERS_INCORRECT);
|
||||
}
|
||||
//--- indicator buffers mapping
|
||||
SetIndexBuffer(0,ExtOpenBuff);
|
||||
SetIndexBuffer(1,ExtHighBuff);
|
||||
SetIndexBuffer(2,ExtLowBuff);
|
||||
SetIndexBuffer(3,ExtCloseBuff);
|
||||
SetIndexBuffer(4,ExtColorBuff,INDICATOR_COLOR_INDEX);
|
||||
//--- set the value that will not be displayed
|
||||
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
|
||||
//--- set labels for indicator buffers
|
||||
PlotIndexSetString(0,PLOT_LABEL,"Open;High;Low;Close");
|
||||
//---
|
||||
return(INIT_SUCCEEDED);
|
||||
}
|
||||
//+------------------------------------------------------------------+
|
||||
//| 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[])
|
||||
{
|
||||
//--- check if unhandled bars are still present
|
||||
if(prev_calculated<rates_total)
|
||||
{
|
||||
//--- receive new values of the right and left borders for volumes
|
||||
if(!GetVolumeBorders())
|
||||
return(0);
|
||||
}
|
||||
//--- start variable for bar calculation
|
||||
int start=prev_calculated;
|
||||
//--- work at the last bar if the indicator values have already been calculated at the previous tick
|
||||
if(start>0)
|
||||
start--;
|
||||
//--- set direct indexing in time series
|
||||
ArraySetAsSeries(time,false);
|
||||
ArraySetAsSeries(open,false);
|
||||
ArraySetAsSeries(high,false);
|
||||
ArraySetAsSeries(low,false);
|
||||
ArraySetAsSeries(close,false);
|
||||
ArraySetAsSeries(tick_volume,false);
|
||||
//--- the loop of calculation of the indicator values
|
||||
for(int i=start;i<rates_total;i++)
|
||||
{
|
||||
//--- fill out candlesticks starting from the initial date
|
||||
if(ExtStartTime<=time[i])
|
||||
{
|
||||
//--- if the value is not less than the right border, fill out the candlestick
|
||||
if(tick_volume[i]>=ExtRightBorder)
|
||||
{
|
||||
//--- receive data for drawing the candlestick
|
||||
ExtOpenBuff[i]=open[i];
|
||||
ExtHighBuff[i]=high[i];
|
||||
ExtLowBuff[i]=low[i];
|
||||
ExtCloseBuff[i]=close[i];
|
||||
//--- DodgerBlue color
|
||||
ExtColorBuff[i]=0;
|
||||
//--- continue the loop
|
||||
continue;
|
||||
}
|
||||
//--- fill out the candlestick if the value does not exceed the left border
|
||||
if(tick_volume[i]<=ExtLeftBorder)
|
||||
{
|
||||
//--- receive data for drawing the candlestick
|
||||
ExtOpenBuff[i]=open[i];
|
||||
ExtHighBuff[i]=high[i];
|
||||
ExtLowBuff[i]=low[i];
|
||||
ExtCloseBuff[i]=close[i];
|
||||
//--- Orange color
|
||||
ExtColorBuff[i]=1;
|
||||
//--- continue the loop
|
||||
continue;
|
||||
}
|
||||
}
|
||||
//--- set empty values for bars that have not been included in the calculation
|
||||
ExtOpenBuff[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtHighBuff[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtLowBuff[i]=INDICATOR_EMPTY_VALUE;
|
||||
ExtCloseBuff[i]=INDICATOR_EMPTY_VALUE;
|
||||
}
|
||||
//--- return value of prev_calculated for next call
|
||||
return(rates_total);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayBsearch](/en/docs/array/arraybsearch)
|
||||
@@ -0,0 +1,81 @@
|
||||
# ArraySwap
|
||||
|
||||
Swaps the contents of two dynamic arrays of the same type. For multidimensional arrays, the number of elements in all dimensions except the first one should match.
|
||||
|
||||
```
|
||||
bool ArraySwap(
|
||||
void& array1[], // first array
|
||||
void& array2[] // second array
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
array1[]
|
||||
|
||||
[in][out] Array of numerical type.
|
||||
|
||||
array2[]
|
||||
|
||||
[in][out] Array of numerical type.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful, otherwise false. In this case, [GetLastError()](/en/docs/check/getlasterror) returns the [ERR_INVALID_ARRAY](/en/docs/constants/errorswarnings/errorcodes) error code.
|
||||
|
||||
Note
|
||||
|
||||
The function accepts dynamic arrays of the same type and the same dimensions except the first one. For integer types, the sign is ignored, i.e. [char](/en/docs/basis/types/integer/integertypes)==uchar)
|
||||
|
||||
Example:
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| Script program start function |
|
||||
//+------------------------------------------------------------------+
|
||||
void OnStart()
|
||||
{
|
||||
//--- arrays for storing quotes
|
||||
double source_array[][8];
|
||||
double dest_array[][8];
|
||||
MqlRates rates[];
|
||||
//--- get the data of the last 20 candles on the current timeframe
|
||||
int copied=CopyRates(NULL,0,0,20,rates);
|
||||
if(copied<=0)
|
||||
{
|
||||
PrintFormat("CopyRates(%s,0,0,20,rates) failed, error=%d",
|
||||
Symbol(),GetLastError());
|
||||
return;
|
||||
}
|
||||
//--- set the array size for the amount of copied data
|
||||
ArrayResize(source_array,copied);
|
||||
//--- fill the rate_array_1[] array by data from rates[]
|
||||
for(int i=0;i<copied;i++)
|
||||
{
|
||||
source_array[i][0]=(double)rates[i].time;
|
||||
source_array[i][1]=rates[i].open;
|
||||
source_array[i][2]=rates[i].high;
|
||||
source_array[i][3]=rates[i].low;
|
||||
source_array[i][4]=rates[i].close;
|
||||
source_array[i][5]=(double)rates[i].tick_volume;
|
||||
source_array[i][6]=(double)rates[i].spread;
|
||||
source_array[i][7]=(double)rates[i].real_volume;
|
||||
}
|
||||
//--- swap data between source_array[] and dest_array[]
|
||||
if(!ArraySwap(source_array,dest_array))
|
||||
{
|
||||
PrintFormat("ArraySwap(source_array,rate_array_2) failed, error code=%d",GetLastError());
|
||||
return;
|
||||
}
|
||||
//--- ensure that the source array has become zero after the swap
|
||||
PrintFormat("ArraySwap() done: ArraySize(source_array)=%d",ArraySize(source_array));
|
||||
//--- display the data of the dest_array[] destination array
|
||||
ArrayPrint(dest_array);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayCopy](/en/docs/array/arraycopy), [ArrayFill](/en/docs/array/arrayfill), [ArrayRange](/en/docs/array/arrayrange), [ArrayIsDynamic](/en/docs/array/arrayisdynamic)
|
||||
@@ -0,0 +1,114 @@
|
||||
# ArrayToFP16
|
||||
|
||||
Copies an array of type float or double into an array of type [ushort](/en/docs/basis/types/integer/integertypes#ushort) with the given format.
|
||||
|
||||
```
|
||||
bool ArrayToFP16(
|
||||
const ushort& dst_array[], // copy to
|
||||
const float& src_array[], // copy from
|
||||
ENUM_FLOAT16_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Overloading for the double type
|
||||
|
||||
```
|
||||
bool ArrayToFP16(
|
||||
const ushort& dst_array[], // copy to
|
||||
const double& src_array[], // copy from
|
||||
ENUM_FLOAT16_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
dst_array[]
|
||||
|
||||
[out] Receiver array or type ushort.
|
||||
|
||||
src_array[]
|
||||
|
||||
[in] Source array of type float or double.
|
||||
|
||||
fmt
|
||||
|
||||
[in] Copying format from the [ENUM_FLOAT16_FORMAT](/en/docs/onnx/onnx_structures#enum_float16_format) enumeration.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful or false otherwise.
|
||||
|
||||
Note
|
||||
|
||||
Formats FLOAT16 and BFLOAT16 are defined in the [ENUM_FLOAT16_FORMAT](/en/docs/onnx/onnx_structures#enum_float16_format) enumeration and are used in MQL5 only for operations with [ONNX models](/en/docs/onnx).
|
||||
|
||||
The function converts input parameters of type float or double to type FLOAT16 and BFLOAT16. These input parameters are then used in the [OnnxRun](/en/docs/onnx/onnxrun) function.
|
||||
|
||||
FLOAT16, also known as [half-precision float](https://en.wikipedia.org/wiki/Half-precision_floating-point_format), uses 16 bits to represent floating-point numbers. This format provides a balance between accuracy and computational efficiency. FLOAT16 is widely used in deep learning algorithms and neural networks, which require high-performance processing of large datasets. This format accelerates computations calculations by reducing the size of numbers, which is especially important when training deep neural networks on GPUs.
|
||||
|
||||
BFLOAT16 (or [Brain Floating Point 16](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format)) also uses 16 bits but differs from FLOAT16 in the approach to format representation. In this format, 8 bits are allocated for representing the exponent, while the remaining 7 bits are used for representing the mantissa. This format was developed for use in deep learning and artificial intelligence, especially in Google's Tensor Processing Unit (TPU). BFLOAT16 demonstrates excellent performance in neural network training and can effectively accelerate computations.
|
||||
|
||||
Example: function from the article [Working with ONNX models in float16 and float8 formats ](https://www.mql5.com/ru/articles/14330)
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| RunCastFloat16ToDouble |
|
||||
//+------------------------------------------------------------------+
|
||||
bool RunCastFloat16ToDouble(long model_handle)
|
||||
{
|
||||
PrintFormat("test=%s",__FUNCTION__);
|
||||
double test_data[12]= {1,2,3,4,5,6,7,8,9,10,11,12};
|
||||
ushort data_uint16[12];
|
||||
if(!ArrayToFP16(data_uint16,test_data,FLOAT_FP16))
|
||||
{
|
||||
Print("error in ArrayToFP16. error code=",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
Print("test array:");
|
||||
ArrayPrint(test_data);
|
||||
Print("ArrayToFP16:");
|
||||
ArrayPrint(data_uint16);
|
||||
U<ushort> input_float16_values[3*4];
|
||||
U<double> output_double_values[3*4];
|
||||
float test_data_float[];
|
||||
if(!ArrayFromFP16(test_data_float,data_uint16,FLOAT_FP16))
|
||||
{
|
||||
Print("error in ArrayFromFP16. error code=",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
for(int i=0; i<12; i++)
|
||||
{
|
||||
input_float16_values[i].value=data_uint16[i];
|
||||
PrintFormat("%d input value =%f Hex float16 = %s ushort value=%d",i,test_data_float[i],ArrayToString(input_float16_values[i].uc),input_float16_values[i].value);
|
||||
}
|
||||
Print("ONNX input array:");
|
||||
ArrayPrint(input_float16_values);
|
||||
bool res=OnnxRun(model_handle,ONNX_NO_CONVERSION,input_float16_values,output_double_values);
|
||||
if(!res)
|
||||
{
|
||||
PrintFormat("error in OnnxRun. error code=%d",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
Print("ONNX output array:");
|
||||
ArrayPrint(output_double_values);
|
||||
//---
|
||||
double sum_error=0.0;
|
||||
for(int i=0; i<12; i++)
|
||||
{
|
||||
double delta=test_data[i]-output_double_values[i].value;
|
||||
sum_error+=MathAbs(delta);
|
||||
PrintFormat("%d output double %f = %s difference=%f",i,output_double_values[i].value,ArrayToString(output_double_values[i].uc),delta);
|
||||
}
|
||||
//---
|
||||
PrintFormat("test=%s sum_error=%f",__FUNCTION__,sum_error);
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayFromFP16](/en/docs/array/arrayfromfp16), [ArrayCopy](/en/docs/array/arraycopy)
|
||||
@@ -0,0 +1,112 @@
|
||||
# ArrayToFP8
|
||||
|
||||
Copies an array of type float or double into an array of type [uchar](/en/docs/basis/types/integer/integertypes#uchar) with the given format.
|
||||
|
||||
```
|
||||
bool ArrayToFP8(
|
||||
const uchar& dst_array[], // copy to
|
||||
const float& src_array[], // copy from
|
||||
ENUM_FLOAT8_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Overloading for the double type
|
||||
|
||||
```
|
||||
bool ArrayToFP8(
|
||||
const uchar& dst_array[], // copy to
|
||||
const double& src_array[], // copy from
|
||||
ENUM_FLOAT8_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
dst_array[]
|
||||
|
||||
[out] Receiver array or type uchar.
|
||||
|
||||
src_array[]
|
||||
|
||||
[in] Source array of type float or double.
|
||||
|
||||
fmt
|
||||
|
||||
[in] Copying format from the [ENUM_FLOAT8_FORMAT](/en/docs/onnx/onnx_structures#enum_float8_format) enumeration.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful or false otherwise.
|
||||
|
||||
Note
|
||||
|
||||
All kinds of FP8 format are defined in the [ENUM_FLOAT8_FORMAT](/en/docs/onnx/onnx_structures#enum_float8_format) enumeration and are used in MQL5 only for operations with [ONNX models](/en/docs/onnx).
|
||||
|
||||
The function converts input parameters of type float or double into one of FP8 types. These input parameters are then used in the [OnnxRun](/en/docs/onnx/onnxrun) function.
|
||||
|
||||
FP8 (8-bit floating point) is one of the data types used to represent floating point numbers. In FP8, each number is represented by 8 data bits, typically divided into three components: sign, exponent and mantissa. This format offers a balance between accuracy and storage efficiency, making it attractive for applications that require memory and computational efficiency.
|
||||
|
||||
By employing compact number representation, FP8 reduces memory requirements and accelerates calculations. In addition, FP8 can be useful for implementing low-level operations such as arithmetic calculations and signal processing.
|
||||
|
||||
Example: function from the article [Working with ONNX models in float16 and float8 formats ](https://www.mql5.com/ru/articles/14330)
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| RunCastFloat8Float |
|
||||
//+------------------------------------------------------------------+
|
||||
bool RunCastFloat8ToFloat(long model_handle,const ENUM_FLOAT8_FORMAT fmt)
|
||||
{
|
||||
PrintFormat("TEST: %s(%s)",__FUNCTION__,EnumToString(fmt));
|
||||
//---
|
||||
float test_data[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
|
||||
uchar data_float8[15] = {};
|
||||
if(!ArrayToFP8(data_float8,test_data,fmt))
|
||||
{
|
||||
Print("error in ArrayToFP8. error code=",GetLastError());
|
||||
OnnxRelease(model_handle);
|
||||
return(false);
|
||||
}
|
||||
U<uchar> input_float8_values[3*5];
|
||||
U<float> output_float_values[3*5];
|
||||
float test_data_float[];
|
||||
//--- convert float8 to float
|
||||
if(!ArrayFromFP8(test_data_float,data_float8,fmt))
|
||||
{
|
||||
Print("error in ArrayFromFP8. error code=",GetLastError());
|
||||
OnnxRelease(model_handle);
|
||||
return(false);
|
||||
}
|
||||
for(uint i=0; i<data_float8.Size(); i++)
|
||||
{
|
||||
input_float8_values[i].value=data_float8[i];
|
||||
PrintFormat("%d input value =%f Hex float8 = %s ushort value=%d",i,test_data_float[i],ArrayToHexString(input_float8_values[i].uc),input_float8_values[i].value);
|
||||
}
|
||||
Print("ONNX input array: ",ArrayToString(input_float8_values));
|
||||
//--- execute model (convert float8 to float using ONNX)
|
||||
if(!OnnxRun(model_handle,ONNX_NO_CONVERSION,input_float8_values,output_float_values))
|
||||
{
|
||||
PrintFormat("error in OnnxRun. error code=%d",GetLastError());
|
||||
OnnxRelease(model_handle);
|
||||
return(false);
|
||||
}
|
||||
Print("ONNX output array: ",ArrayToString(output_float_values));
|
||||
//--- calculate error (compare ONNX and ArrayFromFP8 results)
|
||||
double sum_error=0.0;
|
||||
for(uint i=0; i<test_data.Size(); i++)
|
||||
{
|
||||
double delta=test_data_float[i]-(double)output_float_values[i].value;
|
||||
sum_error+=MathAbs(delta);
|
||||
PrintFormat("%d output float %f = %s difference=%f",i,output_float_values[i].value,ArrayToHexString(output_float_values[i].uc),delta);
|
||||
}
|
||||
//---
|
||||
PrintFormat("%s(%s): sum_error=%f\n",__FUNCTION__,EnumToString(fmt),sum_error);
|
||||
return(true);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayFromFP8](/en/docs/array/arrayfromfp8), [ArrayCopy](/en/docs/array/arraycopy)
|
||||
@@ -0,0 +1,114 @@
|
||||
# ArrayFromFP16
|
||||
|
||||
Copies an array of type [ushort](/en/docs/basis/types/integer/integertypes#ushort) into an array of float or double type with the given format.
|
||||
|
||||
```
|
||||
bool ArrayFromFP16(
|
||||
const float& dst_array[], // copy to
|
||||
const ushort& src_array[], // copy from
|
||||
ENUM_FLOAT16_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Overloading for the double type
|
||||
|
||||
```
|
||||
bool ArrayFromFP16(
|
||||
const double& dst_array[], // copy to
|
||||
const ushort& src_array[], // copy from
|
||||
ENUM_FLOAT16_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
dst_array[]
|
||||
|
||||
[out] Receiver array of type float or double.
|
||||
|
||||
src_array[]
|
||||
|
||||
[in] Source array of type ushort.
|
||||
|
||||
fmt
|
||||
|
||||
[in] Copying format from the [ENUM_FLOAT16_FORMAT](/en/docs/onnx/onnx_structures#enum_float16_format) enumeration.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful or false otherwise.
|
||||
|
||||
Note
|
||||
|
||||
Formats FLOAT16 and BFLOAT16 are defined in the [ENUM_FLOAT16_FORMAT](/en/docs/onnx/onnx_structures#enum_float16_format) enumeration and are used in MQL5 only for operations with [ONNX models](/en/docs/onnx).
|
||||
|
||||
If the output parameters obtained from the [OnnxRun](/en/docs/onnx/onnxrun) function execution are of type FLOAT16 and BFLOAT16, you can use this function to convert the result to float or double arrays.
|
||||
|
||||
FLOAT16, also known as [half-precision float](https://en.wikipedia.org/wiki/Half-precision_floating-point_format), uses 16 bits to represent floating-point numbers. This format provides a balance between accuracy and computational efficiency. FLOAT16 is widely used in deep learning algorithms and neural networks, which require high-performance processing of large datasets. This format accelerates computations calculations by reducing the size of numbers, which is especially important when training deep neural networks on GPUs.
|
||||
|
||||
BFLOAT16 (or [Brain Floating Point 16](https://en.wikipedia.org/wiki/Bfloat16_floating-point_format)) also uses 16 bits but differs from FLOAT16 in the approach to format representation. In this format, 8 bits are allocated for representing the exponent, while the remaining 7 bits are used for representing the mantissa. This format was developed for use in deep learning and artificial intelligence, especially in Google's Tensor Processing Unit (TPU). BFLOAT16 demonstrates excellent performance in neural network training and can effectively accelerate computations.
|
||||
|
||||
Example: function from the article [Working with ONNX models in float16 and float8 formats ](https://www.mql5.com/ru/articles/14330)
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| RunCastFloat16ToDouble |
|
||||
//+------------------------------------------------------------------+
|
||||
bool RunCastFloat16ToDouble(long model_handle)
|
||||
{
|
||||
PrintFormat("test=%s",__FUNCTION__);
|
||||
double test_data[12]= {1,2,3,4,5,6,7,8,9,10,11,12};
|
||||
ushort data_uint16[12];
|
||||
if(!ArrayToFP16(data_uint16,test_data,FLOAT_FP16))
|
||||
{
|
||||
Print("error in ArrayToFP16. error code=",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
Print("test array:");
|
||||
ArrayPrint(test_data);
|
||||
Print("ArrayToFP16:");
|
||||
ArrayPrint(data_uint16);
|
||||
U<ushort> input_float16_values[3*4];
|
||||
U<double> output_double_values[3*4];
|
||||
float test_data_float[];
|
||||
if(!ArrayFromFP16(test_data_float,data_uint16,FLOAT_FP16))
|
||||
{
|
||||
Print("error in ArrayFromFP16. error code=",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
for(int i=0; i<12; i++)
|
||||
{
|
||||
input_float16_values[i].value=data_uint16[i];
|
||||
PrintFormat("%d input value =%f Hex float16 = %s ushort value=%d",i,test_data_float[i],ArrayToString(input_float16_values[i].uc),input_float16_values[i].value);
|
||||
}
|
||||
Print("ONNX input array:");
|
||||
ArrayPrint(input_float16_values);
|
||||
bool res=OnnxRun(model_handle,ONNX_NO_CONVERSION,input_float16_values,output_double_values);
|
||||
if(!res)
|
||||
{
|
||||
PrintFormat("error in OnnxRun. error code=%d",GetLastError());
|
||||
return(false);
|
||||
}
|
||||
Print("ONNX output array:");
|
||||
ArrayPrint(output_double_values);
|
||||
//---
|
||||
double sum_error=0.0;
|
||||
for(int i=0; i<12; i++)
|
||||
{
|
||||
double delta=test_data[i]-output_double_values[i].value;
|
||||
sum_error+=MathAbs(delta);
|
||||
PrintFormat("%d output double %f = %s difference=%f",i,output_double_values[i].value,ArrayToString(output_double_values[i].uc),delta);
|
||||
}
|
||||
//---
|
||||
PrintFormat("test=%s sum_error=%f",__FUNCTION__,sum_error);
|
||||
//---
|
||||
return(true);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayToFP16](/en/docs/array/arraytofp16), [ArrayCopy](/en/docs/array/arraycopy)
|
||||
@@ -0,0 +1,112 @@
|
||||
# ArrayFromFP8
|
||||
|
||||
Copies an array of type [uchar](/en/docs/basis/types/integer/integertypes#uchar) into an array of float or double type with the given format.
|
||||
|
||||
```
|
||||
bool ArrayFromFP8(
|
||||
const float& dst_array[], // copy to
|
||||
const uchar& src_array[], // copy from
|
||||
ENUM_FLOAT8_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Overloading for the double type
|
||||
|
||||
```
|
||||
bool ArrayFromFP8(
|
||||
const double& dst_array[], // copy to
|
||||
const uchar& src_array[], // copy from
|
||||
ENUM_FLOAT8_FORMAT fmt // format
|
||||
);
|
||||
|
||||
```
|
||||
|
||||
Parameters
|
||||
|
||||
dst_array[]
|
||||
|
||||
[out] Receiver array of type float or double.
|
||||
|
||||
src_array[]
|
||||
|
||||
[in] Source array of type uchar.
|
||||
|
||||
fmt
|
||||
|
||||
[in] Copying format from the [ENUM_FLOAT8_FORMAT](/en/docs/onnx/onnx_structures#enum_float8_format) enumeration.
|
||||
|
||||
Return Value
|
||||
|
||||
Returns true if successful or false otherwise.
|
||||
|
||||
Note
|
||||
|
||||
All kinds of FP8 format are defined in the [ENUM_FLOAT8_FORMAT](/en/docs/onnx/onnx_structures#enum_float8_format) enumeration and are used in MQL5 only for operations with [ONNX models](/en/docs/onnx).
|
||||
|
||||
If the output parameters obtained from the [OnnxRun](/en/docs/onnx/onnxrun) function execution are of FP8 from the ENUM_FLOAT8_FORMAT enumeration, you can use this function to convert the result into float or double arrays.
|
||||
|
||||
FP8 (8-bit floating point) is one of the data types used to represent floating point numbers. In FP8, each number is represented by 8 data bits, typically divided into three components: sign, exponent and mantissa. This format offers a balance between accuracy and storage efficiency, making it attractive for applications that require memory and computational efficiency.
|
||||
|
||||
By employing compact number representation, FP8 reduces memory requirements and accelerates calculations. In addition, FP8 can be useful for implementing low-level operations such as arithmetic calculations and signal processing.
|
||||
|
||||
Example: function from the article [Working with ONNX models in float16 and float8 formats ](https://www.mql5.com/ru/articles/14330)
|
||||
|
||||
```
|
||||
//+------------------------------------------------------------------+
|
||||
//| RunCastFloat8Float |
|
||||
//+------------------------------------------------------------------+
|
||||
bool RunCastFloat8ToFloat(long model_handle,const ENUM_FLOAT8_FORMAT fmt)
|
||||
{
|
||||
PrintFormat("TEST: %s(%s)",__FUNCTION__,EnumToString(fmt));
|
||||
//---
|
||||
float test_data[15] = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15};
|
||||
uchar data_float8[15] = {};
|
||||
if(!ArrayToFP8(data_float8,test_data,fmt))
|
||||
{
|
||||
Print("error in ArrayToFP8. error code=",GetLastError());
|
||||
OnnxRelease(model_handle);
|
||||
return(false);
|
||||
}
|
||||
U<uchar> input_float8_values[3*5];
|
||||
U<float> output_float_values[3*5];
|
||||
float test_data_float[];
|
||||
//--- convert float8 to float
|
||||
if(!ArrayFromFP8(test_data_float,data_float8,fmt))
|
||||
{
|
||||
Print("error in ArrayFromFP8. error code=",GetLastError());
|
||||
OnnxRelease(model_handle);
|
||||
return(false);
|
||||
}
|
||||
for(uint i=0; i<data_float8.Size(); i++)
|
||||
{
|
||||
input_float8_values[i].value=data_float8[i];
|
||||
PrintFormat("%d input value =%f Hex float8 = %s ushort value=%d",i,test_data_float[i],ArrayToHexString(input_float8_values[i].uc),input_float8_values[i].value);
|
||||
}
|
||||
Print("ONNX input array: ",ArrayToString(input_float8_values));
|
||||
//--- execute model (convert float8 to float using ONNX)
|
||||
if(!OnnxRun(model_handle,ONNX_NO_CONVERSION,input_float8_values,output_float_values))
|
||||
{
|
||||
PrintFormat("error in OnnxRun. error code=%d",GetLastError());
|
||||
OnnxRelease(model_handle);
|
||||
return(false);
|
||||
}
|
||||
Print("ONNX output array: ",ArrayToString(output_float_values));
|
||||
//--- calculate error (compare ONNX and ArrayFromFP8 results)
|
||||
double sum_error=0.0;
|
||||
for(uint i=0; i<test_data.Size(); i++)
|
||||
{
|
||||
double delta=test_data_float[i]-(double)output_float_values[i].value;
|
||||
sum_error+=MathAbs(delta);
|
||||
PrintFormat("%d output float %f = %s difference=%f",i,output_float_values[i].value,ArrayToHexString(output_float_values[i].uc),delta);
|
||||
}
|
||||
//---
|
||||
PrintFormat("%s(%s): sum_error=%f\n",__FUNCTION__,EnumToString(fmt),sum_error);
|
||||
return(true);
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
See also
|
||||
|
||||
[ArrayToFP8](/en/docs/array/arraytofp8), [ArrayCopy](/en/docs/array/arraycopy)
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 14 KiB |
Reference in New Issue
Block a user