"""修复验收：落盘四列 vs tushare 原值 逐列比对（独立复核，只读）。

用法:
  ./zt_venv/bin/python code/chk_repair_verify.py 300        # 按池均匀抽 300 只
  ./zt_venv/bin/python code/chk_repair_verify.py all        # 全库 5400 只（约 20 分钟）

口径: raw_open/high/low/close 相对差阈值 0（严格相等）; pre_close/change/pct_chg 阈值 1e-4。
每只带 start_date/end_date 边界取数（避免默认"最近 6000 行"口径带来的隐性差异）。
"""
import os, sys, glob, time
import numpy as np
import pandas as pd

os.environ.setdefault('HTTP_PROXY', 'http://127.0.0.1:7897')
os.environ.setdefault('HTTPS_PROXY', 'http://127.0.0.1:7897')
import tushare as ts
ts.set_token('edf6739fe1a4de0d747600cc753a8b4bf335cf27ef0f5aea2d2aa64c')
pro = ts.pro_api()
ROOT = "backtest_zt_full"
FILES = []
for p in ["hs300", "zz500", "zz1000", "zz2000"]:
    FILES += sorted(glob.glob(f"{ROOT}/daily_{p}/*.csv"))

arg = sys.argv[1] if len(sys.argv) > 1 else '300'
if arg == 'all':
    sel = FILES
else:
    n = int(arg)
    step = max(1, len(FILES) // n)
    sel = FILES[::step][:n]

RAW = ['open', 'high', 'low', 'close']
DER = ['pre_close', 'change', 'pct_chg']
bad_raw = bad_der = missing = checked = 0
worst = []
for f in sel:
    c = os.path.basename(f)[:-4]
    lf = pd.read_csv(f)
    if not len(lf):
        continue
    s, e = str(int(lf['trade_date'].min())), str(int(lf['trade_date'].max()))
    q = None
    for _ in range(3):
        try:
            q = pro.daily(ts_code=c, start_date=s, end_date=e)
            if q is not None and len(q):
                break
        except Exception:
            pass
        time.sleep(2)
    if q is None or not len(q):
        missing += 1
        print(f"  [跳过] {c} 无返回")
        continue
    q['trade_date'] = q['trade_date'].astype(int)
    m = lf.merge(q, on='trade_date', how='left', suffixes=('', '_ts'))
    got = m[[x + '_ts' for x in DER]].notna().any(axis=1)
    m = m[got]
    checked += len(m)
    for col in RAW:
        d = (m[f'raw_{col}'] - m[col]).abs().max()
        if d > 0:
            bad_raw += 1
            worst.append((c, f'raw_{col}', float(d), m.loc[(m[f'raw_{col}'] - m[col]).abs().idxmax(), 'trade_date']))
            break
    for col in DER:
        if col not in lf.columns:
            continue
        ref = m[col + '_ts'].astype(float)
        denom = ref.abs().replace(0, np.nan)
        rel = ((m[col] - ref) / denom).abs()
        if (rel > 1e-4).any():
            bad_der += 1
            worst.append((c, col, float(rel.max()), None))
            break
    time.sleep(0.25)

print(f"\n抽检 {len(sel)} 文件 / 对齐 {checked} 行 | 无返回 {missing}")
print(f"raw_* 有差异的文件: {bad_raw}  (阈值 0)")
print(f"pre_close/change/pct_chg 有差异(>1e-4)的文件: {bad_der}")
for w in worst[:20]:
    print("   ", w)
