"""修复 pre_close/change/pct_chg 会不会改变 T0 涨停判定？
grid_or.signal_detect: np.where(pct >= bt - 0.05) —— 阈值 9.95(10%板) / 19.95(20%板)。
比较"库内 pct_chg"与"tushare 原值"分别落入阈值的结果，统计翻转。
用法: ./zt_venv/bin/python code/_chk_pctchg_limitup_impact.py
"""
import os, glob, pickle, 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"
CACHE = '/tmp/_ts_daily_sample.pkl'
qc = pickle.load(open(CACHE, 'rb')) if os.path.exists(CACHE) else {}

files = []
for p in ["hs300", "zz500", "zz1000", "zz2000"]:
    files += glob.glob(f"{ROOT}/daily_{p}/*.csv")
import random
random.seed(7)
sample = random.sample(files, 80)
for f in sample:
    c = os.path.basename(f)[:-4]
    if c in qc:
        continue
    lf = pd.read_csv(f, usecols=['trade_date'])
    s, e = str(int(lf['trade_date'].min())), str(int(lf['trade_date'].max()))
    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):
        continue
    q = q.sort_values('trade_date')
    q['trade_date'] = q['trade_date'].astype(int)
    qc[c] = q
    time.sleep(0.3)
pickle.dump(qc, open(CACHE, 'wb'))


def bt(code):
    if code.startswith(('300', '301', '688')):
        return 20.0
    if code.endswith('.BJ'):
        return 30.0
    return 10.0


rows = chk = flip_add = flip_del = 0
flips = []
for c, q in qc.items():
    fs = glob.glob(f"{ROOT}/daily_*/{c}.csv")
    if not fs:
        continue
    lf = pd.read_csv(fs[0])
    m = lf[['trade_date', 'pct_chg']].merge(q[['trade_date', 'pct_chg']], on='trade_date',
                                           suffixes=('_loc', '_ts'))
    if not len(m):
        continue
    b = bt(c)
    thr = b - 0.05
    lo = m['pct_chg_loc'] >= thr
    to = m['pct_chg_ts'] >= thr
    rows += len(m)
    chk += int((~((m['pct_chg_loc'] - m['pct_chg_ts']).abs() < 1e-9)).sum())
    add = int((~lo & to).sum())
    dele = int((lo & ~to).sum())
    flip_add += add
    flip_del += dele
    for r in m.loc[lo ^ to].head(3).itertuples():
        flips.append((c, int(r.trade_date), b, r.pct_chg_loc, r.pct_chg_ts, '库内判T0→修后不判' if r.pct_chg_loc >= thr else '库内不判→修后判T0'))

print(f"样本 {len(qc)} 只 / {rows} 行")
print(f"库内 pct_chg 与 tushare 原值不同的行: {chk} ({chk/rows:.2%})")
print(f"T0 判定翻转: 修后新增 {flip_add} 行 + 修后消除 {flip_del} 行 = {flip_add+flip_del} 行 ({(flip_add+flip_del)/rows:.3%})")
for x in flips[:12]:
    print("   ", x)
