feat: complete Rust migration with modular architecture

Major changes:
- Migrate Python/shell scripts to Rust modules:
  - analytics/extract.py → src/analytics/extract.rs (ReportExtractor)
  - analytics/analyze.py → src/analytics/analyze.rs (DealAnalyzer)
  - scripts/mqlcompile.sh → src/compile/mql_compiler.rs (MqlCompiler)
  - scripts/backtest_pipeline.sh → src/pipeline/backtest.rs (BacktestPipeline)

- New modular structure:
  - src/models/ - Config, Deal, Metrics, Report structs
  - src/analytics/ - Report parsing and deal analysis
  - src/compile/ - MQL5 compilation via Wine
  - src/pipeline/ - 5-stage backtest orchestration
  - src/tools/ - 27 MCP tool definitions and handlers

- Remove PyInstaller setup (now pure Rust)
- Remove migrated shell scripts (backtest_pipeline.sh, mqlcompile.sh)
- Add GitHub Actions CI/CD for macOS & Linux releases
- Update all documentation for Rust architecture

Binary size: 4.3MB (no Python dependencies)
Tools: 27 MCP tools fully functional
This commit is contained in:
Devid HW
2026-04-18 15:07:08 +07:00
parent 41792b1292
commit a3b046c68f
37 changed files with 3809 additions and 1587 deletions
+495
View File
@@ -0,0 +1,495 @@
use serde_json::{json, Value};
pub fn get_tools_list() -> Value {
let tools = vec![
tool_run_backtest(),
tool_run_optimization(),
tool_get_optimization_results(),
tool_analyze_report(),
tool_compare_baseline(),
tool_compile_ea(),
tool_verify_setup(),
tool_list_symbols(),
tool_list_experts(),
tool_get_backtest_status(),
tool_get_optimization_status(),
tool_prune_reports(),
tool_list_reports(),
tool_tail_log(),
tool_cache_status(),
tool_clean_cache(),
tool_read_set_file(),
tool_write_set_file(),
tool_patch_set_file(),
tool_clone_set_file(),
tool_set_from_optimization(),
tool_diff_set_files(),
tool_describe_sweep(),
tool_list_set_files(),
tool_list_jobs(),
tool_archive_report(),
tool_archive_all_reports(),
tool_get_history(),
tool_promote_to_baseline(),
tool_annotate_history(),
];
json!(tools)
}
fn tool_run_backtest() -> Value {
json!({
"name": "run_backtest",
"description": "Run a complete MT5 backtest pipeline: compile → clean cache → backtest → extract → analyze",
"inputSchema": {
"type": "object",
"required": ["expert"],
"properties": {
"expert": { "type": "string", "description": "EA name without path or extension" },
"symbol": { "type": "string", "description": "Trading symbol" },
"from_date": { "type": "string", "description": "Start date YYYY.MM.DD" },
"to_date": { "type": "string", "description": "End date YYYY.MM.DD" },
"timeframe": { "type": "string", "enum": ["M1", "M5", "M15", "M30", "H1", "H4", "D1"] },
"deposit": { "type": "integer" },
"model": { "type": "integer", "enum": [0, 1, 2] },
"set_file": { "type": "string", "description": "Path to .set parameter file" },
"skip_compile": { "type": "boolean" },
"skip_clean": { "type": "boolean" },
"skip_analyze": { "type": "boolean" },
"deep": { "type": "boolean", "description": "Run deep analysis" },
"shutdown": { "type": "boolean", "description": "Close MT5 after backtest" },
"kill_existing": { "type": "boolean" },
"timeout": { "type": "integer" },
"gui": { "type": "boolean" }
}
}
})
}
fn tool_run_optimization() -> Value {
json!({
"name": "run_optimization",
"description": "Launch MT5 genetic parameter optimization",
"inputSchema": {
"type": "object",
"required": ["expert", "set_file", "from_date", "to_date"],
"properties": {
"expert": { "type": "string" },
"set_file": { "type": "string" },
"symbol": { "type": "string" },
"from_date": { "type": "string" },
"to_date": { "type": "string" },
"deposit": { "type": "integer" }
}
}
})
}
fn tool_get_optimization_results() -> Value {
json!({
"name": "get_optimization_results",
"description": "Parse completed MT5 optimization results",
"inputSchema": {
"type": "object",
"properties": {
"job_id": { "type": "string" },
"report_file": { "type": "string" },
"dd_threshold": { "type": "number" },
"top_n": { "type": "integer" }
}
}
})
}
fn tool_analyze_report() -> Value {
json!({
"name": "analyze_report",
"description": "Read and summarize a completed backtest report",
"inputSchema": {
"type": "object",
"properties": {
"report_dir": { "type": "string" }
}
}
})
}
fn tool_compare_baseline() -> Value {
json!({
"name": "compare_baseline",
"description": "Compare a backtest report against a baseline",
"inputSchema": {
"type": "object",
"required": ["baseline"],
"properties": {
"baseline": {
"type": "object",
"properties": {
"net_profit": { "type": "number" },
"max_dd_pct": { "type": "number" },
"total_trades": { "type": "integer" }
}
},
"report_dir": { "type": "string" },
"promote_dd_limit": { "type": "number" }
}
}
})
}
fn tool_compile_ea() -> Value {
json!({
"name": "compile_ea",
"description": "Compile an MQL5 Expert Advisor via MetaEditor",
"inputSchema": {
"type": "object",
"required": ["expert_path"],
"properties": {
"expert_path": { "type": "string" }
}
}
})
}
fn tool_verify_setup() -> Value {
json!({
"name": "verify_setup",
"description": "Verify MT5-Quant environment",
"inputSchema": { "type": "object", "properties": {} }
})
}
fn tool_list_symbols() -> Value {
json!({
"name": "list_symbols",
"description": "List symbols with local tick history",
"inputSchema": {
"type": "object",
"properties": {
"server": { "type": "string" }
}
}
})
}
fn tool_list_experts() -> Value {
json!({
"name": "list_experts",
"description": "List all compiled Expert Advisors",
"inputSchema": {
"type": "object",
"properties": {
"filter": { "type": "string" }
}
}
})
}
fn tool_get_backtest_status() -> Value {
json!({
"name": "get_backtest_status",
"description": "Check progress of a running backtest pipeline",
"inputSchema": {
"type": "object",
"properties": {
"report_dir": { "type": "string" }
}
}
})
}
fn tool_get_optimization_status() -> Value {
json!({
"name": "get_optimization_status",
"description": "Check if an optimization job is running",
"inputSchema": {
"type": "object",
"required": ["job_id"],
"properties": {
"job_id": { "type": "string" }
}
}
})
}
fn tool_prune_reports() -> Value {
json!({
"name": "prune_reports",
"description": "Delete old backtest report directories",
"inputSchema": {
"type": "object",
"properties": {
"keep_last": { "type": "integer" }
}
}
})
}
fn tool_list_reports() -> Value {
json!({
"name": "list_reports",
"description": "List all backtest report directories",
"inputSchema": {
"type": "object",
"properties": {
"limit": { "type": "integer" },
"include_opt": { "type": "boolean" }
}
}
})
}
fn tool_tail_log() -> Value {
json!({
"name": "tail_log",
"description": "Read the last N lines of a log file",
"inputSchema": {
"type": "object",
"properties": {
"n": { "type": "integer" },
"filter": { "type": "string", "enum": ["all", "errors", "warnings"] },
"log_file": { "type": "string" },
"report_dir": { "type": "string" },
"job_id": { "type": "string" }
}
}
})
}
fn tool_cache_status() -> Value {
json!({
"name": "cache_status",
"description": "Show MT5 tester cache size breakdown",
"inputSchema": { "type": "object", "properties": {} }
})
}
fn tool_clean_cache() -> Value {
json!({
"name": "clean_cache",
"description": "Delete MT5 tester cache files",
"inputSchema": {
"type": "object",
"properties": {
"symbol": { "type": "string" },
"dry_run": { "type": "boolean" }
}
}
})
}
fn tool_read_set_file() -> Value {
json!({
"name": "read_set_file",
"description": "Parse an MT5 .set parameter file",
"inputSchema": {
"type": "object",
"required": ["path"],
"properties": {
"path": { "type": "string" }
}
}
})
}
fn tool_write_set_file() -> Value {
json!({
"name": "write_set_file",
"description": "Write an MT5 .set parameter file",
"inputSchema": {
"type": "object",
"required": ["path", "params"],
"properties": {
"path": { "type": "string" },
"params": { "type": "object" }
}
}
})
}
fn tool_patch_set_file() -> Value {
json!({
"name": "patch_set_file",
"description": "Modify specific parameters in a .set file",
"inputSchema": {
"type": "object",
"required": ["path", "patches"],
"properties": {
"path": { "type": "string" },
"patches": { "type": "object" }
}
}
})
}
fn tool_clone_set_file() -> Value {
json!({
"name": "clone_set_file",
"description": "Copy a .set file to a new path with optional overrides",
"inputSchema": {
"type": "object",
"required": ["source", "destination"],
"properties": {
"source": { "type": "string" },
"destination": { "type": "string" },
"overrides": { "type": "object" }
}
}
})
}
fn tool_set_from_optimization() -> Value {
json!({
"name": "set_from_optimization",
"description": "Generate .set file from optimization result params",
"inputSchema": {
"type": "object",
"required": ["path", "params"],
"properties": {
"path": { "type": "string" },
"params": { "type": "object" },
"template": { "type": "string" },
"sweep": { "type": "object" }
}
}
})
}
fn tool_diff_set_files() -> Value {
json!({
"name": "diff_set_files",
"description": "Compare two .set files",
"inputSchema": {
"type": "object",
"required": ["path_a", "path_b"],
"properties": {
"path_a": { "type": "string" },
"path_b": { "type": "string" }
}
}
})
}
fn tool_describe_sweep() -> Value {
json!({
"name": "describe_sweep",
"description": "Show .set file sweep configuration",
"inputSchema": {
"type": "object",
"required": ["path"],
"properties": {
"path": { "type": "string" }
}
}
})
}
fn tool_list_set_files() -> Value {
json!({
"name": "list_set_files",
"description": "List all .set files in tester profiles directory",
"inputSchema": {
"type": "object",
"properties": {
"ea": { "type": "string" }
}
}
})
}
fn tool_list_jobs() -> Value {
json!({
"name": "list_jobs",
"description": "List all optimization jobs",
"inputSchema": {
"type": "object",
"properties": {
"include_done": { "type": "boolean" }
}
}
})
}
fn tool_archive_report() -> Value {
json!({
"name": "archive_report",
"description": "Convert report to JSON and append to history",
"inputSchema": {
"type": "object",
"properties": {
"report_dir": { "type": "string" },
"delete_after": { "type": "boolean" },
"notes": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } },
"verdict": { "type": "string", "enum": ["winner", "loser", "marginal", "reference"] }
}
}
})
}
fn tool_archive_all_reports() -> Value {
json!({
"name": "archive_all_reports",
"description": "Bulk-archive all backtest reports",
"inputSchema": {
"type": "object",
"properties": {
"delete_after": { "type": "boolean" },
"keep_last": { "type": "integer" },
"dry_run": { "type": "boolean" }
}
}
})
}
fn tool_get_history() -> Value {
json!({
"name": "get_history",
"description": "Query backtest history with filters",
"inputSchema": {
"type": "object",
"properties": {
"ea": { "type": "string" },
"symbol": { "type": "string" },
"tag": { "type": "string" },
"verdict": { "type": "string" },
"sort_by": { "type": "string" },
"limit": { "type": "integer" },
"include_monthly": { "type": "boolean" }
}
}
})
}
fn tool_promote_to_baseline() -> Value {
json!({
"name": "promote_to_baseline",
"description": "Promote a backtest result to baseline",
"inputSchema": {
"type": "object",
"properties": {
"history_id": { "type": "string" },
"report_dir": { "type": "string" },
"notes": { "type": "string" }
}
}
})
}
fn tool_annotate_history() -> Value {
json!({
"name": "annotate_history",
"description": "Add notes/verdict/tags to a history entry",
"inputSchema": {
"type": "object",
"required": ["history_id"],
"properties": {
"history_id": { "type": "string" },
"notes": { "type": "string" },
"tags": { "type": "array", "items": { "type": "string" } },
"add_tags": { "type": "array", "items": { "type": "string" } },
"verdict": { "type": "string", "enum": ["winner", "loser", "marginal", "reference"] }
}
}
})
}