//Viết code lớp mql5 theo mô tả sau đây:
//
Mô hình vai đầu vai cho thấy sự đảo chiều của xu hướng hiện tại. Mô hình này có thể xuất hiện trong cả xu hướng tăng và xu hướng giảm, nhưng có cấu trúc khác nhau. Mô hình
vai đầu vai thuận được hình thành khi giá tạo ra ba đỉnh liên tiếp, trong đó đỉnh thứ hai (đầu) cao hơn
hai đỉnh còn lại (vai trái và vai phải). Đường nối hai điểm thấp nhất giữa ba đỉnh được gọi là đường viền cổ. Khi giá phá vỡ đường viền cổ, mô hình hoàn thành và dự báo giá sẽ giảm. Mô hình
vai đầu vai ngược được hình thành khi giá tạo ra ba đáy liên tiếp, trong đó đáy thứ hai (đầu) thấp hơn
hai đáy còn lại (vai trái và vai phải). Đường nối hai điểm cao nhất giữa ba đáy được gọi là đường viền cổ. Khi giá vượt qua đường viền cổ, mô hình hoàn thành và dự báo giá sẽ tăng.
//Để giao dịch với mô hình
vai đầu vai, người giao dịch có thể chờ xác nhận của sự phá vỡ hoặc vượt qua đường viền cổ, sau đó vào lệnh bán hoặc mua tùy theo loại mô hình. Điểm dừng lỗ có thể được đặt ở trên hoặc dưới vai phải, còn điểm chốt lời có thể được tính bằng khoảng cách từ đỉnh hoặc đáy cao nhất của mô hình tới đường viền cổ.
//Dưới đây là code lớp mql5 để phát hiện và giao dịch với mô hình
vai đầu vai:
// Khai báo lớp mql5 cho mô hình
vai đầu vai
//template<typename double>
//class HeadAndShoulders : public Pattern<double>
//{
class HeadAndShoulders
{
protected:
// Các biến lưu trữ thông tin về ba đỉnh hoặc ba đáy của mô hình
double left_peak;
double head_peak;
double right_peak;
// Các biến lưu trữ thông tin về hai điểm thấp hoặc cao nhất giữa ba đỉnh hoặc ba đáy
double left_neckline;
double right_neckline;
// Biến lưu trữ thông tin về loại mô hình: thuận hay ngược
bool is_reversed;
public:
// Hàm khởi tạo lớp
void HeadAndShouldersInit()
{
// Gán giá trị ban đầu cho các biến
left_peak = 0;
head_peak = 0;
right_peak = 0;
left_neckline = 0;
right_neckline = 0;
is_reversed = false;
}
// Hàm phát hiện mô hình
vai đầu vai trên dữ liệu giá
bool Detect(double &price_data[])
{
// Kiểm tra số lượng phần tử của mảng dữ liệu giá
if(ArraySize(price_data) < 6)
return false; // Không đủ dữ liệu để phát hiện mô hình
// Tìm ba điểm cao nhất trong mảng dữ liệu giá
int left_index = ArrayMaximum(price_data, WHOLE_ARRAY, 0);
int head_index = ArrayMaximum(price_data, left_index - 1, 0);
int right_index = ArrayMaximum(price_data, head_index - 1, 0);
// Nếu không tìm thấy ba điểm cao nhất, thử tìm ba điểm thấp nhất
if(left_index == -1 || head_index == -1 || right_index == -1)
{
left_index = ArrayMinimum(price_data, WHOLE_ARRAY, 0);
head_index = ArrayMinimum(price_data, left_index - 1, 0);
right_index = ArrayMinimum(price_data, head_index - 1, 0);
// Nếu không tìm thấy ba điểm thấp nhất, trả về false
if(left_index == -1 || head_index == -1 || right_index == -1)
return false; // Không tìm thấy mô hình
// Nếu tìm thấy ba điểm thấp nhất, gán giá trị cho các biến tương ứng
left_peak = price_data[left_index];
head_peak = price_data[head_index];
right_peak = price_data[right_index];
// Đánh dấu loại mô hình là ngược
is_reversed = true;
}
else
{
// Nếu tìm thấy ba điểm cao nhất, gán giá trị cho các biến tương ứng
left_peak = price_data[left_index];
head_peak = price_data[head_index];
right_peak = price_data[right_index];
// Đánh dấu loại mô hình là thuận
is_reversed = false;
}
// Kiểm tra xem ba điểm cao hoặc thấp nhất có thoả mãn điều kiện của mô hình không
if(is_reversed)
{
// Nếu là mô hình ngược, kiểm tra xem có phải head_peak < left_peak và head_peak < right_peak không
if(head_peak >= left_peak || head_peak >= right_peak)
return false; // Không thoả mãn điều kiện của mô hình ngược
}
else
{
// Nếu là mô hình thuận, kiểm tra xem có phải head_peak > left_peak và head_peak > right_peak không
if(head_peak <= left_peak || head_peak <= right_peak)
return false; // Không thoả mãn điều kiện của mô hình thuận
}
// Tìm hai điểm thấp hoặc cao nhất giữa ba điểm cao hoặc thấp nhất
if(is_reversed)
{
// Nếu là mô hình ngược, tìm hai điểm cao nhất
int left_neckline_index = ArrayMaximum(price_data, left_index - 1, head_index + 1);
int right_neckline_index = ArrayMaximum(price_data, head_index - 1, right_index + 1);
// Nếu không tìm thấy hai điểm cao nhất, trả về false
if(left_neckline_index == -1 || right_neckline_index == -1)
return false; // Không tìm thấy mô hình
// Nếu tìm thấy hai điểm cao nhất, gán giá trị cho các biến tương ứng
left_neckline = price_data[left_neckline_index];
right_neckline = price_data[right_neckline_index];
}
else
{
// Nếu là mô hình thuận, tìm hai điểm thấp nhất
int left_neckline_index = ArrayMinimum(price_data, left_index - 1, head_index + 1);
int right_neckline_index = ArrayMinimum(price_data, head_index - 1, right_index + 1);
// Nếu không tìm thấy hai điểm thấp nhất, trả về false
if(left_neckline_index == -1 || right_neckline_index == -1)
return false; // Không tìm thấy mô hình
// Nếu tìm thấy hai điểm thấp nhất, gán giá trị cho các biến tương ứng
}
return false;
}
};
// Hàm lấy giá của các nến (bar)
MqlRates PriceInfomationArrayCustom[];
int SizeArrayPriceCustom=0;
void getPriceInfomationBarCustom(int posBar, ENUM_TIMEFRAMES iTimeFrame,int countbar)
{
ArraySetAsSeries(PriceInfomationArrayCustom,true);
double Data=CopyRates(Symbol(),iTimeFrame,posBar,countbar,PriceInfomationArrayCustom);
SizeArrayPriceCustom=ArraySize(PriceInfomationArrayCustom);
}
HeadAndShoulders DetectorShoulder;
void OnInit()
{
DetectorShoulder.HeadAndShouldersInit();
}
double DataPrice[];
input int NumberCandle=30; // Xét trong 30 cây nến
void OnTick()
{
getPriceInfomationBarCustom(0,PERIOD_H1,NumberCandle); // Lấy các mức giá của nến
for(int i=0;i<NumberCandle;i++)
{
DataPrice
=PriceInfomationArrayCustom.close; // Chỉ xét giá đóng cửa
}
if(DetectorShoulder.Detect(DataPrice)==true) // Kiểm tra và phát hiện mô hình
{
Comment("Phát hiện mô hình vai đầu vai");
}
}