This commit is contained in:
2026-09-21 12:38:13 +08:00
parent bcacbed427
commit ed6d4ee7a5
14 changed files with 2458 additions and 1073 deletions

View File

@@ -0,0 +1,62 @@
"""校验 py-client/etc/_etf.yaml用策略自己的 config.load 解析,并核对每只标的的数据可用性。
用法: py -3.14 -B labs/analysis/etf/validate_config.py
"""
import sys
import tempfile
from pathlib import Path
HERE = Path(__file__).resolve().parent
REPO = HERE.parents[2]
sys.path.insert(0, str(HERE))
sys.path.insert(0, str(REPO / "py-client"))
try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
except Exception:
pass
import yaml # noqa: E402
import config # noqa: E402
from backtest import CACHE, fetch_daily # noqa: E402
ETC = REPO / "py-client" / "etc"
# 1) 用策略自身的校验逻辑加载(除了 _global/account 这两层,直接调 _etf_config
cfg = config._etf_config(ETC / "_etf.yaml")
if cfg is None:
print("FAIL: _etf_config 返回 None文件不存在")
raise SystemExit(1)
print(f"配置解析通过:{len(cfg.symbols)} 只标的,顺序 = 资金优先级")
print(f"{'#':>3} {'代码':11} {'每档':>6} {'上限':>7} {'T+0':>5} {'atr×':>5} {'inner':>6} 数据")
ok = True
for index, code in enumerate(cfg.codes, 1):
symbol = cfg.symbols[code]
try:
bars = fetch_daily(code)
first, last = bars[0]["date"], bars[-1]["date"]
data = f"{len(bars)}{first}..{last}"
if len(bars) < 61:
data += " ← 不足 61 根,策略会跳过"
ok = False
except Exception as exc:
data = f"抓取失败:{exc}"
ok = False
print(f"{index:3} {code:11} {symbol.buy_shares:6} {symbol.max_shares:7} "
f"{str(symbol.is_t0):>5} {symbol.atr_multiplier:5.1f} {symbol.inner_step:6.1f} {data}")
# 2) 断言inner_grids × inner_step < min_profit_pct否则副出口不可能触发
grids, step = cfg.defaults.inner_grids, min(s.inner_step for s in cfg.symbols.values())
profit = cfg.defaults.min_profit_pct
print()
print(f"副出口可达性inner_grids({grids}) × inner_step({step}) = {grids * step:.2f}% "
f"vs min_profit_pct {profit}% → {'可达' if grids * step < profit else '不可达(会被主出口压制)'}")
# 3) 估算资金需求
need_one = sum(cfg.symbols[c].buy_shares * fetch_daily(c)[-1]["close"] for c in cfg.codes)
print(f"资金需求16 只各铺 1 档 ≈ {need_one:,.0f} 元;各铺满 10 档 ≈ {need_one * 10:,.0f}")
print()
print("校验结果:", "通过" if ok else "存在问题(见上)")
raise SystemExit(0 if ok else 1)