# MCP Tool Specification Full input/output schemas for MT5-Quant tools. > **Documentation Status:** All 90 tools are documented. --- ## `run_backtest` Run a complete backtest pipeline: compile → clean cache → backtest → extract → analyze. **When to call:** Any time you need fresh backtest results. Always runs the full pipeline unless `skip_*` flags are set. ### Input schema ```typescript { // Required expert: string; // EA name without path or extension. e.g. "MyEA_v1.2" // Date range — use either preset OR from+to preset?: "last_month" | "last_3months" | "ytd" | "last_year"; from?: string; // "YYYY-MM-DD" to?: string; // "YYYY-MM-DD" // Optional overrides symbol?: string; // Default from config. e.g. "XAUUSD" timeframe?: "M1" | "M5" | "M15" | "M30" | "H1" | "H4" | "D1"; // Default: M5 deposit?: number; // Default from config. e.g. 10000 currency?: string; // Default: "USD" model?: 0 | 1 | 2; // 0=every tick (default), 1=1min OHLC, 2=open price set_file?: string; // Path to .set file. If omitted, uses EA defaults. leverage?: number; // Default: 500 // Pipeline flags skip_compile?: boolean; // Skip EA compilation (use existing .ex5) skip_clean?: boolean; // Skip cache clean (faster but risks stale cache) skip_analyze?: boolean; // Extract only, skip deal analysis deep_analyze?: boolean; // Add hourly_pnl and volume_profile to analysis.json strategy?: "grid" | "scalper" | "trend" | "hedge" | "generic"; // Analysis strategy profile (default: "grid"). // Controls depth tracking, exit keywords, and cycle grouping. } ``` ### Output schema ```typescript { success: boolean; report_dir: string; // "reports/20250619_143022_MyEA_XAUUSD_M5" duration_seconds: number; // Inline summary from metrics.json (always present on success) metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; sharpe_ratio: number; total_trades: number; recovery_factor: number; expected_payoff: number; gross_profit: number; gross_loss: number; win_rate_pct: number; avg_profit: number; avg_loss: number; }; // Deal analysis summary (present unless skip_analyze=true) analysis_summary: { green_months: number; total_months: number; worst_month: string; // "2025-10" worst_month_pnl: number; worst_dd_event_pct: number; worst_dd_date: string; max_grid_depth: number; // highest layer reached in any cycle l5_plus_count: number; // cycles that reached L5+ }; // File paths for direct reading files: { metrics_json: string; analysis_json: string; // Note: deals are stored in SQLite DB, not on disk. // Call export_deals_csv(report_id) to generate a CSV file on demand. }; error?: string; // Present on failure } ``` ### Example ```json // Input { "expert": "MyEA_v1.2", "from": "2025-01-01", "to": "2025-06-30", "deposit": 10000, "model": 0 } // Output { "success": true, "report_dir": "reports/20250619_143022_MyEA_XAUUSD_M5", "duration_seconds": 287, "metrics": { "net_profit": 4832.10, "profit_factor": 1.54, "max_dd_pct": 12.3, "sharpe_ratio": 1.18, "total_trades": 891 }, "analysis_summary": { "green_months": 5, "total_months": 6, "worst_month": "2025-03", "worst_month_pnl": -412.80, "worst_dd_event_pct": 12.3, "worst_dd_date": "2025-03-14", "max_grid_depth": 6, "l5_plus_count": 8 }, "files": { "metrics_json": "reports/20250619_143022_MyEA_XAUUSD_M5/metrics.json", "analysis_json": "reports/20250619_143022_MyEA_XAUUSD_M5/analysis.json" } } ``` --- ## `run_backtest_quick` Quick backtest using pre-compiled EA: clean cache → backtest → extract → analyze. **When to call:** When EA code hasn't changed and you just want to test different parameters or date ranges. Faster than `run_backtest` because it skips compilation. ### Input schema Same as `run_backtest`, but `skip_compile` is automatically set to `true`. ### Output schema Same as `run_backtest`. --- ## `run_backtest_only` Backtest only: clean cache → backtest → extract. No analysis phase. **When to call:** When you just need raw trade data (stored in DB) and don't need analytics. Fastest option for batch processing. Use `export_deals_csv` afterwards if you need a CSV file. ### Input schema Same as `run_backtest`, but `skip_compile` and `skip_analyze` are automatically set to `true`. ### Output schema Same as `run_backtest` but without `analysis_summary`. --- ## `launch_backtest` Fire-and-forget mode: compile → clean → launch MT5 backtest, return immediately with job info. **When to call:** When you want to launch a backtest without waiting for completion. Use `get_backtest_status` to poll for completion. ### Input schema ```typescript { expert: string; // Required. EA name without path or extension symbol?: string; // Trading symbol (default: from config or first available) from_date?: string; // Start date YYYY.MM.DD (default: past complete month) to_date?: string; // End date YYYY.MM.DD (default: past complete month) timeframe?: string; // M1, M5, M15, M30, H1, H4, D1 (default: M5) deposit?: number; // Initial deposit (default: 10000) model?: 0 | 1 | 2; // Tick model (default: 0) set_file?: string; // Path to .set parameter file skip_compile?: boolean; // Skip compilation skip_clean?: boolean; // Skip cache cleaning timeout?: number; // Max time in seconds (default: 900) gui?: boolean; // Enable MT5 visualization shutdown?: boolean; // Shut down MT5 after test (default: true). // NOTE: on Wine/macOS terminal64.exe may not exit naturally // even with ShutdownTerminal=1. Use inactivity_kill_secs too. inactivity_kill_secs?: number; // Kill MT5 if tester log hasn't grown for N seconds // (default: disabled / not set). Recommended: 120. // After silence, pipeline polls for HTML report for 30s, // then kills MT5 unconditionally. If HTML present → extracted; // otherwise falls back to journal extraction (no P&L data). } ``` ### Output schema ```typescript { success: true; message: string; // "Backtest launched successfully..." report_id: string; // e.g., "20250122_034455_MyEA_XAUUSD_M5" report_dir: string; // Full path to report directory expert: string; symbol: string; timeframe: string; launched_at: string; // ISO8601 timestamp timeout_seconds: number; poll_hint: string; // "Call get_backtest_status with report_dir to check progress" } ``` --- ## `run_rolling_backtest` Run N consecutive weekly backtests sequentially and return aggregated results. Compiles once, then each week runs with `skip_compile`. Kills and restarts MT5 between weeks for a clean state. **When to call:** When you want to test EA stability across multiple weeks to detect performance degradation, regime change sensitivity, or parameter drift. ### Input schema ```typescript { // Required expert: string; // EA name without path or extension // Date range — specify both or omit for auto-calculation (N weeks back to last Sunday) from_date?: string; // "YYYY.MM.DD" (default: auto-calculate N weeks back) to_date?: string; // "YYYY.MM.DD" (default: auto-calculate to last Sunday) // Optional overrides symbol?: string; // Trading symbol (default: from config or first available) timeframe?: "M1" | "M5" | "M15" | "M30" | "H1" | "H4" | "D1"; // Default: M5 deposit?: number; // Initial deposit (default: 10000) model?: 0 | 1 | 2; // Tick model: 0=Every tick, 1=OHLC, 2=Open prices set_file?: string; // Path to .set parameter file for EA inputs // Rolling options weeks?: number; // Number of weekly backtests to run (default: 4, max: 52) // Pipeline flags skip_compile?: boolean; // Skip initial compilation (default: false — compiles on first week) shutdown?: boolean; // Close MT5 after backtest completes (default: true) kill_existing?: boolean; // Kill any running MT5 instance first (default: true) timeout?: number; // Max wait time per week in seconds (default: 900) gui?: boolean; // Enable MT5 visualization window (default: false) startup_delay_secs?: number; // Seconds to wait for MT5 initialization (default: 10) } ``` ### Output schema ```typescript { success: true; message: string; // "Rolling backtest launched with N weeks. Use get_backtest_status to poll for completion." report_id: string; // "ROLLING_MyEA_2026.06.24_2026.07.01" report_dir: string; // Full path to report directory expert: string; weeks: Array<{ label: string; // "Week 1", "Week 2", etc. from_date: string; // "2026.06.24" to_date: string; // "2026.06.30" }>; poll_hint: string; // "Call get_backtest_status with report_dir to check progress" } ``` ### Status polling After launch, poll with `get_backtest_status(report_dir=)` to track progress. The rolling backtest runs all weeks in a background task — each week is a full backtest pipeline (clean → launch → poll → extract → analyze). Once complete, the report directory contains: - `rolling_results.json` — full summary with per-week metrics and totals - `progress.log` — current week being processed - `weeks.json` — the weekly schedule ### Example ```json // Input { "expert": "MyEA", "symbol": "XAUUSD", "weeks": 4, "deposit": 10000 } // Output { "success": true, "message": "Rolling backtest launched with 4 weeks. Use get_backtest_status to poll for completion.", "report_id": "ROLLING_MyEA_2026.06.03_2026.07.01", "report_dir": "reports/ROLLING_MyEA_2026.06.03_2026.07.01", "expert": "MyEA", "weeks": [ { "label": "Jun 03 - Jun 07", "from_date": "2026.06.03", "to_date": "2026.06.07" }, { "label": "Jun 10 - Jun 14", "from_date": "2026.06.10", "to_date": "2026.06.14" }, { "label": "Jun 17 - Jun 21", "from_date": "2026.06.17", "to_date": "2026.06.21" }, { "label": "Jun 24 - Jun 28", "from_date": "2026.06.24", "to_date": "2026.06.28" } ] } ``` ### Rolling results format (rolling_results.json) ```json { "success": true, "weeks_run": 4, "summary": { "total_net_profit": 12450.50, "max_drawdown_pct": 8.5, "total_trades": 342 }, "weekly_results": [ { "label": "Jun 03 - Jun 07", "from_date": "2026.06.03", "to_date": "2026.06.07", "success": true, "net_profit": 3200.00, "max_dd_pct": 3.2, "total_trades": 85, "profit_factor": 1.45, "report_dir": "reports/20260701_120000_MyEA_XAUUSD_M5" }, { "label": "Jun 10 - Jun 14", "from_date": "2026.06.10", "to_date": "2026.06.14", "success": true, "net_profit": -450.00, "max_dd_pct": 8.5, "total_trades": 92, "profit_factor": 0.92, "report_dir": "reports/20260701_123000_MyEA_XAUUSD_M5" } ] } ``` --- ## `get_backtest_status` Check progress of a running backtest pipeline launched via `launch_backtest`. **When to call:** Poll periodically after calling `launch_backtest` to check completion status. ### Input schema ```typescript { report_dir: string; // Report directory path from launch_backtest output } ``` ### Output schema ```typescript { success: true; report_dir: string; status: "completed" | "running" | "failed" | "in_progress" | "not_started"; stage: string; // Current pipeline stage: COMPILE, CLEAN, BACKTEST, EXTRACT, ANALYZE, DONE is_complete: boolean; // True if backtest finished successfully mt5_running: boolean; // Whether MT5 process is active report_found: boolean; // Whether report file exists metrics_extracted: boolean; deals_extracted: boolean; elapsed_seconds: number; // Time since launch message: string; // Human-readable status message job?: { report_id: string; expert: string; symbol: string; timeframe: string; launched_at: string; timeout_seconds: number; } } ``` --- ## `run_optimization` Launch genetic parameter optimization as a detached background process. **Important:** This tool returns immediately. MT5 runs for 2-6 hours. The AI agent must NOT poll for results — the user monitors MT5 and signals when done. Call `get_optimization_results` only after user confirmation. **Uses Model=1 (1-min OHLC) for faster optimization.** Use a separate `run_backtest` with `model=0` to verify top optimization results — Model 1 optimization parameters may overfit grid/martingale EAs because intra-bar price movement is not simulated. The `get_optimization_status` tool now auto-parses results when optimization completes, returning top passes, best PF, and best profit. ### Input schema ```typescript { expert: string; // EA name set_file: string; // Path to optimization .set file (with ||Y flags) from: string; // "YYYY-MM-DD" to: string; // "YYYY-MM-DD" symbol?: string; // Default from config deposit?: number; // Default from config max_passes?: number; // Cap on genetic optimization passes (e.g. 5000 to run fewer) currency?: string; // Default: "USD" leverage?: number; // Default: 500 log_file?: string; // Where to write nohup output (default: /tmp/opt_.log) } ``` ### Output schema ```typescript { success: boolean; job_id: string; // "opt_20250619_143022" log_file: string; // "/tmp/opt_20250619_143022.log" pid: number; // Process ID (for user monitoring if needed) combinations: number; // Estimated from set_file analysis (product of all ||Y ranges) message: string; // "Optimization launched. Signal me when MT5 completes." } ``` ### Optimization set file format ```ini ; param=current_value||start||step||stop||Y (Y = include in sweep) ; param=value||N (N = fixed, not swept) Min_Entry_Confidence=0.610||0.580||0.010||0.650||Y ; 8 values TP_Pips_Layer1=400||300||50||500||Y ; 5 values Max_DD_Percent=15.0||N ; fixed ; Total combinations: 8 × 5 = 40 ``` **MT5-Quant handles automatically:** - UTF-16LE encoding with BOM - `chmod 444` (read-only) before launch - `OptMode=0` reset in `terminal.ini` - `LastOptimization` line removal from `terminal.ini` - `ExpertParameters` = filename only (not full path) in launch INI --- ## `get_optimization_results` Parse completed optimization results. Handles both HTML (`.htm`) and SpreadsheetML XML (`.htm.xml`) formats transparently. ### Input schema ```typescript { job_id?: string; // From run_optimization response. If omitted, uses latest _opt/ dir. report_dir?: string; // Explicit path to *_opt/ directory top_n?: number; // How many top results to return (default: 20) dd_threshold?: number; // Flag results above this DD% as high-risk (default: 20) sort_by?: "profit" | "profit_factor" | "sharpe"; // Default: "profit" } ``` ### Output schema ```typescript { success: boolean; total_passes: number; converged: boolean; // True if passes stopped improving in last 10% report_format: "html" | "xml"; results: Array<{ rank: number; net_profit: number; profit_factor: number; max_dd_pct: number; total_trades: number; sharpe_ratio: number; high_risk: boolean; // DD > dd_threshold params: Record; // All swept parameter values }>; convergence_analysis: { top_10_agreement: Record; // Params same across top 10 = strong signal high_variance_params: string[]; // Params that vary in top 10 = uncertain }; recommendation: { best_params: Record; reasoning: string; next_step: "verify_model0" | "auto_promote" | "investigate"; }; } ``` ### Convergence analysis A parameter that appears with the same value across all top-10 results is a strong optimization signal — the genetic algorithm converged on it. A parameter that varies across top-10 means the optimizer couldn't distinguish between values — either the parameter doesn't matter much, or more passes are needed. --- ## `verify_setup` Check all required paths, Wine version, and EA/set file inventory. Run this first if `run_backtest` or `run_optimization` fails with path errors. ### Input schema ```typescript {} // No parameters required ``` ### Output schema ```typescript { success: boolean; wine_path: string; wine_version: string; mt5_dir: string; terminal_exe: string; experts_dir: string; display_mode: "gui" | "headless"; ea_count: number; // .ex5 files found in Experts/ set_count: number; // .set files found missing: string[]; // List of paths/tools that couldn't be found hints: string[]; // Actionable fix hints for each missing item } ``` --- ## `get_backtest_status` Check the current stage and elapsed time of a running backtest pipeline by reading its `progress.log`. ### Input schema ```typescript { report_dir: string; // Path to the report directory from run_backtest } ``` ### Output schema ```typescript { success: boolean; report_dir: string; stage: "COMPILE" | "CLEAN" | "BACKTEST" | "EXTRACT" | "ANALYZE" | "DONE"; elapsed_seconds: number; finished: boolean; log_lines: string[]; // Last 5 lines of progress.log } ``` --- ## `get_optimization_status` Check the live state of a background optimization job (started by `run_optimization`). ### Input schema ```typescript { job_id: string; // From run_optimization response } ``` ### Output schema ```typescript { success: boolean; status: "running" | "stopped" | "completed"; job_id: string; pid: number; expert?: string; symbol?: string; from_date?: string; to_date?: string; started_at?: string; // Present when status is "completed": total_passes?: number; top_10?: Array<{ pass: number; profit: number; profit_factor: number; drawdown_pct: number; }>; best_pf?: { /* best pass by profit factor */ }; best_profit?: { /* best pass by profit */ }; } ``` --- ## `prune_reports` Delete old report directories to reclaim disk space, keeping the most recent N runs. Optimization result directories (`*_opt/`) are always preserved. ### Input schema ```typescript { keep_last?: number; // How many recent reports to keep (default from config, usually 10) dry_run?: boolean; // If true, list what would be deleted without deleting (default: false) } ``` ### Output schema ```typescript { success: boolean; deleted: string[]; // Paths that were (or would be) deleted kept: string[]; // Paths that were kept freed_mb: number; // Approximate disk space freed } ``` --- ## `analyze_report` Read and summarize a completed backtest report without re-running MT5. Loads deals from the SQLite database. ### Input schema ```typescript { report_id?: string; // Preferred: report ID from list_reports report_dir?: string; // Legacy: path to report directory (looks up DB entry) // Omit both to use the latest report automatically strategy?: "grid" | "scalper" | "trend" | "hedge" | "generic"; // Strategy profile that was used (default: "grid"). // Only affects interpretation of analysis.json fields — // does not re-run analysis. include_deals?: boolean; // Include top 20 deals in output (default: false) include_monthly?: boolean; // Include full monthly P/L table (default: true) include_dd_events?: boolean; // Include DD event reconstruction (default: true) deep?: boolean; // Include hourly_pnl and volume_profile (default: false) } ``` ### Output schema ```typescript { success: boolean; report_dir: string; strategy: string; // Active profile: "grid" | "scalper" | "trend" | "hedge" | "generic" metrics: { /* same as run_backtest metrics */ }; // ── Always present (strategy-agnostic) ───────────────────────────────────── monthly_pnl: Array<{ month: string; // "2025-01" pnl: number; trades: number; green: boolean; }>; dd_events: Array<{ peak_dd_pct: number; start_date: string; end_date: string; duration_days: number; recovery_date: string | null; recovery_days: number | null; cause: string; // Profile-driven: e.g. "locking_cascade" (grid) or "whipsaw" (trend) // Falls back to "unknown" when no keyword matched }>; top_losses: Array<{ date: string; loss_usd: number; grid_depth_at_close: number; // 0 for non-grid strategies volume: number; comment: string; }>; loss_sequences: Array<{ length: number; total_loss: number; start: string; end: string; }>; position_pairs: Array<{ time: string; type: "buy" | "sell"; profit: number; volume: number; layer: number; hold_minutes: number | null; comment: string; magic: string; order: string; }>; // ── Strategy-driven (content varies by profile) ──────────────────────────── depth_histogram: Record; // grid: { L1: n, L2: n, …, "L8+": n } // others: {} (empty — no depth_re in profile) grid_depth_histogram: Record; // Backward-compat alias for depth_histogram (grid only) cycle_stats: { total_cycles: number; win_rate: number; // percent avg_profit: number; win_rate_by_depth: Record; // win_rate_by_depth populated for grid; keys = "L?" for non-depth profiles }; exit_reason_breakdown: Record< string, // Keys depend on strategy profile exit_keywords // grid: "locking" | "cutloss" | "zombie" | "timeout" | "tp" | "sl" // scalper: "manual" | "trailing" | "tp" | "sl" // trend: "breakeven" | "trailing" | "partial" | "tp" | "sl" // generic: "tp" | "sl" { count: number; total_pnl: number; avg_pnl: number } >; direction_bias: { buy?: { trades: number; win_rate: number; total_pnl: number; avg_pnl: number }; sell?: { trades: number; win_rate: number; total_pnl: number; avg_pnl: number }; }; streak_analysis: { max_win_streak: number; max_win_start: string; max_win_end: string; max_loss_streak: number; max_loss_start: string; max_loss_end: string; current_streak: number; current_streak_type: "win" | "loss"; }; session_breakdown: Record< "asian" | "london" | "london_ny_overlap" | "new_york" | "off_hours", { trades: number; win_rate: number; total_pnl: number } >; weekday_pnl: Array<{ day: string; // "Monday" … "Sunday" pnl: number; trades: number; win_rate: number; }>; concurrent_peak: { peak_open: number; peak_time: string; }; // ── Deep mode only (deep=true) ────────────────────────────────────────────── hourly_pnl?: Array<{ hour: number; // 0–23 pnl: number; trades: number; win_rate: number; }>; volume_profile?: Array<{ lot_tier: string; // "0.01" | "0.02-0.04" | "0.05-0.09" | "0.10-0.49" | … pnl: number; trades: number; win_rate: number; }>; // ── Optional raw deals ────────────────────────────────────────────────────── deals?: Array<{ /* all 13 deal columns */ }>; // Only if include_deals=true } ``` --- ## `compare_baseline` Compare a report against a baseline and return a structured verdict. ### Input schema ```typescript { report_dir: string; // Report to evaluate baseline: { net_profit: number; max_dd_pct: number; total_trades?: number; label?: string; // e.g. "v1.2 production" }; promote_threshold?: { profit_gt: number; // Auto-promote if profit > this (default: baseline profit) dd_lt: number; // AND DD < this (default: 20) }; } ``` ### Output schema ```typescript { verdict: "winner" | "loser" | "marginal"; auto_promote: boolean; delta: { profit_usd: number; // positive = improvement profit_pct: number; // relative to baseline dd_pp: number; // positive = DD got worse trades_delta: number; }; summary: string; // Human-readable one-liner details: { candidate: { net_profit: number; max_dd_pct: number; total_trades: number; }; baseline: { net_profit: number; max_dd_pct: number; label: string; }; }; } ``` ### Example ```json // Input { "report_dir": "reports/20250619_143022_MyEA_v1.3_XAUUSD_M5", "baseline": { "net_profit": 8660, "max_dd_pct": 15.66, "label": "v1.2 production" } } // Output { "verdict": "winner", "auto_promote": true, "delta": { "profit_usd": 3186.32, "profit_pct": 36.8, "dd_pp": -7.27, "trades_delta": -3 }, "summary": "+$3,186 (+37%) profit vs v1.2. DD dropped from 15.66% to 8.39%. Auto-promoting.", "details": { "candidate": { "net_profit": 11846.32, "max_dd_pct": 8.39, "total_trades": 1963 }, "baseline": { "net_profit": 8660.00, "max_dd_pct": 15.66, "label": "v1.2 production" } } } ``` --- ## `compile_ea` Compile an MQL5 Expert Advisor via MetaEditor (Wine/CrossOver). ### Input schema ```typescript { expert_path: string; // e.g. "src/MyEA_v1.2.mq5" include_dirs?: string[]; // Additional include search paths } ``` ### Output schema ```typescript { success: boolean; binary_path: string; // Path where .ex5 was written binary_size_bytes: number; warnings: number; errors: number; error_list: Array<{ file: string; line: number; message: string; }>; compile_time_ms: number; } ``` --- ## Error Handling All tools return `success: false` with an `error` field on failure. Pipeline failures are non-fatal by default — the tool returns partial results if any stages completed. ```typescript { success: false, error: "COMPILE_FAILED", error_detail: "2 errors in src/MyEA_v1.2.mq5: line 847: undeclared identifier 'Max_New_Param'", completed_stages: ["COMPILE"], failed_stage: "COMPILE" } ``` **Error codes:** | Code | Stage | Cause | |------|-------|-------| | `COMPILE_FAILED` | COMPILE | MQL5 syntax errors | | `WINE_NOT_FOUND` | Any | Wine/CrossOver not installed or wrong path | | `MT5_TIMEOUT` | BACKTEST | MT5 didn't exit within timeout (default: 15min) | | `REPORT_NOT_FOUND` | EXTRACT | MT5 produced no report (usually parameter error) | | `EXTRACT_FAILED` | EXTRACT | Report parse error (format change?) | | `NO_DEALS` | ANALYZE | Report has 0 trades (check date range, symbol) | | `OPT_NOT_FINISHED` | get_opt_results | Optimization still running | --- ## `list_reports` List all backtest report directories with compact key metrics. Use this to survey what runs exist before deciding which to analyze — much cheaper than calling `analyze_report` repeatedly. ### Input schema ```typescript { include_opt?: boolean; // Include _opt dirs (default: false) limit?: number; // Max reports, newest first (default: 30) } ``` ### Output schema ```typescript { success: boolean; count: number; reports: Array<{ name: string; // "20250619_143022_MyEA_XAUUSD_M5" is_opt: boolean; net_profit?: number; max_dd_pct?: number; total_trades?: number; symbol?: string; timeframe?: string; from_date?: string; to_date?: string; metrics?: "missing"; // Present only if metrics.json is absent }>; } ``` --- ## `tail_log` Read the last N lines of a log file. Supports `filter=errors` to return only lines containing error/fail keywords — avoids streaming full logs into context. ### Input schema ```typescript { // Provide one of: report_dir, job_id, or log_file report_dir?: string; // Reads progress.log from this dir (omit for latest) job_id?: string; // Reads the nohup log for this optimization job log_file?: string; // Absolute path to any log file n?: number; // Lines to return (default: 50) filter?: "all" | "errors" | "warnings"; // Default: "all" } ``` ### Output schema ```typescript { success: boolean; log_file: string; // Resolved path of the file that was read total_lines: number; // Lines matched after filter applied lines: string[]; // Last n of the matched lines } ``` --- ## `cache_status` Show the MT5 tester cache directory size broken down by symbol. Use before `clean_cache` to see what's there. ### Input schema ```typescript {} // No parameters ``` ### Output schema ```typescript { success: boolean; cache_dir: string; total_size_mb: number; symbols: Array<{ symbol: string; // Subdirectory name (broker symbol) size_mb: number; }>; } ``` --- ## `clean_cache` Delete MT5 tester cache files. Forces MT5 to regenerate tick data on the next backtest (slower first run after clean). Supports dry-run preview and per-symbol targeting. ### Input schema ```typescript { symbol?: string; // Delete only this symbol's cache. Omit to delete all. dry_run?: boolean; // Report what would be deleted without deleting (default: false) } ``` ### Output schema ```typescript { success: boolean; dry_run: boolean; deleted_symbols: string[]; freed_mb: number; hint: string; // Reminder that next backtest will be slower } ``` --- ## `read_set_file` Parse an MT5 `.set` parameter file (UTF-16LE or UTF-8) into structured JSON. Handles BOM detection automatically. Use this instead of reading raw `.set` files. ### Input schema ```typescript { path: string; // Path to .set file } ``` ### Output schema ```typescript { success: boolean; path: string; param_count: number; comments: string[]; // Header comment lines (stripped of semicolons) params: Record; } ``` ### Example ```json // Input { "path": "config/MyEA_opt.set" } // Output { "success": true, "path": "config/MyEA_opt.set", "param_count": 5, "comments": ["MyEA optimization set — XAUUSD M5"], "params": { "Min_Entry_Confidence": { "value": "0.610", "from": "0.580", "to": "0.650", "step": "0.010", "optimize": true }, "TP_Pips": { "value": "400", "from": "300", "to": "500", "step": "50", "optimize": true }, "Max_DD_Percent": { "value": "15.0" } } } ``` --- ## `write_set_file` Write an MT5 `.set` parameter file with correct UTF-16LE encoding and `chmod 444`. Overwrites any existing file at the path. ### Input schema ```typescript { path: string; // Output path for .set file params: Record; } ``` ### Output schema ```typescript { success: boolean; path: string; param_count: number; encoding: "utf-16-le"; permissions: string; // "444 (read-only, required by MT5)" } ``` ### Example ```json // Input { "path": "config/MyEA_opt.set", "params": { "Min_Entry_Confidence": { "value": 0.61, "from": 0.58, "to": 0.65, "step": 0.01, "optimize": true }, "TP_Pips": { "value": 400, "from": 300, "to": 500, "step": 50, "optimize": true }, "Max_DD_Percent": 15.0 } } // Output { "success": true, "path": "config/MyEA_opt.set", "param_count": 3, "encoding": "utf-16-le", "permissions": "444 (read-only, required by MT5)" } ``` --- ## `list_jobs` List all optimization jobs tracked in `.mt5mcp_jobs/` with compact status. Cheaper than calling `get_optimization_status` per job. ### Input schema ```typescript { include_done?: boolean; // Include completed/failed jobs (default: true) } ``` ### Output schema ```typescript { success: boolean; count: number; jobs: Array<{ job_id: string; // "opt_20250619_143022" status: "running" | "done" | "failed"; elapsed_seconds: number | null; expert: string; started_at: string; // ISO timestamp log_file: string; }>; } ``` --- ## `patch_set_file` Modify specific parameters in an existing `.set` file in-place. Preserves all other params, comments, and sweep config untouched. Returns a diff of what changed. **Use instead of `read_set_file` → edit → `write_set_file`** — saves two round-trips. ### Input schema ```typescript { path: string; // .set file to modify (must exist) patches: Record; } ``` ### Output schema ```typescript { success: boolean; path: string; changed_count: number; param_count: number; changed: Array<{ name: string; old: string; new: string; }>; } ``` ### Example ```json // Input — change two params without touching the rest of the file { "path": "config/MyEA_opt.set", "patches": { "TP_Pips": 350, "Min_Entry_Confidence": { "value": 0.62, "from": 0.60, "to": 0.65, "optimize": true } } } // Output { "success": true, "path": "config/MyEA_opt.set", "changed_count": 2, "param_count": 12, "changed": [ { "name": "TP_Pips", "old": "400", "new": "350" }, { "name": "Min_Entry_Confidence", "old": "0.610", "new": "0.62" } ] } ``` --- ## `clone_set_file` Copy a `.set` file to a new path, applying optional param overrides. One call instead of read → modify → write. Preserves header comments. ### Input schema ```typescript { source: string; // Source .set file destination: string; // Output path (created if needed) overrides?: Record; } ``` ### Output schema ```typescript { success: boolean; source: string; destination: string; param_count: number; overridden_count: number; overridden: Array<{ name: string; old: string | null; new: string; }>; } ``` --- ## `set_from_optimization` Generate a clean backtest `.set` file directly from an optimization result's params dict. Strips all sweep flags (`||Y`) so the file is ready for `run_backtest`. Optionally fills params not in the optimization result from a template `.set`, and optionally re-adds sweep ranges to selected params for a narrowed follow-on optimization. **Typical call**: immediately after `get_optimization_results`, use `results[0].params` as the `params` argument. ### Input schema ```typescript { path: string; // Output .set file path params: Record; // Flat param→value dict from optimization result. // e.g. { "TP_Pips": 400, "Min_Confidence": 0.61 } template?: string; // Path to existing .set. Params NOT in 'params' are // copied from here as fixed values. sweep?: Record; // Re-add sweep ranges to specific params after applying opt values. // Used to create a narrowed follow-on optimization .set. } ``` ### Output schema ```typescript { success: boolean; path: string; param_count: number; from_template: boolean; opt_params_applied: number; swept_params: number; // > 0 if sweep was provided total_combinations: number; // 0 for pure backtest .set } ``` ### Example ```json // After get_optimization_results returned: // results[0].params = { "TP_Pips": 400, "Min_Entry_Confidence": 0.62, "Max_DD_Percent": 15.0 } { "path": "config/MyEA_v1.3.set", "params": { "TP_Pips": 400, "Min_Entry_Confidence": 0.62, "Max_DD_Percent": 15.0 }, "template": "config/MyEA_base.set" } // Output { "success": true, "path": "config/MyEA_v1.3.set", "param_count": 12, "from_template": true, "opt_params_applied": 3, "swept_params": 0, "total_combinations": 0 } ``` --- ## `diff_set_files` Compare two `.set` files and return only the differences. Use instead of reading both files and comparing manually. ### Input schema ```typescript { path_a: string; // Baseline / old file path_b: string; // Candidate / new file } ``` ### Output schema ```typescript { success: boolean; path_a: string; path_b: string; identical: boolean; added_count: number; // Params in b but not a removed_count: number; // Params in a but not b changed_count: number; // Params in both but with different value or sweep flag added: Array<{ name: string; value: string; }>; removed: Array<{ name: string; value: string; }>; changed: Array<{ name: string; a: string; // value in path_a b: string; // value in path_b sweep_a?: boolean; // Present only if sweep flag differs sweep_b?: boolean; }>; } ``` ### Example ```json { "path_a": "config/MyEA_v1.2.set", "path_b": "config/MyEA_v1.3.set" } // Output { "success": true, "identical": false, "added_count": 1, "removed_count": 0, "changed_count": 2, "added": [{ "name": "Trailing_Activation", "value": "50" }], "removed": [], "changed": [ { "name": "TP_Pips", "a": "400", "b": "350" }, { "name": "Min_Entry_Confidence", "a": "0.610", "b": "0.620", "sweep_a": true, "sweep_b": false } ] } ``` --- ## `describe_sweep` Show a `.set` file's sweep configuration: which params are swept, their ranges, per-param value counts, and total combinations. Use before `run_optimization` to verify scope. ### Input schema ```typescript { path: string; } ``` ### Output schema ```typescript { success: boolean; path: string; total_params: number; swept_count: number; fixed_count: number; total_combinations: number; swept_params: Array<{ name: string; from: string; to: string; step: string; count: number; // Number of distinct values in this param's range }>; hint: string; // e.g. "240 combinations. Typical range: 1–8h depending on EA tick speed." } ``` ### Example ```json // Input { "path": "config/MyEA_opt.set" } // Output { "success": true, "total_params": 12, "swept_count": 3, "fixed_count": 9, "total_combinations": 240, "swept_params": [ { "name": "TP_Pips", "from": "300", "to": "500", "step": "50", "count": 5 }, { "name": "Min_Entry_Confidence", "from": "0.58","to": "0.65","step": "0.01", "count": 8 }, { "name": "Max_DD_Percent", "from": "12", "to": "20", "step": "2", "count": 5 } ], "hint": "240 combinations. Typical range: 1–8h depending on EA tick speed." } ``` --- ## `list_set_files` List all `.set` files in the MT5 tester profiles directory with param counts, swept param counts, and total combinations per file. Use to find the right `.set` without reading each one. ### Input schema ```typescript { ea?: string; // Filter by EA name substring (case-insensitive) } ``` ### Output schema ```typescript { success: boolean; profiles_dir: string; count: number; files: Array<{ name: string; // filename only param_count: number; swept_count: number; total_combinations: number; // 0 for backtest-only .set files modified: string; // "YYYY-MM-DD HH:MM" error?: string; // Present only if file is unreadable }>; } ``` --- ## `get_active_account` Get current MT5 account session information: login, server, and available symbols. This is essential for pre-flight checks to ensure symbol availability before backtesting. ### Input schema ```typescript {} // No parameters ``` ### Output schema ```typescript { success: boolean; ready_for_backtest: boolean; // true if account exists and symbols available account: { login: string; server: string; } | null; server: string; // Active server name available_servers: string[]; // All servers with history data symbols: string[]; // Symbols available for active server symbol_count: number; hint: string; // "Ready for backtesting" or instructions } ``` --- ## `check_symbol_data_status` Validate if a symbol has sufficient historical tick data for a specified date range before running backtest. Prevents failed backtests due to missing history data. ### Input schema ```typescript { symbol: string; // e.g., "XAUUSDc" from_date: string; // "YYYY.MM.DD" to_date: string; // "YYYY.MM.DD" } ``` ### Output schema ```typescript { success: boolean; symbol: string; server: string; has_sufficient_data: boolean; requested_range: { from: string; to: string }; data_range: string; // "YYYY.MM.DD - YYYY.MM.DD" or "unknown" years_available: number; // Count of years with data hcc_files_count: number; // Number of history cache files warnings: string[] | null; // Data range issues suggestion: string; // Action recommendation } ``` --- ## `check_mt5_status` Check if MT5 terminal is properly installed and configured. Returns comprehensive status of all required components. ### Input schema ```typescript {} // No parameters ``` ### Output schema ```typescript { success: boolean; terminal_ready: boolean; // true if all components present checks: { mt5_dir_exists: boolean; terminal64_exe: boolean; metaeditor64_exe: boolean; metatester64_exe: boolean; wine_executable: boolean; wine_path: string | null; }; mt5_version: string | null; current_account: { login: string; server: string; } | null; hint: string; } ``` --- ## `get_backtest_history` List all backtests previously run for a specific EA and/or symbol with summary metrics. Use for tracking performance over time. ### Input schema ```typescript { expert?: string; // Filter by EA name symbol?: string; // Filter by symbol limit?: number; // Max results (default: 10) } ``` ### Output schema ```typescript { success: boolean; count: number; total: number; filters: { expert: string | null; symbol: string | null; }; history: Array<{ report_dir: string; date: string | null; expert: string | null; symbol: string | null; period: string | null; profit: number | null; profit_factor: number | null; expected_payoff: number | null; drawdown_pct: number | null; total_trades: number | null; win_rate: number | null; }>; hint: string; } ``` --- ## `compare_backtests` Compare two or more backtest results side-by-side with key metrics analysis. Includes profit/drawdown differences and verdict on which performed better. ### Input schema ```typescript { report_dirs: string[]; // List of report directory paths to compare } ``` ### Output schema ```typescript { success: boolean; count: number; comparisons: Array<{ report_dir: string; expert: string | null; symbol: string | null; net_profit: number | null; profit_factor: number | null; drawdown_pct: number | null; total_trades: number | null; win_rate: number | null; expected_payoff: number | null; recovery_factor: number | null; sharpe_ratio: number | null; }>; analysis: Array<{ compare_to: string | null; report: string | null; profit_diff: number; profit_pct_change: number; drawdown_diff: number; profit_factor_diff: number; verdict: "better" | "worse" | "mixed"; }> | null; verdict: string | null; // "Best: " } ``` --- ## `init_project` Create a new MQL5 project with standard directory structure and template files. Supports scalper, swing, grid, and basic templates. ### Input schema ```typescript { name: string; // Project name (used for EA filename) template?: "scalper" | "swing" | "grid" | "basic"; // Default: "basic" } ``` ### Output schema ```typescript { success: boolean; project_name: string; template: string; created_files: string[]; // Paths to created files hint: string; } ``` --- ## `validate_ea_syntax` Perform pre-compile syntax check on MQL5 source file without running full compilation. Detects common issues before expensive MetaEditor compilation. ### Input schema ```typescript { path: string; // Path to .mq5 source file } ``` ### Output schema ```typescript { success: boolean; valid: boolean; path: string; checks: { has_on_init: boolean; has_on_tick: boolean; has_on_deinit: boolean; lines: number; }; errors: Array<{ line: number; message: string; severity: "error"; }> | null; warnings: Array<{ line: number; message: string; severity: "warning"; }> | null; hint: string; } ``` --- ## `create_set_template` Generate a .set parameter file template based on an EA's input variables. Automatically parses input declarations from source code. ### Input schema ```typescript { ea: string; // EA name or path to .mq5/.ex5 file output_path?: string; // Optional custom output path } ``` ### Output schema ```typescript { success: boolean; ea: string; inputs_found: number; inputs: Array<{ name: string; type: string; default: string; description: string | null; }>; set_file: string; // Path to generated file hint: string; } ``` --- ## `export_report` Export backtest report to various formats (CSV, JSON, Markdown) for external analysis or sharing. ### Input schema ```typescript { report_dir: string; // Path to backtest report directory format?: "csv" | "json" | "md"; // Default: "csv" output_path?: string; // Optional custom output file path } ``` ### Output schema ```typescript { success: boolean; format: string; output_file: string; source: string; hint: string; } ``` --- ## `archive_report` Convert a backtest report directory into a compact JSON entry appended to `config/backtest_history.json`. Idempotent — re-archiving the same report is a no-op. Optionally deletes the source directory to reclaim disk space. ### Input schema ```typescript { report_dir?: string; // Directory to archive. Omit for latest. delete_after?: boolean; // Delete source dir after archiving (default: false) verdict?: "winner" | "loser" | "marginal" | "reference"; notes?: string; // Free-text notes for the entry tags?: string[]; // Tags e.g. ["tight-sl", "new-filter"] } ``` ### Output schema ```typescript { success: boolean; id: string; // Report dir basename used as history entry id already_existed: boolean; deleted_source: boolean; history_file: string; // Absolute path to backtest_history.json entry_summary: { ea: string; symbol: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; sharpe_ratio: number; total_trades: number; }; verdict: string | null; }; } ``` --- ## `archive_all_reports` Bulk-archive all backtest report directories into `config/backtest_history.json`. Entries already in history are skipped. Use `delete_after=true` to reclaim disk space while preserving all results as JSON. Optimization dirs (`_opt` suffix) are never deleted. ### Input schema ```typescript { delete_after?: boolean; // Delete source dirs after archiving (default: false) keep_last?: number; // Protect newest N dirs from deletion even with delete_after=true (default: 5) dry_run?: boolean; // Preview without making changes (default: false) } ``` ### Output schema ```typescript { success: boolean; dry_run: boolean; archived_count: number; skipped_count: number; // Already in history deleted_count: number; failed_count: number; // Dirs with no parseable metrics archived: string[]; skipped: string[]; deleted: string[]; failed: string[]; history_file: string; } ``` --- ## `get_history` Query `config/backtest_history.json` with filters and sorting. Strips `monthly_pnl` arrays by default — set `include_monthly=true` when you need the full breakdown. ### Input schema ```typescript { ea?: string; // Substring match on EA name symbol?: string; // Exact match (uppercase) verdict?: "winner" | "loser" | "marginal" | "reference"; tag?: string; // Entry must contain this tag min_profit?: number; // net_profit >= this max_dd_pct?: number; // max_dd_pct <= this sort_by?: "date" | "profit" | "dd" | "sharpe"; // Default: date, newest first limit?: number; // Default: 20 include_monthly?: boolean; // Include monthly_pnl arrays (default: false) } ``` ### Output schema ```typescript { success: boolean; count: number; entries: Array<{ id: string; // Report dir basename archived_at: string; // ISO timestamp report_dir_deleted: boolean; ea: string; symbol: string; timeframe: string; from_date: string; to_date: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; sharpe_ratio: number; total_trades: number; recovery_factor: number; win_rate_pct: number; expected_payoff: number; }; summary?: { green_months: number; total_months: number; worst_month: string; worst_month_pnl: number; dominant_exit?: string; max_win_streak?: number; max_loss_streak?: number; }; worst_dd_event?: { peak_dd_pct: number; start_date: string; end_date: string; duration_days: number; cause: string; }; monthly_pnl?: Array<{ month: string; pnl: number; trades: number; green: boolean; }>; verdict: string | null; notes: string; tags: string[]; promoted_to_baseline: boolean; }>; } ``` --- ## `promote_to_baseline` Write a backtest result to `config/baseline.json` — the production reference used by `compare_baseline` and the Claude Code baseline hook. Also marks the source history entry as `promoted_to_baseline: true`. ### Input schema ```typescript { // Provide one: history_id, report_dir, or neither (uses latest report) history_id?: string; // Entry id from get_history report_dir?: string; // Direct path to report directory notes?: string; // Written to baseline.json notes field } ``` ### Output schema ```typescript { success: boolean; baseline_file: string; baseline: { ea: string; symbol: string; period: string; // "YYYY-MM-DD/YYYY-MM-DD" net_profit: number; profit_factor: number; max_drawdown_pct: number; sharpe_ratio: number; total_trades: number; recovery_factor: number; promoted_from: string; // History entry id promoted_at: string; // Date promoted (YYYY-MM-DD) notes: string; }; } ``` ### Example ```json // Input { "history_id": "20250619_143022_MyEA_XAUUSD_M5", "notes": "v1.3 after walk-forward validation" } // Output { "success": true, "baseline_file": "/path/to/config/baseline.json", "baseline": { "ea": "MyEA", "symbol": "XAUUSD", "period": "2025-01-01/2025-06-30", "net_profit": 4832.10, "profit_factor": 1.54, "max_drawdown_pct": 12.3, "sharpe_ratio": 1.18, "total_trades": 891, "recovery_from": "20250619_143022_MyEA_XAUUSD_M5", "promoted_at": "2025-06-20", "notes": "v1.3 after walk-forward validation" } } ``` --- ## `annotate_history` Update the verdict, notes, or tags on an existing history entry. Use this after `compare_baseline` to record the decision, or to tag runs for later retrieval. ### Input schema ```typescript { history_id: string; // Required — entry id to update verdict?: "winner" | "loser" | "marginal" | "reference"; notes?: string; // Replaces existing notes tags?: string[]; // Replaces existing tags add_tags?: string[]; // Appends to existing tags without overwriting } ``` ### Output schema ```typescript { success: boolean; id: string; verdict: string | null; notes: string; tags: string[]; } ``` --- ## Token-efficient usage patterns ### Surveying past runs ``` list_reports(limit=10) → see what's there (live dirs) get_history(ea="MyEA", limit=10) → see what's been archived analyze_report(report_dir=X) → drill into one specific run ``` Never call `analyze_report` on multiple directories to find the best run — use `list_reports` or `get_history` first. ### Checking logs without noise ``` tail_log(job_id=X, filter=errors) → only failures tail_log(report_dir=X, n=20) → last 20 lines of backtest progress ``` ### Managing disk space ``` archive_all_reports(dry_run=true) → preview what would be archived archive_all_reports(delete_after=true, keep_last=3) → archive all, delete old, keep 3 newest get_history(sort_by=profit, limit=5) → find best archived runs ``` ### Labelling experiments ``` annotate_history(history_id=X, verdict="loser", notes="SL too tight, reversed at L3") annotate_history(history_id=X, add_tags=["walk-forward-fail"]) get_history(verdict="winner") → all winners across all sessions ``` ### Promoting a new production config ``` run_backtest(...) compare_baseline(...) → get verdict archive_report(delete_after=true, verdict="winner") promote_to_baseline(notes="v1.4 after WF") → update baseline.json ``` ### Managing cache ``` cache_status() → see symbol breakdown and total size clean_cache(symbol=XAUUSD, dry_run=true) → preview clean_cache(symbol=XAUUSD) → execute ``` ### Pre-flight validation ``` get_active_account() → current login, server, available symbols check_symbol_data_status(symbol=XAUUSD, from=2025.01.01, to=2025.03.31) → verify data availability before backtest check_mt5_status() → verify MT5 installation and readiness validate_ea_syntax(path=MyEA.mq5) → pre-compile syntax check ``` ### Project management ``` init_project(name=MyStrategy, template=scalper) → scaffold new EA with template create_set_template(ea=MyEA) → generate .set from EA inputs export_report(report_dir=..., format=csv) → export to CSV/JSON/Markdown ``` ### History and comparison ``` get_backtest_history(expert=MyEA, limit=10) → list past backtests with metrics compare_backtests(report_dirs=["dir1", "dir2"]) → side-by-side comparison ``` ### Working with set files ``` # Inspect list_set_files(ea="MyEA") → all variants, swept param counts, combinations describe_sweep(path=MyEA_opt.set) → verify 240 combinations before launching opt diff_set_files(a=v1.2.set, b=v1.3.set) → only changed params, not full file content # Edit (never read+write manually) patch_set_file(path, {TP_Pips: 350}) → change one param, keep everything else intact clone_set_file(src, dest, overrides) → create variant from base in one call # Generate after optimization set_from_optimization( → map results[0].params → clean backtest .set path=MyEA_v1.3.set, params=results[0].params, template=MyEA_base.set → fills non-swept params from existing file ) ``` --- ## `list_symbols` List all available symbols in the MT5 terminal. **When to call:** To verify a symbol is available before running backtests, or to discover available symbols. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; symbols: Array<{ name: string; // e.g. "XAUUSD", "EURUSD" description?: string; // Symbol description visible: boolean; // Whether symbol is visible in Market Watch }>; error?: string; } ``` --- ## `check_update` Check if a newer version of MT5-Quant is available on GitHub. **When to call:** Periodically to stay up to date with the latest features and fixes. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; current_version: string; // Current version, e.g. "1.31.5" latest_version: string; // Latest version from GitHub releases update_available: boolean; download_url?: string; // URL to latest release if update available release_notes?: string; // Release notes from latest version error?: string; } ``` --- ## `update` Update MT5-Quant to the latest version from GitHub releases. **When to call:** After `check_update` indicates a newer version is available. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; message: string; // Update status message new_version: string; // Version installed error?: string; } ``` --- ## `healthcheck` Quick server health check to verify the MCP server is running. **When to call:** To verify the server is responsive after installation or configuration changes. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; version: string; // MT5-Quant version status: "healthy" | "unhealthy"; uptime_seconds: number; error?: string; } ``` --- ## `list_experts` List all Expert Advisors (EAs) in the MQL5/Experts directory. **When to call:** To discover available EAs before running backtests. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; experts: Array<{ name: string; // EA name without extension path: string; // Full path to .mq5 file has_ex5: boolean; // Whether compiled .ex5 exists modified: string; // Last modified timestamp }>; error?: string; } ``` --- ## `list_indicators` List all indicators in the MQL5/Indicators directory. **When to call:** To discover available indicators for use in projects. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; indicators: Array<{ name: string; // Indicator name without extension path: string; // Full path to .mq5 file has_ex5: boolean; // Whether compiled .ex5 exists modified: string; // Last modified timestamp }>; error?: string; } ``` --- ## `list_scripts` List all scripts in the MQL5/Scripts directory. **When to call:** To discover available scripts for one-time execution. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; scripts: Array<{ name: string; // Script name without extension path: string; // Full path to .mq5 file has_ex5: boolean; // Whether compiled .ex5 exists modified: string; // Last modified timestamp }>; error?: string; } ``` --- ## `search_experts` Search EAs by name pattern across all directories. **When to call:** To find EAs matching a specific pattern when the exact name is unknown. ### Input schema ```typescript { pattern: string; // Search pattern, e.g. "Grid" or "v1." } ``` ### Output schema ```typescript { success: boolean; matches: Array<{ name: string; // EA name without extension path: string; // Full path to .mq5 file has_ex5: boolean; // Whether compiled .ex5 exists modified: string; // Last modified timestamp }>; error?: string; } ``` --- ## `search_indicators` Search indicators by name pattern. **When to call:** To find indicators matching a specific pattern. ### Input schema ```typescript { pattern: string; // Search pattern } ``` ### Output schema ```typescript { success: boolean; matches: Array<{ name: string; // Indicator name without extension path: string; // Full path to .mq5 file has_ex5: boolean; // Whether compiled .ex5 exists modified: string; // Last modified timestamp }>; error?: string; } ``` --- ## `search_scripts` Search scripts by name pattern. **When to call:** To find scripts matching a specific pattern. ### Input schema ```typescript { pattern: string; // Search pattern } ``` ### Output schema ```typescript { success: boolean; matches: Array<{ name: string; // Script name without extension path: string; // Full path to .mq5 file has_ex5: boolean; // Whether compiled .ex5 exists modified: string; // Last modified timestamp }>; error?: string; } ``` --- ## `copy_indicator_to_project` Copy indicator to project directory. **When to call:** To include an indicator in your EA project. ### Input schema ```typescript { indicator_name: string; // Name of indicator to copy project_dir: string; // Target project directory path } ``` ### Output schema ```typescript { success: boolean; source_path: string; // Original indicator path target_path: string; // Copied indicator path error?: string; } ``` --- ## `copy_script_to_project` Copy script to project directory. **When to call:** To include a script in your EA project. ### Input schema ```typescript { script_name: string; // Name of script to copy project_dir: string; // Target project directory path } ``` ### Output schema ```typescript { success: boolean; source_path: string; // Original script path target_path: string; // Copied script path error?: string; } ``` --- ## `diagnose_wine` Check Wine installation, version, and prefix health. **When to call:** When experiencing Wine-related issues or to verify Wine setup. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; wine_found: boolean; wine_path?: string; wine_version?: string; prefix_path?: string; prefix_health: "healthy" | "corrupted" | "missing"; error?: string; } ``` --- ## `get_mt5_logs` Get MT5 terminal, tester, or MetaEditor logs with filtering. **When to call:** To diagnose backtest failures or compile errors. ### Input schema ```typescript { log_type: "terminal" | "tester" | "metaeditor"; lines?: number; // Number of lines to retrieve (default: 100) filter?: "all" | "errors" | "warnings"; // Default: "all" } ``` ### Output schema ```typescript { success: boolean; log_path: string; lines: Array<{ timestamp: string; level: "info" | "warning" | "error"; message: string; }>; error?: string; } ``` --- ## `search_mt5_errors` Search logs for error patterns (crash, exception, access violation). **When to call:** To quickly find crash causes in logs. ### Input schema ```typescript { log_type: "terminal" | "tester" | "metaeditor" | "all"; patterns?: string[]; // Custom error patterns (default: common MT5 errors) max_results?: number; // Maximum error entries to return (default: 50) } ``` ### Output schema ```typescript { success: boolean; errors: Array<{ timestamp: string; log_type: string; message: string; context?: string; // Surrounding lines for context }>; total_found: number; error?: string; } ``` --- ## `check_mt5_process` Check if MT5 processes are running, get PID, CPU, memory usage. **When to call:** To verify MT5 is running or to check for stuck processes. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; processes: Array<{ pid: number; name: string; // "terminal64.exe" or "metatester64.exe" cpu_percent: number; memory_mb: number; uptime_seconds: number; status: "running" | "zombie" | "stopped"; }>; error?: string; } ``` --- ## `kill_mt5_process` Kill stuck MT5 processes. **When to call:** When MT5 is stuck or hung and needs to be terminated. ### Input schema ```typescript { pid?: number; // Specific PID to kill (optional, kills all if omitted) force?: boolean; // Force kill wineserver too (default: false) } ``` ### Output schema ```typescript { success: boolean; killed_pids: number[]; message: string; error?: string; } ``` --- ## `check_system_resources` Check disk space, memory, CPU availability. **When to call:** Before running long optimizations to ensure sufficient resources. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; disk: { path: string; total_gb: number; free_gb: number; used_percent: number; }; memory: { total_mb: number; free_mb: number; used_percent: number; }; cpu: { cores: number; usage_percent: number; }; error?: string; } ``` --- ## `validate_mt5_config` Validate terminal.ini and tester configuration files. **When to call:** When experiencing configuration-related backtest failures. ### Input schema ```typescript { // No inputs required (auto-detects config paths) } ``` ### Output schema ```typescript { success: boolean; terminal_ini: { path: string; valid: boolean; issues?: string[]; }; tester_ini?: { path: string; valid: boolean; issues?: string[]; }; error?: string; } ``` --- ## `get_wine_prefix_info` Get Wine prefix details: Windows version, installed programs, registry. **When to call:** To diagnose Wine prefix issues or verify Wine setup. ### Input schema ```typescript { // No inputs required } ``` ### Output schema ```typescript { success: boolean; prefix_path: string; windows_version: string; installed_programs: string[]; registry_keys?: Array<{ key: string; value: string; }>; error?: string; } ``` --- ## `get_backtest_crash_info` Investigate backtest failures: incomplete markers, missing metrics.json, Wine/MT5 errors. **When to call:** When a backtest fails unexpectedly. ### Input schema ```typescript { report_dir: string; // Path to the failed backtest report directory } ``` ### Output schema ```typescript { success: boolean; status: "complete" | "incomplete" | "crashed" | "missing"; issues: Array<{ type: string; message: string; severity: "error" | "warning"; }>; error_log?: string; error?: string; } ``` --- ## `get_latest_report` Get most recent report with optional equity chart. **When to call:** To quickly access the latest backtest results. ### Input schema ```typescript { include_chart?: boolean; // Include equity chart data (default: false) } ``` ### Output schema ```typescript { success: boolean; report: { id: string; report_dir: string; ea: string; symbol: string; timeframe: string; from_date: string; to_date: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; total_trades: number; }; equity_chart?: Array<{date: string; equity: number}>; }; error?: string; } ``` --- ## `search_reports` Find reports by EA, symbol, date range, or profit criteria. **When to call:** To find specific reports matching criteria. ### Input schema ```typescript { ea?: string; symbol?: string; from_date?: string; // "YYYY-MM-DD" to_date?: string; // "YYYY-MM-DD" min_profit?: number; max_profit?: number; min_profit_factor?: number; max_dd_pct?: number; limit?: number; // Max results (default: 50) } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; ea: string; symbol: string; timeframe: string; from_date: string; to_date: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; total_trades: number; }; }>; total: number; error?: string; } ``` --- ## `get_report_by_id` Get specific report by ID with equity chart. **When to call:** To retrieve a specific report's full details. ### Input schema ```typescript { report_id: string; // Report directory basename include_chart?: boolean; // Include equity chart data (default: false) } ``` ### Output schema ```typescript { success: boolean; report: { id: string; report_dir: string; ea: string; symbol: string; timeframe: string; from_date: string; to_date: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; total_trades: number; sharpe_ratio: number; recovery_factor: number; win_rate_pct: number; }; equity_chart?: Array<{date: string; equity: number}>; }; error?: string; } ``` --- ## `get_reports_summary` Aggregate stats: counts, averages, pass rates. **When to call:** To get overview statistics across all reports. ### Input schema ```typescript { ea?: string; // Filter by EA symbol?: string; // Filter by symbol from_date?: string; // Filter by date range to_date?: string; } ``` ### Output schema ```typescript { success: boolean; summary: { total_reports: number; avg_profit: number; avg_profit_factor: number; avg_dd_pct: number; profitable_count: number; pass_rate_pct: number; }; error?: string; } ``` --- ## `get_best_reports` Top N reports sorted by any metric (profit factor, drawdown, etc.). **When to call:** To find the best performing reports. ### Input schema ```typescript { sort_by: "net_profit" | "profit_factor" | "sharpe_ratio" | "recovery_factor" | "win_rate_pct"; order: "desc" | "asc"; // Default: "desc" limit?: number; // Max results (default: 10) ea?: string; symbol?: string; } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; ea: string; symbol: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; sharpe_ratio: number; recovery_factor: number; win_rate_pct: number; }; }>; error?: string; } ``` --- ## `search_reports_by_tags` Find reports by tags. **When to call:** To find reports tagged with specific keywords. ### Input schema ```typescript { tags: string[]; // Tags to search for match_all?: boolean; // Require all tags (default: false) limit?: number; } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; tags: string[]; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; }; }>; error?: string; } ``` --- ## `search_reports_by_date_range` Query by backtest date range. **When to call:** To find reports from a specific time period. ### Input schema ```typescript { from_date: string; // "YYYY-MM-DD" to_date: string; // "YYYY-MM-DD" limit?: number; } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; timestamp: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; }; }>; error?: string; } ``` --- ## `search_reports_by_notes` Full-text search in report notes. **When to call:** To find reports with specific notes. ### Input schema ```typescript { query: string; // Search query limit?: number; } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; notes: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; }; }>; error?: string; } ``` --- ## `get_reports_by_set_file` Find all reports using a specific .set file. **When to call:** To see all backtests run with a specific parameter set. ### Input schema ```typescript { set_file: string; // .set file name (without path) } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; set_file: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; }; }>; error?: string; } ``` --- ## `get_comparable_reports` Find comparable reports (same EA/symbol/timeframe). **When to call:** To find reports for comparison/analysis. ### Input schema ```typescript { ea: string; symbol: string; timeframe?: string; // Optional, uses default if omitted } ``` ### Output schema ```typescript { success: boolean; reports: Array<{ id: string; report_dir: string; from_date: string; to_date: string; metrics: { net_profit: number; profit_factor: number; max_dd_pct: number; total_trades: number; }; }>; error?: string; } ``` --- ## `export_deals_csv` Export deals for a report to a CSV file on demand. Deals are stored in the database — use this when you need a CSV file for external tools (Excel, pandas, etc.). **When to call:** When you need a `deals.csv` file. CSV is not written automatically after backtests anymore. ### Input schema ```typescript { report_id?: string; // Report ID to export (default: latest report) output_path?: string; // File path for CSV output (default: /deals.csv) } ``` ### Output schema ```typescript { success: boolean; report_id: string; deals_count: number; output_path: string; // Absolute path to the written CSV file } ``` ### Example ```json // Input — export latest report to default path {} // Input — export specific report to custom path { "report_id": "20260422_051041_DPS21_XAUUSDc_M5_1", "output_path": "/tmp/dps21_deals.csv" } // Output { "success": true, "report_id": "20260422_051041_DPS21_XAUUSDc_M5_1", "deals_count": 891, "output_path": "/Users/…/reports/20260422_051041_DPS21_XAUUSDc_M5_1/deals.csv" } ``` --- ## Granular Analytics — Common Input Pattern All granular analytics tools below (`analyze_monthly_pnl` through `analyze_efficiency`, plus `list_deals` and `search_deals_*`) share the same report resolution logic: ```typescript { report_id?: string; // Preferred: ID from list_reports report_dir?: string; // Legacy: filesystem path (looks up DB entry) // Omit both → uses the latest report automatically } ``` Deals are loaded from **SQLite DB**, not from CSV files. The `report_dir` parameter is kept for backward compatibility — if your report is in the DB, passing `report_dir` will resolve to its `report_id` automatically. --- ## `analyze_monthly_pnl` Monthly P/L breakdown only. **When to call:** To analyze performance by month without full analysis. ### Input schema ```typescript { report_id?: string; // Preferred: from list_reports report_dir?: string; // Legacy: path to report directory } // Omit all args to use the latest report ``` ### Output schema ```typescript { success: boolean; monthly_data: Array<{ month: string; // "2025-01" profit: number; trades: number; win_rate: number; }>; green_months: number; total_months: number; error?: string; } ``` --- ## `analyze_drawdown_events` Drawdown events and causes only. **When to call:** To identify and analyze drawdown periods. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; drawdowns: Array<{ start_date: string; end_date: string; depth_pct: number; duration_days: number; recovery_days: number; cause?: string; }>; worst_dd_event: { depth_pct: number; date: string; }; error?: string; } ``` --- ## `analyze_top_losses` Worst losing deals only. **When to call:** To identify the biggest losing trades for analysis. ### Input schema ```typescript { report_dir: string; top_n?: number; // Number of worst deals to return (default: 10) } ``` ### Output schema ```typescript { success: boolean; worst_deals: Array<{ entry_time: string; exit_time: string; profit: number; profit_pct: number; volume: number; comment?: string; }>; error?: string; } ``` --- ## `analyze_loss_sequences` Consecutive loss patterns only. **When to call:** To analyze losing streak patterns. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; loss_streaks: Array<{ start_index: number; end_index: number; length: number; total_loss: number; avg_loss: number; }>; max_loss_streak: { length: number; total_loss: number; }; error?: string; } ``` --- ## `analyze_position_pairs` Position hold time and P/L pairs. **When to call:** To analyze relationship between hold time and profit. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; pairs: Array<{ hold_time_minutes: number; profit: number; profit_pct: number; count: number; }>; correlation: number; error?: string; } ``` --- ## `analyze_direction_bias` Buy vs Sell performance. **When to call:** To analyze directional bias in trading. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; buy_trades: { count: number; profit: number; win_rate: number; }; sell_trades: { count: number; profit: number; win_rate: number; }; bias: "buy" | "sell" | "neutral"; error?: string; } ``` --- ## `analyze_streaks` Win/loss streak analysis. **When to call:** To analyze winning and losing streak patterns. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; win_streaks: Array<{ length: number; total_profit: number; }>; loss_streaks: Array<{ length: number; total_loss: number; }>; max_win_streak: number; max_loss_streak: number; error?: string; } ``` --- ## `analyze_concurrent_peak` Peak simultaneous positions. **When to call:** To analyze maximum position concurrency. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; max_concurrent: number; avg_concurrent: number; distribution: Array<{ concurrent_count: number; occurrences: number; }>; error?: string; } ``` --- ## `list_deals` List individual deals with filters (type, profit range, volume, dates). Loads from SQLite DB. **When to call:** To query individual trades with specific criteria. ### Input schema ```typescript { report_id?: string; // Preferred: from list_reports report_dir?: string; // Legacy: path to report directory // Omit all to use latest report deal_type?: "buy" | "sell" | "all"; min_profit?: number; max_profit?: number; min_volume?: number; max_volume?: number; from_date?: string; // "YYYY-MM-DD" to_date?: string; // "YYYY-MM-DD" limit?: number; } ``` ### Output schema ```typescript { success: boolean; deals: Array<{ entry_time: string; exit_time: string; type: "buy" | "sell"; profit: number; profit_pct: number; volume: number; comment?: string; magic?: number; }>; total: number; error?: string; } ``` --- ## `search_deals_by_comment` Full-text search in deal comments (e.g., "Layer #3"). Loads from SQLite DB. **When to call:** To find deals with specific comment patterns. ### Input schema ```typescript { report_id?: string; // Preferred: from list_reports report_dir?: string; // Legacy: path to report directory query: string; // Search pattern in comment field (required) limit?: number; } ``` ### Output schema ```typescript { success: boolean; deals: Array<{ entry_time: string; exit_time: string; type: "buy" | "sell"; profit: number; profit_pct: number; volume: number; comment: string; magic?: number; }>; total: number; error?: string; } ``` --- ## `search_deals_by_magic` Filter deals by EA magic number. **When to call:** To find trades from a specific EA (by magic number). ### Input schema ```typescript { report_dir: string; magic: number; // EA magic number to filter by limit?: number; } ``` ### Output schema ```typescript { success: boolean; deals: Array<{ entry_time: string; exit_time: string; type: "buy" | "sell"; profit: number; profit_pct: number; volume: number; comment?: string; magic: number; }>; total: number; error?: string; } ``` --- ## `analyze_profit_distribution` Profit histogram: small/medium/large wins and losses. **When to call:** To understand profit distribution across trade sizes. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; distribution: { small_wins: {count: number; avg_profit: number}; medium_wins: {count: number; avg_profit: number}; large_wins: {count: number; avg_profit: number}; small_losses: {count: number; avg_loss: number}; medium_losses: {count: number; avg_loss: number}; large_losses: {count: number; avg_loss: number}; }; error?: string; } ``` --- ## `analyze_time_performance` Performance by hour of day and day of week. **When to call:** To identify best/worst trading times. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; hourly_performance: Array<{ hour: number; profit: number; trades: number; win_rate: number; }>; daily_performance: Array<{ day: "Mon" | "Tue" | "Wed" | "Thu" | "Fri"; profit: number; trades: number; win_rate: number; }>; error?: string; } ``` --- ## `analyze_hold_time_distribution` Hold time buckets + correlation with profit. **When to call:** To analyze relationship between position duration and profit. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; buckets: Array<{ label: string; // e.g. "<5m", "5-15m", "15-60m", ">1h" min_minutes: number; max_minutes: number; count: number; avg_profit: number; win_rate: number; }>; correlation: number; error?: string; } ``` --- ## `analyze_layer_performance` Grid/martingale layer analysis from comments. **When to call:** To analyze performance by grid layer (for grid/martingale strategies). ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; layers: Array<{ layer: number; // e.g. "L1", "L2", "L3" count: number; profit: number; win_rate: number; avg_profit: number; }>; max_layer: number; l5_plus_count: number; error?: string; } ``` --- ## `analyze_volume_vs_profit` Volume correlation + performance by lot size. **When to call:** To analyze relationship between position size and profit. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; by_volume: Array<{ volume: number; count: number; avg_profit: number; win_rate: number; }>; correlation: number; optimal_volume: number; error?: string; } ``` --- ## `analyze_costs` Commission and swap impact on profitability. **When to call:** To understand the impact of trading costs. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; costs: { total_commission: number; total_swap: number; total_spread: number; avg_commission_per_trade: number; avg_swap_per_trade: number; }; cost_impact_pct: number; // Costs as % of gross profit error?: string; } ``` --- ## `analyze_efficiency` Profit per hour/day, annualized return, trade frequency. **When to call:** To measure overall trading efficiency. ### Input schema ```typescript { report_dir: string; } ``` ### Output schema ```typescript { success: boolean; efficiency: { profit_per_hour: number; profit_per_day: number; profit_per_trade: number; trades_per_day: number; annualized_return_pct: number; }; error?: string; } ``` --- ## Autonomous Loop Pattern The tools are designed to support a fully autonomous experiment → evaluate → promote → optimize loop: ``` 1. run_backtest(new_params) 2. compare_baseline(result, current_production) 3a. if winner: - archive_report(delete_after=true, verdict="winner") - promote_to_baseline(notes="...") - write_set_file(new_production.set) - run_optimization(new_production_set) - [wait for user signal] - get_optimization_results() - set_from_optimization(path=verify.set, params=results[0].params, template=prod.set) - verify top result: run_backtest(expert, set_file=verify.set, skip_compile=true) - if still beats baseline → goto step 1 3b. if loser: - archive_report(delete_after=true, verdict="loser", notes="root cause") - analyze_report(result) → find root cause - read_set_file() → inspect current params - propose parameter or code change → goto step 1 ``` No user confirmation needed between steps 1→2→3. The AI agent drives the full loop; the user monitors and signals when optimization completes (since that runs for hours). Every run is archived before the directory is deleted, so nothing is lost.