| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122 |
- from __future__ import annotations
- import json
- from dataclasses import asdict
- from pathlib import Path
- import pandas as pd
- from dragon_branch_configs import alpha_first_selective_veto_config
- def _load_csv(base_dir: Path, name: str) -> pd.DataFrame:
- return pd.read_csv(base_dir / name, encoding="utf-8-sig")
- def _format_pct(value: float) -> str:
- if pd.isna(value):
- return "NA"
- if value == float("inf"):
- return "inf"
- return f"{value:.2%}"
- def _format_num(value: float) -> str:
- if pd.isna(value):
- return "NA"
- if value == float("inf"):
- return "inf"
- return f"{value:.2f}"
- def main() -> None:
- base_dir = Path(__file__).resolve().parent
- audit = _load_csv(base_dir, "dragon_short_holding_audit.csv")
- pressure = _load_csv(base_dir, "dragon_short_holding_family_pressure.csv")
- experiments = _load_csv(base_dir, "dragon_short_holding_experiments.csv")
- best = experiments[experiments["experiment"] != "baseline_alpha_first"].sort_values(
- ["avg_return", "profit_factor"], ascending=[False, False]
- ).iloc[0]
- winner_config = alpha_first_selective_veto_config().with_updates(
- glued_selective_hot_c1_min=40.0,
- glued_selective_hot_b1_min=0.10,
- glued_selective_low_c1_min=23.0,
- glued_selective_low_c1_max=28.0,
- glued_selective_low_b1_max=0.02,
- )
- snapshot = asdict(winner_config)
- snapshot["disabled_rules"] = sorted(winner_config.disabled_rules)
- (base_dir / "dragon_short_holding_candidate_config.json").write_text(
- json.dumps(snapshot, indent=2, ensure_ascii=False) + "\n",
- encoding="utf-8",
- )
- root_summary = (
- audit.groupby("failure_root")
- .agg(trades=("buy_date", "count"), avg_return=("return_pct", "mean"))
- .reset_index()
- .sort_values("trades", ascending=False)
- )
- top_entry_drag = pressure[pressure["group_type"] == "entry_family"].sort_values("drag_score", ascending=False).head(5)
- top_path_drag = pressure[pressure["group_type"] == "path_combo"].sort_values("drag_score", ascending=False).head(5)
- lines = [
- "# Dragon Short Holding Master Review",
- "",
- "- Branch under audit: `alpha_first_selective_veto`.",
- "- Goal: identify the dominant short-holding drag and the next narrow optimization target.",
- "",
- "## Audit Conclusions",
- f"- audited short trades: `{int(len(audit))}`",
- ]
- for _, row in root_summary.iterrows():
- lines.append(
- f"- failure_root `{row['failure_root']}`: trades `{int(row['trades'])}`, avg_return `{_format_pct(float(row['avg_return']))}`"
- )
- lines.extend(["", "## Lead Drag Families"])
- for _, row in top_entry_drag.iterrows():
- lines.append(
- f"- `{row['holding_bucket']} / {row['entry_family']}`: trades `{int(row['trades'])}`, "
- f"avg_return `{_format_pct(float(row['avg_return']))}`, drag_score `{row['drag_score']:.4f}`"
- )
- lines.extend(["", "## Lead Drag Paths"])
- for _, row in top_path_drag.iterrows():
- lines.append(
- f"- `{row['holding_bucket']} / {row['entry_family']} -> {row['sell_reason']}`: trades `{int(row['trades'])}`, "
- f"avg_return `{_format_pct(float(row['avg_return']))}`, drag_score `{row['drag_score']:.4f}`"
- )
- lines.extend(
- [
- "",
- "## Experiment Winner",
- f"- best branch: `{best['experiment']}`",
- f"- trades: `{int(best['trades'])}`",
- f"- avg_return: `{_format_pct(float(best['avg_return']))}`",
- f"- profit_factor: `{_format_num(float(best['profit_factor']))}`",
- f"- short_avg_return: `{_format_pct(float(best['short_avg_return']))}`",
- f"- `00-05d`: `{_format_pct(float(best['short_00_05d_avg_return']))}`",
- f"- `06-10d`: `{_format_pct(float(best['short_06_10d_avg_return']))}`",
- f"- real BUY / SELL overlap: `{int(best['real_buy_overlap'])}/{int(best['real_sell_overlap'])}`",
- "",
- "## Interpretation",
- "- `post_sell_rebound_buy` is not the main short-holding problem in this pack; disabling it hurts or adds little value.",
- "- The dominant short-holding drag is `glued_buy`, especially in mid-regime short exits.",
- "- The winning branch confirms that narrow glued-entry veto is more valuable than attacking `post_sell_rebound_buy` first.",
- "- The most useful next alpha-first direction is now a glued-focused selective-veto branch, not a post-sell-rebound branch.",
- "",
- "## Candidate Config",
- "- Snapshot file: `dragon_short_holding_candidate_config.json`.",
- "- This candidate should remain alpha-first research only until a branch-level governance decision upgrades it.",
- ]
- )
- (base_dir / "dragon_short_holding_master_review.md").write_text("\n".join(lines) + "\n", encoding="utf-8")
- if __name__ == "__main__":
- main()
|