"""build_strength_v4 兼容重建（Mac 迁移包缺原文件）
原文件功能（按 skill 记载 + scan_daily_tb.py 引用）：
  - feats(d, t0i, tai, tbi, target) -> 14特征 dict：11链特征 + 3上下文特征(f12/f13/f14 由调用方补)
  - 输出 v3 兼容格式 strength_model.json（weights + pools.percentiles[101] + raw_scores）
11链特征的计算公式与 scan_daily_tb.py find_tb_today() 逐行一致（同源移植）。
"""
import pandas as pd
import numpy as np

def feats(d, t0i, tai, tbi, target=None):
    """d: 个股日线df(已sort by trade_date); t0i/tai/tbi: 涨停/缩量/突破的原df索引"""
    d = d.sort_values('trade_date').reset_index(drop=True)
    pct = d['pct_chg'].astype(float).values
    close = d['close'].astype(float).values
    vol = d['vol'].astype(float).values
    t0, ta, k = t0i, tai, tbi
    v0 = vol[t0]
    p0 = close[t0]
    m10 = vol[max(0, k - 10):k].mean() if k >= 10 else vol[:k].mean()
    ma5 = pd.Series(close).rolling(5).mean().values
    ma10 = pd.Series(close).rolling(10).mean().values
    ma20 = pd.Series(close).rolling(20).mean().values
    f = {
        'f1_t0_pct': float(pct[t0]),
        'f2_t0_vol_ratio': float(v0 / vol[max(0, t0 - 10):t0].mean()) if t0 >= 10 and vol[max(0, t0 - 10):t0].mean() > 0 else np.nan,
        'f3_ta_shrink': float(vol[ta] / v0) if v0 > 0 else np.nan,
        'f4_ta_drawdown': float(close[ta] / p0 - 1),
        'f5_ta_gap': float(ta - t0),
        'f6_tb_strength': float(close[k] / p0 - 1),
        'f7_tb_gap': float(k - t0),
        'f8_chain_len': float(k + 1 - t0),
        'f9_tb_vol': float(vol[k] / m10) if m10 > 0 else np.nan,
        'f10_tb_ma5_slope': float((ma5[k] - ma5[k - 3]) / ma5[k - 3]) if k >= 3 and ma5[k - 3] > 0 else np.nan,
        'f11_tb_ma_align': float(1 if (ma5[k] > ma10[k] > ma20[k]) else (-1 if (ma5[k] < ma10[k] < ma20[k]) else 0)),
    }
    return f
