Files
Jyotisha/scripts/historical_event_backtest.py
2026-07-05 18:27:33 +08:00

205 lines
8.0 KiB
Python

#!/usr/bin/env python3
"""Reusable historical event backtest entrypoint built on strict workflow."""
from __future__ import annotations
import argparse
import json
import sys
from pathlib import Path
from typing import Any
ROOT = Path(__file__).resolve().parents[1]
if str(ROOT) not in sys.path:
sys.path.insert(0, str(ROOT))
import mcp_server
SUPPORTED_DOMAINS = {
"career": {
"route": "career",
"question": "请严格回测这条事业事件是否成立,并判断是职业状态、角色变化、升迁窗口还是项目兑现。",
},
"wealth": {
"route": "finance",
"question": "请严格回测这条财富事件是否成立,并判断更接近收入增长、到账、套现还是公众财富状态。",
},
"finance": {
"route": "finance",
"question": "请严格回测这条财富事件是否成立,并判断更接近收入增长、到账、套现还是公众财富状态。",
},
"marriage": {
"route": "relationship",
"question": "请严格回测这条婚恋事件是否成立,并判断是否达到正式关系或婚姻层。",
},
"relationship": {
"route": "relationship",
"question": "请严格回测这条婚恋事件是否成立,并判断是否达到正式关系或婚姻层。",
},
}
def _route_for_domain(domain: str) -> dict[str, str] | None:
return SUPPORTED_DOMAINS.get(str(domain).strip().lower())
def _load_payload(path: str) -> dict[str, Any]:
with open(path, "r", encoding="utf-8") as handle:
return json.load(handle)
def _event_result_class(
verdict: str | None,
blocked: bool,
expected_label: str | None,
actual_label: str | None,
) -> tuple[str, dict[str, Any]]:
if blocked:
return "blocked", {"reason": "strict_workflow_blocked"}
if verdict == "high_probability_window" and actual_label and (
not expected_label or expected_label == actual_label
):
return "strong_hit", {"reason": "supported_route_and_label"}
if verdict in {"high_probability_window", "moderate_probability_window"}:
if expected_label and actual_label and expected_label != actual_label:
return "weak_hit", {"reason": "label_mismatch_under_supported_route"}
return "weak_hit", {"reason": "supported_route_without_exact_label"}
if verdict == "weak_window_needs_confirmation":
return "weak_hit", {"reason": "weak_window_needs_confirmation"}
return "miss", {"reason": verdict or "insufficient_evidence"}
def _official_snapshot_summary(strict: dict[str, Any]) -> dict[str, Any]:
present = strict.get("present_evidence") or {}
official = present.get("vedastro_official_snapshot")
if not isinstance(official, dict):
return {"level": "missing", "status": "missing", "source": None}
return {
"level": official.get("level") or "missing",
"status": official.get("status"),
"source": official.get("source"),
}
def _source_priority_mode(strict: dict[str, Any]) -> str | None:
present = strict.get("present_evidence") or {}
source_priority = present.get("source_priority")
if not isinstance(source_priority, dict):
return None
return source_priority.get("mode")
def _run_supported_event(subject: dict[str, Any], event: dict[str, Any]) -> dict[str, Any]:
route_info = _route_for_domain(event.get("domain", ""))
if route_info is None:
return {
"id": event.get("id"),
"date": event.get("date"),
"domain": event.get("domain"),
"route": None,
"expected_label": event.get("expected_label"),
"actual_label": None,
"matched_expected_label": False,
"result_class": "unsupported_domain",
"boundary": {"reason": "route_not_yet_implemented_for_event_backtest"},
"official_snapshot": {"level": "missing", "status": "missing", "source": None},
"evidence": {"source_priority_mode": None, "confidence_cap": "unsupported"},
}
result = mcp_server.strict_workflow(
question=route_info["question"],
year=int(subject["year"]),
month=int(subject["month"]),
day=int(subject["day"]),
hour=int(subject["hour"]),
minute=int(subject["minute"]),
lat=float(subject["lat"]),
lon=float(subject["lon"]),
tz=float(subject["tz"]),
age=int(subject.get("age", 0)),
transit_date=str(event["date"]),
node_mode=str(subject.get("node_mode", "mean")),
)
strict = result.get("strict_workflow") if isinstance(result, dict) else {}
if not isinstance(strict, dict):
strict = {}
judgement = strict.get("event_judgement") if isinstance(strict.get("event_judgement"), dict) else {}
actual_label = judgement.get("dominant_label")
expected_label = event.get("expected_label")
verdict = judgement.get("verdict")
blocked = bool(strict.get("blocked"))
result_class, boundary = _event_result_class(verdict, blocked, expected_label, actual_label)
return {
"id": event.get("id"),
"date": event.get("date"),
"domain": event.get("domain"),
"route": route_info["route"],
"expected_label": expected_label,
"actual_label": actual_label,
"matched_expected_label": bool(expected_label and expected_label == actual_label),
"result_class": result_class,
"boundary": boundary,
"official_snapshot": _official_snapshot_summary(strict),
"evidence": {
"verdict": verdict,
"score": judgement.get("score"),
"confidence_cap": strict.get("confidence_cap"),
"missing_evidence": strict.get("missing_evidence") or [],
"blocked_items": strict.get("blocked_items") or [],
"conflicts": strict.get("conflicts") or [],
"adjudication_stages": strict.get("adjudication_stages") or {},
"multi_reference_reading_summary": strict.get("multi_reference_reading_summary") or {},
"main_conflicts": strict.get("main_conflicts") or strict.get("conflicts") or [],
"source_priority_mode": _source_priority_mode(strict),
"primary_drivers": judgement.get("primary_drivers") or [],
"secondary_context": judgement.get("secondary_context") or [],
"technique_audit": strict.get("technique_audit") or [],
"life_event_graph": strict.get("life_event_graph") or {},
},
}
def build_report(payload: dict[str, Any]) -> dict[str, Any]:
subject = payload.get("subject") or {}
events = payload.get("events") or []
rows = [_run_supported_event(subject, event) for event in events]
summary = {
"total_events": len(rows),
"strong_hits": sum(1 for row in rows if row["result_class"] == "strong_hit"),
"weak_hits": sum(1 for row in rows if row["result_class"] == "weak_hit"),
"misses": sum(1 for row in rows if row["result_class"] == "miss"),
"blocked_events": sum(1 for row in rows if row["result_class"] == "blocked"),
"unsupported_domain_events": sum(1 for row in rows if row["result_class"] == "unsupported_domain"),
"official_primary_events": sum(
1 for row in rows if row["official_snapshot"].get("level") == "primary"
),
}
return {
"scope": "historical_event_backtest",
"summary": summary,
"boundary": (
"This report measures whether current strict routes can support supplied historical events. "
"Unsupported domains and blocked routes must not be overstated as validated predictive accuracy."
),
"events": rows,
}
def main() -> int:
parser = argparse.ArgumentParser(description="Run reusable historical-event backtest")
parser.add_argument("--input", required=True, help="Path to local backtest payload JSON")
args = parser.parse_args()
report = build_report(_load_payload(args.input))
print(json.dumps(report, ensure_ascii=False, indent=2))
return 0
if __name__ == "__main__":
raise SystemExit(main())