p05 / backtest /make_chart.py
goldlab
D28 补漏:模拟器预设/退出线下拉落地平滑3;组合预设解耦回 raw
0580e8e
Raw History Blame Contribute Delete
2.24 kB
"""净值曲线图:策略 vs 买入持有(对数轴),标注逻辑退出区间与 2026 OOS 分界。
用法:python make_chart.py [tag] (默认 final,读 results/<tag>/{curve.csv,stats.json})
"""
import csv
import json
import sys
from pathlib import Path
import matplotlib
matplotlib.use("Agg")
import matplotlib.pyplot as plt # noqa: E402
matplotlib.rcParams["font.sans-serif"] = ["Microsoft YaHei", "SimHei", "DejaVu Sans"]
matplotlib.rcParams["axes.unicode_minus"] = False
HERE = Path(__file__).resolve().parent
tag = sys.argv[1] if len(sys.argv) > 1 else "final"
res = HERE / "results" / tag
rows = list(csv.DictReader(open(res / "curve.csv", encoding="utf-8")))
dates = [r["date"] for r in rows]
V = [float(r["V"]) for r in rows]
B = [float(r["bh_V"]) for r in rows]
stats = json.loads((res / "stats.json").read_text(encoding="utf-8"))
exit_spans = stats["exit_spans"]
has_oos = "oos" in stats
fig, ax = plt.subplots(figsize=(11.5, 6), dpi=150)
ax.plot(dates, B, lw=1.2, color="#b8b8b8", label="买入持有 (LBMA PM)")
ax.plot(dates, V, lw=1.6, color="#c8912a", label="金仓 v2.1 策略")
ax.set_yscale("log")
for lo, hi in exit_spans:
ax.axvspan(lo, hi, color="#c0392b", alpha=0.13, lw=0)
if has_oos:
ax.axvline("2026-01-01", color="#4569a0", ls="--", lw=1.1)
xmax = len(dates) - 1
ax.annotate("2026 样本外 →", xy=(0.865, 0.045), xycoords="axes fraction",
fontsize=9, color="#4569a0")
ax.annotate("红色底纹 = 逻辑退出区间\n(pace < 102 吨/季)",
xy=(0.02, 0.74), xycoords="axes fraction", fontsize=9, color="#c0392b")
tick_idx = [i for i, d in enumerate(dates)
if d[5:7] == "01" and (i == 0 or dates[i - 1][5:7] != "01")]
step = max(1, len(tick_idx) // 8)
ax.set_xticks([dates[i] for i in tick_idx[::step]])
ax.set_xticklabels([dates[i][:4] for i in tick_idx[::step]], fontsize=9)
ax.set_ylabel("净值(V0 = 10,000,对数轴)", fontsize=10)
ax.set_title(f"金仓 v2.1 全历史回测 {dates[0]} → {dates[-1]}(USD,含 0.05% 单边成本)", fontsize=12)
ax.grid(alpha=0.25, which="both")
ax.legend(loc="upper left", fontsize=10)
fig.tight_layout()
out = res / "equity.png"
fig.savefig(out)
print(f"已写 {out}")