from __future__ import annotations import argparse import json import sys from hashlib import sha256 from pathlib import Path from typing import Any ROOT = Path(__file__).resolve().parents[1] DEFAULT_JSON = ROOT / "GatherTradingData.json" DEFAULT_OUT = ROOT / "Temp" / "cash_recovery_optimizer_v4.json" FORMULA_ID = "CASH_RECOVERY_OPTIMIZER_V4" if sys.stdout.encoding and sys.stdout.encoding.lower() not in ("utf-8", "utf8"): sys.stdout = open(sys.stdout.fileno(), mode="w", encoding="utf-8", buffering=1) def _load(path: Path) -> dict[str, Any]: if not path.exists(): return {} try: obj = json.loads(path.read_text(encoding="utf-8")) except Exception: return {} return obj if isinstance(obj, dict) else {} def _extract_harness_root(payload: dict[str, Any]) -> dict[str, Any]: h_apex = payload.get("hApex") data_apex = ((payload.get("data") or {}).get("_harness_context")) if isinstance(payload.get("data"), dict) else None if isinstance(h_apex, dict) and isinstance(data_apex, dict): merged = dict(data_apex) merged.update(h_apex) return merged if isinstance(h_apex, dict): return h_apex if isinstance(data_apex, dict): return data_apex return payload def _canonical(obj: Any) -> str: return json.dumps(obj, ensure_ascii=False, sort_keys=True, separators=(",", ":")) def _hash_text(text: str) -> str: return sha256(text.encode("utf-8")).hexdigest()[:16] def _rows(v: Any) -> list[dict[str, Any]]: if isinstance(v, list): return [x for x in v if isinstance(x, dict)] if isinstance(v, str) and v.strip(): try: return _rows(json.loads(v)) except Exception: return [] if isinstance(v, dict): for key in ("rows", "data", "tickers"): candidate = v.get(key) if isinstance(candidate, list): return [x for x in candidate if isinstance(x, dict)] return [] def main() -> int: ap = argparse.ArgumentParser(description="Build deterministic cash recovery optimizer v4.") ap.add_argument("--json", default=str(DEFAULT_JSON)) ap.add_argument("--out", default=str(DEFAULT_OUT)) args = ap.parse_args() json_path = Path(args.json) out_path = Path(args.out) if not json_path.is_absolute(): json_path = ROOT / json_path if not out_path.is_absolute(): out_path = ROOT / out_path payload = _load(json_path) hctx = _extract_harness_root(payload) scr7_path = ROOT / "Temp" / "smart_cash_recovery_v7_authoritative.json" scr6_path = ROOT / "Temp" / "smart_cash_recovery_v6.json" sell_audit_path = ROOT / "Temp" / "sell_engine_audit_v1.json" scr7 = _load(scr7_path) scr6 = _load(scr6_path) sell_audit = _load(sell_audit_path) selected_combo = _rows(scr7.get("selected_sell_combo")) or _rows(scr6.get("selected_sell_combo")) selected_sell_combo_source = "SMART_CASH_RECOVERY_V7_AUTH" if _rows(scr7.get("selected_sell_combo")) else "SMART_CASH_RECOVERY_V6" # v7 authoritative artifact already contains the K2 50/50 redesign with raw damage <= 10. value_damage_pct_avg = ( scr7.get("optimized_value_damage_pct_avg") if scr7.get("optimized_value_damage_pct_avg") is not None else scr7.get("raw_value_damage_pct_avg") if scr7.get("raw_value_damage_pct_avg") is not None else scr6.get("value_damage_pct_avg") ) cash_shortfall_min_krw = scr7.get("cash_shortfall_min_krw") or scr6.get("cash_shortfall_min_krw") cash_shortfall_covered = bool(scr7.get("cash_shortfall_covered") if scr7 else scr6.get("cash_shortfall_covered")) execution_allowed = bool(scr7.get("execution_allowed") if scr7 else scr6.get("execution_allowed")) raw_damage_pct = ( float(selected_combo[0].get("raw_value_damage_pct") or selected_combo[0].get("adjusted_value_damage_pct") or 0.0) if selected_combo else float(scr6.get("value_damage_pct_avg") or 0.0) ) adjusted_damage_pct = ( float(selected_combo[0].get("adjusted_value_damage_pct") or selected_combo[0].get("raw_value_damage_pct") or 0.0) if selected_combo else raw_damage_pct ) sell_authority_conflict_count = 0 if isinstance(sell_audit.get("scr_plan"), dict): audit_combo_count = int(sell_audit["scr_plan"].get("combo_count") or 0) if audit_combo_count != len(selected_combo): sell_authority_conflict_count += 1 if any(not isinstance(row, dict) for row in selected_combo): sell_authority_conflict_count += 1 result = { "formula_id": FORMULA_ID, "status": "PASS" if sell_authority_conflict_count == 0 else "WARN", "execution_allowed": execution_allowed, "selected_sell_combo_source": selected_sell_combo_source, "sell_authority_conflict_count": sell_authority_conflict_count, "selected_sell_combo": selected_combo, "cash_shortfall_min_krw": cash_shortfall_min_krw, "cash_shortfall_covered": cash_shortfall_covered, "value_damage_pct_avg": value_damage_pct_avg, "value_damage_raw_pct": round(raw_damage_pct, 2), "value_damage_adjusted_pct": round(adjusted_damage_pct, 2), "value_damage_pct_avg_max": 10.0, "sell_engine_audit_gate": sell_audit.get("gate", "MISSING"), "optimizer_scr_divergence_count": sell_authority_conflict_count, "source": { "source_json": str(json_path), "smart_cash_recovery_v7_authoritative_json": str(scr7_path), "smart_cash_recovery_v6_json": str(scr6_path), "sell_engine_audit_v1_json": str(sell_audit_path), "generated_by_llm": False, }, "input_hash": _hash_text(_canonical(payload) + _canonical(scr6) + _canonical(sell_audit)), } out_path.parent.mkdir(parents=True, exist_ok=True) out_path.write_text(json.dumps(result, ensure_ascii=False, indent=2), encoding="utf-8") print(json.dumps(result, ensure_ascii=False, indent=2)) return 0 if __name__ == "__main__": raise SystemExit(main())