Fix weekend gap risk and short signal detection

Grid EA (v3.1):
- Add weekend protection: close positions Friday before market close
- New settings: InpCloseBeforeWeekend, InpWeekendCloseHour, InpCancelPendingBeforeWeekend
- Prevents gap risk when market reopens Sunday/Monday
- FIX: Restore missing #include statements

Confluence EA (v1.14):
- Fix short signal detection by removing restrictive 'belowPivot' check
- Mirror BUY and SELL logic for symmetry
- Relax harmonic pattern tolerances (0.3-1.0 vs 0.5-0.8)
- Short signals now match buy signal generation

Add verify-short-signals.py to test short signal generation
This commit is contained in:
2026-03-29 23:40:59 -04:00
parent ac32303eeb
commit c53dff6d9f
3 changed files with 221 additions and 61 deletions

View File

@@ -5,7 +5,7 @@
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Abbey Road Tech"
#property link "https://www.abbeyroadtech.com"
#property version "1.13"
#property version "1.14"
#property strict
#include <Trade\Trade.mqh>
@@ -309,29 +309,28 @@ void CheckSignals(int &buyCount, int &sellCount, string &sources)
double distToR2 = MathAbs(close - r2);
double distToP = MathAbs(close - p);
// Buy at support (price near support OR bounced off support)
bool nearSupport = (distToS1 < threshold) || (distToS2 < threshold);
bool bouncedFromSupport = (low <= s1 && close > s1) || (low <= s2 && close > s2) ||
(low <= s1 * 1.0005 && close > s1); // Slight buffer
bool abovePivot = close > p; // Above pivot = bullish context
if(nearSupport || (bouncedFromSupport && abovePivot))
{
buyCount++;
sources += "P" + IntegerToString((int)(distToS1 < distToS2 ? distToS1*10000 : distToS2*10000)) + " ";
}
// Sell at resistance (price near resistance OR rejected from resistance)
bool nearResistance = (distToR1 < threshold) || (distToR2 < threshold);
bool rejectedFromResistance = (high >= r1 && close < r1) || (high >= r2 && close < r2) ||
(high >= r1 * 0.9995 && close < r1); // Slight buffer
bool belowPivot = close < p; // Below pivot = bearish context
if(nearResistance || (rejectedFromResistance && belowPivot))
{
sellCount++;
sources += "P" + IntegerToString((int)(distToR1 < distToR2 ? distToR1*10000 : distToR2*10000)) + " ";
}
// Buy at support (price near support OR bounced off support)
bool nearSupport = (distToS1 < threshold) || (distToS2 < threshold);
bool bouncedFromSupport = (low <= s1 && close > s1) || (low <= s2 && close > s2) ||
(low <= s1 * 1.0005 && close > s1);
if(nearSupport || bouncedFromSupport)
{
buyCount++;
sources += "P" + IntegerToString((int)(distToS1 < distToS2 ? distToS1*10000 : distToS2*10000)) + " ";
}
// Sell at resistance (price near resistance OR rejected from resistance)
bool nearResistance = (distToR1 < threshold) || (distToR2 < threshold);
bool rejectedFromResistance = (high >= r1 && close < r1) || (high >= r2 && close < r2) ||
(high >= r1 * 0.9995 && close < r1);
// FIXED: Removed restrictive belowPivot check - mirror buy logic
if(nearResistance || rejectedFromResistance)
{
sellCount++;
sources += "P" + IntegerToString((int)(distToR1 < distToR2 ? distToR1*10000 : distToR2*10000)) + " ";
}
if(InpDebugMode && (nearSupport || nearResistance || bouncedFromSupport || rejectedFromResistance))
{
@@ -390,31 +389,31 @@ void CheckSignals(int &buyCount, int &sellCount, string &sources)
double BC = MathAbs(C - B);
double CD = MathAbs(D - C);
if(XA > 0 && AB > 0 && BC > 0)
{
double ab_xa = AB / XA;
double bc_ab = BC / AB;
double cd_bc = CD / BC;
// Bullish AB=CD
if(X > A && A < B && B > C && C < D &&
ab_xa >= 0.5 && ab_xa <= 0.8 &&
bc_ab >= 0.5 && bc_ab <= 0.8 &&
cd_bc >= 0.9 && cd_bc <= 1.1)
{
buyCount++;
sources += "H ";
}
// Bearish AB=CD
else if(X < A && A > B && B < C && C > D &&
ab_xa >= 0.5 && ab_xa <= 0.8 &&
bc_ab >= 0.5 && bc_ab <= 0.8 &&
cd_bc >= 0.9 && cd_bc <= 1.1)
{
sellCount++;
sources += "H ";
}
}
if(XA > 0 && AB > 0 && BC > 0)
{
double ab_xa = AB / XA;
double bc_ab = BC / AB;
double cd_bc = CD / BC;
// Bullish AB=CD - relaxed tolerances
if(X > A && A < B && B > C && C < D &&
ab_xa >= 0.3 && ab_xa <= 1.0 &&
bc_ab >= 0.3 && bc_ab <= 1.0 &&
cd_bc >= 0.7 && cd_bc <= 1.3)
{
buyCount++;
sources += "H ";
}
// Bearish AB=CD - relaxed tolerances
else if(X < A && A > B && B < C && C > D &&
ab_xa >= 0.3 && ab_xa <= 1.0 &&
bc_ab >= 0.3 && bc_ab <= 1.0 &&
cd_bc >= 0.7 && cd_bc <= 1.3)
{
sellCount++;
sources += "H ";
}
}
}
}

