#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
CYB50 T+1 转换器 - 基于多空版本的做多交易转换为T+1规则
规则：
1. 提取多空版本中的所有做多交易
2. 买入当天不能卖出（T+1限制）
3. 如果原交易是T0（当天买卖），则延期到T+1开盘卖出
4. 重新计算延期后的盈亏（基于实际价格变化）
"""

import pandas as pd
import numpy as np
from datetime import datetime, timedelta
import sys
sys.path.insert(0, '/root/.openclaw/workspace/cat-fly')

from cyb50_30min_dual_direction import (
    ConfigManager, IntradayDataFetcher, 
    DualDirectionSignalGenerator, DualDirectionExecutor
)


def get_next_trading_session_open(data_df, current_time):
    """获取下一个交易日的第一个开盘时间（注意：不是当天，是下一天）"""
    current_date = current_time.date()
    
    # 查找当前日期之后的所有数据
    future_data = data_df[data_df.index > current_time]
    
    if future_data.empty:
        return None, None
    
    # 获取所有日期，找到第一个不同于current_date的日期
    future_dates = future_data.index.date
    next_date = None
    
    for d in future_dates:
        if d != current_date:
            next_date = d
            break
    
    if next_date is None:
        return None, None
    
    # 获取下一个交易日的所有数据
    next_day_data = data_df[data_df.index.date == next_date]
    
    if next_day_data.empty:
        return None, None
    
    open_time = next_day_data.index[0]
    open_price = next_day_data.iloc[0]['Open']  # 使用开盘价
    
    return open_time, open_price


def simulate_t1_trades(data_df, long_trades_df, initial_capital=1000000):
    """模拟T+1规则下的交易
    
    规则：
    - 买入当天不能卖出
    - 如果原T0交易（当天买卖），延期到T+1开盘卖出
    - 卖出后当天可以再买（这是关键特性）
    """
    print("\n" + "="*80)
    print("T+1规则转换 - 基于多空版本做多交易")
    print("="*80)
    
    if len(long_trades_df) == 0:
        print("没有做多交易记录")
        return pd.DataFrame()
    
    # 按开仓时间排序
    long_trades_df = long_trades_df.sort_values('开仓时间').reset_index(drop=True)
    
    t1_trades = []
    capital = initial_capital
    
    for idx, trade in long_trades_df.iterrows():
        entry_time = trade['开仓时间']
        entry_price = trade['开仓价格']
        original_exit_time = trade['平仓时间']
        original_exit_price = trade['平仓价格']
        position_size = int(trade['仓位'])
        entry_signals = trade.get('入场信号', '')
        
        entry_date = entry_time.date()
        exit_date = original_exit_time.date()
        
        # 判断是否是T0交易
        is_t0 = (entry_date == exit_date)
        
        if is_t0:
            # T0交易需要延期到T+1开盘
            new_exit_time, new_exit_price = get_next_trading_session_open(data_df, entry_time)
            
            if new_exit_time is None:
                print(f"⚠️  交易 #{idx+1}: 无法找到T+1开盘时间，使用原平仓价格")
                new_exit_time = original_exit_time
                new_exit_price = original_exit_price
                t1_adjusted = False
            else:
                # 计算新的盈亏
                # 假设使用开盘价卖出
                original_pnl = trade['盈亏金额']
                
                # 计算手续费（万分之一）
                commission_rate = 0.0001
                open_cost = position_size * entry_price * commission_rate
                close_cost = position_size * new_exit_price * commission_rate
                
                # 新的盈亏
                gross_pnl = (new_exit_price - entry_price) * position_size
                new_pnl = gross_pnl - open_cost - close_cost
                new_pnl_pct = (new_exit_price - entry_price) / entry_price * 100
                
                # 判断新的退出原因
                stop_loss = entry_price * 0.992  # 0.8%止损
                take_profit = entry_price * 1.02  # 2%止盈
                
                if new_exit_price <= stop_loss:
                    exit_reason = f"T+1延期止损(价格{new_exit_price:.2f}触及止损线{stop_loss:.2f},亏损{abs(new_pnl_pct):.2f}%)"
                elif new_exit_price >= take_profit:
                    exit_reason = f"T+1延期止盈(价格{new_exit_price:.2f}触及止盈线{take_profit:.2f},盈利{new_pnl_pct:.2f}%)"
                else:
                    exit_reason = f"T+1延期平仓(价格{new_exit_price:.2f},盈亏{new_pnl_pct:+.2f}%)"
                
                # 计算持仓时长（小时）
                hold_hours = (new_exit_time - entry_time).total_seconds() / 3600
                
                print(f"\n[T0→T1调整] 交易 #{idx+1}")
                print(f"  原交易: {entry_time.strftime('%m-%d %H:%M')} 买 → {original_exit_time.strftime('%m-%d %H:%M')} 卖")
                print(f"  新交易: {entry_time.strftime('%m-%d %H:%M')} 买 → {new_exit_time.strftime('%m-%d %H:%M')} 卖")
                print(f"  原盈亏: {original_pnl:+.2f}元")
                print(f"  新盈亏: {new_pnl:+.2f}元 (基于T+1开盘{new_exit_price:.2f})")
                print(f"  盈亏变化: {(new_pnl - original_pnl):+.2f}元")
                
                t1_adjusted = True
                
                # 更新交易记录
                trade_record = {
                    '交易方向': '做多',
                    '开仓时间': entry_time,
                    '平仓时间': new_exit_time,
                    '开仓价格': entry_price,
                    '平仓价格': new_exit_price,
                    '仓位': position_size,
                    '盈亏金额': new_pnl,
                    '盈亏百分比': new_pnl_pct,
                    '退出原因': exit_reason,
                    '持仓周期数': int(hold_hours * 2),  # 30分钟周期数
                    '持仓小时数': hold_hours,
                    'T+1调整': '是(T0→T1)',
                    '原平仓时间': original_exit_time,
                    '原平仓价格': original_exit_price,
                    '原盈亏': original_pnl,
                    '盈亏变化': new_pnl - original_pnl,
                    '入场信号': entry_signals,
                    '开仓市值': position_size * entry_price,
                }
                
                capital += new_pnl
                trade_record['平仓时资金'] = capital
                t1_trades.append(trade_record)
                continue
        
        # 非T0交易，保持原样
        hold_hours = trade['持仓小时数']
        
        # 计算盈亏（使用原始数据）
        commission_rate = 0.0001
        gross_pnl = (original_exit_price - entry_price) * position_size
        open_cost = position_size * entry_price * commission_rate
        close_cost = position_size * original_exit_price * commission_rate
        pnl = gross_pnl - open_cost - close_cost
        pnl_pct = (original_exit_price - entry_price) / entry_price * 100
        
        capital += pnl
        
        trade_record = {
            '交易方向': '做多',
            '开仓时间': entry_time,
            '平仓时间': original_exit_time,
            '开仓价格': entry_price,
            '平仓价格': original_exit_price,
            '仓位': position_size,
            '盈亏金额': pnl,
            '盈亏百分比': pnl_pct,
            '退出原因': trade['退出原因'],
            '持仓周期数': trade['持仓周期数'],
            '持仓小时数': hold_hours,
            'T+1调整': '否',
            '原平仓时间': original_exit_time,
            '原平仓价格': original_exit_price,
            '原盈亏': trade['盈亏金额'],
            '盈亏变化': 0,
            '入场信号': entry_signals,
            '开仓市值': position_size * entry_price,
            '平仓时资金': capital,
        }
        t1_trades.append(trade_record)
    
    t1_trades_df = pd.DataFrame(t1_trades)
    
    return t1_trades_df


def compare_results(original_trades, t1_trades, initial_capital=1000000):
    """对比原始交易和T+1转换后的结果"""
    print("\n" + "="*80)
    print("T+1转换前后对比")
    print("="*80)
    
    # 原始统计
    original_total_pnl = original_trades['盈亏金额'].sum()
    original_final = initial_capital + original_total_pnl
    original_return = (original_final / initial_capital - 1) * 100
    original_win_rate = (original_trades['盈亏金额'] > 0).sum() / len(original_trades) * 100
    
    # T+1统计
    t1_total_pnl = t1_trades['盈亏金额'].sum()
    t1_final = initial_capital + t1_total_pnl
    t1_return = (t1_final / initial_capital - 1) * 100
    t1_win_rate = (t1_trades['盈亏金额'] > 0).sum() / len(t1_trades) * 100
    
    # T0交易统计
    t0_adjusted = t1_trades[t1_trades['T+1调整'] == '是(T0→T1)']
    
    print(f"\n【原始交易（T0规则）】")
    print(f"  交易次数: {len(original_trades)}")
    print(f"  总盈亏: {original_total_pnl:+,.2f}元")
    print(f"  最终资金: {original_final:,.2f}元")
    print(f"  收益率: {original_return:+.2f}%")
    print(f"  胜率: {original_win_rate:.1f}%")
    
    print(f"\n【T+1转换后】")
    print(f"  交易次数: {len(t1_trades)}")
    print(f"  总盈亏: {t1_total_pnl:+,.2f}元")
    print(f"  最终资金: {t1_final:,.2f}元")
    print(f"  收益率: {t1_return:+.2f}%")
    print(f"  胜率: {t1_win_rate:.1f}%")
    
    print(f"\n【T+1调整统计】")
    print(f"  T0→T1调整交易数: {len(t0_adjusted)}笔")
    if len(t0_adjusted) > 0:
        print(f"  调整后盈亏变化: {t0_adjusted['盈亏变化'].sum():+,.2f}元")
        print(f"  平均每笔变化: {t0_adjusted['盈亏变化'].mean():+,.2f}元")
        print(f"  调整交易明细:")
        for _, row in t0_adjusted.iterrows():
            print(f"    {row['开仓时间'].strftime('%m-%d %H:%M')} - "
                  f"原盈亏{row['原盈亏']:+.0f} → 新盈亏{row['盈亏金额']:+.0f} "
                  f"({row['盈亏变化']:+.0f})")
    
    print(f"\n【收益差异】")
    print(f"  收益率变化: {(t1_return - original_return):+.2f}%")
    print(f"  绝对盈亏差: {(t1_total_pnl - original_total_pnl):+,.2f}元")


def main():
    """主程序"""
    print("="*80)
    print("CYB50 T+1 交易转换器")
    print("基于多空版本的做多交易，应用T+1规则")
    print("="*80)
    
    initial_capital = 1000000
    
    # 1. 运行多空版本获取原始交易数据
    print("\n【步骤1】运行多空版本获取原始交易...")
    config_manager = ConfigManager('config.json')
    fetcher = IntradayDataFetcher(config_manager)
    
    end_date = datetime.now()
    start_date = end_date - timedelta(days=70)
    
    raw_data = fetcher.fetch_30min_data(start_date, end_date)
    data_with_indicators = fetcher.calculate_intraday_indicators(raw_data)
    
    signal_generator = DualDirectionSignalGenerator()
    signals_df = signal_generator.generate_dual_direction_signals(data_with_indicators)
    
    executor = DualDirectionExecutor(initial_capital=initial_capital)
    results_df, trades_df = executor.execute_dual_direction_trades(signals_df)
    
    # 提取做多交易
    long_trades = trades_df[trades_df['交易方向'] == '做多'].copy()
    print(f"✅ 获取到 {len(long_trades)} 笔做多交易")
    
    # 2. 应用T+1规则
    print("\n【步骤2】应用T+1规则转换...")
    t1_trades = simulate_t1_trades(data_with_indicators, long_trades, initial_capital)
    
    # 3. 对比结果
    print("\n【步骤3】对比分析...")
    compare_results(long_trades, t1_trades, initial_capital)
    
    # 4. 导出结果
    if len(t1_trades) > 0:
        print("\n【步骤4】导出T+1交易记录...")
        
        # 格式化时间
        export_df = t1_trades.copy()
        for col in ['开仓时间', '平仓时间', '原平仓时间']:
            if col in export_df.columns:
                export_df[col] = export_df[col].dt.strftime('%Y-%m-%d %H:%M:%S')
        
        timestamp = datetime.now().strftime('%Y%m%d_%H%M%S')
        output_file = f'cyb50_t1_converted_trades_{timestamp}.csv'
        export_df.to_csv(output_file, index=False, encoding='utf-8-sig')
        print(f"✅ T+1交易记录已保存: {output_file}")
    
    print("\n" + "="*80)
    print("转换完成!")
    print("="*80)


if __name__ == "__main__":
    main()
