"""
A/B测试：添加东南亚科技ETF的影响（受限测试）
对比：
- A组（对照组）：当前配置（无东南亚）
- B组（实验组）：添加东南亚科技ETF

限制说明：
- 东南亚科技ETF（513730.SH）2023年12月上市，数据仅约2年
- 新交所泛东南亚科技指数在YFinance中暂无数据
- 本次测试使用ETF价格作为信号源（非最佳实践，仅作参考）
- 回测时间范围将被缩短

核心问题：新兴市场ETF流动性是否优于印度LOF
"""

import sys
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent.parent))

from strategies.rotation.engine import RotationStrategy
import pandas as pd
import yaml


def create_config_with_sea(base_config: dict) -> dict:
    """在基础配置上添加东南亚科技"""
    config = base_config.copy()
    config['code_list'] = base_config['code_list'].copy()
    
    # 添加东南亚科技（新大类）
    # 注意：由于指数数据不可用，使用ETF价格作为信号源
    # 513730.SH 同时作为指数代码和ETF代码
    config['code_list']['513730.SH'] = {
        'name': '东南亚科技',
        'etf': '513730.SH',  # 华泰柏瑞东南亚科技ETF
        'market': 'SEA'  # 东南亚大类
    }
    
    return config


def run_backtest(config: dict, label: str) -> dict:
    """运行回测并返回关键指标"""
    print(f"\n{'='*60}")
    print(f"  {label}")
    print(f"{'='*60}")
    
    strategy = RotationStrategy(config)
    result = strategy.run()
    
    if result is None or len(result) == 0:
        return None
    
    # 计算指标
    strategy_nav = result['轮动策略净值']
    strategy_ret = result['轮动策略日收益率']
    
    total_return = strategy_nav.iloc[-1] - 1
    days = len(result)
    years = days / 250
    cagr = (strategy_nav.iloc[-1] ** (1/years)) - 1 if years > 0 else 0
    excess_ret = strategy_ret.mean() * 250
    vol = strategy_ret.std() * (250 ** 0.5)
    sharpe = excess_ret / vol if vol > 0 else 0
    rolling_max = strategy_nav.cummax()
    drawdown = (strategy_nav - rolling_max) / rolling_max
    max_dd = drawdown.min()
    calmar = cagr / abs(max_dd) if max_dd < 0 else 0
    win_rate = (strategy_ret > 0).sum() / len(strategy_ret)
    
    # 统计大类数量
    markets = set()
    for code_info in config['code_list'].values():
        markets.add(code_info.get('market', 'A'))
    
    metrics = {
        'label': label,
        '大类数量': len(markets),
        '回测天数': days,
        '回测年数': years,
        '累计收益': total_return,
        'CAGR': cagr,
        'Sharpe': sharpe,
        'MaxDD': max_dd,
        'Calmar': calmar,
        '日胜率': win_rate,
    }
    
    print(f"\n大类数量: {metrics['大类数量']}")
    print(f"回测天数: {metrics['回测天数']}")
    print(f"回测年数: {metrics['回测年数']:.2f}")
    print(f"累计收益: {metrics['累计收益']:.2%}")
    print(f"CAGR: {metrics['CAGR']:.2%}")
    print(f"Sharpe: {metrics['Sharpe']:.2f}")
    print(f"MaxDD: {metrics['MaxDD']:.2%}")
    print(f"Calmar: {metrics['Calmar']:.2f}")
    print(f"日胜率: {metrics['日胜率']:.2%}")
    
    return metrics


