Meaningful names for contexts.mqh
This commit is contained in:
@@ -3,47 +3,49 @@
|
||||
|
||||
// Module: Contexts – cập nhật D1 bias, H1/M5 trend (swing + MSS), daily risk
|
||||
|
||||
inline HTFBias ResolveBias(double b1H, double b1L, double b1C, double b2H, double b2L)
|
||||
inline HTFBias ResolveBias(double bar1High, double bar1Low, double bar1Close,
|
||||
double bar2High, double bar2Low)
|
||||
{
|
||||
if (b1C > b2H) return BIAS_UP; // Close bar 1 trên range bar 2 → tăng
|
||||
if (b1C < b2L) return BIAS_DOWN; // Close bar 1 dưới range bar 2 → giảm
|
||||
if (b1H > b2H && b1C < b2H) return BIAS_DOWN; // Phá cao rồi đóng dưới → bearish
|
||||
if (b1L < b2L && b1C > b2L) return BIAS_UP; // Phá thấp rồi đóng trên → bullish
|
||||
if (bar1Close > bar2High) return BIAS_UP; // Close bar 1 trên range bar 2 → tăng
|
||||
if (bar1Close < bar2Low) return BIAS_DOWN; // Close bar 1 dưới range bar 2 → giảm
|
||||
if (bar1High > bar2High && bar1Close < bar2High) return BIAS_DOWN; // Phá cao rồi đóng dưới → bearish
|
||||
if (bar1Low < bar2Low && bar1Close > bar2Low) return BIAS_UP; // Phá thấp rồi đóng trên → bullish
|
||||
return BIAS_SIDEWAY; // Còn lại = sideway
|
||||
}
|
||||
|
||||
inline void UpdateBiasContext()
|
||||
{
|
||||
datetime t0 = iTime(_Symbol, InpBiasTF, 0); // Bar D1 hiện tại (đang hình thành)
|
||||
if (t0 == g_Bias.lastBarTime) return; // Đã xử lý bar này rồi → bỏ qua
|
||||
g_Bias.lastBarTime = t0;
|
||||
datetime currentBiasBarTime = iTime(_Symbol, InpBiasTF, 0); // Bar D1 hiện tại (đang hình thành)
|
||||
if (currentBiasBarTime == g_Bias.lastBarTime) return; // Đã xử lý bar này rồi → bỏ qua
|
||||
g_Bias.lastBarTime = currentBiasBarTime;
|
||||
|
||||
if (Bars(_Symbol, InpBiasTF) < 4) { g_Bias.bias = BIAS_NONE; return; } // Không đủ dữ liệu
|
||||
|
||||
double b1H = iHigh (_Symbol, InpBiasTF, 1); // Bar D1 vừa đóng
|
||||
double b1L = iLow (_Symbol, InpBiasTF, 1);
|
||||
double b1C = iClose(_Symbol, InpBiasTF, 1);
|
||||
double b2H = iHigh (_Symbol, InpBiasTF, 2); // Bar D1 trước đó
|
||||
double b2L = iLow (_Symbol, InpBiasTF, 2);
|
||||
double bar1High = iHigh (_Symbol, InpBiasTF, 1); // Bar D1 vừa đóng
|
||||
double bar1Low = iLow (_Symbol, InpBiasTF, 1);
|
||||
double bar1Close = iClose(_Symbol, InpBiasTF, 1);
|
||||
double bar2High = iHigh (_Symbol, InpBiasTF, 2); // Bar D1 trước đó
|
||||
double bar2Low = iLow (_Symbol, InpBiasTF, 2);
|
||||
|
||||
HTFBias prev = g_Bias.bias;
|
||||
g_Bias.bias = ResolveBias(b1H, b1L, b1C, b2H, b2L); // Tính bias
|
||||
g_Bias.rangeHigh = (g_Bias.bias == BIAS_SIDEWAY) ? b2H : 0; // Vùng sideway
|
||||
g_Bias.rangeLow = (g_Bias.bias == BIAS_SIDEWAY) ? b2L : 0;
|
||||
g_Bias.bias = ResolveBias(bar1High, bar1Low, bar1Close, bar2High, bar2Low); // Tính bias
|
||||
g_Bias.rangeHigh = (g_Bias.bias == BIAS_SIDEWAY) ? bar2High : 0; // Vùng sideway
|
||||
g_Bias.rangeLow = (g_Bias.bias == BIAS_SIDEWAY) ? bar2Low : 0;
|
||||
|
||||
if (InpDebugLog && g_Bias.bias != prev) // Chỉ log khi bias đổi
|
||||
PrintFormat("[BIAS] %s → %s | b1[H=%.5f L=%.5f C=%.5f] b2[H=%.5f L=%.5f]",
|
||||
EnumToString(prev), EnumToString(g_Bias.bias), b1H, b1L, b1C, b2H, b2L);
|
||||
EnumToString(prev), EnumToString(g_Bias.bias),
|
||||
bar1High, bar1Low, bar1Close, bar2High, bar2Low);
|
||||
}
|
||||
|
||||
inline void UpdateTFTrendContext(ENUM_TIMEFRAMES tf, int lookback, TFTrendContext &ctx)
|
||||
{
|
||||
datetime t0 = iTime(_Symbol, tf, 0);
|
||||
if (t0 == ctx.lastBarTime) return; // Bar chưa đổi → không cập nhật
|
||||
ctx.lastBarTime = t0;
|
||||
datetime currentTfBarTime = iTime(_Symbol, tf, 0);
|
||||
if (currentTfBarTime == ctx.lastBarTime) return; // Bar chưa đổi → không cập nhật
|
||||
ctx.lastBarTime = currentTfBarTime;
|
||||
|
||||
double bar1C = iClose(_Symbol, tf, 1); // Close bar vừa đóng
|
||||
datetime bar1T = iTime (_Symbol, tf, 1);
|
||||
double lastBarClose = iClose(_Symbol, tf, 1); // Close bar vừa đóng
|
||||
datetime lastBarTime = iTime (_Symbol, tf, 1);
|
||||
|
||||
// Chỉ detect MSS khi đang WAIT_TRIGGER, trên M5, đã có h0/l0, H1 trend rõ
|
||||
if (tf == InpTriggerTF
|
||||
@@ -51,46 +53,47 @@ inline void UpdateTFTrendContext(ENUM_TIMEFRAMES tf, int lookback, TFTrendContex
|
||||
&& ctx.h0 > 0 && ctx.l0 > 0
|
||||
&& g_MiddleTrend.trend != DIR_NONE)
|
||||
{
|
||||
bool mssHit = false;
|
||||
MarketDir breakDir = DIR_NONE;
|
||||
double entryLevel = 0, slLevel = 0;
|
||||
bool isMssTriggered = false;
|
||||
MarketDir mssBreakDirection = DIR_NONE;
|
||||
double entryLevel = 0;
|
||||
double slLevel = 0;
|
||||
|
||||
if (g_MiddleTrend.trend == DIR_UP && bar1C > ctx.h0) // H1 uptrend + M5 close phá tH0 = bull MSS
|
||||
if (g_MiddleTrend.trend == DIR_UP && lastBarClose > ctx.h0) // H1 uptrend + M5 close phá tH0 = bull MSS
|
||||
{
|
||||
mssHit = true;
|
||||
breakDir = DIR_UP;
|
||||
entryLevel = ctx.h0; // Entry = tH0
|
||||
slLevel = ctx.l0; // SL = tL0
|
||||
isMssTriggered = true;
|
||||
mssBreakDirection = DIR_UP;
|
||||
entryLevel = ctx.h0; // Entry = tH0
|
||||
slLevel = ctx.l0; // SL = tL0
|
||||
}
|
||||
else if (g_MiddleTrend.trend == DIR_DOWN && bar1C < ctx.l0) // Bear MSS
|
||||
else if (g_MiddleTrend.trend == DIR_DOWN && lastBarClose < ctx.l0) // Bear MSS
|
||||
{
|
||||
mssHit = true;
|
||||
breakDir = DIR_DOWN;
|
||||
entryLevel = ctx.l0;
|
||||
slLevel = ctx.h0;
|
||||
isMssTriggered = true;
|
||||
mssBreakDirection = DIR_DOWN;
|
||||
entryLevel = ctx.l0;
|
||||
slLevel = ctx.h0;
|
||||
}
|
||||
|
||||
if (mssHit && bar1T != ctx.lastMssTime) // MSS mới (chưa ghi nhận bar này)
|
||||
if (isMssTriggered && lastBarTime != ctx.lastMssTime) // MSS mới (chưa ghi nhận bar này)
|
||||
{
|
||||
double swingDepth = MathAbs(ctx.h0 - ctx.l0) / _Point; // Độ sâu swing (point)
|
||||
if (swingDepth < InpMSSMinDepthPts) // Quá nông → bỏ qua
|
||||
double mssSwingDepthPoints = MathAbs(ctx.h0 - ctx.l0) / _Point; // Độ sâu swing (point)
|
||||
if (mssSwingDepthPoints < InpMSSMinDepthPts) // Quá nông → bỏ qua
|
||||
{
|
||||
if (InpDebugLog)
|
||||
PrintFormat("[M5 MSS SKIP] depth=%.0f pts < %d | H0=%.5f L0=%.5f | %s",
|
||||
swingDepth, InpMSSMinDepthPts, ctx.h0, ctx.l0, TimeToString(bar1T));
|
||||
mssSwingDepthPoints, InpMSSMinDepthPts, ctx.h0, ctx.l0, TimeToString(lastBarTime));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctx.lastMssTime = bar1T; // Ghi nhận thời điểm MSS
|
||||
ctx.lastMssTime = lastBarTime; // Ghi nhận thời điểm MSS
|
||||
ctx.lastMssLevel = entryLevel; // Giá entry
|
||||
ctx.lastMssBreak = breakDir; // UP/DOWN
|
||||
ctx.lastMssBreak = mssBreakDirection; // UP/DOWN
|
||||
ctx.mssSLSwing = slLevel; // Giá SL (tL0 hoặc tH0)
|
||||
|
||||
if (InpDebugLog)
|
||||
PrintFormat("[M5 MSS] %s | entry=%.5f SL=%.5f depth=%.0fpts | close=%.5f | H0=%.5f L0=%.5f | %s",
|
||||
(breakDir == DIR_UP) ? "▲ Bull" : "▼ Bear",
|
||||
entryLevel, slLevel, swingDepth, bar1C,
|
||||
ctx.h0, ctx.l0, TimeToString(bar1T));
|
||||
(mssBreakDirection == DIR_UP) ? "▲ Bull" : "▼ Bear",
|
||||
entryLevel, slLevel, mssSwingDepthPoints, lastBarClose,
|
||||
ctx.h0, ctx.l0, TimeToString(lastBarTime));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -116,10 +119,10 @@ inline void UpdateTFTrendContext(ENUM_TIMEFRAMES tf, int lookback, TFTrendContex
|
||||
|
||||
inline void UpdateDailyRiskContext()
|
||||
{
|
||||
datetime today = iTime(_Symbol, PERIOD_D1, 0); // Mốc D1 hiện tại
|
||||
if (today != g_DailyRisk.dayStartTime) // Sang ngày mới
|
||||
datetime currentDayTime = iTime(_Symbol, PERIOD_D1, 0); // Mốc D1 hiện tại
|
||||
if (currentDayTime != g_DailyRisk.dayStartTime) // Sang ngày mới
|
||||
{
|
||||
g_DailyRisk.dayStartTime = today;
|
||||
g_DailyRisk.dayStartTime = currentDayTime;
|
||||
g_DailyRisk.startBalance = AccountInfoDouble(ACCOUNT_BALANCE); // Balance đầu ngày
|
||||
g_DailyRisk.limitHit = false; // Reset cờ chạm limit
|
||||
if (InpDebugLog) PrintFormat("[DAILY RISK] New day | start=%.2f", g_DailyRisk.startBalance);
|
||||
@@ -127,13 +130,13 @@ inline void UpdateDailyRiskContext()
|
||||
if (g_DailyRisk.limitHit) return; // Đã chạm limit → không cập nhật gì thêm
|
||||
|
||||
g_DailyRisk.currentBalance = AccountInfoDouble(ACCOUNT_BALANCE);
|
||||
double lostPct = (g_DailyRisk.startBalance - g_DailyRisk.currentBalance)
|
||||
/ g_DailyRisk.startBalance * 100.0; // % lỗ so với đầu ngày
|
||||
if (lostPct >= InpMaxDailyLossPct) // Vượt ngưỡng max daily loss
|
||||
double lossPercentToday = (g_DailyRisk.startBalance - g_DailyRisk.currentBalance)
|
||||
/ g_DailyRisk.startBalance * 100.0; // % lỗ so với đầu ngày
|
||||
if (lossPercentToday >= InpMaxDailyLossPct) // Vượt ngưỡng max daily loss
|
||||
{
|
||||
g_DailyRisk.limitHit = true;
|
||||
PrintFormat("[DAILY RISK] ⛔ Limit hit | lost=%.2f%% | bal=%.2f",
|
||||
lostPct, g_DailyRisk.currentBalance);
|
||||
lossPercentToday, g_DailyRisk.currentBalance);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user