Confirm trend

This commit is contained in:
Bell
2025-10-22 23:58:51 +07:00
parent 144aa7c991
commit 17f36609e8
2 changed files with 165 additions and 2 deletions
+1 -2
View File
@@ -138,8 +138,7 @@ void OnTick()
static datetime lastCheck = 0;
// chỉ check 1 lần mỗi phút
if(TimeCurrent() - lastCheck >= 60)
{
if(TimeCurrent() - lastCheck >= 60) {
string trend = GetTrendDirection();
Comment("Current Trend (", EnumToString(TrendTF), "): ", trend);
lastCheck = TimeCurrent();
+164
View File
@@ -0,0 +1,164 @@
//+------------------------------------------------------------------+
//| EA_Trend_EMA50_EMA200.mq5 |
//| Phiên bản: 1.0 |
//| Mục đích: |
//| - Xác định xu hướng bằng EMA50 & EMA200 (m15) |
//| - Vào lệnh trên M5 khi có tín hiệu: 2 đáy / 2 đỉnh / nến nhấn chìm |
//| - Rủi ro cố định: 1% Equity mỗi lệnh |
//| - Giới hạn tối đa 2 lệnh mở cùng lúc |
//| - Tùy chọn hiển thị EMA lên biểu đồ |
//+------------------------------------------------------------------+
#property copyright "Bell Hyperpush"
#property version "1.00"
#property strict
#include <Trade/Trade.mqh>
CTrade trade;
int handleEMA50 = INVALID_HANDLE;
int handleEMA200 = INVALID_HANDLE;
// ================== INPUTS =========================================
input ENUM_TIMEFRAMES TrendTF = PERIOD_M15; // khung thời gian dùng để lọc xu hướng
input ENUM_TIMEFRAMES EntryTF = PERIOD_M5; // khung thời gian để tìm điểm vào
input int EMA_Fast = 50; // EMA nhanh
input int EMA_Slow = 200; // EMA chậm
input double RiskPercent = 1.0; // rủi ro % equity cho mỗi lệnh
input double TP_Multiplier = 2.0; // tỉ lệ TP = Risk * multiplier
input int MaxOpenPositions = 2; // tối đa 2 lệnh mở
input double DoubleTolerancePoints = 30; // dung sai giữa 2 đáy/đỉnh
input int MinBarsBetweenDouble = 4; // khoảng cách tối thiểu giữa 2 đáy/đỉnh
input int SL_Pips_Default = 35; // SL mặc định (points)
input int Slippage = 10; // trượt giá tối đa
input bool VisualizeEMAs = true; // có vẽ EMA lên chart không
input int TrendShift = 1; // shift dùng để đọc nến đóng (tránh nến đang hình thành)
input int StructureRecentOffset = 1; // offset cho nến recent khi kiểm tra cấu trúc (high1/low1)
input int StructurePrevOffset = 2; // offset cho nến trước đó khi kiểm tra cấu trúc (high2/low2)
// ================== FUNCTIONS =====================================
// ----- Enums for structured states (avoid hard-coded strings) -----
enum TREND_STRUCTURE { STRUCTURE_NEUTRAL = 0, STRUCTURE_HH_HL, STRUCTURE_LH_LL, STRUCTURE_SIDEWAY };
enum EMA_COND { EMA_INSUFFICIENT = 0, EMA_UPTREND, EMA_DOWNTREND, EMA_NEUTRAL };
enum TREND_RESULT { TREND_NEUTRAL = 0, TREND_UPTREND, TREND_DOWNTREND, TREND_SIDEWAY_RESULT };
string StructureToString(const int s) {
switch(s) {
case STRUCTURE_HH_HL: return "HH-HL (Uptrend)";
case STRUCTURE_LH_LL: return "LH-LL (Downtrend)";
case STRUCTURE_SIDEWAY: return "Sideway";
default: return "Neutral";
}
}
string EmaConditionToString(const int e) {
switch(e) {
case EMA_UPTREND: return "EMA Uptrend";
case EMA_DOWNTREND: return "EMA Downtrend";
case EMA_NEUTRAL: return "EMA Neutral";
default: return "EMA InsufficientData";
}
}
string TrendResultToString(const int r) {
switch(r) {
case TREND_UPTREND: return "UPTREND";
case TREND_DOWNTREND: return "DOWNTREND";
case TREND_SIDEWAY_RESULT: return "SIDEWAY";
default: return "NEUTRAL";
}
}
// Xác định xu hướng hiện tại
string GetTrendDirection() {
int shift = TrendShift; // tránh dùng nến đang chạy (mặc định = 1)
double emaFast = 0.0;
double emaSlow = 0.0;
double buf[];
// read EMA50 value by copying buffer from handle
if(handleEMA50 != INVALID_HANDLE) {
if(CopyBuffer(handleEMA50, 0, shift, 1, buf) > 0) emaFast = buf[0];
}
// read EMA200 value by copying buffer from handle
if(handleEMA200 != INVALID_HANDLE) {
if(CopyBuffer(handleEMA200, 0, shift, 1, buf) > 0) emaSlow = buf[0];
}
double priceClose = iClose(_Symbol, TrendTF, shift);
// Lấy giá cao thấp theo cấu hình offsets (recent vs prev)
double high1 = iHigh(_Symbol, TrendTF, StructureRecentOffset);
double high2 = iHigh(_Symbol, TrendTF, StructurePrevOffset);
double low1 = iLow(_Symbol, TrendTF, StructureRecentOffset);
double low2 = iLow(_Symbol, TrendTF, StructurePrevOffset);
int structureEnum = STRUCTURE_NEUTRAL;
int emaEnum = EMA_INSUFFICIENT;
int trendEnum = TREND_NEUTRAL;
// --- B1: Kiểm tra cấu trúc xu hướng
if(high1 > high2 && low1 > low2)
structureEnum = STRUCTURE_HH_HL;
else if(high1 < high2 && low1 < low2)
structureEnum = STRUCTURE_LH_LL;
else
structureEnum = STRUCTURE_SIDEWAY;
// --- B2: Kiểm tra EMA (an toàn: đảm bảo dữ liệu hợp lệ)
if(priceClose <= 0.0 || emaFast <= 0.0 || emaSlow <= 0.0)
emaEnum = EMA_INSUFFICIENT;
else if(emaFast > emaSlow && priceClose > emaFast)
emaEnum = EMA_UPTREND;
else if(emaFast < emaSlow && priceClose < emaFast)
emaEnum = EMA_DOWNTREND;
else
emaEnum = EMA_NEUTRAL;
// --- B3: Tổng hợp kết luận
if(structureEnum == STRUCTURE_HH_HL && emaEnum == EMA_UPTREND)
trendEnum = TREND_UPTREND;
else if(structureEnum == STRUCTURE_LH_LL && emaEnum == EMA_DOWNTREND)
trendEnum = TREND_DOWNTREND;
else
trendEnum = TREND_SIDEWAY_RESULT;
// --- B4: Log chi tiết (debug)
PrintFormat("[TREND DEBUG] === %s ===", TimeToString(TimeCurrent(), TIME_DATE|TIME_SECONDS));
PrintFormat("EMA50=%.2f | EMA200=%.2f | Close=%.2f", emaFast, emaSlow, priceClose);
PrintFormat("Structure: %s | EMA: %s | => TREND: %s",
StructureToString(structureEnum), EmaConditionToString(emaEnum), TrendResultToString(trendEnum));
return TrendResultToString(trendEnum);
}
// ================== VÒNG LẶP CHÍNH ================================
void OnTick()
{
static datetime lastCheck = 0;
// chỉ check 1 lần mỗi phút
if(TimeCurrent() - lastCheck >= 60) {
string trend = GetTrendDirection();
Comment("Current Trend (", EnumToString(TrendTF), "): ", trend);
lastCheck = TimeCurrent();
}
}
// ================== KHỞI TẠO & KẾT THÚC ===========================
int OnInit() {
// create EMA indicator handles
handleEMA50 = iMA(_Symbol, TrendTF, EMA_Fast, 0, MODE_EMA, PRICE_CLOSE);
handleEMA200 = iMA(_Symbol, TrendTF, EMA_Slow, 0, MODE_EMA, PRICE_CLOSE);
if(handleEMA50 == INVALID_HANDLE || handleEMA200 == INVALID_HANDLE) {
Print("Failed to create EMA handles. Err=", GetLastError());
return(INIT_FAILED);
}
return(INIT_SUCCEEDED);
}
void OnDeinit(const int reason) {
if(handleEMA50 != INVALID_HANDLE) IndicatorRelease(handleEMA50);
if(handleEMA200 != INVALID_HANDLE) IndicatorRelease(handleEMA200);
}