**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`.
**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.
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)
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.",
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.
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
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'",
| `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
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)
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
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
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."
"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 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)
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
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)
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")
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
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.
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.