This commit is contained in:
Bell
2026-03-10 20:51:27 +07:00
parent c7aeabeafa
commit a5069481b4
7 changed files with 504 additions and 243 deletions
+38 -39
View File
@@ -1,76 +1,75 @@
#ifndef EA_ICT_CL__SWING_MQH
#define EA_ICT_CL__SWING_MQH // Tránh include trùng
#define EA_ICT_CL__SWING_MQH
// Module: Swing tìm bar shift theo time, swing high/low, quét cấu trúc swing, suy trend
//+------------------------------------------------------------------+
//| MyBarShift: tìm chỉ số bar (series) ứng với thời gian time |
//+------------------------------------------------------------------+
/** Returns bar index (series) for given time; -1 if not found or exact and no match. */
inline int MyBarShift(string symbol, ENUM_TIMEFRAMES tf, datetime time, bool exact = false)
{
datetime arr[];
int maxCopy = MathMin(Bars(symbol, tf), 5000); // Giới hạn copy
int copied = CopyTime(symbol, tf, 0, maxCopy, arr);
if (copied <= 0) return -1;
int maxBarsToCopy = MathMin(Bars(symbol, tf), 5000);
int copiedCount = CopyTime(symbol, tf, 0, maxBarsToCopy, arr);
if (copiedCount <= 0) return -1;
for (int i = copied - 1; i >= 0; i--) // Duyệt từ bar cũ → mới
for (int i = copiedCount - 1; i >= 0; i--)
{
if (arr[i] <= time)
return copied - 1 - i; // Index trong series (0 = mới nhất)
return copiedCount - 1 - i;
}
return exact ? -1 : copied - 1; // exact: không tìm thấy = -1; không exact: trả về bar xa nhất
return exact ? -1 : copiedCount - 1;
}
inline bool IsSwingHighAt(ENUM_TIMEFRAMES tf, int i)
/** True if bar at index i is a swing high (InpSwingRange bars each side lower). */
inline bool IsSwingHighAt(ENUM_TIMEFRAMES tf, int barIndex)
{
double p = iHigh(_Symbol, tf, i); // High tại bar i
for (int k = 1; k <= InpSwingRange; k++) // So với InpSwingRange bar mỗi bên
if (iHigh(_Symbol, tf, i-k) >= p || iHigh(_Symbol, tf, i+k) >= p) return false; // Có high cao hơn → không phải swing high
return true;
}
inline bool IsSwingLowAt(ENUM_TIMEFRAMES tf, int i)
{
double p = iLow(_Symbol, tf, i);
double highAtBar = iHigh(_Symbol, tf, barIndex);
for (int k = 1; k <= InpSwingRange; k++)
if (iLow(_Symbol, tf, i-k) <= p || iLow(_Symbol, tf, i+k) <= p) return false;
if (iHigh(_Symbol, tf, barIndex - k) >= highAtBar || iHigh(_Symbol, tf, barIndex + k) >= highAtBar) return false;
return true;
}
/** True if bar at index i is a swing low (InpSwingRange bars each side higher). */
inline bool IsSwingLowAt(ENUM_TIMEFRAMES tf, int barIndex)
{
double lowAtBar = iLow(_Symbol, tf, barIndex);
for (int k = 1; k <= InpSwingRange; k++)
if (iLow(_Symbol, tf, barIndex - k) <= lowAtBar || iLow(_Symbol, tf, barIndex + k) <= lowAtBar) return false;
return true;
}
/** Scans for two most recent swing highs and two most recent swing lows; fills out params, returns true if all found. */
inline bool ScanSwingStructure(
ENUM_TIMEFRAMES tf, int lookback,
double &h0, double &h1, int &idxH0, int &idxH1,
double &l0, double &l1, int &idxL0, int &idxL1)
{
int maxBar = MathMin(lookback, Bars(_Symbol, tf) - InpSwingRange - 2); // Giới hạn quét
double highs[2]; int hiIdx[2]; int hc = 0; // 2 swing high gần nhất
double lows [2]; int loIdx[2]; int lc = 0; // 2 swing low gần nhất
int maxBar = MathMin(lookback, Bars(_Symbol, tf) - InpSwingRange - 2);
double highs[2]; int hiIdx[2]; int highCount = 0;
double lows [2]; int loIdx[2]; int lowCount = 0;
for (int i = InpSwingRange + 1; i <= maxBar; i++) // Từ bar gần hiện tại trở lại
for (int i = InpSwingRange + 1; i <= maxBar; i++)
{
if (hc < 2 && IsSwingHighAt(tf, i)) { highs[hc] = iHigh(_Symbol, tf, i); hiIdx[hc] = i; hc++; }
if (lc < 2 && IsSwingLowAt (tf, i)) { lows [lc] = iLow (_Symbol, tf, i); loIdx[lc] = i; lc++; }
if (hc == 2 && lc == 2) break; // Đủ 2 high + 2 low thì dừng
if (highCount < 2 && IsSwingHighAt(tf, i)) { highs[highCount] = iHigh(_Symbol, tf, i); hiIdx[highCount] = i; highCount++; }
if (lowCount < 2 && IsSwingLowAt (tf, i)) { lows [lowCount] = iLow (_Symbol, tf, i); loIdx[lowCount] = i; lowCount++; }
if (highCount == 2 && lowCount == 2) break;
}
if (hc < 2 || lc < 2) return false; // Không đủ swing
if (highCount < 2 || lowCount < 2) return false;
h0 = highs[0]; idxH0 = hiIdx[0]; // h0 = swing high gần nhất (index nhỏ)
h1 = highs[1]; idxH1 = hiIdx[1]; // h1 = swing high cũ hơn
h0 = highs[0]; idxH0 = hiIdx[0];
h1 = highs[1]; idxH1 = hiIdx[1];
l0 = lows [0]; idxL0 = loIdx[0];
l1 = lows [1]; idxL1 = loIdx[1];
return true;
}
/** Resolves trend and key level from swing highs/lows and last close. */
inline void ResolveTrendFromSwings(
ENUM_TIMEFRAMES tf,
double h0, double h1, double l0, double l1,
MarketDir &trend, double &keyLevel)
{
double c1 = iClose(_Symbol, tf, 1); // Close bar 1 (gần nhất đã đóng)
if (h0 > h1 && l0 > l1 && c1 > l0) { trend = DIR_UP; keyLevel = l0; } // HH + HL, giá trên L0 → uptrend
else if (h0 < h1 && l0 < l1 && c1 < h0) { trend = DIR_DOWN; keyLevel = h0; } // LH + LL, giá dưới H0 → downtrend
else { trend = DIR_NONE; keyLevel = 0; } // Không rõ
double lastClose = iClose(_Symbol, tf, 1);
if (h0 > h1 && l0 > l1 && lastClose > l0) { trend = DIR_UP; keyLevel = l0; }
else if (h0 < h1 && l0 < l1 && lastClose < h0) { trend = DIR_DOWN; keyLevel = h0; }
else { trend = DIR_NONE; keyLevel = 0; }
}
#endif // EA_ICT_CL__SWING_MQH
#endif