View File

@@ -5,13 +5,12 @@
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, Garfield Heron"
#property link "https://fetcherpay.com"
#property version "3.0"
#property strict
#property version "3.1"
#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#define VERSION "Version 3.0 Smart Grid MT5"
#define VERSION "Version 3.1 Smart Grid MT5"
#define MAX_TRADES 600
#define MAX_LOG_TRADES 1200
@@ -60,6 +59,12 @@ input bool Master= false;
input bool DiagnosticModeOn= false;
input double InpMaxDailyDrawdown = 3.0; // Max daily drawdown % (0=disable)
//--- Weekend Protection
input string WeekendSettings = "=== Weekend Protection ===";
input bool InpCloseBeforeWeekend = true; // Close positions Friday before market close
input int InpWeekendCloseHour = 17; // Hour to close (17 = 5 PM broker time)
input bool InpCancelPendingBeforeWeekend = true; // Cancel pending orders too
//--- Trade Object
CTrade trade;
CPositionInfo positionInfo;
@@ -123,6 +128,10 @@ bool S1HitToday = false;
double dailyStartEquity = 0;
datetime lastEquityReset = 0;
//--- Weekend Protection Variables
bool weekendCloseExecuted = false;
datetime lastWeekendCheck = 0;
//+------------------------------------------------------------------+
//| Check Daily Drawdown Protection |
//+------------------------------------------------------------------+
@@ -169,7 +178,50 @@ bool CheckDailyDrawdown()
}
return true;
}
}
//+------------------------------------------------------------------+
//| Check Weekend Protection |
//+------------------------------------------------------------------+
bool CheckWeekendProtection()
{
if(!InpCloseBeforeWeekend) return true;
MqlDateTime dt;
TimeToStruct(TimeCurrent(), dt);
// Only check on Friday
if(dt.day_of_week != FRIDAY)
{
// Reset flag on other days
if(weekendCloseExecuted)
weekendCloseExecuted = false;
return true;
}
// Already executed this Friday
if(weekendCloseExecuted) return true;
// Check if it's close to weekend close time
if(dt.hour >= InpWeekendCloseHour)
{
Print("⚠️ WEEKEND CLOSE: It's Friday ", dt.hour, ":00 - Closing all positions!");
SendNotificationEx("WEEKEND CLOSE", "Closing all positions before weekend");
// Close all open positions
CloseAllPositions("Weekend protection - Friday close");
// Cancel pending orders if enabled
if(InpCancelPendingBeforeWeekend)
CancelAllOrders("Weekend protection - Friday cancel pending");
weekendCloseExecuted = true;
gridPlaced = false;
return false;
}
return true;
}
//+------------------------------------------------------------------+
//| Calculate Pivot Points |
@@ -614,15 +666,19 @@ void OnTick()
// Check daily drawdown limit
if(!CheckDailyDrawdown())
{
// Drawdown limit reached - don't place new grids
if(gridPlaced)
{
Print("Daily drawdown limit reached - not placing new grids");
gridPlaced = false;
}
{
// Drawdown limit reached - don't place new grids
if(gridPlaced)
{
Print("Daily drawdown limit reached - not placing new grids");
gridPlaced = false;
}
return;
}
// Check weekend protection (close Friday before weekend)
if(!CheckWeekendProtection())
return;
}
// Recalculate pivots at new day (hour 0, first 5 minutes)
// Only cancel PENDING orders, let positions run to SL/TP

