Add CheckValidEntry() for filtering trend

This commit is contained in:
Bell
2025-12-13 22:43:05 +07:00
parent 954e4d1c37
commit 7f5dbb64b9
+214 -12
View File
@@ -11,10 +11,13 @@
bool PrintEntryLog = true; // nếu true -> in log chỉ liên quan tới entry
input double RishPercent = 1.0; // % vốn rủi ro cho mỗi lệnh
input double RiskRewardRatio = 8.0; // tỉ lệ R:R mặc định
input double RiskRewardRatio = 6.0; // tỉ lệ R:R mặc định
input double moveSLRange = 1; // số R cần đạt để dời SL về entry (BE)
input int MaxLimitOrderTime = 60;
input double moveSLRange = 1; // Nomal moving SL: số R cần đạt để dời SL về entry (BE)
input int MaxLimitOrderTime = 120;
input double moveSLStartR = 3; // Advanced moving SL: bắt đầu kích hoạt trailing
input double trailOffsetR = 3; // Advanced moving SL: khoảng cách SL so với giá hiện tại
// Cấu hình Swing
input int htfSwingRange = 2; // X: số nến trước và sau để xác định 1 đỉnh/đáy
@@ -1737,22 +1740,116 @@ void DetectMSSOnTimeframe(string sym, ENUM_TIMEFRAMES tf, int slot, bool enabled
mss.key_level = newer.broken_sw_price;
// Nếu đang watch và MSS direction trùng với FVG direction -> xử lý pending
if(watchingMSSMode && watchingFVGIndex >= 0)
{
if(watchingMSSMode && watchingFVGIndex >= 0) {
if(mss.found && mss.direction == watchingFVGDir)
{
if(PrintEntryLog) PrintFormat("MSS matched watched FVG dir=%d -> creating pending", mss.direction);
watchingMSSMode = false;
watchingFVGIndex = -1;
watchingFVGDir = 0;
bool valid = CheckValidEntry(
mss.direction,
TrendTF[0], // HTF trend
TrendTF[1], // MTF trend
watchingFVGIndex
);
SetUpPendingEntryForMSS(mss, slot);
if(valid)
{
if(PrintEntryLog)
Print(">>> ENTRY CONDITIONS PASSED → Create Pending");
watchingMSSMode = false;
watchingFVGIndex = -1;
watchingFVGDir = 0;
SetUpPendingEntryForMSS(mss, slot);
}
else
{
if(PrintEntryLog)
Print(">>> ENTRY BLOCKED by CheckValidEntry()");
}
}
}
DrawMss(sym, tf, mss, slot);
}
bool CheckValidEntry(
int mssDirection,
int htfTrend,
int mtfTrend,
int fvgIndex
)
{
// =============================
// 0. Sanity check
// =============================
if(mssDirection == 0)
return false;
if(fvgIndex < 0 || fvgIndex >= FVG_count)
{
if(PrintEntryLog)
Print("CheckValidEntry: invalid FVG index");
return false;
}
int fvgDir = FVGs[fvgIndex].type; // 1 bull, -1 bear
// =============================
// 1. MSS direction == FVG direction
// (thường đã đúng do watchingMSSMode,
// nhưng giữ lại cho chắc)
// =============================
if(mssDirection != fvgDir)
{
if(PrintEntryLog)
PrintFormat(
"CheckValidEntry FAIL: MSS dir=%d != FVG dir=%d",
mssDirection, fvgDir
);
return false;
}
// =============================
// 2. FVG direction thuận MTF trend
// =============================
if(mtfTrend != 0 && fvgDir != mtfTrend)
{
if(PrintEntryLog)
PrintFormat(
"CheckValidEntry FAIL: FVG dir=%d not aligned with MTF trend=%d",
fvgDir, mtfTrend
);
return false;
}
// =============================
// 3. MTF trend thuận HTF trend
// =============================
if(htfTrend != 0 && mtfTrend != 0 && htfTrend != mtfTrend)
{
if(PrintEntryLog)
PrintFormat(
"CheckValidEntry FAIL: MTF trend=%d not aligned with HTF trend=%d",
mtfTrend, htfTrend
);
return false;
}
// =============================
// PASS ALL CONDITIONS
// =============================
if(PrintEntryLog)
{
PrintFormat(
"CheckValidEntry PASS: dir=%d | FVG=%d | MTF trend=%d | HTF trend=%d",
mssDirection, fvgDir, mtfTrend, htfTrend
);
}
return true;
}
void HandleLogicForTimeframe(string sym, ENUM_TIMEFRAMES tf, int slot, bool detectMSS,
int swingRange, bool requireFVG,
double minBreakPips, int minConsec,
@@ -2043,7 +2140,7 @@ bool PlacePendingOrderFromPendingEntry()
}
// 1) Vẽ visuals trước (đảm bảo compositeName cập nhật)
DrawPendingEntryVisuals(sym);
// DrawPendingEntryVisuals(sym);
// 2) Chuẩn bị trade request
MqlTradeRequest request;
@@ -2430,12 +2527,117 @@ void CancelExpiredLimitOrder()
}
}
void MoveStoplossAdvanced()
{
string sym = Symbol();
// chỉ quản lý 1 position cho symbol
if(!PositionSelect(sym))
return;
ulong ticket = (ulong)PositionGetInteger(POSITION_TICKET);
ENUM_POSITION_TYPE type =
(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);
double entry = PositionGetDouble(POSITION_PRICE_OPEN);
double sl = PositionGetDouble(POSITION_SL);
double tp = PositionGetDouble(POSITION_TP);
if(entry <= 0.0 || sl <= 0.0)
return;
// ===== R BAN ĐẦU =====
double R = MathAbs(entry - sl);
if(R <= 0.0)
return;
double bid = SymbolInfoDouble(sym, SYMBOL_BID);
double ask = SymbolInfoDouble(sym, SYMBOL_ASK);
// ===== PROFIT HIỆN TẠI (theo R) =====
double profitR = 0.0;
if(type == POSITION_TYPE_BUY)
profitR = (bid - entry) / R;
else
profitR = (entry - ask) / R;
// ===== CHƯA ĐỦ ĐIỀU KIỆN BE =====
if(profitR < moveSLStartR)
return;
int digits = (int)SymbolInfoInteger(sym, SYMBOL_DIGITS);
double newSL = sl;
// =========================================================
// 1️⃣ BE PHASE
// =========================================================
if(profitR >= moveSLStartR && profitR < (moveSLStartR + trailOffsetR))
{
newSL = entry;
}
else
{
// =========================================================
// 2️⃣ STEP TRAIL PHASE (theo bậc R)
// =========================================================
int step = (int)MathFloor(
(profitR - moveSLStartR) / trailOffsetR
);
double targetR = step * trailOffsetR;
if(type == POSITION_TYPE_BUY)
newSL = entry + targetR * R;
else
newSL = entry - targetR * R;
}
newSL = NormalizeDouble(newSL, digits);
// ===== KHÔNG CHO SL ĐI LÙI =====
if(type == POSITION_TYPE_BUY && newSL <= sl)
return;
if(type == POSITION_TYPE_SELL && newSL >= sl)
return;
// ===== GỬI MODIFY =====
MqlTradeRequest req;
MqlTradeResult res;
ZeroMemory(req);
ZeroMemory(res);
req.action = TRADE_ACTION_SLTP;
req.position = ticket;
req.symbol = sym;
req.sl = newSL;
req.tp = tp;
if(!OrderSend(req, res))
{
if(PrintEntryLog)
PrintFormat("MoveSL ICT-C: OrderSend failed ticket=%I64u", ticket);
return;
}
if(res.retcode == TRADE_RETCODE_DONE && PrintEntryLog)
{
PrintFormat(
"MoveSL ICT-C: SL -> %.5f | profitR=%.2fR | step=%d",
newSL, profitR,
(int)MathFloor((profitR - moveSLStartR) / trailOffsetR)
);
}
}
void OnTick()
{
string sym = Symbol();
CancelExpiredLimitOrder();
MoveStoploss(); // ⭐ quản lý vốn
if (moveSLRange > 0) {
// MoveStoploss();
// MoveStoplossAdvanced();
}
if(IsNewClosedBar(sym, HighTF, 0)) {
HandleLogicForTimeframe(sym, HighTF, 0, DetectMSS_HTF, htfSwingRange, false, 10.0, 2, 50, FVGLookback);