"""落盘 adj_factor 偏差的板块分布（按日全市场口径）——用于圈定重刷 roster。
用法: ./zt_venv/bin/python code/_chk_factor_prefix_breakdown.py 20210802 20250115
"""
import os, sys, glob
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"

loc = {}
for p in ["hs300", "zz500", "zz1000", "zz2000"]:
    for f in glob.glob(f"{ROOT}/daily_{p}/*.csv"):
        code = os.path.basename(f)[:-4]
        d = pd.read_csv(f, usecols=['trade_date', 'adj_factor'])
        loc[code] = dict(zip(d['trade_date'].astype(int), d['adj_factor']))


def bucket(c):
    if c.endswith('.BJ'):
        return '北交所 BJ'
    if c.startswith('688'):
        return '科创 688'
    if c.startswith('300') or c.startswith('301'):
        return '创业 300/301'
    if c.startswith('60'):
        return '沪主板 60'
    return '深主板 00'


for dt in sys.argv[1:] or ['20210802']:
    s = pro.adj_factor(trade_date=dt).set_index('ts_code')['adj_factor'].astype(float)
    rec = []
    for c, dd in loc.items():
        v = dd.get(int(dt))
        if v is None or c not in s.index or float(s[c]) <= 0:
            continue
        rec.append((c, abs(float(v) / float(s[c]) - 1), float(v) / float(s[c])))
    df = pd.DataFrame(rec, columns=['code', 'rel', 'ratio'])
    df['grp'] = df['code'].map(bucket)
    print(f"=== {dt} 比对 {len(df)} 只 ===")
    for g, sub in df.groupby('grp'):
        print(f"  {g:<12} n={len(sub):<5} >1e-4 {(sub['rel']>1e-4).mean():>6.1%} "
              f">1e-3 {(sub['rel']>1e-3).mean():>6.1%} 偏差中位 {sub['rel'].median():.2e} "
              f"| 比率中位 {sub['ratio'].median():.4f} (1.0=对)")
