Files
mt5-quant/docs/MCP_TOOLS.md
T

3930 lines
86 KiB
Markdown
Raw Normal View History

# 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=<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_<timestamp>.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<string, number | boolean>; // All swept parameter values
}>;
convergence_analysis: {
top_10_agreement: Record<string, string>; // Params same across top 10 = strong signal
high_variance_params: string[]; // Params that vary in top 10 = uncertain
};
recommendation: {
best_params: Record<string, number | boolean>;
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<string, number>;
// grid: { L1: n, L2: n, …, "L8+": n }
// others: {} (empty — no depth_re in profile)
grid_depth_histogram: Record<string, number>;
// 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<string, { total: number; win_rate: number }>;
// 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; // 023
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<string, {
value: string; // Current / default value
from?: string; // Sweep start (present for optimization params)
to?: string; // Sweep end
step?: string; // Sweep step
optimize?: boolean; // True if ||Y flag is set
}>;
}
```
### 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<string,
| string | number // Simple fixed value
| {
value: string | number;
from?: string | number; // Include for optimization sweep
to?: string | number;
step?: string | number;
optimize?: boolean; // true → ||Y, false → ||N (default: false)
}
>;
}
```
### 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<string,
| string | number // scalar → only updates value, keeps existing sweep config
| {
value?: string | number;
from?: string | number;
to?: string | number;
step?: string | number;
optimize?: boolean;
}
>;
}
```
### 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<string, string | number | { value; from?; to?; step?; optimize? }>;
}
```
### 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<string, string | number>;
// 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<string, { from: number; to: number; step: number; optimize?: boolean }>;
// 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: 18h 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: 18h 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: <report_dir>"
}
```
---
## `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: <report_dir>/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.