fix: remove stale deals.csv references, add extract+store to launch_backtest
- FilePaths struct: remove deals_csv/deals_json fields (deals go to DB only) - save_metadata: stop writing stale CSV/JSON paths to pipeline_metadata.json - get_backtest_status: remove deals.csv artifact check (was unused in logic) - get_backtest_crash_info: check DB deal count and metrics.json instead of deals.csv - export_report: remove unused _deals_path variable - launch_backtest: monitor_backtest_completion now calls extract_and_store when report found — extracts metrics+deals, registers report in DB, deletes htm file Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -289,7 +289,7 @@ pub fn tool_get_wine_prefix_info() -> Value {
|
||||
pub fn tool_get_backtest_crash_info() -> Value {
|
||||
json!({
|
||||
"name": "get_backtest_crash_info",
|
||||
"description": "Investigate backtest crashes/failures. Checks for incomplete markers, missing deals.csv, error logs. Can scan recent reports.",
|
||||
"description": "Investigate backtest crashes/failures. Checks for incomplete markers, missing metrics.json, DB deal count, error logs. Can scan recent reports.",
|
||||
"inputSchema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
|
||||
@@ -355,7 +355,6 @@ pub async fn handle_get_backtest_status(_config: &Config, args: &Value) -> Resul
|
||||
|
||||
// Check for completed artifacts
|
||||
let metrics_exists = report_path.join("metrics.json").exists();
|
||||
let deals_exists = report_path.join("deals.csv").exists();
|
||||
let is_complete = stage == "DONE" || (report_found && metrics_exists);
|
||||
|
||||
// Calculate elapsed time if job exists
|
||||
@@ -400,7 +399,6 @@ pub async fn handle_get_backtest_status(_config: &Config, args: &Value) -> Resul
|
||||
"mt5_running": mt5_running,
|
||||
"report_found": report_found,
|
||||
"metrics_extracted": metrics_exists,
|
||||
"deals_extracted": deals_exists,
|
||||
"elapsed_seconds": elapsed_seconds,
|
||||
"message": message,
|
||||
"job": job.map(|j| {
|
||||
|
||||
@@ -3,6 +3,7 @@ use serde_json::{json, Value};
|
||||
use std::fs;
|
||||
use std::path::{Path, PathBuf};
|
||||
use crate::models::Config;
|
||||
use crate::storage::ReportDb;
|
||||
|
||||
/// Validate that `user_path` resolves to a location within `allowed_base`.
|
||||
/// Returns the canonicalized absolute path on success.
|
||||
@@ -785,7 +786,6 @@ pub async fn handle_export_report(_config: &Config, args: &Value) -> Result<Valu
|
||||
|
||||
let path = Path::new(report_dir);
|
||||
let metrics_path = path.join("metrics.json");
|
||||
let _deals_path = path.join("deals.csv");
|
||||
|
||||
// Read metrics
|
||||
let metrics: Value = if metrics_path.exists() {
|
||||
@@ -1640,21 +1640,33 @@ pub async fn handle_get_backtest_crash_info(config: &Config, args: &Value) -> Re
|
||||
}
|
||||
}
|
||||
|
||||
// Check if deals.csv is missing or empty
|
||||
let deals_csv = path.join("deals.csv");
|
||||
if !deals_csv.exists() {
|
||||
result["crashes_found"].as_array_mut().unwrap().push(json!({
|
||||
"report_dir": dir,
|
||||
"type": "missing_deals",
|
||||
"reason": "deals.csv not found - backtest likely failed",
|
||||
}));
|
||||
} else if let Ok(meta) = deals_csv.metadata() {
|
||||
if meta.len() < 100 {
|
||||
result["crashes_found"].as_array_mut().unwrap().push(json!({
|
||||
"report_dir": dir,
|
||||
"type": "empty_deals",
|
||||
"reason": "deals.csv is nearly empty - no trades were made",
|
||||
}));
|
||||
// Check deal count in DB
|
||||
let db = ReportDb::new(&Config::db_path());
|
||||
if db.init().is_ok() {
|
||||
match db.get_by_report_dir(dir) {
|
||||
Ok(Some(entry)) => {
|
||||
let deal_count = db.get_deals(&entry.id)
|
||||
.map(|d| d.len())
|
||||
.unwrap_or(0);
|
||||
if deal_count == 0 {
|
||||
result["crashes_found"].as_array_mut().unwrap().push(json!({
|
||||
"report_dir": dir,
|
||||
"type": "empty_deals",
|
||||
"reason": "No deals stored in DB - EA did not trade or extraction failed",
|
||||
}));
|
||||
}
|
||||
}
|
||||
Ok(None) | Err(_) => {
|
||||
// Not in DB at all means extraction never completed
|
||||
let metrics_exists = path.join("metrics.json").exists();
|
||||
if !metrics_exists {
|
||||
result["crashes_found"].as_array_mut().unwrap().push(json!({
|
||||
"report_dir": dir,
|
||||
"type": "missing_deals",
|
||||
"reason": "Report not found in DB and no metrics.json - backtest likely crashed before extraction",
|
||||
}));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1676,10 +1688,10 @@ pub async fn handle_get_backtest_crash_info(config: &Config, args: &Value) -> Re
|
||||
if let Ok(modified) = meta.modified() {
|
||||
if modified >= cutoff {
|
||||
// Check for failure indicators
|
||||
let has_deals = path.join("deals.csv").exists();
|
||||
let has_metrics = path.join("metrics.json").exists();
|
||||
let has_incomplete = path.join(".incomplete").exists();
|
||||
|
||||
if !has_deals || has_incomplete {
|
||||
|
||||
if !has_metrics || has_incomplete {
|
||||
failures += 1;
|
||||
}
|
||||
}
|
||||
@@ -1701,7 +1713,7 @@ pub async fn handle_get_backtest_crash_info(config: &Config, args: &Value) -> Re
|
||||
|
||||
if types.contains(&"missing_deals".to_string()) {
|
||||
result["common_patterns"].as_array_mut().unwrap().push(
|
||||
json!("Missing deals.csv suggests MT5 crashed during backtest")
|
||||
json!("Report not in DB and no metrics.json suggests MT5 crashed before extraction completed")
|
||||
);
|
||||
}
|
||||
if types.contains(&"incomplete".to_string()) {
|
||||
|
||||
Reference in New Issue
Block a user