def compare_results(a_metrics: dict, b_metrics: dict):
    """对比两组结果"""
    print(f"\n{'='*60}")
    print(f"  对比结果")
    print(f"{'='*60}")
    
    print(f"\n{'指标':<15} {'A组(无东南亚)':<15} {'B组(有东南亚)':<15} {'差异':<15}")
    print("-" * 60)
    
    metrics_keys = ['大类数量', '回测天数', '回测年数', '累计收益', 'CAGR', 'Sharpe', 'MaxDD', 'Calmar', '日胜率']
    
    for key in metrics_keys:
        a_val = a_metrics.get(key, 0)
        b_val = b_metrics.get(key, 0)
        
        diff = b_val - a_val
        if key in ['累计收益', 'CAGR', 'MaxDD', '日胜率']:
            a_str = f"{a_val:.2%}"
            b_str = f"{b_val:.2%}"
            diff_str = f"{diff*100:+.2f}%"
        elif key in ['大类数量', '回测天数']:
            a_str = str(int(a_val))
            b_str = str(int(b_val))
            diff_str = f"+{int(diff)}" if diff > 0 else str(int(diff))
        else:
            a_str = f"{a_val:.2f}"
            b_str = f"{b_val:.2f}"
            diff_str = f"{diff:+.2f}"
        
        print(f"{key:<15} {a_str:<15} {b_str:<15} {diff_str:<15}")
    
    print("-" * 60)
    
    print(f"\n【限制说明】")
    print(f"  ⚠ 本次测试数据量受限（东南亚ETF仅2年数据）")
    print(f"  ⚠ 使用ETF价格作为信号源（指数数据暂不可用）")
    print(f"  ⚠ 结果仅供参考，不建议直接用于决策")
    
    print(f"\n【关键发现】")
    
    if b_metrics['大类数量'] > a_metrics['大类数量']:
        print(f"  ✓ 大类数量增加 {b_metrics['大类数量'] - a_metrics['大类数量']}")
    
    if b_metrics['累计收益'] > a_metrics['累计收益']:
        print(f"  ✓ 累计收益提升 {b_metrics['累计收益'] - a_metrics['累计收益']:.2%}")
    else:
        print(f"  ✗ 累计收益下降 {a_metrics['累计收益'] - b_metrics['累计收益']:.2%}")
    
    if b_metrics['Sharpe'] > a_metrics['Sharpe']:
        print(f"  ✓ Sharpe改善 {b_metrics['Sharpe'] - a_metrics['Sharpe']:.2f}")
    else:
        print(f"  ✗ Sharpe下降 {a_metrics['Sharpe'] - b_metrics['Sharpe']:.2f}")
    
    print(f"\n【策略建议】")
    print(f"  建议：等待东南亚科技ETF积累更多数据后再测试")
    print(f"  原因：")
    print(f"    1. 数据量不足（仅{b_metrics['回测年数']:.1f}年）")
    print(f"    2. 指数信号源暂不可用")
    print(f"    3. ETF价格作为信号源存在溢价干扰")


def main():
    """主函数"""
    config_path = Path(__file__).parent.parent.parent / 'config' / 'strategies' / 'rotation.yaml'
    with open(config_path, 'r') as f:
        base_config = yaml.safe_load(f)
    
    # 设置回测结束日期
    from datetime import datetime
    base_config['end_date'] = datetime.now().strftime('%Y-%m-%d')
    
    # ⚠ 重要：由于东南亚ETF数据从2023年12月开始
    # 需要调整start_date以匹配数据可用范围
    # 本次测试将使用较短的时间窗口
    
    print(f"\n{'='*60}")
    print(f"  A/B测试：添加东南亚科技ETF（受限测试）")
    print(f"{'='*60}")
    print(f"\n⚠ 限制说明：")
    print(f"  - 东南亚科技ETF（513730.SH）2023年12月上市")
    print(f"  - 数据仅约2年，回测时间范围受限")
    print(f"  - 指数数据暂不可用，使用ETF价格作为信号源")
    print(f"  - 结果仅供参考，不建议直接用于决策")
    
    # A组：当前配置（使用较短时间窗口）
    config_a = base_config.copy()
    config_a['start_date'] = '2024-01-01'  # 调整为东南亚ETF有数据的起始时间
    a_metrics = run_backtest(config_a, "A组: 当前配置（2024年起）")
    
    # B组：添加东南亚科技
    config_b = create_config_with_sea(base_config)
    config_b['start_date'] = '2024-01-01'
    b_metrics = run_backtest(config_b, "B组: 添加东南亚科技")
    
    # 对比
    if a_metrics and b_metrics:
        compare_results(a_metrics, b_metrics)
        
        # 保存结果
        results_df = pd.DataFrame([a_metrics, b_metrics])
        results_path = Path(__file__).parent.parent.parent / 'results' / 'ab_test_sea_etf.csv'
        results_df.to_csv(results_path, index=False)
        print(f"\n对比结果已保存: {results_path}")


if __name__ == '__main__':
    main()