Files
big-qmt/labs/analysis/etf/check_gaps.py
2026-09-21 12:38:13 +08:00

56 lines
1.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""扫描候选 ETF 的日线是否存在"份额折算/拆分"造成的价格断层。
接口无复权若有拆分MA60/ATR 会被污染 → 策略会在错误价位建网。
判定:单日收盘跳空超过 15% 视为异常ETF 涨跌停一般 ±10%)。
用法: py -3.14 -B labs/analysis/etf/check_gaps.py
"""
import json
import sys
from pathlib import Path
HERE = Path(__file__).resolve().parent
sys.path.insert(0, str(HERE))
try:
sys.stdout.reconfigure(encoding="utf-8", errors="replace")
except Exception:
pass
from backtest import CACHE # noqa: E402
from check_candidates import CANDIDATES # noqa: E402
def scan(code: str) -> list[tuple[str, str, float, float, float]]:
path = CACHE / f"{code}.json"
if not path.exists():
return []
rows = sorted(json.loads(path.read_text(encoding="utf-8")), key=lambda r: str(r["trade_date"]))
out = []
for prev, cur in zip(rows, rows[1:]):
a, b = float(prev["close"]), float(cur["close"])
if a <= 0:
continue
change = (b / a - 1) * 100
if abs(change) > 15:
out.append((str(prev["trade_date"]), str(cur["trade_date"]), a, b, change))
return out
print(f"{'板块':12} {'代码':11} {'异常跳空':>8} 明细")
flagged = []
for sector, code in CANDIDATES.items():
gaps = scan(code)
detail = "; ".join(f"{a}->{b}: {x:.2f}{y:.2f} ({c:+.1f}%)" for a, b, x, y, c in gaps[:3])
print(f"{sector:12} {code:11} {len(gaps):8} {detail}")
if gaps:
flagged.append((sector, code, gaps))
print()
if flagged:
print("⚠️ 以下标的日线存在断层(多半是份额折算/拆分,接口无复权)→ 网格锚点会被污染:")
for sector, code, gaps in flagged:
print(f" {sector}({code}){len(gaps)} 处,最大 {max(abs(g[4]) for g in gaps):.1f}%")
else:
print("未发现异常跳空")