"""
快速对比: 15min vs 1H IC
分辨率越低，噪音越小，信号可能更强
"""
import pandas as pd, numpy as np
from sklearn.linear_model import Ridge
from sklearn.preprocessing import StandardScaler
from scipy.stats import spearmanr

df = pd.read_parquet("data/btc_multidim.parquet")

def run_ic_analysis(data, label, horizon_bars=4, time_label=""):
    """通用滚动IC"""
    X_cols = ["ret_5","ret_20","ma_dev","fr_level","fr_chg","taker_pct","taker_dev"]
    # 只保留存在的列
    avail = [c for c in X_cols if c in data.columns]
    
    window = min(30 * 24 * 4, len(data) // 3)  # 30天，或数据量的1/3
    step = max(24 * 4, window // 30)  # 至少1天
    
    ics = []
    for i in range(0, len(data) - window - step, step):
        train, test = data.iloc[i:i+window], data.iloc[i+window:i+window+step]
        if len(test) < 10: break
        sc = StandardScaler()
        X_tr = sc.fit_transform(train[avail])
        X_te = sc.transform(test[avail])
        m = Ridge(alpha=1.0).fit(X_tr, train[label])
        pred = m.predict(X_te)
        ic, _ = spearmanr(pred, test[label])
        if not np.isnan(ic): ics.append(ic)
    
    mean_ic = np.mean(ics) if ics else 0
    ic_pos = (np.array(ics) > 0).mean() if ics else 0
    print(f"  {time_label:6s}  IC={mean_ic:+.4f}  IC>0={ic_pos:.1%}  n_rolls={len(ics)}")
    return mean_ic

# ── 1. 原始15分钟 ──
print("时间框架对比:\n")
d15 = df.copy()
d15.index.name = "ts"
d15["fwd_ret"] = d15["close"].shift(-4) / d15["close"] - 1  # 1小时
d15 = d15.dropna()

# ── 2. Resample 到 1H ──
d1h = d15.resample("1h").agg({
    "open": "first", "high": "max", "low": "min", "close": "last",
    "volume": "sum", "taker_pct": "mean", "funding_rate": "last"
}).dropna()

# 在1H数据上重新构造因子
d1h["ret_5"] = d1h["close"].pct_change(5)
d1h["ret_20"] = d1h["close"].pct_change(20)
d1h["ma_dev"] = d1h["close"] / d1h["close"].rolling(20).mean() - 1
d1h["fr_level"] = d1h["funding_rate"]
d1h["fr_chg"] = d1h["funding_rate"].diff(20)
d1h["taker_pct"] = d1h["taker_pct"].clip(0, 1)
d1h["taker_dev"] = d1h["taker_pct"] - d1h["taker_pct"].rolling(20).mean()
d1h["fwd_ret"] = d1h["close"].shift(-4) / d1h["close"] - 1  # 4小时
d1h = d1h.dropna()

print(f"15min: {len(d15)} candles | 1H: {len(d1h)} candles\n")

# ── 逐因子对比 ──
print("逐因子 IC 对比:")
print(f"{'因子':12s}  {'15min':>8s}  {'1H':>8s}")
print("-" * 32)
for col in ["ret_5","ret_20","ma_dev","fr_level","fr_chg","taker_pct","taker_dev"]:
    i15, i1h = [], []
    window_15 = 30*24*4
    step_15 = 24*4
    for i in range(0, len(d15) - window_15 - step_15, step_15):
        tr, te = d15.iloc[i:i+window_15], d15.iloc[i+window_15:i+window_15+step_15]
        if len(te) < 10: break
        sc = StandardScaler()
        m = Ridge(alpha=1.0).fit(sc.fit_transform(tr[[col]]), tr["fwd_ret"])
        ic, _ = spearmanr(m.predict(sc.transform(te[[col]])), te["fwd_ret"])
        if not np.isnan(ic): i15.append(ic)
    
    window_1h = 30*24
    step_1h = 24
    for i in range(0, len(d1h) - window_1h - step_1h, step_1h):
        tr, te = d1h.iloc[i:i+window_1h], d1h.iloc[i+window_1h:i+window_1h+step_1h]
        if len(te) < 5: break
        sc = StandardScaler()
        m = Ridge(alpha=1.0).fit(sc.fit_transform(tr[[col]]), tr["fwd_ret"])
        ic, _ = spearmanr(m.predict(sc.transform(te[[col]])), te["fwd_ret"])
        if not np.isnan(ic): i1h.append(ic)
    
    m15 = np.mean(i15) if i15 else 0
    m1h = np.mean(i1h) if i1h else 0
    better = "← 1H更强" if abs(m1h) > abs(m15) + 0.005 else ("← 15min更强" if abs(m15) > abs(m1h) + 0.005 else "")
    print(f"{col:12s}  {m15:+8.4f}  {m1h:+8.4f}  {better}")

# ── 多因子对比 ──
print(f"\n多因子 Ridge:\n")
run_ic_analysis(d15, "fwd_ret", 4, "15min")
run_ic_analysis(d1h, "fwd_ret", 4, "1H")