105
verify-short-signals.py Normal file
View File

@@ -0,0 +1,105 @@
#!/usr/bin/env python3
"""
Short Signal Verification Script for MultiSignal Confluence EA
Tests that both BUY and SELL signals can fire
"""
import sys
import re
from pathlib import Path
EA_FILE = Path("/home/garfield/mql-trading-bots/MultiSignal_Confluence_EA.mq5")
def verify_short_signals():
content = EA_FILE.read_text()
print("=" * 60)
print("SHORT SIGNAL VERIFICATION REPORT")
print("=" * 60)
issues = []
fixes = []
# Check 1: belowPivot restriction removed
if "bool belowPivot = close < p;" in content:
# Count usage
below_pivot_count = content.count("belowPivot")
if below_pivot_count > 1: # Definition + usage
issues.append(
f"'belowPivot' still used {below_pivot_count} times - may restrict shorts"
)
else:
fixes.append("⚠️ 'belowPivot' variable exists but check usage")
else:
fixes.append("'belowPivot = close < p' removed")
# Check 2: nearResistance logic
near_resistance_pattern = r"if\(nearResistance \|\| rejectedFromResistance\)"
if re.search(near_resistance_pattern, content):
fixes.append(
"✅ SELL logic: nearResistance || rejectedFromResistance (balanced)"
)
else:
issues.append("❌ SELL logic may still have restrictive conditions")
# Check 3: harmonic pattern tolerances
if "ab_xa >= 0.3 && ab_xa <= 1.0" in content:
fixes.append("✅ Harmonic patterns relaxed (0.3-1.0 instead of 0.5-0.8)")
else:
issues.append("⚠️ Harmonic tolerances may still be too tight")
# Check 4: strength calculation for sells
strength_neg = re.findall(r"strength = -\(.*?\)", content)
if strength_neg:
fixes.append(f"✅ Negative strength calculation found: {strength_neg[0]}")
# Check 5: OpenSellPosition exists and is called
if "OpenSellPosition" in content:
fixes.append("✅ OpenSellPosition() function exists")
if "if(sellCount >= InpMinConfluence" in content:
fixes.append("✅ SELL signals can trigger when sellCount >= min confluence")
# Check 6: Verify symmetry between BUY and SELL
buy_patterns = [r"nearSupport", r"bouncedFromSupport"]
sell_patterns = [r"nearResistance", r"rejectedFromResistance"]
buy_found = all(re.search(p, content) for p in buy_patterns)
sell_found = all(re.search(p, content) for p in sell_patterns)
if buy_found and sell_found:
fixes.append("✅ BUY and SELL patterns are symmetric")
elif buy_found and not sell_found:
issues.append("❌ SELL patterns may be incomplete compared to BUY")
print("\n📋 FIXES APPLIED:")
for f in fixes:
print(f" {f}")
if issues:
print("\n⚠️ ISSUES FOUND:")
for i in issues:
print(f" {i}")
print("\n" + "=" * 60)
# Summary
if len(issues) == 0:
print("✅ SHORT SIGNAL FIXES: PASSED")
print("\nTo verify in MT5 Strategy Tester:")
print("1. Load EA on a chart with recent bearish price action")
print("2. Enable DebugMode and watch Expert Advisor log")
print("3. Look for '🔴 CONFLUENCE SELL' messages")
print("4. Check 'sellCount' is >= InpMinConfluence (default 2)")
else:
print("❌ SHORT SIGNAL FIXES: NEED REVIEW")
for i in issues:
print(f" - {i}")
print("=" * 60)
return len(issues) == 0
if __name__ == "__main__":
success = verify_short_signals()
sys.exit(0 if success else 1)