Compare commits

..

6 Commits

36 changed files with 1580 additions and 80 deletions

View File

@@ -131,6 +131,10 @@ tail -100 ~/mt5-docker/config/.wine/drive_c/Program\ Files/MetaTrader\ 5/MQL5/Lo
- **Largest Win:** $8,091
- **Largest Loss:** -$805
## DevOps / Infrastructure
Server infrastructure details saved in: `/home/garfield/devops/INFRASTRUCTURE.md`
## Conversation History
Before working on this codebase, read:
@@ -138,6 +142,7 @@ Before working on this codebase, read:
conversation-history/2026-03-21-mql-trading-bots.md
conversation-history/2026-03-29-session-save.md
conversation-history/2026-03-30-weekend-gap-short-signal-fix.md
conversation-history/2026-03-30-dns-whitelist.md
```
## Notes for AI Agents

View File

@@ -5,7 +5,7 @@
//+------------------------------------------------------------------+
#property copyright "Copyright 2025, Abbey Road Tech"
#property link "https://www.abbeyroadtech.com"
#property version "1.14"
#property version "1.16"
#property strict
#include <Trade\Trade.mqh>
@@ -23,6 +23,9 @@ input double InpRiskPercent = 1.0; // Risk % per trade (1.0 = 1% of a
input int InpStopLoss = 100; // Stop Loss in points
input int InpTakeProfit = 200; // Take Profit in points
input bool InpUseTrailingStop = true; // Use trailing stop
input int InpTrailingStart = 50; // Points of profit before trailing begins
input int InpTrailingStop = 30; // Trailing stop distance in points
input int InpTrailingStep = 10; // Minimum step to move SL
input int InpMaxPositions = 3; // Max concurrent positions per symbol
input group "=== Filters ==="
@@ -45,6 +48,10 @@ input bool InpDebugMode = true; // Print debug info
input group "=== Equity Protection ==="
input double InpMaxDailyDrawdown = 3.0; // Max daily drawdown % (0=disable)
input group "=== Weekend Protection ==="
input bool InpCloseBeforeWeekend = true; // Close positions Friday before market close
input int InpWeekendCloseHour = 17; // Hour to close (17 = 5 PM broker time)
//--- Global Variables
CTrade Trade;
int TrendMAHandle;
@@ -59,6 +66,9 @@ int totalSellPositions = 0;
double dailyStartEquity = 0;
datetime lastEquityReset = 0;
//--- Weekend Protection
bool weekendCloseExecuted = false;
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
@@ -82,14 +92,23 @@ int OnInit()
lastBarTime = iTime(_Symbol, _Period, 0);
Print("=== MultiSignal Confluence EA v1.12 Initialized ===");
Print("=== MultiSignal Confluence EA v1.16 Initialized ===");
Print("Symbol: ", _Symbol);
Print("Magic: ", InpMagicNumber);
Print("Min Confluence: ", InpMinConfluence);
Print("Min Strength: ", InpMinStrength);
Print("Volatility Filter: ", InpUseVolatilityFilter ? "ON" : "OFF");
Print("ADX Filter: ", InpUseADXFilter ? "ON" : "OFF");
Print("This EA trades DIRECTLY - no external indicator needed!");
Print("Trailing Stop: ", InpUseTrailingStop ? "ON" : "OFF");
if(InpUseTrailingStop)
{
Print(" Trailing Start: ", InpTrailingStart, " pts");
Print(" Trailing Stop: ", InpTrailingStop, " pts");
Print(" Trailing Step: ", InpTrailingStep, " pts");
}
Print("Weekend Protection: ", InpCloseBeforeWeekend ? "ON" : "OFF");
if(InpCloseBeforeWeekend)
Print(" Close Hour: ", InpWeekendCloseHour, ":00 broker time");
return(INIT_SUCCEEDED);
}
@@ -680,14 +699,20 @@ void OnTick()
return; // Don't trade if daily limit reached
}
// Check weekend protection
if(!CheckWeekendProtection())
{
return; // Don't trade, weekend close executed
}
// Check for new bar
datetime currentBarTime = iTime(_Symbol, _Period, 0);
bool isNewBar = (currentBarTime != lastBarTime);
// Update trailing stops on every tick
if(InpUseTrailingStop && !isNewBar)
if(InpUseTrailingStop)
{
// Simple trailing stop logic can be added here
UpdateTrailingStops();
}
// Only process on new bar
@@ -770,4 +795,163 @@ void OnTick()
}
}
}
//+------------------------------------------------------------------+
//| Update trailing stops for all open positions |
//+------------------------------------------------------------------+
void UpdateTrailingStops()
{
double point = SymbolInfoDouble(_Symbol, SYMBOL_POINT);
double trailingStart = InpTrailingStart * point;
double trailingDist = InpTrailingStop * point;
double trailingStep = InpTrailingStep * point;
for(int i = PositionsTotal() - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
// Only process positions for this EA
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
long posType = PositionGetInteger(POSITION_TYPE);
double openPrice = PositionGetDouble(POSITION_PRICE_OPEN);
double currentSL = PositionGetDouble(POSITION_SL);
double currentTP = PositionGetDouble(POSITION_TP);
double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
bool modify = false;
double newSL = 0;
if(posType == POSITION_TYPE_BUY)
{
// For BUY: trailing stop below price
double profit = bid - openPrice;
if(profit >= trailingStart)
{
newSL = NormalizeDouble(bid - trailingDist, _Digits);
// Only move if new SL is better and meets step requirement
if(newSL > currentSL + trailingStep || currentSL == 0)
{
modify = true;
}
}
}
else if(posType == POSITION_TYPE_SELL)
{
// For SELL: trailing stop above price
double profit = openPrice - ask;
if(profit >= trailingStart)
{
newSL = NormalizeDouble(ask + trailingDist, _Digits);
// Only move if new SL is better and meets step requirement
if(currentSL == 0 || newSL < currentSL - trailingStep)
{
modify = true;
}
}
}
if(modify)
{
// Ensure SL is valid (not too close to current price)
double minDist = SymbolInfoInteger(_Symbol, SYMBOL_TRADE_STOPS_LEVEL) * point;
if(posType == POSITION_TYPE_BUY)
{
if(bid - newSL < minDist)
newSL = NormalizeDouble(bid - minDist, _Digits);
}
else
{
if(newSL - ask < minDist)
newSL = NormalizeDouble(ask + minDist, _Digits);
}
if(Trade.PositionModify(ticket, newSL, currentTP))
{
Print("✅ Trailing stop updated for #", ticket, " New SL: ", DoubleToString(newSL, _Digits));
}
else
{
Print("❌ Failed to update trailing stop for #", ticket, ": ", Trade.ResultRetcodeDescription());
}
}
}
}
//+------------------------------------------------------------------+
//| Close all positions for this EA |
//+------------------------------------------------------------------+
void CloseAllPositions(string reason)
{
int total = PositionsTotal();
int closed = 0;
for(int i = total - 1; i >= 0; i--)
{
ulong ticket = PositionGetTicket(i);
if(ticket == 0) continue;
// Only close positions for this EA and symbol
if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
if(PositionGetInteger(POSITION_MAGIC) != InpMagicNumber) continue;
long posType = PositionGetInteger(POSITION_TYPE);
if(posType == POSITION_TYPE_BUY)
{
if(Trade.PositionClose(ticket))
closed++;
}
else if(posType == POSITION_TYPE_SELL)
{
if(Trade.PositionClose(ticket))
closed++;
}
}
Print("📊 Closed ", closed, " positions for weekend protection. Reason: ", reason);
}
//+------------------------------------------------------------------+
//| 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!");
SendNotification("WEEKEND CLOSE: Closing all positions before weekend");
// Close all open positions
CloseAllPositions("Weekend protection - Friday close");
weekendCloseExecuted = true;
return false; // Block new trades
}
return true;
}
//+------------------------------------------------------------------+

152
N8N_WORKFLOW_SETUP.md Normal file
View File

@@ -0,0 +1,152 @@
# N8N Workflow for MQL Settings Monitoring
## Overview
This n8n workflow monitors your `.set` files every 6 hours and alerts you if there are issues like:
- Invalid variable names (typos)
- Missing critical parameters
- Overly restrictive settings blocking trades
- Weekend protection disabled
- Files not tracked in git
## Files Included
| File | Purpose |
|------|---------|
| `n8n-workflow-simple.json` | Simple workflow (recommended) |
| `n8n-workflow-check-sets.json` | Advanced workflow with Discord |
| `scripts/validate-settings.sh` | Validation script |
## Quick Setup (Simple Workflow)
### 1. Install N8N
```bash
# Using Docker
docker run -it --rm \
--name n8n \
-p 5678:5678 \
-v ~/.n8n:/home/node/.n8n \
n8nio/n8n
```
### 2. Import Workflow
1. Open N8N: http://localhost:5678
2. Click **"Add Workflow"**
3. Click **"Import from File"**
4. Select `n8n-workflow-simple.json`
### 3. Configure Environment Variables
Add these to your n8n credentials or `.env`:
```bash
# Telegram Notifications (recommended)
TELEGRAM_BOT_TOKEN=your_bot_token
TELEGRAM_CHAT_ID=your_chat_id
# Optional: Email Notifications
ALERT_EMAIL=garfield@fetcherpay.com
# Optional: Discord Notifications
DISCORD_WEBHOOK_URL=https://discord.com/api/webhooks/...
```
### 4. Get Telegram Chat ID
1. Message @userinfobot on Telegram - it will give you your ID
2. Or use @getidsbot
### 5. Activate Workflow
1. Open the imported workflow
2. Click **"Active"** toggle (top right)
3. Click **"Save"**
## Validation Script
You can also run the validation manually:
```bash
# Run validation
./scripts/validate-settings.sh
# Run from anywhere
/home/garfield/mql-trading-bots/scripts/validate-settings.sh
```
## What It Checks
| Check | Description | Alert Level |
|-------|-------------|-------------|
| File count | Ensures .set files exist | Error |
| Invalid variables | Finds typos like `InpMinConfluenceStrength` | Error |
| Missing parameters | Checks critical params exist | Error |
| High strength | Warns if `InpMinStrength` > 0.8 | Warning |
| Debug mode | Warns if debug disabled | Warning |
| Weekend protection | Ensures `InpCloseBeforeWeekend=true` | Error |
| Git status | Warns about untracked files | Warning |
## Sample Telegram Alert
```
🚨 MQL Settings Issues Found:
ISSUE: confluence-eurusd.set missing: InpCloseBeforeWeekend
ISSUE: confluence-usdjpy.set missing: InpCloseBeforeWeekend
WARNING: High strength thresholds (may block trades):
- confluence-gbpusd.set: InpMinStrength=0.80
⏰ 2026-03-30 14:30
```
## Sample Success Message
```
✅ Settings check passed
Confluence settings: 13 files
Grid settings: 13 files
✓ No invalid variable names found
✓ All files have weekend protection enabled
```
## Scheduling Options
Edit the Schedule Trigger node to change frequency:
| Frequency | Settings |
|-----------|----------|
| Every 15 minutes | `interval: 15 minutes` |
| Every hour | `interval: 1 hour` |
| Every 6 hours | `interval: 6 hours` (default) |
| Daily at 9am | `cron: 0 9 * * *` |
## Troubleshooting
### No alerts received
- Check Telegram bot token is valid
- Verify chat ID is correct
- Check n8n execution log
### Script fails with permission denied
```bash
chmod +x /home/garfield/mql-trading-bots/scripts/validate-settings.sh
```
### Workflow shows error
- Ensure n8n can access `/home/garfield/mql-trading-bots`
- Check that script exists and is executable
## Advanced: Custom Checks
Edit `scripts/validate-settings.sh` to add your own checks:
```bash
# Example: Check for specific EA version
grep -q "EA_Version=1.16" *.set || echo "ISSUE: Files not updated to v1.16"
```
## Related Documentation
- [AGENTS.md](AGENTS.md) - Project context
- [SETTINGS_GUIDE.md](SETTINGS_GUIDE.md) - Settings documentation

41
confluence-aggressive.set Normal file
View File

@@ -0,0 +1,41 @@
; === MultiSignal Confluence EA - AGGRESSIVE Settings ===
; Maximum trades, higher risk per trade
; WARNING: Only use with small accounts or demo!
; Timeframe: H1
; === Confluence Settings ===
InpMinConfluence=1 ; Single signal enough
InpMinStrength=0.50 ; Very low threshold
InpRequireAllAgree=false ; Take any dominant signal
; === Risk Management ===
InpLotSize=0.01
InpUseRiskPercent=true
InpRiskPercent=1.5 ; Higher risk per trade
InpStopLoss=80 ; Tighter stops
InpTakeProfit=160 ; 1:2 R:R
InpUseTrailingStop=true
InpTrailingStart=40
InpTrailingStop=25
InpTrailingStep=5
InpMaxPositions=5 ; More concurrent positions
InpMaxDailyDrawdown=5.0 ; Allow more daily risk
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17
; === Filters (MINIMAL) ===
InpUseTrendFilter=false
InpTrendMAPeriod=50
InpUseVolatilityFilter=false
InpATRPeriod=14
InpMinATRPercent=0.2
InpUseADXFilter=false
InpADXPeriod=14
InpMinADX=15.0
; === EA Settings ===
InpMagicNumber=777777
InpSlippage=5 ; Allow more slippage
InpDebugMode=true

View File

@@ -39,3 +39,7 @@ InpMinADX=20.0 ; Standard trend strength
InpMagicNumber=777777
InpSlippage=3
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -39,3 +39,7 @@ InpMinADX=23.0 ; Moderate trend strength
InpMagicNumber=777775
InpSlippage=4
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -1,11 +1,11 @@
; === MultiSignal Confluence EA - EURUSD Settings ===
; Balanced settings for major pair
; Balanced settings for most liquid pair
; Timeframe: H1
; === Confluence Settings ===
InpMinConfluence=2
InpMinStrength=0.70
InpRequireAllAgree=true
InpMinStrength=0.70 ; MODERATE: Not too strict
InpRequireAllAgree=false ; CHANGED: Allow if buy signals dominate
; === Risk Management ===
InpLotSize=0.01
@@ -15,22 +15,26 @@ InpStopLoss=100 ; Standard 10 pips
InpTakeProfit=200 ; 1:2 R:R
InpUseTrailingStop=true
InpTrailingStart=50
InpTrailingStep=50
InpTrailingStop=50
InpTrailingStop=30
InpTrailingStep=10
InpMaxPositions=3
InpMaxDailyDrawdown=3.0
; === Filters ===
InpUseTrendFilter=true ; Enable trend filter for major pair
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17
; === Filters (MODERATE) ===
InpUseTrendFilter=false ; CHANGED: Let confluence work, not MA
InpTrendMAPeriod=50
InpUseVolatilityFilter=true
InpATRPeriod=14
InpMinATRPercent=0.3
InpMinATRPercent=0.25 ; RELAXED: Was 0.3
InpUseADXFilter=true
InpADXPeriod=14
InpMinADX=20.0
InpMinADX=18.0 ; RELAXED: Was 20
; === EA Settings ===
InpMagicNumber=777772
InpSlippage=3
InpDebugMode=false
InpDebugMode=true ; CHANGED: See what's happening!

View File

@@ -1,50 +1,40 @@
; === MultiSignal Confluence EA - GBPJPY Settings ===
; GBPJPY (The Beast) - EXTREME VOLATILITY WARNING
; Volatile pair - still selective but not too restrictive
; Timeframe: H1
; Characteristics: Most volatile major pair, 200+ pip moves possible
; WARNING: Use with extreme caution - not for beginners
; === Confluence Settings ===
InpMinConfluence=2
InpMinStrength=0.85 ; VERY HIGH threshold - only strongest signals
InpRequireAllAgree=true
InpMinStrength=0.75 ; RELAXED: Was 0.85 (too high!)
InpRequireAllAgree=false ; CHANGED: Allow dominant signals
; === Risk Management ===
InpLotSize=0.01
InpUseRiskPercent=true
InpRiskPercent=0.5 ; HALF normal risk - extreme volatility
InpStopLoss=200 ; 20 pips - wide but can be blown through
InpTakeProfit=400 ; 1:2 R:R
InpRiskPercent=0.8 ; LOWER risk for volatile pair
InpStopLoss=200 ; Wider stops for volatility (200 points = ~14 pips)
InpTakeProfit=400 ; 1:2 R:R
InpUseTrailingStop=true
InpTrailingStart=100
InpTrailingStep=50
InpTrailingStop=80
InpMaxPositions=2 ; MAX 2 positions only
InpMaxDailyDrawdown=2.0 ; Conservative daily limit
InpTrailingStart=100 ; Wider trailing start
InpTrailingStop=50 ; Wider trailing distance
InpTrailingStep=20
InpMaxPositions=2 ; Fewer positions for volatile pair
InpMaxDailyDrawdown=3.0
; === Filters - STRICT ===
InpUseTrendFilter=true ; ENABLE to help avoid chop
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17
; === Filters (IMPORTANT for volatile pair) ===
InpUseTrendFilter=false ; CHANGED: Was true
InpTrendMAPeriod=50
InpUseVolatilityFilter=true
InpATRPeriod=14
InpMinATRPercent=1.2 ; VERY HIGH - only high volatility
InpUseADXFilter=true
InpMinATRPercent=0.4 ; Higher minimum for volatility
InpUseADXFilter=true ; Keep ADX for trend confirmation
InpADXPeriod=14
InpMinADX=28.0 ; Strong trend required
; === CRITICAL WARNINGS ===
; GBPJPY can gap 100+ pips on weekend open
; Can move 200-500 pips in minutes during news
; Known as "The Beast" or "The Dragon"
; Requires constant monitoring
; NOT RECOMMENDED for accounts under $10,000
; === News to AVOID ===
; UK: GDP, Employment, Inflation, BOE meetings, Brexit news
; Japan: BOJ meetings, Tankan, GDP, intervention threats
; Global: Risk-off events (massive JPY appreciation)
InpMinADX=20.0 ; RELAXED: Was 28
; === EA Settings ===
InpMagicNumber=777780
InpSlippage=10 ; High slippage tolerance
InpDebugMode=true ; Keep debug on for monitoring
InpSlippage=5 ; Higher slippage tolerance
InpDebugMode=true ; CHANGED: Monitor this volatile pair

View File

@@ -34,3 +34,7 @@ InpMinADX=22.0
InpMagicNumber=777773
InpSlippage=5 ; Higher slippage tolerance
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -35,3 +35,7 @@ InpMinADX=21.0
InpMagicNumber=777778
InpSlippage=4
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -1,38 +1,40 @@
; === Confluence Trading Settings (RELAXED for Low Volatility Market) ===
InpMinConfluence=2
InpMinConfluenceStrength=0.65
InpRequireAllAgree=true
InpMaxSignalAge=3
; === MultiSignal Confluence EA - RELAXED Settings ===
; For maximum trade frequency - use when markets are active
; Timeframe: H1
; === Confluence Settings ===
InpMinConfluence=1 ; REDUCED: Only 1 signal needed (was 2)
InpMinStrength=0.60 ; RELAXED: Lower threshold for more trades
InpRequireAllAgree=false ; CHANGED: Allow conflicting signals if one side dominates
; === Risk Management ===
InpLotSize=0.01
InpRiskPercent=1.0
InpUseRiskPercent=true
InpRiskPercent=0.8 ; Slightly lower risk for more frequent trades
InpStopLoss=100
InpTakeProfit=200
InpUseTrailingStop=true
InpTrailingStart=50
InpTrailingStep=75
InpTrailingStop=30
InpTrailingStep=10
InpMaxPositions=3
InpMaxDailyTrades=5
InpMaxDailyDrawdown=3.0
; === Confluence Indicator ===
InpIndicatorName=MultiSignal_Confluence
InpConfluenceBuffer=5
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17
; === Filters (RELAXED) ===
InpUseTrendFilter=false
InpUseTrendFilter=false ; DISABLED: Don't filter by trend
InpTrendMAPeriod=50
InpUseATRFilter=true
InpUseVolatilityFilter=false ; DISABLED: Trade all volatility conditions
InpATRPeriod=14
InpMinATR=0.0002
InpAvoidWeekends=true
; === Alerts ===
InpUseAlerts=true
InpUsePushNotifications=false
InpEmailAlerts=false
InpMinATRPercent=0.3
InpUseADXFilter=false ; DISABLED: Don't require ADX confirmation
InpADXPeriod=14
InpMinADX=20.0
; === EA Settings ===
InpMagicNumber=777777
InpSlippage=3
InpDebugMode=true ; ENABLED: See why trades fire or don't fire

40
confluence-standard.set Normal file
View File

@@ -0,0 +1,40 @@
; === MultiSignal Confluence EA - STANDARD Settings ===
; Balanced for regular market conditions
; Timeframe: H1
; === Confluence Settings ===
InpMinConfluence=2 ; Need 2 signals to confirm
InpMinStrength=0.75 ; Moderate threshold
InpRequireAllAgree=false ; Allow if one side dominates by 2+ signals
; === Risk Management ===
InpLotSize=0.01
InpUseRiskPercent=true
InpRiskPercent=1.0
InpStopLoss=100
InpTakeProfit=200
InpUseTrailingStop=true
InpTrailingStart=50
InpTrailingStop=30
InpTrailingStep=10
InpMaxPositions=3
InpMaxDailyDrawdown=3.0
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17
; === Filters (MODERATE) ===
InpUseTrendFilter=false ; Let confluence determine direction
InpTrendMAPeriod=50
InpUseVolatilityFilter=true ; Filter very low volatility
InpATRPeriod=14
InpMinATRPercent=0.3
InpUseADXFilter=true ; Require some trend strength
InpADXPeriod=14
InpMinADX=18.0 ; RELAXED: Lower ADX threshold (was 20+)
; === EA Settings ===
InpMagicNumber=777777
InpSlippage=3
InpDebugMode=true ; See trade decisions in Experts tab

View File

@@ -35,3 +35,7 @@ InpMinADX=22.0 ; Moderate trend strength
InpMagicNumber=777776
InpSlippage=4
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -39,3 +39,7 @@ InpMinADX=25.0 ; Higher - need strong trend
InpMagicNumber=777779
InpSlippage=3
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -1,36 +1,40 @@
; === MultiSignal Confluence EA - USDJPY Settings ===
; Optimized for trending JPY pairs
; Trending pair - moderate settings
; Timeframe: H1
; === Confluence Settings ===
InpMinConfluence=2
InpMinStrength=0.75 ; Higher threshold for quality signals
InpRequireAllAgree=true
InpMinStrength=0.70 ; RELAXED: Was 0.75
InpRequireAllAgree=false ; CHANGED: Allow dominant signals
; === Risk Management ===
InpLotSize=0.01
InpUseRiskPercent=true
InpRiskPercent=1.0 ; 1% risk per trade
InpStopLoss=80 ; Tighter SL for JPY (8 pips)
InpTakeProfit=240 ; 1:3 R:R for trending pairs
InpRiskPercent=1.0
InpStopLoss=80 ; Tighter for JPY pairs (80 points = ~7 pips)
InpTakeProfit=240 ; 1:3 R:R for trending pair
InpUseTrailingStop=true
InpTrailingStart=50
InpTrailingStep=30
InpTrailingStop=40
InpTrailingStop=30
InpTrailingStep=10
InpMaxPositions=3
InpMaxDailyDrawdown=3.0 ; Stop after 3% daily loss
InpMaxDailyDrawdown=3.0
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17
; === Filters ===
InpUseTrendFilter=false ; Let confluence determine direction
InpUseTrendFilter=false ; CHANGED: Was true
InpTrendMAPeriod=50
InpUseVolatilityFilter=true
InpATRPeriod=14
InpMinATRPercent=0.4
InpMinATRPercent=0.25
InpUseADXFilter=true
InpADXPeriod=14
InpMinADX=25.0 ; Stronger trend required for JPY
InpMinADX=18.0 ; RELAXED: Was 25
; === EA Settings ===
InpMagicNumber=777771
InpSlippage=3
InpDebugMode=false
InpDebugMode=true ; CHANGED: See trade decisions

View File

@@ -34,3 +34,7 @@ InpMinADX=20.0
InpMagicNumber=777774
InpSlippage=10 ; High slippage tolerance for gold
InpDebugMode=false
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -47,3 +47,7 @@ InpMaxDailyDrawdown=2.5
; === EA Settings ===
MagicNum=333007
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -43,3 +43,7 @@ InpMaxDailyDrawdown=2.5
; === EA Settings ===
MagicNum=333005
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -48,3 +48,7 @@ InpMaxDailyDrawdown=3.0 ; Standard for major pair
; === EA Settings ===
MagicNum=333011
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -52,3 +52,7 @@ InpMaxDailyDrawdown=1.5 ; VERY conservative
; === EA Settings ===
MagicNum=333014
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -50,3 +50,7 @@ InpMaxDailyDrawdown=2.0 ; Conservative (volatile)
; === EA Settings ===
MagicNum=333013
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -43,3 +43,7 @@ InpMaxDailyDrawdown=3.0
; === EA Settings ===
MagicNum=333003
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -47,3 +47,7 @@ InpMaxDailyDrawdown=2.5
; === EA Settings ===
MagicNum=333008
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -43,3 +43,7 @@ InpMaxDailyDrawdown=2.0 ; Conservative daily limit
; === EA Settings ===
MagicNum=333001
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -47,3 +47,7 @@ InpMaxDailyDrawdown=2.5
; === EA Settings ===
MagicNum=333006
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -48,3 +48,7 @@ InpMaxDailyDrawdown=2.0 ; Conservative (SNB risk)
; === EA Settings ===
MagicNum=333009
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -49,3 +49,7 @@ InpMaxDailyDrawdown=2.5 ; Conservative (trending pair)
; === EA Settings ===
MagicNum=333012
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -43,3 +43,7 @@ InpMaxDailyDrawdown=2.0 ; Conservative limit for volatile pairs
; === EA Settings ===
MagicNum=333002
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -49,3 +49,7 @@ InpMaxDailyDrawdown=1.5 ; VERY conservative
; === EA Settings ===
MagicNum=333010
; === Weekend Protection ===
InpCloseBeforeWeekend=true
InpWeekendCloseHour=17

View File

@@ -0,0 +1,411 @@
{
"name": "MQL Trading Bots - Settings Validator",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"name": "Schedule Trigger",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [
250,
300
]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && ls -la *.set 2>/dev/null | wc -l"
},
"name": "Count Set Files",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
450,
300
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "8ef4b80d-8c5a-4ea3-9a5a-b8be7355f4a7",
"leftValue": "={{ $json.stdout }}",
"rightValue": "0",
"operator": {
"type": "number",
"operation": "notEquals"
}
}
]
}
},
"name": "Files Exist?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
650,
300
]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && for f in confluence-*.set; do echo \"=== $f ===\"; grep -E 'InpMinStrength|InpMinConfluence|InpRequireAllAgree|InpDebugMode' \"$f\" | grep -v '^;'; done"
},
"name": "Check Confluence Sets",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
850,
200
]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && for f in grid-*.set; do echo \"=== $f ===\"; grep -E 'MaxLevels|InpMaxDailyDrawdown|InpCloseBeforeWeekend' \"$f\" | grep -v '^;'; done"
},
"name": "Check Grid Sets",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
850,
400
]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && grep -l 'InpMinConfluenceStrength' confluence-*.set 2>/dev/null || echo 'No invalid variables found'"
},
"name": "Check Invalid Variables",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
1050,
200
]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && grep 'InpDebugMode=false' confluence-*.set grid-*.set 2>/dev/null | wc -l"
},
"name": "Count Debug Off",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
1050,
400
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "e6b7c7d1-6d61-413f-90a4-5ce2e8b7dc2e",
"leftValue": "={{ $json.stdout }}",
"rightValue": "No invalid",
"operator": {
"type": "string",
"operation": "notContains"
}
}
]
}
},
"name": "Invalid Vars Found?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1250,
200
]
},
{
"parameters": {
"conditions": {
"options": {
"caseSensitive": true,
"leftValue": "",
"typeValidation": "strict"
},
"conditions": [
{
"id": "b7c8d9e0-f1a2-4b3c-5d6e-7f8a9b0c1d2e",
"leftValue": "={{ $json.stdout }}",
"rightValue": "0",
"operator": {
"type": "number",
"operation": "notEquals"
}
}
]
}
},
"name": "Debug Disabled?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [
1250,
400
]
},
{
"parameters": {
"options": {}
},
"name": "Merge Issues",
"type": "n8n-nodes-base.merge",
"typeVersion": 2.1,
"position": [
1450,
300
]
},
{
"parameters": {
"to": "={{ $env.ALERT_EMAIL }}",
"subject": "🚨 MQL Settings Issues Detected",
"text": "=Issues found in MQL Trading Bots settings:
Invalid Variables Found:
{{ $('Check Invalid Variables').item.json.stdout }}
Files with Debug Disabled: {{ $('Count Debug Off').item.json.stdout }}
Confluence Settings:
{{ $('Check Confluence Sets').item.json.stdout }}
Grid Settings:
{{ $('Check Grid Sets').item.json.stdout }}
Please review and fix ASAP.
Server: {{ $env.HOSTNAME }}
Time: {{ $now }}"
},
"name": "Send Alert Email",
"type": "n8n-nodes-base.emailSend",
"typeVersion": 2.1,
"position": [
1650,
200
]
},
{
"parameters": {
"content": "={{$json}}",
"options": {}
},
"name": "No Action Needed",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [
1650,
500
]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && git diff --name-only HEAD~1 2>/dev/null | grep '\.set$' || echo 'No recent set file changes'"
},
"name": "Check Recent Changes",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [
850,
600
]
},
{
"parameters": {
"webhookUri": "={{ $env.DISCORD_WEBHOOK_URL }}",
"text": "={ '🚨 **MQL Settings Alert**' if $json.stdout != 'No recent set file changes' and $json.stdout != '' else '✅ **MQL Settings Check** - All OK' }",
"options": {}
},
"name": "Discord Notification",
"type": "n8n-nodes-base.discord",
"typeVersion": 2,
"position": [
1250,
600
]
}
],
"pinData": {},
"settings": {
"executionOrder": "v1"
},
"staticData": null,
"tags": [
{
"name": "trading",
"id": "trading-tag",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
},
{
"name": "mql5",
"id": "mql5-tag",
"createdAt": "2024-01-01T00:00:00.000Z",
"updatedAt": "2024-01-01T00:00:00.000Z"
}
],
"connections": {
"Schedule Trigger": {
"main": [
[
{
"node": "Count Set Files",
"type": "main",
"index": 0
}
]
]
},
"Count Set Files": {
"main": [
[
{
"node": "Files Exist?",
"type": "main",
"index": 0
}
]
]
},
"Files Exist?": {
"main": [
[
{
"node": "Check Confluence Sets",
"type": "main",
"index": 0
},
{
"node": "Check Grid Sets",
"type": "main",
"index": 0
},
{
"node": "Check Recent Changes",
"type": "main",
"index": 0
}
],
[
{
"node": "No Action Needed",
"type": "main",
"index": 0
}
]
]
},
"Check Confluence Sets": {
"main": [
[
{
"node": "Check Invalid Variables",
"type": "main",
"index": 0
}
]
]
},
"Check Grid Sets": {
"main": [
[
{
"node": "Count Debug Off",
"type": "main",
"index": 0
}
]
]
},
"Check Invalid Variables": {
"main": [
[
{
"node": "Invalid Vars Found?",
"type": "main",
"index": 0
}
]
]
},
"Count Debug Off": {
"main": [
[
{
"node": "Debug Disabled?",
"type": "main",
"index": 0
}
]
]
},
"Invalid Vars Found?": {
"main": [
[
{
"node": "Merge Issues",
"type": "main",
"index": 0
}
]
]
},
"Debug Disabled?": {
"main": [
[
{
"node": "Merge Issues",
"type": "main",
"index": 0
}
]
]
},
"Merge Issues": {
"main": [
[
{
"node": "Send Alert Email",
"type": "main",
"index": 0
}
]
]
},
"Check Recent Changes": {
"main": [
[
{
"node": "Discord Notification",
"type": "main",
"index": 0
}
]
]
}
}
}

89
n8n-workflow-http.json Normal file
View File

@@ -0,0 +1,89 @@
{
"name": "MQL Settings Monitor - HTTP Version",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"name": "Every 6 Hours",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [250, 300]
},
{
"parameters": {
"requestMethod": "POST",
"url": "http://localhost:8080/validate",
"options": {
"timeout": 30000
}
},
"name": "Call Validation API",
"type": "n8n-nodes-base.httpRequest",
"typeVersion": 1,
"position": [450, 300]
},
{
"parameters": {
"conditions": {
"string": [
{
"value1": "={{ $json.status }}",
"operation": "equal",
"value2": "error"
}
]
}
},
"name": "Has Issues?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [650, 300]
},
{
"parameters": {
"chatId": "={{ $env.TELEGRAM_CHAT_ID }}",
"text": "=🚨 MQL Settings Alert:\n\n{{ $json.message }}\n\nIssues: {{ $json.issues }}\n\n⏰ {{ new Date().toISOString() }}"
},
"name": "Send Telegram",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [850, 200]
},
{
"parameters": {},
"name": "No Action",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [850, 400]
}
],
"connections": {
"Every 6 Hours": {
"main": [
[{ "node": "Call Validation API", "type": "main", "index": 0 }]
]
},
"Call Validation API": {
"main": [
[{ "node": "Has Issues?", "type": "main", "index": 0 }]
]
},
"Has Issues?": {
"main": [
[{ "node": "Send Telegram", "type": "main", "index": 0 }],
[{ "node": "No Action", "type": "main", "index": 0 }]
]
}
},
"settings": {},
"staticData": null,
"tags": []
}

88
n8n-workflow-simple.json Normal file
View File

@@ -0,0 +1,88 @@
{
"name": "MQL Settings Monitor - Simple",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"name": "Every 6 Hours",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1.1,
"position": [250, 300]
},
{
"parameters": {
"command": "cd /home/garfield/mql-trading-bots && ./scripts/validate-settings.sh"
},
"name": "Run Validation Script",
"type": "n8n-nodes-base.executeCommand",
"typeVersion": 1,
"position": [450, 300]
},
{
"parameters": {
"conditions": {
"conditions": [
{
"leftValue": "={{ $json.stdout }}",
"operator": "contains",
"rightValue": "ISSUE"
}
]
}
},
"name": "Issues Found?",
"type": "n8n-nodes-base.if",
"typeVersion": 2,
"position": [650, 300]
},
{
"parameters": {
"chatId": "={{ $env.TELEGRAM_CHAT_ID }}",
"text": "=🚨 MQL Settings Issues Found:\n\n{{ $json.stdout }}\n\n⏰ {{ $now.format('YYYY-MM-DD HH:mm') }}"
},
"name": "Send Telegram Alert",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1.1,
"position": [850, 200]
},
{
"parameters": {
"content": "=✅ Settings check passed\n\n{{ $json.stdout }}",
"options": {}
},
"name": "Success - No Action",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [850, 400]
}
],
"connections": {
"Every 6 Hours": {
"main": [
[{ "node": "Run Validation Script", "type": "main", "index": 0 }]
]
},
"Run Validation Script": {
"main": [
[{ "node": "Issues Found?", "type": "main", "index": 0 }]
]
},
"Issues Found?": {
"main": [
[{ "node": "Send Telegram Alert", "type": "main", "index": 0 }],
[{ "node": "Success - No Action", "type": "main", "index": 0 }]
]
}
},
"settings": {
"executionOrder": "v1"
}
}

98
n8n-workflow-ssh.json Normal file
View File

@@ -0,0 +1,98 @@
{
"name": "MQL Settings Monitor - SSH Version",
"nodes": [
{
"parameters": {
"rule": {
"interval": [
{
"field": "hours",
"hoursInterval": 6
}
]
}
},
"name": "Every 6 Hours",
"type": "n8n-nodes-base.scheduleTrigger",
"typeVersion": 1,
"position": [250, 300]
},
{
"parameters": {
"command": "/home/garfield/mql-trading-bots/scripts/validate-settings.sh",
"cwd": "/home/garfield/mql-trading-bots"
},
"name": "Run Validation Script",
"type": "n8n-nodes-base.ssh",
"typeVersion": 1,
"position": [450, 300],
"credentials": {
"sshPassword": {
"id": "local-ssh",
"name": "Local SSH"
}
}
},
{
"parameters": {
"conditions": {
"number": [
{
"value1": "={{ $json.code }}",
"operation": "notEqual",
"value2": 0
}
]
}
},
"name": "Issues Found?",
"type": "n8n-nodes-base.if",
"typeVersion": 1,
"position": [650, 300]
},
{
"parameters": {
"chatId": "={{ $env.TELEGRAM_CHAT_ID }}",
"text": "=🚨 MQL Settings Issues:\n\n{{ $json.stdout }}\n\n⏰ {{ new Date().toISOString() }}"
},
"name": "Send Telegram Alert",
"type": "n8n-nodes-base.telegram",
"typeVersion": 1,
"position": [850, 200],
"credentials": {
"telegramApi": {
"id": "telegram-bot",
"name": "Telegram Bot"
}
}
},
{
"parameters": {},
"name": "No Issues",
"type": "n8n-nodes-base.noOp",
"typeVersion": 1,
"position": [850, 400]
}
],
"connections": {
"Every 6 Hours": {
"main": [
[{ "node": "Run Validation Script", "type": "main", "index": 0 }]
]
},
"Run Validation Script": {
"main": [
[{ "node": "Issues Found?", "type": "main", "index": 0 }]
]
},
"Issues Found?": {
"main": [
[{ "node": "Send Telegram Alert", "type": "main", "index": 0 }],
[{ "node": "No Issues", "type": "main", "index": 0 }]
]
}
},
"settings": {},
"staticData": null,
"tags": []
}

27
scripts/setup-cron.sh Executable file
View File

@@ -0,0 +1,27 @@
#!/bin/bash
# Setup cron job for MQL settings monitoring
echo "Setting up cron job for MQL settings monitoring..."
# Check if python3 is available
if ! command -v python3 &> /dev/null; then
echo "ERROR: python3 not found"
exit 1
fi
# Create cron entry
CRON_CMD="0 */6 * * * cd /home/garfield/mql-trading-bots && python3 scripts/validate-and-notify.py >> /tmp/mql-validate.log 2>&1"
# Add to crontab
(crontab -l 2>/dev/null; echo "$CRON_CMD") | crontab -
echo "Cron job added: Runs every 6 hours"
echo "Logs: /tmp/mql-validate.log"
echo ""
echo "To configure Telegram notifications, set these environment variables:"
echo " export TELEGRAM_BOT_TOKEN='your_bot_token'"
echo " export TELEGRAM_CHAT_ID='your_chat_id'"
echo ""
echo "Add these to your ~/.bashrc to persist:"
echo " echo 'export TELEGRAM_BOT_TOKEN=\"your_token\"' >> ~/.bashrc"
echo " echo 'export TELEGRAM_CHAT_ID=\"your_id\"' >> ~/.bashrc"

157
scripts/validate-and-notify.py Executable file
View File

@@ -0,0 +1,157 @@
#!/usr/bin/env python3
"""
MQL Settings Validator with Telegram Notifications
Run via cron: python3 validate-and-notify.py
"""
import os
import re
import subprocess
import sys
from datetime import datetime
try:
import requests
except ImportError:
print("Installing requests...")
subprocess.run([sys.executable, "-m", "pip", "install", "requests", "-q"])
import requests
# Configuration
TELEGRAM_BOT_TOKEN = os.environ.get("TELEGRAM_BOT_TOKEN", "")
TELEGRAM_CHAT_ID = os.environ.get("TELEGRAM_CHAT_ID", "")
REPO_DIR = "/home/garfield/mql-trading-bots"
def send_telegram(message):
"""Send message to Telegram"""
if not TELEGRAM_BOT_TOKEN or not TELEGRAM_CHAT_ID:
print("Telegram not configured. Message:")
print(message)
return False
url = f"https://api.telegram.org/bot{TELEGRAM_BOT_TOKEN}/sendMessage"
payload = {
"chat_id": TELEGRAM_CHAT_ID,
"text": message,
"parse_mode": "HTML"
}
try:
response = requests.post(url, json=payload, timeout=10)
return response.status_code == 200
except Exception as e:
print(f"Failed to send Telegram: {e}")
return False
def check_set_files():
"""Validate all .set files"""
issues = []
warnings = []
os.chdir(REPO_DIR)
# Check confluence files
confluence_files = [f for f in os.listdir(".") if f.startswith("confluence-") and f.endswith(".set")]
grid_files = [f for f in os.listdir(".") if f.startswith("grid-") and f.endswith(".set")]
print(f"Found {len(confluence_files)} confluence files, {len(grid_files)} grid files")
# Check for invalid variable names
invalid_pattern = re.compile(r'InpMinConfluenceStrength|MinConfluenceStrength', re.IGNORECASE)
for f in confluence_files:
with open(f, 'r') as file:
content = file.read()
if invalid_pattern.search(content):
issues.append(f"❌ <b>Invalid variable</b> in {f}: InpMinConfluenceStrength (should be InpMinStrength)")
# Check for missing critical parameters
critical_params_conf = ['InpMinConfluence', 'InpMinStrength', 'InpMagicNumber', 'InpCloseBeforeWeekend']
critical_params_grid = ['InpCloseBeforeWeekend', 'InpMaxDailyDrawdown']
for f in confluence_files:
with open(f, 'r') as file:
content = file.read()
for param in critical_params_conf:
if param not in content:
issues.append(f"❌ <b>Missing {param}</b> in {f}")
for f in grid_files:
with open(f, 'r') as file:
content = file.read()
for param in critical_params_grid:
if param not in content:
issues.append(f"❌ <b>Missing {param}</b> in {f}")
# Check for high strength thresholds (warnings)
for f in confluence_files:
with open(f, 'r') as file:
content = file.read()
match = re.search(r'InpMinStrength=(\d+\.?\d*)', content)
if match:
strength = float(match.group(1))
if strength >= 0.80:
warnings.append(f"⚠️ <b>High threshold</b> in {f}: {strength} (may block trades)")
# Check debug mode
debug_off = 0
for f in confluence_files + grid_files:
with open(f, 'r') as file:
content = file.read()
if 'InpDebugMode=false' in content:
debug_off += 1
if debug_off > 5:
warnings.append(f"⚠️ <b>Debug disabled</b> in {debug_off} files - you won't see trade decisions")
return issues, warnings, len(confluence_files), len(grid_files)
def main():
"""Main function"""
print("=" * 50)
print("MQL Settings Validator")
print(f"Time: {datetime.now().isoformat()}")
print("=" * 50)
issues, warnings, conf_count, grid_count = check_set_files()
# Build report
report_lines = [
"<b>📊 MQL Settings Check</b>",
f"Confluence files: {conf_count}",
f"Grid files: {grid_count}",
""
]
if issues:
report_lines.append("<b>❌ Issues Found:</b>")
report_lines.extend(issues[:10]) # Limit to 10 issues
if len(issues) > 10:
report_lines.append(f"... and {len(issues) - 10} more issues")
report_lines.append("")
if warnings:
report_lines.append("<b>⚠️ Warnings:</b>")
report_lines.extend(warnings[:5])
report_lines.append("")
if not issues and not warnings:
report_lines.append("✅ <b>All checks passed!</b>")
report_lines.append("No issues found.")
report_lines.append(f"\n{datetime.now().strftime('%Y-%m-%d %H:%M')}")
report = "\n".join(report_lines)
print("\n" + report.replace('<b>', '').replace('</b>', ''))
# Send notification if issues found or if it's a scheduled check
if issues or warnings:
send_telegram(report)
return 1
else:
# Only send success message on first run of the day
if datetime.now().hour == 9:
send_telegram(report)
return 0
if __name__ == "__main__":
sys.exit(main())

128
scripts/validate-settings.sh Executable file
View File

@@ -0,0 +1,128 @@
#!/bin/bash
# MQL Trading Bot Settings Validator
# This script validates .set files for common issues
REPO_DIR="/home/garfield/mql-trading-bots"
cd "$REPO_DIR" || exit 1
ISSUES=0
echo "=== MQL Settings Validation Report ==="
echo "Date: $(date)"
echo ""
# Check 1: Count set files
echo "[INFO] Checking set files..."
CONFLUENCE_COUNT=$(ls -1 confluence-*.set 2>/dev/null | wc -l)
GRID_COUNT=$(ls -1 grid-*.set 2>/dev/null | wc -l)
echo " Confluence settings: $CONFLUENCE_COUNT files"
echo " Grid settings: $GRID_COUNT files"
if [ $CONFLUENCE_COUNT -eq 0 ] && [ $GRID_COUNT -eq 0 ]; then
echo "ISSUE: No .set files found!"
ISSUES=$((ISSUES + 1))
fi
# Check 2: Invalid variable names (typos)
echo ""
echo "[INFO] Checking for invalid variable names..."
INVALID=$(grep -l "InpMinConfluenceStrength\|MinConfluenceStrength\|ConfluenceStrength" confluence-*.set 2>/dev/null)
if [ -n "$INVALID" ]; then
echo "ISSUE: Invalid variable names found:"
echo "$INVALID" | while read -r file; do
echo " - $file"
done
ISSUES=$((ISSUES + 1))
else
echo " ✓ No invalid variable names found"
fi
# Check 3: Missing critical parameters in Confluence sets
echo ""
echo "[INFO] Checking Confluence settings completeness..."
for file in confluence-*.set; do
[ -f "$file" ] || continue
MISSING=""
grep -q "^InpMinConfluence=" "$file" || MISSING="$MISSING InpMinConfluence"
grep -q "^InpMinStrength=" "$file" || MISSING="$MISSING InpMinStrength"
grep -q "^InpRequireAllAgree=" "$file" || MISSING="$MISSING InpRequireAllAgree"
grep -q "^InpMagicNumber=" "$file" || MISSING="$MISSING InpMagicNumber"
grep -q "^InpMaxDailyDrawdown=" "$file" || MISSING="$MISSING InpMaxDailyDrawdown"
grep -q "^InpCloseBeforeWeekend=" "$file" || MISSING="$MISSING InpCloseBeforeWeekend"
if [ -n "$MISSING" ]; then
echo "ISSUE: $file missing:$MISSING"
ISSUES=$((ISSUES + 1))
fi
done
# Check 4: Missing critical parameters in Grid sets
echo ""
echo "[INFO] Checking Grid settings completeness..."
for file in grid-*.set; do
[ -f "$file" ] || continue
MISSING=""
grep -q "^InpMaxDailyDrawdown=" "$file" || MISSING="$MISSING InpMaxDailyDrawdown"
grep -q "^InpCloseBeforeWeekend=" "$file" || MISSING="$MISSING InpCloseBeforeWeekend"
if [ -n "$MISSING" ]; then
echo "ISSUE: $file missing:$MISSING"
ISSUES=$((ISSUES + 1))
fi
done
# Check 5: Very restrictive settings (may explain no trades)
echo ""
echo "[INFO] Checking for overly restrictive settings..."
HIGH_STRENGTH=$(grep "InpMinStrength=0.8" confluence-*.set 2>/dev/null | cut -d: -f1)
if [ -n "$HIGH_STRENGTH" ]; then
echo "WARNING: High strength thresholds (may block trades):"
echo "$HIGH_STRENGTH" | while read -r file; do
strength=$(grep "InpMinStrength=" "$file" | head -1)
echo " - $file: $strength"
done
fi
# Check 6: Debug mode status
echo ""
echo "[INFO] Debug mode status..."
DEBUG_OFF=$(grep "InpDebugMode=false" confluence-*.set grid-*.set 2>/dev/null | wc -l)
DEBUG_ON=$(grep "InpDebugMode=true" confluence-*.set grid-*.set 2>/dev/null | wc -l)
echo " Debug ON: $DEBUG_ON files"
echo " Debug OFF: $DEBUG_OFF files"
if [ $DEBUG_OFF -gt 5 ]; then
echo "WARNING: Many files have debug disabled - you won't see trade decisions"
fi
# Check 7: Weekend protection status
echo ""
echo "[INFO] Weekend protection status..."
WEEKEND_OFF=$(grep "InpCloseBeforeWeekend=false" confluence-*.set grid-*.set 2>/dev/null | wc -l)
if [ $WEEKEND_OFF -gt 0 ]; then
echo "WARNING: $WEEKEND_OFF files have weekend protection DISABLED"
ISSUES=$((ISSUES + 1))
else
echo " ✓ All files have weekend protection enabled"
fi
# Check 8: Git status
echo ""
echo "[INFO] Checking git status..."
UNTRACKED=$(git ls-files --others --exclude-standard *.set 2>/dev/null | wc -l)
if [ $UNTRACKED -gt 0 ]; then
echo "WARNING: $UNTRACKED untracked .set files:"
git ls-files --others --exclude-standard *.set 2>/dev/null | head -5
fi
# Summary
echo ""
echo "=== Summary ==="
if [ $ISSUES -eq 0 ]; then
echo "✅ All checks passed!"
else
echo "❌ Found $ISSUES issue(s)"
fi
exit $ISSUES