Remove bias
This commit is contained in:
+10
-15
@@ -1,21 +1,17 @@
|
||||
//+------------------------------------------------------------------+
|
||||
//| ICT EA – FVG Edition (MQL5) v4.3 |
|
||||
//| Architecture : BiasTF(D1) + MiddleTF(H1) + TriggerTF(M5) |
|
||||
//| Architecture : MiddleTF(H1) + TriggerTF(M5) |
|
||||
//| State Machine: IDLE → WAIT_TOUCH → WAIT_TRIGGER → IN_TRADE |
|
||||
//| |
|
||||
//| Flow tổng thể: |
|
||||
//| 1. D1 bias (UP/DOWN) đồng thuận H1 trend |
|
||||
//| 2. H1 FVG thuận xu hướng → chờ price retrace vào FVG |
|
||||
//| 3. Giá touch H1 FVG → chờ M5 MSS xác nhận đảo chiều |
|
||||
//| 4. M5 MSS = swing break thuận chiều H1: |
|
||||
//| 1. H1 trend xác định hướng, tìm FVG thuận xu hướng |
|
||||
//| 2. Giá touch H1 FVG → chờ M5 MSS xác nhận |
|
||||
//| 3. M5 MSS = swing break thuận chiều H1: |
|
||||
//| - H1 UP → close > tH0 (phá swing high) = bull MSS |
|
||||
//| - H1 DOWN → close < tL0 (phá swing low) = bear MSS |
|
||||
//| v4.3: MSS chỉ detect khi WAIT_TRIGGER, không vẽ/detect khác |
|
||||
//| 5. Entry = limit tại swing level vừa bị phá (tH0 hoặc tL0) |
|
||||
//| 6. SL = swing đối diện (tL0 cho buy, tH0 cho sell) |
|
||||
//| 7. TP = Entry ± 2R |
|
||||
//| |
|
||||
//| Drawing: objects KHÔNG BAO GIỜ bị xóa, chỉ update |
|
||||
//| 4. Entry = limit tại swing level vừa bị phá (tH0 hoặc tL0) |
|
||||
//| 5. SL = swing đối diện (tL0 cho buy, tH0 cho sell) |
|
||||
//| 6. TP = Entry ± 2R |
|
||||
//+------------------------------------------------------------------+
|
||||
#property copyright "Bell's ICT EA"
|
||||
#property version "4.30"
|
||||
@@ -39,7 +35,6 @@
|
||||
EAState g_State = EA_IDLE;
|
||||
BlockReason g_BlockReason = BLOCK_NONE;
|
||||
|
||||
BiasContext g_Bias;
|
||||
TFTrendContext g_MiddleTrend;
|
||||
TFTrendContext g_TriggerTrend;
|
||||
DailyRiskContext g_DailyRisk;
|
||||
@@ -71,7 +66,7 @@ const string PREFIX_SESSION = "Session_";
|
||||
/** Initializes globals, contexts, FVG pool and first draw. */
|
||||
int OnInit()
|
||||
{
|
||||
ZeroMemory(g_Bias); ZeroMemory(g_MiddleTrend); ZeroMemory(g_TriggerTrend);
|
||||
ZeroMemory(g_MiddleTrend); ZeroMemory(g_TriggerTrend);
|
||||
ZeroMemory(g_DailyRisk); ZeroMemory(g_OrderPlan);
|
||||
for (int i = 0; i < MAX_FVG_POOL; i++) ZeroMemory(g_FVGPool[i]);
|
||||
g_FVGCount = 0; g_NextFVGId = 0;
|
||||
@@ -82,8 +77,8 @@ int OnInit()
|
||||
ScanAndRegisterFVGs();
|
||||
DrawVisuals();
|
||||
|
||||
PrintFormat("✅ ICT EA v4.3 | Bias=%s | H1=%s | M5=%s | Pool=%d",
|
||||
EnumToString(g_Bias.bias), EnumToString(g_MiddleTrend.trend),
|
||||
PrintFormat("✅ ICT EA v4.3 | H1=%s | M5=%s | Pool=%d",
|
||||
EnumToString(g_MiddleTrend.trend),
|
||||
EnumToString(g_TriggerTrend.trend), g_FVGCount);
|
||||
return INIT_SUCCEEDED;
|
||||
}
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#ifndef EA_ICT_CL__CONFIG_MQH
|
||||
#define EA_ICT_CL__CONFIG_MQH
|
||||
|
||||
input ENUM_TIMEFRAMES InpBiasTF = PERIOD_D1;
|
||||
input ENUM_TIMEFRAMES InpMiddleTF = PERIOD_H1;
|
||||
input ENUM_TIMEFRAMES InpTriggerTF = PERIOD_M5;
|
||||
|
||||
@@ -9,13 +8,13 @@ input double InpRiskPercent = 1.0;
|
||||
input double InpRiskReward = 2.0;
|
||||
input double InpMaxDailyLossPct = 3.0;
|
||||
|
||||
input int InpLondonStartHour = 8;
|
||||
input int InpLondonStartHour = 7;
|
||||
input int InpLondonEndHour = 17;
|
||||
input int InpNYStartHour = 13;
|
||||
input int InpNYEndHour = 22;
|
||||
|
||||
input int InpMiddleTfSwingRange = 3;
|
||||
input int InpTriggerTfSwingRange = 3;
|
||||
input int InpMiddleTfSwingRange = 2;
|
||||
input int InpTriggerTfSwingRange = 2;
|
||||
input int InpSwingLookback = 50;
|
||||
input int InpTriggerSwingLookback = 30;
|
||||
|
||||
|
||||
@@ -1,66 +1,6 @@
|
||||
#ifndef EA_ICT_CL__CONTEXTS_MQH
|
||||
#define EA_ICT_CL__CONTEXTS_MQH
|
||||
|
||||
/** Resolves D1 bias from two consecutive daily bars (bar1 = last closed, bar2 = prior). */
|
||||
inline HTFBias ResolveBias(double bar1High, double bar1Low, double bar1Close,
|
||||
double bar2High, double bar2Low)
|
||||
{
|
||||
if (bar1Close > bar2High) return BIAS_UP;
|
||||
if (bar1Close < bar2Low) return BIAS_DOWN;
|
||||
|
||||
bool sweptHigh = (bar1High > bar2High);
|
||||
bool sweptLow = (bar1Low < bar2Low);
|
||||
|
||||
// Trường hợp quét cả hai đầu: so sánh độ dài râu vượt khỏi range bar2.
|
||||
// Râu nào dài hơn → ưu tiên chiều NGƯỢC LẠI (stop run –> đi ngược sweep mạnh hơn).
|
||||
if (sweptHigh && sweptLow)
|
||||
{
|
||||
double upperSweep = bar1High - bar2High; // khoảng quét lên trên đỉnh cũ
|
||||
double lowerSweep = bar2Low - bar1Low; // khoảng quét xuống dưới đáy cũ
|
||||
|
||||
if (upperSweep > lowerSweep) return BIAS_DOWN; // quét đỉnh mạnh hơn → bearish
|
||||
if (lowerSweep > upperSweep) return BIAS_UP; // quét đáy mạnh hơn → bullish
|
||||
|
||||
// Nếu hai râu gần như bằng nhau → dùng close tương đối với mid-range để phân định
|
||||
double mid = (bar2High + bar2Low) * 0.5;
|
||||
if (bar1Close > mid) return BIAS_UP;
|
||||
if (bar1Close < mid) return BIAS_DOWN;
|
||||
return BIAS_SIDEWAY;
|
||||
}
|
||||
|
||||
// Chỉ quét 1 đầu: giữ logic cũ với điều kiện close quay lại trong range.
|
||||
if (sweptLow && bar1Close > bar2Low) return BIAS_UP;
|
||||
if (sweptHigh && bar1Close < bar2High) return BIAS_DOWN;
|
||||
|
||||
return BIAS_SIDEWAY;
|
||||
}
|
||||
|
||||
/** Updates global D1 bias context once per new bias-TF bar. */
|
||||
inline void UpdateBiasContext()
|
||||
{
|
||||
datetime currentBiasBarTime = iTime(_Symbol, InpBiasTF, 0);
|
||||
if (currentBiasBarTime == g_Bias.lastBarTime) return;
|
||||
g_Bias.lastBarTime = currentBiasBarTime;
|
||||
|
||||
if (Bars(_Symbol, InpBiasTF) < 4) { g_Bias.bias = BIAS_NONE; return; }
|
||||
|
||||
double bar1High = iHigh (_Symbol, InpBiasTF, 1);
|
||||
double bar1Low = iLow (_Symbol, InpBiasTF, 1);
|
||||
double bar1Close = iClose(_Symbol, InpBiasTF, 1);
|
||||
double bar2High = iHigh (_Symbol, InpBiasTF, 2);
|
||||
double bar2Low = iLow (_Symbol, InpBiasTF, 2);
|
||||
|
||||
HTFBias prev = g_Bias.bias;
|
||||
g_Bias.bias = ResolveBias(bar1High, bar1Low, bar1Close, bar2High, bar2Low);
|
||||
g_Bias.rangeHigh = (g_Bias.bias == BIAS_SIDEWAY) ? bar2High : 0;
|
||||
g_Bias.rangeLow = (g_Bias.bias == BIAS_SIDEWAY) ? bar2Low : 0;
|
||||
|
||||
if (InpDebugLog && g_Bias.bias != prev)
|
||||
PrintFormat("[BIAS] %s → %s | b1[H=%.5f L=%.5f C=%.5f] b2[H=%.5f L=%.5f]",
|
||||
EnumToString(prev), EnumToString(g_Bias.bias),
|
||||
bar1High, bar1Low, bar1Close, bar2High, bar2Low);
|
||||
}
|
||||
|
||||
/** Updates TF trend context (swing + trend + MSS detection when on trigger TF). */
|
||||
inline void UpdateTFTrendContext(ENUM_TIMEFRAMES tf, int lookback, TFTrendContext &ctx)
|
||||
{
|
||||
@@ -85,8 +25,8 @@ inline void UpdateTFTrendContext(ENUM_TIMEFRAMES tf, int lookback, TFTrendContex
|
||||
{
|
||||
isMssTriggered = true;
|
||||
mssBreakDirection = DIR_UP;
|
||||
entryLevel = ctx.h0; // Entry = tH0
|
||||
slLevel = ctx.l0; // SL = tL0
|
||||
entryLevel = ctx.h0;
|
||||
slLevel = ctx.l0;
|
||||
}
|
||||
else if (g_MiddleTrend.trend == DIR_DOWN && lastBarClose < ctx.l0)
|
||||
{
|
||||
@@ -164,14 +104,12 @@ inline void UpdateDailyRiskContext()
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates all contexts: daily risk, bias, middle TF trend, trigger TF trend. */
|
||||
/** Updates all contexts: daily risk, middle TF trend, trigger TF trend. */
|
||||
inline void UpdateAllContexts()
|
||||
{
|
||||
UpdateDailyRiskContext();
|
||||
UpdateBiasContext();
|
||||
UpdateTFTrendContext(InpMiddleTF, InpSwingLookback, g_MiddleTrend);
|
||||
UpdateTFTrendContext(InpTriggerTF, InpTriggerSwingLookback, g_TriggerTrend);
|
||||
}
|
||||
|
||||
#endif // EA_ICT_CL__CONTEXTS_MQH
|
||||
|
||||
#endif
|
||||
|
||||
@@ -489,18 +489,6 @@ inline void DrawContextDebug()
|
||||
|
||||
LBL(PREFIX_DEBUG_PANEL + "HDR", "── ICT EA v4.3 ──", 10, clrSilver)
|
||||
|
||||
color cB = (g_Bias.bias == BIAS_UP)
|
||||
? clrLime
|
||||
: (g_Bias.bias == BIAS_DOWN)
|
||||
? clrTomato
|
||||
: (g_Bias.bias == BIAS_SIDEWAY) ? clrOrange : clrGray;
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "BIAS",
|
||||
StringFormat("Bias : %s", EnumToString(g_Bias.bias)),
|
||||
34,
|
||||
cB
|
||||
)
|
||||
|
||||
color cMT = (g_MiddleTrend.trend == DIR_UP)
|
||||
? clrLime
|
||||
: (g_MiddleTrend.trend == DIR_DOWN) ? clrTomato : clrGray;
|
||||
@@ -511,7 +499,7 @@ inline void DrawContextDebug()
|
||||
EnumToString(g_MiddleTrend.trend),
|
||||
g_MiddleTrend.keyLevel
|
||||
),
|
||||
58,
|
||||
34,
|
||||
cMT
|
||||
)
|
||||
|
||||
@@ -525,7 +513,7 @@ inline void DrawContextDebug()
|
||||
EnumToString(g_TriggerTrend.trend),
|
||||
g_TriggerTrend.keyLevel
|
||||
),
|
||||
82,
|
||||
58,
|
||||
cTT
|
||||
)
|
||||
|
||||
@@ -545,7 +533,7 @@ inline void DrawContextDebug()
|
||||
TimeToString(g_FVGPool[ai].mssTime, TIME_MINUTES),
|
||||
g_FVGPool[ai].id
|
||||
),
|
||||
106,
|
||||
82,
|
||||
cM
|
||||
)
|
||||
}
|
||||
@@ -561,7 +549,7 @@ inline void DrawContextDebug()
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "RISK",
|
||||
StringFormat("Risk : %.2f%% / %.2f%%", lostPct, InpMaxDailyLossPct),
|
||||
130,
|
||||
106,
|
||||
cR
|
||||
)
|
||||
|
||||
@@ -573,7 +561,7 @@ inline void DrawContextDebug()
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "ST",
|
||||
StringFormat("State: %s", EnumToString(g_State)),
|
||||
154,
|
||||
130,
|
||||
cS
|
||||
)
|
||||
|
||||
@@ -582,7 +570,7 @@ inline void DrawContextDebug()
|
||||
LBL(
|
||||
PREFIX_DEBUG_PANEL + "BLK",
|
||||
StringFormat("Block: %s", EnumToString(g_BlockReason)),
|
||||
178,
|
||||
154,
|
||||
clrTomato
|
||||
)
|
||||
}
|
||||
@@ -610,7 +598,7 @@ inline void DrawContextDebug()
|
||||
g_FVGCount,
|
||||
MAX_FVG_POOL
|
||||
),
|
||||
202,
|
||||
178,
|
||||
clrDodgerBlue
|
||||
)
|
||||
|
||||
@@ -627,7 +615,7 @@ inline void DrawContextDebug()
|
||||
g_FVGPool[ai].high,
|
||||
EnumToString(g_FVGPool[ai].status)
|
||||
),
|
||||
226,
|
||||
202,
|
||||
clrDeepSkyBlue
|
||||
)
|
||||
}
|
||||
@@ -645,7 +633,7 @@ inline void DrawContextDebug()
|
||||
g_OrderPlan.stopLoss,
|
||||
g_OrderPlan.takeProfit
|
||||
),
|
||||
250,
|
||||
226,
|
||||
clrGold
|
||||
)
|
||||
}
|
||||
@@ -703,8 +691,8 @@ inline void DrawSessionMarkers()
|
||||
|
||||
if (InpLondonStartHour < InpLondonEndHour)
|
||||
{
|
||||
datetime t1 = dayStart + startL;
|
||||
datetime t2 = dayStart + endL;
|
||||
datetime t1 = (datetime)(dayStart + startL);
|
||||
datetime t2 = (datetime)(dayStart + endL);
|
||||
if (t2 > firstTime && t1 < lastTime)
|
||||
{
|
||||
string name = PREFIX_SESSION + "L_" + IntegerToString(d);
|
||||
@@ -719,8 +707,8 @@ inline void DrawSessionMarkers()
|
||||
}
|
||||
else
|
||||
{
|
||||
datetime t1 = dayStart + startL;
|
||||
datetime t2 = dayStart + 86400 + endL;
|
||||
datetime t1 = (datetime)(dayStart + startL);
|
||||
datetime t2 = (datetime)(dayStart + 86400 + endL);
|
||||
if (t2 > firstTime && t1 < lastTime)
|
||||
{
|
||||
string name = PREFIX_SESSION + "L_" + IntegerToString(d);
|
||||
@@ -736,8 +724,8 @@ inline void DrawSessionMarkers()
|
||||
|
||||
if (InpNYStartHour < InpNYEndHour)
|
||||
{
|
||||
datetime t1 = dayStart + startN;
|
||||
datetime t2 = dayStart + endN;
|
||||
datetime t1 = (datetime)(dayStart + startN);
|
||||
datetime t2 = (datetime)(dayStart + endN);
|
||||
if (t2 > firstTime && t1 < lastTime)
|
||||
{
|
||||
string name = PREFIX_SESSION + "N_" + IntegerToString(d);
|
||||
@@ -752,8 +740,8 @@ inline void DrawSessionMarkers()
|
||||
}
|
||||
else
|
||||
{
|
||||
datetime t1 = dayStart + startN;
|
||||
datetime t2 = dayStart + 86400 + endN;
|
||||
datetime t1 = (datetime)(dayStart + startN);
|
||||
datetime t2 = (datetime)(dayStart + 86400 + endN);
|
||||
if (t2 > firstTime && t1 < lastTime)
|
||||
{
|
||||
string name = PREFIX_SESSION + "N_" + IntegerToString(d);
|
||||
@@ -776,7 +764,6 @@ inline void DrawVisuals()
|
||||
DrawContextDebug();
|
||||
DrawMiddleSwingPoints();
|
||||
DrawFVGPool();
|
||||
return; // TESTING ONLY
|
||||
DrawTriggerSwingPoints();
|
||||
DrawMSSMarkers();
|
||||
DrawOrderVisualization();
|
||||
|
||||
@@ -9,26 +9,17 @@ inline bool IsSessionAllowed()
|
||||
|| IsHourInRange(hourUtc, InpNYStartHour, InpNYEndHour);
|
||||
}
|
||||
/** True if daily loss limit has not been hit. */
|
||||
inline bool IsDailyLossOK() { return !g_DailyRisk.limitHit; }
|
||||
/** True if bias is UP or DOWN (not NONE or SIDEWAY). */
|
||||
inline bool IsBiasValid() { return g_Bias.bias == BIAS_UP || g_Bias.bias == BIAS_DOWN; }
|
||||
|
||||
/** True if H1 trend aligns with D1 bias (same direction). */
|
||||
inline bool IsMiddleTrendAligned()
|
||||
{
|
||||
if (g_MiddleTrend.trend == DIR_NONE) return false;
|
||||
return (g_Bias.bias == BIAS_UP && g_MiddleTrend.trend == DIR_UP) ||
|
||||
(g_Bias.bias == BIAS_DOWN && g_MiddleTrend.trend == DIR_DOWN);
|
||||
}
|
||||
inline bool IsDailyLossOK() { return !g_DailyRisk.limitHit; }
|
||||
/** True if middle TF has a clear trend (UP or DOWN). */
|
||||
inline bool IsMiddleTrendValid() { return g_MiddleTrend.trend != DIR_NONE; }
|
||||
|
||||
/** Evaluates all guards; sets g_BlockReason and returns false if any guard fails. */
|
||||
inline bool EvaluateGuards()
|
||||
{
|
||||
g_BlockReason = BLOCK_NONE;
|
||||
if (!IsSessionAllowed()) { g_BlockReason = BLOCK_SESSION; return false; }
|
||||
if (!IsDailyLossOK()) { g_BlockReason = BLOCK_DAILY_LOSS; return false; }
|
||||
if (!IsBiasValid()) { g_BlockReason = BLOCK_NO_BIAS; return false; }
|
||||
if (!IsMiddleTrendAligned()) { g_BlockReason = BLOCK_BIAS_MISMATCH; return false; }
|
||||
if (!IsSessionAllowed()) { g_BlockReason = BLOCK_SESSION; return false; }
|
||||
if (!IsDailyLossOK()) { g_BlockReason = BLOCK_DAILY_LOSS; return false; }
|
||||
if (!IsMiddleTrendValid()) { g_BlockReason = BLOCK_NO_TREND; return false; }
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
| File | Chức năng |
|
||||
|------|-----------|
|
||||
| **`Config.mqh`** | Toàn bộ **input** của EA: timeframe (Bias/Middle/Trigger), risk %, session giờ (London/NY), swing/FVG/MSS params, magic, slippage, debug flags. |
|
||||
| **`State.mqh`** | **Enums** và **struct**: `EAState`, `HTFBias`, `MarketDir`, `BlockReason`, `FVGStatus`; struct `BiasContext`, `TFTrendContext`, `FVGRecord`, `OrderPlan`, `DailyRiskContext`. Không chứa biến global. |
|
||||
| **`State.mqh`** | **Enums** và **struct**: `EAState`, `MarketDir`, `BlockReason`, `FVGStatus`; struct `TFTrendContext`, `FVGRecord`, `OrderPlan`, `DailyRiskContext`. Không chứa biến global. |
|
||||
|
||||
### Layer 2 – Tiện ích (sau Config + State)
|
||||
|
||||
@@ -39,8 +39,8 @@
|
||||
|
||||
| File | Chức năng |
|
||||
|------|-----------|
|
||||
| **`Contexts.mqh`** | Cập nhật context: `ResolveBias`, `UpdateBiasContext`, `UpdateTFTrendContext`, `UpdateDailyRiskContext`, `UpdateAllContexts`. Dùng globals `g_Bias`, `g_MiddleTrend`, `g_TriggerTrend`, `g_DailyRisk`. |
|
||||
| **`Guards.mqh`** | Điều kiện trước khi trade: `IsSessionAllowed`, `IsDailyLossOK`, `IsBiasValid`, `IsMiddleTrendAligned`, `EvaluateGuards`. Set `g_BlockReason` khi block. |
|
||||
| **`Contexts.mqh`** | Cập nhật context: `UpdateTFTrendContext`, `UpdateDailyRiskContext`, `UpdateAllContexts`. Dùng globals `g_MiddleTrend`, `g_TriggerTrend`, `g_DailyRisk`. |
|
||||
| **`Guards.mqh`** | Điều kiện trước khi trade: `IsSessionAllowed`, `IsDailyLossOK`, `IsMiddleTrendValid`, `EvaluateGuards`. Set `g_BlockReason` khi block. |
|
||||
| **`Signals_BOS_FVG_OB.mqh`** | **FVG**: `IsCandleStrong`, `IsFVGInPool`, `ScanAndRegisterFVGs`, `UpdateFVGStatuses`, `GetBestActiveFVGIdx`. Quản lý pool FVG và trạng thái PENDING/TOUCHED/USED. |
|
||||
| **`Trade.mqh`** | **Order plan & execution**: `CalcLotFromRisk`, `BuildOrderPlan`, `ExecuteLimitOrder`. Gửi lệnh pending limit, dùng `g_OrderPlan`. |
|
||||
| **`StateMachine.mqh`** | **State machine**: `TransitionTo`, `ResetToIdle`, `OnStateIdle`, `OnStateWaitTouch`, `OnStateWaitTrigger`, `OnStateInTrade`, `RunStateMachine`. Điều phối theo `g_State`. |
|
||||
@@ -53,7 +53,7 @@
|
||||
```
|
||||
Layer 1: Config.mqh → State.mqh
|
||||
Layer 2: Utils, Logging, Market, Indicators, Sessions, Filters, Risk, Orders, Swing, Trailing
|
||||
Globals: g_State, g_Bias, g_MiddleTrend, g_TriggerTrend, g_DailyRisk, g_FVGPool, g_OrderPlan, PREFIX_*
|
||||
Globals: g_State, g_MiddleTrend, g_TriggerTrend, g_DailyRisk, g_FVGPool, g_OrderPlan, PREFIX_*
|
||||
Layer 3: Contexts.mqh → Guards.mqh → Signals_BOS_FVG_OB.mqh → Trade.mqh → StateMachine.mqh → Drawing.mqh
|
||||
```
|
||||
|
||||
@@ -65,7 +65,6 @@ Layer 3 phải include **sau** khi globals và prefix đã được khai báo tr
|
||||
|
||||
### Timeframe
|
||||
|
||||
- **BiasTF (D1):** xác định bias (UP/DOWN/SIDEWAY/NONE).
|
||||
- **MiddleTF (H1):** trend + quét FVG thuận xu hướng.
|
||||
- **TriggerTF (M5):** xác nhận entry bằng MSS (market structure shift).
|
||||
|
||||
@@ -80,8 +79,8 @@ Layer 3 phải include **sau** khi globals và prefix đã được khai báo tr
|
||||
|
||||
### Luồng quyết định (mỗi tick)
|
||||
|
||||
1. **UpdateAllContexts()** – Cập nhật D1 bias, H1/M5 swing (và MSS nếu đang WAIT_TRIGGER).
|
||||
2. **EvaluateGuards()** – Kiểm tra session, daily loss, bias, alignment H1/D1.
|
||||
1. **UpdateAllContexts()** – Cập nhật H1/M5 swing (và MSS nếu đang WAIT_TRIGGER).
|
||||
2. **EvaluateGuards()** – Kiểm tra session, daily loss, H1 trend.
|
||||
3. Nếu pass → **RunStateMachine()**: `UpdateFVGStatuses()` + `ScanAndRegisterFVGs()` + xử lý theo state (Idle → chọn FVG; WaitTouch → chờ touch/switch FVG; WaitTrigger → khi FVG triggered thì BuildOrderPlan + ExecuteLimitOrder; InTrade → theo dõi order/position).
|
||||
4. Nếu **InpDebugDraw** bật → **DrawVisuals()** (swing, MSS, FVG pool, order, debug panel).
|
||||
|
||||
@@ -102,7 +101,7 @@ Các hằng trong `EA_ICT_CL.mq5` dùng cho Drawing:
|
||||
- `PREFIX_MSS_MARKER` – Điểm đánh dấu MSS.
|
||||
- `PREFIX_FVG_POOL` – Các hình chữ nhật FVG.
|
||||
- `PREFIX_ORDER_VISUAL` – Vùng/label Entry/SL/TP.
|
||||
- `PREFIX_DEBUG_PANEL` – Bảng thông tin góc trái (Bias, H1/M5, Risk, State, Pool, Order).
|
||||
- `PREFIX_DEBUG_PANEL` – Bảng thông tin góc trái (H1/M5, Risk, State, Pool, Order).
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -127,7 +127,7 @@ inline void ScanAndRegisterFVGs()
|
||||
}
|
||||
}
|
||||
|
||||
/** Updates status of each FVG in pool (broken, touched, expired, MSS-triggered). */
|
||||
/** Updates status of each FVG in pool (broken, touched, MSS-triggered). TOUCHED chỉ chuyển USED khi broke hoặc MSS, không expire. */
|
||||
inline void UpdateFVGStatuses()
|
||||
{
|
||||
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
|
||||
@@ -194,24 +194,8 @@ inline void UpdateFVGStatuses()
|
||||
(g_TriggerTrend.lastMssBreak == DIR_UP) ? "▲" : "▼",
|
||||
g_FVGPool[i].mssEntry, g_FVGPool[i].mssSL,
|
||||
TimeToString(g_FVGPool[i].mssTime, TIME_MINUTES));
|
||||
continue;
|
||||
}
|
||||
|
||||
int ageMinutes = (int)((TimeCurrent() - g_FVGPool[i].createdTime) / 60);
|
||||
if (ageMinutes > InpFVGMaxAliveMin)
|
||||
{
|
||||
g_FVGPool[i].status = FVG_USED;
|
||||
g_FVGPool[i].usedCase = 0;
|
||||
g_FVGPool[i].usedTime = TimeCurrent();
|
||||
|
||||
if (g_ActiveFVGIdx >= 0
|
||||
&& g_FVGPool[g_ActiveFVGIdx].id == g_FVGPool[i].id)
|
||||
g_ActiveFVGIdx = -1;
|
||||
|
||||
if (InpDebugLog)
|
||||
PrintFormat("[FVG #%d] TOUCHED EXPIRED (age=%dmin > %d) → USED",
|
||||
g_FVGPool[i].id, ageMinutes, InpFVGMaxAliveMin);
|
||||
}
|
||||
// TOUCHED chỉ kết thúc khi BROKE (usedCase 1) hoặc MSS (usedCase 2); không expire theo thời gian.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,12 +9,10 @@ enum EAState
|
||||
EA_IN_TRADE
|
||||
};
|
||||
|
||||
enum HTFBias { BIAS_NONE=0, BIAS_UP=1, BIAS_DOWN=-1, BIAS_SIDEWAY=2 };
|
||||
enum MarketDir { DIR_NONE=0, DIR_UP=1, DIR_DOWN=-1 };
|
||||
enum MarketDir { DIR_NONE=0, DIR_UP=1, DIR_DOWN=-1 };
|
||||
enum BlockReason
|
||||
{
|
||||
BLOCK_NONE, BLOCK_SESSION, BLOCK_DAILY_LOSS,
|
||||
BLOCK_BIAS_MISMATCH, BLOCK_NO_BIAS
|
||||
BLOCK_NONE, BLOCK_SESSION, BLOCK_DAILY_LOSS, BLOCK_NO_TREND
|
||||
};
|
||||
enum FVGStatus
|
||||
{
|
||||
@@ -23,13 +21,6 @@ enum FVGStatus
|
||||
FVG_USED
|
||||
};
|
||||
|
||||
struct BiasContext
|
||||
{
|
||||
HTFBias bias;
|
||||
double rangeHigh, rangeLow;
|
||||
datetime lastBarTime;
|
||||
};
|
||||
|
||||
struct TFTrendContext
|
||||
{
|
||||
MarketDir trend;
|
||||
|
||||
Reference in New Issue
Block a user