ArraySort
Sắp xếp các giá trị trong chiều đầu tiên của một mảng số đa chiều theo thứ tự tăng dần.
cpp
bool ArraySort(
void& array[] // mảng để sắp xếp
);
1
2
3
2
3
Tham số
array[]
[in][out] Mảng số để sắp xếp.
Giá trị trả về
Hàm trả về true nếu thành công, nếu không trả về false.
Ghi chú
Mảng luôn được sắp xếp theo thứ tự tăng dần bất kể giá trị cờ AS_SERIES.
Các hàm ArraySort
và ArrayBSearch
chấp nhận mảng đa chiều làm tham số. Tuy nhiên, việc tìm kiếm và sắp xếp luôn được áp dụng cho chiều đầu tiên (chiều zero).
Ví dụ:
cpp
#property description "Chỉ báo phân tích dữ liệu trong tháng vừa qua và vẽ tất cả các nến có khối lượng tick nhỏ"
#property description "và lớn. Mảng khối lượng tick được sắp xếp để xác định các nến như vậy. Các nến có khối lượng thuộc"
#property description "phần trăm đầu tiên InpSmallVolume của mảng được coi là nhỏ. Các nến có khối lượng tick thuộc"
#property description "phần trăm cuối cùng InpBigVolume của mảng được coi là lớn."
//--- cài đặt chỉ báo
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots 1
//--- vẽ
#property indicator_label1 "VolumeFactor"
#property indicator_type1 DRAW_COLOR_CANDLES
#property indicator_color1 clrDodgerBlue,clrOrange
#property indicator_style1 STYLE_SOLID
#property indicator_width1 2
//--- hằng số định sẵn
#define INDICATOR_EMPTY_VALUE 0.0
//--- tham số đầu vào
input int InpSmallVolume=15; // Giá trị phần trăm của khối lượng nhỏ (<50)
input int InpBigVolume=20; // Giá trị phần trăm của khối lượng lớn (<50)
//--- thời gian bắt đầu phân tích (sẽ được dịch chuyển)
datetime ExtStartTime;
//--- bộ đệm chỉ báo
double ExtOpenBuff[];
double ExtHighBuff[];
double ExtLowBuff[];
double ExtCloseBuff[];
double ExtColorBuff[];
//--- giá trị biên khối lượng để hiển thị nến
long ExtLeftBorder=0;
long ExtRightBorder=0;
//+------------------------------------------------------------------+
//| Nhận giá trị biên cho khối lượng tick |
//+------------------------------------------------------------------+
bool GetVolumeBorders(void)
{
//--- biến
datetime stop_time; // thời gian kết thúc sao chép
long buff[]; // bộ đệm để sao chép
//--- thời gian kết thúc là thời gian hiện tại
stop_time=TimeCurrent();
//--- thời gian bắt đầu là một tháng trước thời gian hiện tại
ExtStartTime=GetStartTime(stop_time);
//--- nhận giá trị của khối lượng tick
ResetLastError();
if(CopyTickVolume(Symbol(),Period(),ExtStartTime,stop_time,buff)==-1)
{
//--- không nhận được dữ liệu, trả về false để khởi động lệnh tính toán lại
PrintFormat("Không thể nhận giá trị khối lượng tick. Mã lỗi = %d",GetLastError());
return(false);
}
//--- tính kích thước mảng
int size=ArraySize(buff);
//--- sắp xếp mảng
ArraySort(buff);
//--- xác định giá trị của biên trái và phải cho khối lượng tick
ExtLeftBorder=buff[size*InpSmallVolume/100];
ExtRightBorder=buff[(size-1)*(100-InpBigVolume)/100];
//--- thực thi thành công
return(true);
}
//+------------------------------------------------------------------+
//| Nhận dữ liệu nhỏ hơn một tháng so với dữ liệu được truyền vào |
//+------------------------------------------------------------------+
datetime GetStartTime(const datetime stop_time)
{
//--- chuyển đổi thời gian kết thúc thành biến cấu trúc kiểu MqlDateTime
MqlDateTime temp;
TimeToStruct(stop_time,temp);
//--- nhận dữ liệu nhỏ hơn một tháng
if(temp.mon>1)
temp.mon-=1; // tháng hiện tại không phải là tháng đầu tiên trong năm, do đó số của tháng trước nhỏ hơn một
else
{
temp.mon=12; // tháng hiện tại là tháng đầu tiên trong năm, do đó số của tháng trước là 12,
temp.year-=1; // trong khi số năm nhỏ hơn một
}
//--- số ngày không vượt quá 28
if(temp.day>28)
temp.day=28;
//--- trả về ngày thu được
return(StructToTime(temp));
}
//+------------------------------------------------------------------+
//| Hàm khởi tạo chỉ báo tùy chỉnh |
//+------------------------------------------------------------------+
int OnInit()
{
//--- kiểm tra xem tham số đầu vào có thỏa mãn điều kiện không
if(InpSmallVolume<0 || InpSmallVolume>=50 || InpBigVolume<0 || InpBigVolume>=50)
{
Print("Tham số đầu vào không chính xác");
return(INIT_PARAMETERS_INCORRECT);
}
//--- ánh xạ bộ đệm chỉ báo
SetIndexBuffer(0,ExtOpenBuff);
SetIndexBuffer(1,ExtHighBuff);
SetIndexBuffer(2,ExtLowBuff);
SetIndexBuffer(3,ExtCloseBuff);
SetIndexBuffer(4,ExtColorBuff,INDICATOR_COLOR_INDEX);
//--- đặt giá trị sẽ không được hiển thị
PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
//--- đặt nhãn cho bộ đệm chỉ báo
PlotIndexSetString(0,PLOT_LABEL,"Open;High;Low;Close");
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Hàm lặp chỉ báo tùy chỉnh |
//+------------------------------------------------------------------+
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[])
{
//--- kiểm tra xem còn thanh nào chưa xử lý không
if(prev_calculated<rates_total)
{
//--- nhận giá trị mới của biên phải và trái cho khối lượng
if(!GetVolumeBorders())
return(0);
}
//--- biến bắt đầu để tính toán thanh
int start=prev_calculated;
//--- làm việc tại thanh cuối cùng nếu giá trị chỉ báo đã được tính toán tại tick trước đó
if(start>0)
start--;
//--- đặt lập chỉ mục trực tiếp trong chuỗi thời gian
ArraySetAsSeries(time,false);
ArraySetAsSeries(open,false);
ArraySetAsSeries(high,false);
ArraySetAsSeries(low,false);
ArraySetAsSeries(close,false);
ArraySetAsSeries(tick_volume,false);
//--- vòng lặp tính toán giá trị chỉ báo
for(int i=start;i<rates_total;i++)
{
//--- điền nến bắt đầu từ ngày ban đầu
if(ExtStartTime<=time[i])
{
//--- nếu giá trị không nhỏ hơn biên phải, điền nến
if(tick_volume[i]>=ExtRightBorder)
{
//--- nhận dữ liệu để vẽ nến
ExtOpenBuff[i]=open[i];
ExtHighBuff[i]=high[i];
ExtLowBuff[i]=low[i];
ExtCloseBuff[i]=close[i];
//--- màu DodgerBlue
ExtColorBuff[i]=0;
//--- tiếp tục vòng lặp
continue;
}
//--- điền nến nếu giá trị không vượt quá biên trái
if(tick_volume[i]<=ExtLeftBorder)
{
//--- nhận dữ liệu để vẽ nến
ExtOpenBuff[i]=open[i];
ExtHighBuff[i]=high[i];
ExtLowBuff[i]=low[i];
ExtCloseBuff[i]=close[i];
//--- màu Orange
ExtColorBuff[i]=1;
//--- tiếp tục vòng lặp
continue;
}
}
//--- đặt giá trị rỗng cho các thanh không được đưa vào tính toán
ExtOpenBuff[i]=INDICATOR_EMPTY_VALUE;
ExtHighBuff[i]=INDICATOR_EMPTY_VALUE;
ExtLowBuff[i]=INDICATOR_EMPTY_VALUE;
ExtCloseBuff[i]=INDICATOR_EMPTY_VALUE;
}
//--- trả về giá trị của prev_calculated cho lần gọi tiếp theo
return(rates_total);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181