"""
资金费率套利回测 (Funding Rate Arbitrage)
策略：做多现货 + 做空合约 (1x)，无风险吃费率
数据源：OKX 公开 API
"""
import pandas as pd
import numpy as np
import requests
import time

print("🚀 开始拉取 OKX 历史资金费率数据...")

# OKX API: 获取 BTC-USDT-SWAP 的历史费率
url = "https://www.okx.com/api/v5/public/funding-rate-history"
params = {
    "instId": "BTC-USDT-SWAP",
    "limit": "100"  # 每次最多100条
}

all_data = []
total_count = 0
max_pages = 500  # 防止死循环

for i in range(max_pages):
    try:
        resp = requests.get(url, params=params, timeout=5)
        data = resp.json()
        
        if data['code'] != '0' or not data['data']:
            print(f"⚠️ 第 {i+1} 次请求无数据或错误，停止。")
            break
        
        rows = data['data']
        all_data.extend(rows)
        
        # 更新参数拉取更早的数据
        # OKX 返回是按时间倒序，最后一条是最早的
        if len(rows) < 100:
            print("✅ 已拉取到最早数据。")
            break
            
        # 取最后一条的时间作为 endTime 继续往前拉
        last_funding_time = rows[-1]['fundingTime']
        params['before'] = last_funding_time  # OKX 分页参数
        
        total_count += len(rows)
        if total_count % 1000 == 0:
            print(f"  已拉取 {total_count} 条费率记录...")
            
        time.sleep(0.2)  # 礼貌请求
        
    except Exception as e:
        print(f"❌ 请求失败: {e}")
        break

if not all_data:
    print("❌ 没有获取到任何数据！")
else:
    print(f"\n✅ 成功拉取 {len(all_data)} 条费率记录。")
    
    # 转 DataFrame
    df = pd.DataFrame(all_data)
    
    # 清洗数据
    df['fundingTime'] = pd.to_datetime(df['fundingTime'].astype(int), unit='ms')
    df['rate'] = df['fundingRate'].astype(float)
    df = df.sort_values('fundingTime').reset_index(drop=True)
    
    print(f"时间范围: {df['fundingTime'].min()} ~ {df['fundingTime'].max()}")
    print(f"数据条数: {len(df)} (约 {len(df)/3/365:.1f} 年)")
    
    # ──────────────────────────────────────────────────────
    # 回测分析
    # ──────────────────────────────────────────────────────
    print("\n📊 资金费率统计分析")
    print("="*80)
    
    # 基本统计
    avg_rate = df['rate'].mean()
    sum_rate = df['rate'].sum()
    positive_count = (df['rate'] > 0).sum()
    negative_count = (df['rate'] <= 0).sum()
    
    print(f"平均单次费率: {avg_rate*100:.4f}%")
    print(f"累计总费率: {sum_rate*100:.2f}%")
    print(f"正费率次数: {positive_count} ({positive_count/len(df)*100:.1f}%)")
    print(f"负费率次数: {negative_count} ({negative_count/len(df)*100:.1f}%) -> 此时需反向操作或空仓")
    
    # 年化收益估算 (假设全年满仓)
    # 一天3次，一年约1095次
    daily_avg = df.groupby(df['fundingTime'].dt.date)['rate'].sum().mean()
    yearly_est = daily_avg * 365
    
    print(f"\n预估日均收益: {daily_avg*100:.4f}%")
    print(f"预估年化收益 (单利): {yearly_est*100:.2f}%")
    
    # 如果只吃正费率 (负费率时空仓)
    df_positive_only = df[df['rate'] > 0]
    if len(df_positive_only) > 0:
        daily_avg_pos = df_positive_only.groupby(df_positive_only['fundingTime'].dt.date)['rate'].sum().mean()
        # 但要注意，空仓天数会减少收益，这里简化计算：假设负费率那天就一分钱没有
        # 更精确的算法是累加每天的 max(0, sum_rate)
        
        daily_real = df.groupby(df['fundingTime'].dt.date)['rate'].apply(lambda x: sum(x) if sum(x)>0 else 0).mean()
        yearly_real = daily_real * 365
        
        print(f"\n优化策略 (负费率时空仓):")
        print(f"预估真实日均收益: {daily_real*100:.4f}%")
        print(f"预估真实年化收益: {yearly_real*100:.2f}%")
    
    # 按月统计
    print(f"\n📅 月度收益分布 (最近12个月):")
    df['month'] = df['fundingTime'].dt.to_period('M')
    monthly = df.groupby('month')['rate'].sum() * 100
    print(monthly.tail(12).to_string())
    
    # 极端情况
    print(f"\n⚠️ 极端风险提示:")
    print(f"最大单笔正费率: {df['rate'].max()*100:.4f}%")
    print(f"最大单笔负费率: {df['rate'].min()*100:.4f}%")
    
    # 保存数据
    df.to_csv('/root/quant_pipeline/data/okx_funding_rate_history.csv', index=False)
    print(f"\n✅ 数据已保存至: /root/quant_pipeline/data/okx_funding_rate_history.csv")

    # 结论
    print("\n" + "="*80)
    print("💡 结论:")
    if yearly_real > 0.1:
        print(f"✅ 费率套利可行！历史年化约 {yearly_real:.1f}%。")
        print("   策略：费率>0 时开仓，费率<0 时空仓。")
    else:
        print("⚠️ 历史费率较低，需结合趋势策略增强。")