Filter trend h1

This commit is contained in:
Bell
2025-12-20 05:28:49 +07:00
parent ef307514c8
commit 28b917f89b
2 changed files with 342 additions and 10 deletions
+10 -10
View File
@@ -86,9 +86,9 @@ input bool PrintToExperts = false; // không dùng — logs đã được c
// slot 0 = HTF, 1 = MTF, 2 = LTF
int TrendTF[3]; // 1 = up, -1 = down, 0 = sideway / unknown
input ENUM_TIMEFRAMES HighTF = PERIOD_D1; // Khung thời gian cao
input ENUM_TIMEFRAMES MiddleTF = PERIOD_H1; // Khung thời gian trung bình (dùng để tìm FVG)
input ENUM_TIMEFRAMES LowTF = PERIOD_M5; // Khung thời gian thấp (Tìm điểm vào lệnh)
input ENUM_TIMEFRAMES HighTF = PERIOD_H4; // Khung thời gian cao
input ENUM_TIMEFRAMES MiddleTF = PERIOD_M15; // Khung thời gian trung bình (dùng để tìm FVG)
input ENUM_TIMEFRAMES LowTF = PERIOD_M1; // Khung thời gian thấp (Tìm điểm vào lệnh)
// --- multi-TF swing storage (slots) ---
// slot 0 = HighTF, slot 1 = MiddleTF, slot 2 = LowTF
@@ -1928,13 +1928,13 @@ bool CheckValidEntry(
if(mssDirection == 0)
return false;
// HTF phải có trend rõ ràng
if(htfTrend == 0)
{
if(PrintEntryLog)
Print("CheckValidEntry FAIL: HTF is SIDEWAY");
return false;
}
// HTF phải có trend rõ ràng // TEST
// if(htfTrend == 0)
// {
// if(PrintEntryLog)
// Print("CheckValidEntry FAIL: HTF is SIDEWAY");
// return false;
// }
if(fvgIndex < 0 || fvgIndex >= MTF_FVG_count)
{
+332
View File
@@ -0,0 +1,332 @@
//+------------------------------------------------------------------+
//| ICT Early Trend Detection EA |
//| Structure + Early Key-Level Break (MSS-style) |
//| Clean Architecture Meaningful Naming |
//| Author: Bell CW |
//+------------------------------------------------------------------+
#property strict
//====================================================
// INPUT PARAMETERS
//====================================================
input ENUM_TIMEFRAMES TrendTimeframe = PERIOD_H1; // Timeframe xác định trend
input ENUM_TIMEFRAMES TriggerTimeframe = PERIOD_M5; // Timeframe kích hoạt logic
input int SwingDetectionRange = 2; // Số nến trái/phải xác định swing
input int StructureScanLookbackBars = 150; // Số nến quét structure
//====================================================
// DATA STRUCTURE
//====================================================
struct TrendState
{
int trendDirection; // 1 = uptrend, -1 = downtrend, 0 = neutral
double latestSwingHigh; // Swing High mới nhất
double previousSwingHigh; // Swing High trước đó
double latestSwingLow; // Swing Low mới nhất
double previousSwingLow; // Swing Low trước đó
int latestSwingHighIndex;
int previousSwingHighIndex;
int latestSwingLowIndex;
int previousSwingLowIndex;
double currentKeyLevel; // Key level theo ICT structure
bool earlyFlipUsedThisBar; // Đã dùng early flip trong HTF bar này chưa
datetime lastStructureUpdateTime; // Thời gian HTF bar cuối cùng đã xử lý
};
//====================================================
// GLOBAL STATE
//====================================================
TrendState g_TrendState;
datetime g_LastTriggerBarTime = 0;
//====================================================
// INITIALIZATION
//====================================================
int OnInit()
{
ZeroMemory(g_TrendState);
g_TrendState.trendDirection = 0;
g_TrendState.lastStructureUpdateTime = 0;
Print("ICT Early Trend Detection EA initialized successfully");
return INIT_SUCCEEDED;
}
//====================================================
// BAR UTILITY
//====================================================
bool IsNewBarFormed(ENUM_TIMEFRAMES timeframe, datetime &lastBarTime)
{
datetime currentBarTime = iTime(_Symbol, timeframe, 0);
if(currentBarTime != lastBarTime)
{
lastBarTime = currentBarTime;
return true;
}
return false;
}
//====================================================
// SWING DETECTION (GENERIC)
//====================================================
bool IsSwingHighAtBar(
ENUM_TIMEFRAMES timeframe,
int barIndex
)
{
double highPrice = iHigh(_Symbol, timeframe, barIndex);
for(int offset = 1; offset <= SwingDetectionRange; offset++)
{
if(iHigh(_Symbol, timeframe, barIndex - offset) >= highPrice) return false;
if(iHigh(_Symbol, timeframe, barIndex + offset) >= highPrice) return false;
}
return true;
}
bool IsSwingLowAtBar(
ENUM_TIMEFRAMES timeframe,
int barIndex
)
{
double lowPrice = iLow(_Symbol, timeframe, barIndex);
for(int offset = 1; offset <= SwingDetectionRange; offset++)
{
if(iLow(_Symbol, timeframe, barIndex - offset) <= lowPrice) return false;
if(iLow(_Symbol, timeframe, barIndex + offset) <= lowPrice) return false;
}
return true;
}
//====================================================
// STRUCTURE VALIDATION
//====================================================
bool HasConfirmedMarketStructure(const TrendState &state)
{
return (
state.latestSwingHigh > 0 &&
state.previousSwingHigh > 0 &&
state.latestSwingLow > 0 &&
state.previousSwingLow > 0
);
}
//====================================================
// STRUCTURE UPDATE (TIMEFRAME AGNOSTIC)
//====================================================
void UpdateMarketStructure(
ENUM_TIMEFRAMES timeframe,
TrendState &state
)
{
datetime currentStructureBarTime = iTime(_Symbol, timeframe, 0);
if(currentStructureBarTime == state.lastStructureUpdateTime)
return;
state.lastStructureUpdateTime = currentStructureBarTime;
state.earlyFlipUsedThisBar = false;
double detectedSwingHighs[2];
double detectedSwingLows[2];
int detectedSwingHighIndices[2];
int detectedSwingLowIndices[2];
int highCount = 0;
int lowCount = 0;
for(int barIndex = SwingDetectionRange + 1;
barIndex < StructureScanLookbackBars;
barIndex++)
{
if(highCount < 2 && IsSwingHighAtBar(timeframe, barIndex))
{
detectedSwingHighs[highCount] = iHigh(_Symbol, timeframe, barIndex);
detectedSwingHighIndices[highCount] = barIndex;
highCount++;
}
if(lowCount < 2 && IsSwingLowAtBar(timeframe, barIndex))
{
detectedSwingLows[lowCount] = iLow(_Symbol, timeframe, barIndex);
detectedSwingLowIndices[lowCount] = barIndex;
lowCount++;
}
if(highCount == 2 && lowCount == 2)
break;
}
if(highCount < 2 || lowCount < 2)
return;
state.latestSwingHigh = detectedSwingHighs[0];
state.previousSwingHigh = detectedSwingHighs[1];
state.latestSwingLow = detectedSwingLows[0];
state.previousSwingLow = detectedSwingLows[1];
state.latestSwingHighIndex = detectedSwingHighIndices[0];
state.previousSwingHighIndex = detectedSwingHighIndices[1];
state.latestSwingLowIndex = detectedSwingLowIndices[0];
state.previousSwingLowIndex = detectedSwingLowIndices[1];
// ===== STRUCTURE INTERPRETATION =====
if(state.previousSwingHigh < state.latestSwingHigh &&
state.previousSwingLow < state.latestSwingLow)
{
state.trendDirection = 1;
state.currentKeyLevel = state.latestSwingLow;
}
else if(state.previousSwingHigh > state.latestSwingHigh &&
state.previousSwingLow > state.latestSwingLow)
{
state.trendDirection = -1;
state.currentKeyLevel = state.latestSwingHigh;
}
}
//====================================================
// EARLY TREND FLIP (MSS-STYLE)
//====================================================
void CheckForEarlyTrendFlip(
TrendState &state,
double currentPrice
)
{
if(!HasConfirmedMarketStructure(state)) return;
if(state.earlyFlipUsedThisBar) return;
if(state.trendDirection == 1 &&
currentPrice < state.currentKeyLevel)
{
state.trendDirection = -1;
state.currentKeyLevel = state.latestSwingHigh;
state.earlyFlipUsedThisBar = true;
}
else if(state.trendDirection == -1 &&
currentPrice > state.currentKeyLevel)
{
state.trendDirection = 1;
state.currentKeyLevel = state.latestSwingLow;
state.earlyFlipUsedThisBar = true;
}
}
//====================================================
// DRAWING UTILITIES
//====================================================
void DrawSwingLabel(
string objectName,
string labelText,
ENUM_TIMEFRAMES timeframe,
int barIndex,
double price,
color labelColor
)
{
if(barIndex < 0) return;
datetime barTime = iTime(_Symbol, timeframe, barIndex);
ObjectDelete(0, objectName);
ObjectCreate(0, objectName, OBJ_TEXT, 0, barTime, price);
ObjectSetInteger(0, objectName, OBJPROP_COLOR, labelColor);
ObjectSetInteger(0, objectName, OBJPROP_FONTSIZE, 8);
ObjectSetString (0, objectName, OBJPROP_TEXT, labelText);
}
void DrawMarketStructure(
ENUM_TIMEFRAMES timeframe,
const TrendState &state
)
{
DrawSwingLabel("SWING_HIGH_LATEST", "H0", timeframe,
state.latestSwingHighIndex,
state.latestSwingHigh, clrLime);
DrawSwingLabel("SWING_HIGH_PREVIOUS", "H1", timeframe,
state.previousSwingHighIndex,
state.previousSwingHigh, clrGreen);
DrawSwingLabel("SWING_LOW_LATEST", "L0", timeframe,
state.latestSwingLowIndex,
state.latestSwingLow, clrRed);
DrawSwingLabel("SWING_LOW_PREVIOUS", "L1", timeframe,
state.previousSwingLowIndex,
state.previousSwingLow, clrMaroon);
}
void DrawTrendSummaryLabel(const TrendState &state)
{
string labelName = "TREND_SUMMARY";
ObjectDelete(0, labelName);
string labelText = "TREND: NEUTRAL";
color labelColor = clrGray;
if(state.trendDirection == 1)
{
labelText = StringFormat(
"UPTREND - Key Level: %.2f%s",
state.currentKeyLevel,
state.earlyFlipUsedThisBar ? " -> EARLY FLIP" : ""
);
labelColor = state.earlyFlipUsedThisBar ? clrOrange : clrLime;
}
else if(state.trendDirection == -1)
{
labelText = StringFormat(
"DOWNTREND - Key Level: %.2f%s",
state.currentKeyLevel,
state.earlyFlipUsedThisBar ? " -> EARLY FLIP" : ""
);
labelColor = state.earlyFlipUsedThisBar ? clrOrange : clrRed;
}
ObjectCreate(0, labelName, OBJ_LABEL, 0, 0, 0);
ObjectSetInteger(0, labelName, OBJPROP_CORNER, CORNER_LEFT_UPPER);
ObjectSetInteger(0, labelName, OBJPROP_XDISTANCE, 10);
ObjectSetInteger(0, labelName, OBJPROP_YDISTANCE, 20);
ObjectSetInteger(0, labelName, OBJPROP_COLOR, labelColor);
ObjectSetInteger(0, labelName, OBJPROP_FONTSIZE, 9);
ObjectSetString (0, labelName, OBJPROP_TEXT, labelText);
}
//====================================================
// MAIN LOOP
//====================================================
void OnTick()
{
if(!IsNewBarFormed(TriggerTimeframe, g_LastTriggerBarTime))
return;
UpdateMarketStructure(TrendTimeframe, g_TrendState);
double currentBidPrice = SymbolInfoDouble(_Symbol, SYMBOL_BID);
CheckForEarlyTrendFlip(g_TrendState, currentBidPrice);
DrawMarketStructure(TrendTimeframe, g_TrendState);
DrawTrendSummaryLabel(g_TrendState);
// === Entry logic sẽ gắn tại đây ===
}
//+------------------------------------------------------------------+