import pandas as pd
import numpy as np
from sqlalchemy import create_engine, text
from datetime import datetime, timedelta, time
import uuid
import logging
import sys
from typing import Dict, List, Optional, Tuple, Union

# 配置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    handlers=[
        logging.FileHandler("simulation.log"),
        logging.StreamHandler(sys.stdout)
    ]
)
logger = logging.getLogger("stock_simulation")

class StockSimulator:
    def __init__(self, db_connection_string):
        """
        初始化股票模拟交易平台
        :param db_connection_string: 数据库连接字符串
        """
        self.engine = create_engine(db_connection_string, future=True)
        self.MORNING_OPEN = time(9, 30)  # 早市开盘时间 9:30
        self.AFTERNOON_CLOSE = time(15, 0)  # 午市收盘时间 15:00
    
    def _is_before_open(self, dt: datetime) -> bool:
        """判断是否在开盘前"""
        return dt.time() < self.MORNING_OPEN
    
    def _is_after_close(self, dt: datetime) -> bool:
        """判断是否在收盘后"""
        return dt.time() > self.AFTERNOON_CLOSE
    
    def _read_sql(self, query: str) -> pd.DataFrame:
        raw_conn = self.engine.raw_connection()
        try:
            df = pd.read_sql(query, raw_conn)
        finally:
            raw_conn.close()
        return df
    
    def _get_stock_info(self, stock_code: str) -> Dict:
        """获取股票基本信息"""
        try:
            query = f"""
            SELECT gp_name FROM gp_code_all 
            WHERE gp_code = '{stock_code}' OR gp_code_two = '{stock_code}' OR gp_code_three = '{stock_code}'
            LIMIT 1
            """
            result = self._read_sql(query)
            
            if result.empty:
                return {"success": False, "message": f"股票代码 {stock_code} 不存在"}
            
            return {
                "success": True,
                "stock_code": stock_code,
                "stock_name": result.iloc[0]['gp_name']
            }
        except Exception as e:
            logger.error(f"获取股票信息出错: {str(e)}")
            return {"success": False, "message": f"获取股票信息出错: {str(e)}"}
    
    def _get_latest_trade_date(self) -> str:
        """获取最新交易日期"""
        try:
            query = """
            SELECT MAX(timestamp) as latest_date FROM gp_day_data
            """
            result = self._read_sql(query)
            
            if result.empty or pd.isna(result.iloc[0]['latest_date']):
                # 如果查询失败，返回当前日期
                return datetime.now().strftime('%Y-%m-%d')
            
            return result.iloc[0]['latest_date'].strftime('%Y-%m-%d')
        except Exception as e:
            logger.error(f"获取最新交易日期出错: {str(e)}")
            # 如果出错，返回当前日期
            return datetime.now().strftime('%Y-%m-%d')
    
    def _get_next_trade_date(self, date_str: str) -> str:
        """获取下一个交易日期"""
        try:
            query = f"""
            SELECT MIN(timestamp) as next_date 
            FROM gp_day_data 
            WHERE timestamp > '{date_str}'
            """
            result = self._read_sql(query)
            
            if result.empty or pd.isna(result.iloc[0]['next_date']):
                # 如果查询失败，返回当前日期加1天
                next_date = datetime.strptime(date_str, '%Y-%m-%d') + timedelta(days=1)
                return next_date.strftime('%Y-%m-%d')
            
            return result.iloc[0]['next_date'].strftime('%Y-%m-%d')
        except Exception as e:
            logger.error(f"获取下一个交易日期出错: {str(e)}")
            # 如果出错，返回当前日期加1天
            next_date = datetime.strptime(date_str, '%Y-%m-%d') + timedelta(days=1)
            return next_date.strftime('%Y-%m-%d')
    
    def _get_stock_price(self, stock_code: str, trade_date: str, price_type: str = 'close') -> float:
        """
        获取指定股票在指定日期的价格
        :param stock_code: 股票代码
        :param trade_date: 交易日期
        :param price_type: 价格类型 (open/close)
        :return: 股票价格
        """
        try:
            query = f"""
            SELECT CAST({price_type} as DECIMAL(10,2)) as price 
            FROM gp_day_data 
            WHERE symbol = '{stock_code}' AND timestamp = '{trade_date}'
            """
            result = self._read_sql(query)
            
            if result.empty:
                return None
            
            return float(result.iloc[0]['price'])
        except Exception as e:
            logger.error(f"获取股票价格出错: {str(e)}")
            return None
    
    def _calculate_buy_quantity(self, available_capital: float, price: float, single_position_limit: float) -> int:
        """
        计算可买入的股票数量，必须是100的整数倍
        """
        # 计算可用资金和单支标的限额的较小值
        max_amount = min(available_capital, single_position_limit)
        
        # 计算理论上可买入的最大数量
        theoretical_max = max_amount / price
        
        # 取100的整数倍，确保不少于100股
        quantity = int(theoretical_max / 100) * 100
        
        # 如果不足100股，检查是否有足够资金买入100股
        if quantity == 0 and available_capital >= price * 100:
            quantity = 100
        
        return quantity
    
    def _execute_database_operation(self, query: str, params: Optional[Dict] = None) -> bool:
        """执行数据库操作"""
        try:
            with self.engine.begin() as conn:
                if params:
                    conn.execute(text(query), params)
                else:
                    conn.execute(text(query))
            return True
        except Exception as e:
            logger.error(f"数据库操作出错: {str(e)}")
            return False
    
    def _get_account_info(self, account_id: str) -> Dict:
        """获取账户信息"""
        try:
            query = f"""
            SELECT * FROM simulation_account WHERE id = '{account_id}'
            """
            result = self._read_sql(query)
            
            if result.empty:
                return {"success": False, "message": f"账户ID {account_id} 不存在"}
            
            account_data = result.iloc[0].to_dict()
            
            if account_data['status'] == 'closed':
                return {"success": False, "message": f"账户ID {account_id} 已关闭"}
            
            return {
                "success": True,
                "account_data": account_data
            }
        except Exception as e:
            logger.error(f"获取账户信息出错: {str(e)}")
            return {"success": False, "message": f"获取账户信息出错: {str(e)}"}
    
    def _check_holding_exists(self, account_id: str, stock_code: str) -> bool:
        """检查是否已持有该股票"""
        try:
            query = f"""
            SELECT * FROM simulation_holding 
            WHERE account_id = '{account_id}' AND stock_code = '{stock_code}'
            """
            result = self._read_sql(query)
            
            return not result.empty
        except Exception as e:
            logger.error(f"检查持仓出错: {str(e)}")
            return False
    
    def init_simulation_account(self, total_capital: float, single_position_limit: float) -> Dict:
        """
        初始化模拟账户
        :param total_capital: 总仓位金额
        :param single_position_limit: 单支股票最大仓位
        :return: 账户信息
        """
        try:
            account_id = str(uuid.uuid4())
            now = datetime.now()
            
            # 插入账户记录
            query = """
            INSERT INTO simulation_account (
                id, total_capital, single_position_limit, available_capital, 
                create_time, update_time
            ) VALUES (
                :account_id, :total_capital, :single_position_limit, :available_capital,
                :create_time, :update_time
            )
            """
            
            params = {
                'account_id': account_id,
                'total_capital': total_capital,
                'single_position_limit': single_position_limit,
                'available_capital': total_capital,
                'create_time': now,
                'update_time': now
            }
            
            success = self._execute_database_operation(query, params)
            
            if not success:
                return {"success": False, "message": "创建模拟账户失败"}
            
            # 记录操作日志
            log_query = """
            INSERT INTO simulation_operation_log (
                account_id, operation_type, operation_time, status, message
            ) VALUES (
                :account_id, 'init', :operation_time, 'executed', 
                :message
            )
            """
            
            log_params = {
                'account_id': account_id,
                'operation_time': now,
                'message': f"初始化账户，总资金: {total_capital}，单支最大仓位: {single_position_limit}"
            }
            
            self._execute_database_operation(log_query, log_params)
            
            # 初始化净值记录
            today = now.strftime('%Y-%m-%d')
            net_value_query = """
            INSERT INTO simulation_net_value (
                account_id, trade_date, net_value, available_capital, holding_value,
                daily_profit_loss, accumulated_profit_loss, yield_rate
            ) VALUES (
                :account_id, :trade_date, :net_value, :available_capital, :holding_value,
                :daily_profit_loss, :accumulated_profit_loss, :yield_rate
            )
            """
            
            net_value_params = {
                'account_id': account_id,
                'trade_date': today,
                'net_value': total_capital,
                'available_capital': total_capital,
                'holding_value': 0,
                'daily_profit_loss': 0,
                'accumulated_profit_loss': 0,
                'yield_rate': 0
            }
            
            self._execute_database_operation(net_value_query, net_value_params)
            
            return {
                "success": True,
                "account_id": account_id,
                "total_capital": total_capital,
                "available_capital": total_capital,
                "message": "模拟账户创建成功"
            }
            
        except Exception as e:
            logger.error(f"初始化模拟账户出错: {str(e)}")
            return {"success": False, "message": f"初始化模拟账户出错: {str(e)}"}
    
    def buy_stock(self, account_id: str, stock_code: str) -> Dict:
        """
        买入股票
        :param account_id: 账户ID
        :param stock_code: 股票代码
        :return: 操作结果
        """
        try:
            now = datetime.now()
            # 记录操作
            operation_query = """
            INSERT INTO simulation_operation_log (
                account_id, operation_type, stock_code, operation_time, status, message
            ) VALUES (
                :account_id, 'buy', :stock_code, :operation_time, 'pending', 
                :message
            )
            """
            
            operation_params = {
                'account_id': account_id,
                'stock_code': stock_code,
                'operation_time': now,
                'message': f"买入股票 {stock_code}"
            }
            
            self._execute_database_operation(operation_query, operation_params)
            
            # 获取账户信息
            account_info = self._get_account_info(account_id)
            if not account_info['success']:
                return account_info
            
            account_data = account_info['account_data']
            
            # 获取股票信息
            stock_info = self._get_stock_info(stock_code)
            if not stock_info['success']:
                return stock_info
            
            # 确定交易日期和价格
            today = now.strftime('%Y-%m-%d')
            latest_trade_date = self._get_latest_trade_date()
            
            # 判断买入执行时间
            is_before_open = self._is_before_open(now)
            trade_date = today if is_before_open else self._get_next_trade_date(today)
            price_type = 'open'  # 按开盘价交易
            
            # 获取股票价格
            price = self._get_stock_price(stock_code, trade_date, price_type)
            
            # 如果获取不到下一个交易日的价格，使用最新交易日的收盘价作为参考
            if price is None:
                price = self._get_stock_price(stock_code, latest_trade_date, 'close')
                if price is None:
                    return {"success": False, "message": f"无法获取股票 {stock_code} 的价格信息"}
            
            # 计算可买入数量
            available_capital = float(account_data['available_capital'])
            single_position_limit = float(account_data['single_position_limit'])
            
            # 检查是否已持有该股票
            already_holding = self._check_holding_exists(account_id, stock_code)
            if already_holding:
                return {"success": False, "message": f"账户已持有股票 {stock_code}，不能重复买入"}
            
            quantity = self._calculate_buy_quantity(available_capital, price, single_position_limit)
            
            if quantity < 100:
                return {"success": False, "message": f"可用资金不足以购买最小交易单位(100股)的股票 {stock_code}"}
            
            # 计算交易金额
            trade_amount = quantity * price
            
            # 更新操作日志
            update_log_query = """
            UPDATE simulation_operation_log SET
                execution_time = :execution_time,
                execution_price = :execution_price,
                status = 'executed',
                message = :message
            WHERE account_id = :account_id AND operation_type = 'buy' AND stock_code = :stock_code
            ORDER BY id DESC LIMIT 1
            """
            
            update_log_params = {
                'execution_time': now,
                'execution_price': price,
                'message': f"买入股票 {stock_code}, 数量: {quantity}, 价格: {price}, 金额: {trade_amount}",
                'account_id': account_id,
                'stock_code': stock_code
            }
            
            self._execute_database_operation(update_log_query, update_log_params)
            
            # 添加持仓记录
            holding_query = """
            INSERT INTO simulation_holding (
                account_id, stock_code, stock_name, quantity, cost_price, 
                current_price, market_value
            ) VALUES (
                :account_id, :stock_code, :stock_name, :quantity, :cost_price,
                :current_price, :market_value
            )
            """
            
            holding_params = {
                'account_id': account_id,
                'stock_code': stock_code,
                'stock_name': stock_info['stock_name'],
                'quantity': quantity,
                'cost_price': price,
                'current_price': price,
                'market_value': trade_amount
            }
            
            self._execute_database_operation(holding_query, holding_params)
            
            # 添加交易记录
            transaction_query = """
            INSERT INTO simulation_transaction (
                account_id, stock_code, stock_name, transaction_type, 
                transaction_price, quantity, transaction_amount, trade_time
            ) VALUES (
                :account_id, :stock_code, :stock_name, 'buy',
                :transaction_price, :quantity, :transaction_amount, :trade_time
            )
            """
            
            transaction_params = {
                'account_id': account_id,
                'stock_code': stock_code,
                'stock_name': stock_info['stock_name'],
                'transaction_price': price,
                'quantity': quantity,
                'transaction_amount': trade_amount,
                'trade_time': now
            }
            
            self._execute_database_operation(transaction_query, transaction_params)
            
            # 更新账户信息
            new_available_capital = available_capital - trade_amount
            holding_value = float(account_data['holding_value']) + trade_amount
            
            update_account_query = """
            UPDATE simulation_account SET
                available_capital = :available_capital,
                holding_value = :holding_value,
                update_time = :update_time
            WHERE id = :account_id
            """
            
            update_account_params = {
                'available_capital': new_available_capital,
                'holding_value': holding_value,
                'update_time': now,
                'account_id': account_id
            }
            
            self._execute_database_operation(update_account_query, update_account_params)
            
            # 更新净值记录
            net_value_date = datetime.strptime(trade_date, '%Y-%m-%d').date()
            self._update_net_value(account_id, net_value_date)
            
            return {
                "success": True,
                "message": f"买入股票 {stock_code} 成功",
                "stock_code": stock_code,
                "stock_name": stock_info['stock_name'],
                "quantity": quantity,
                "price": price,
                "amount": trade_amount,
                "trade_date": trade_date
            }
            
        except Exception as e:
            logger.error(f"买入股票出错: {str(e)}")
            return {"success": False, "message": f"买入股票出错: {str(e)}"}
    
    def sell_stock(self, account_id: str, stock_code: str) -> Dict:
        """
        卖出股票
        :param account_id: 账户ID
        :param stock_code: 股票代码
        :return: 操作结果
        """
        try:
            now = datetime.now()
            
            # 记录操作
            operation_query = """
            INSERT INTO simulation_operation_log (
                account_id, operation_type, stock_code, operation_time, status, message
            ) VALUES (
                :account_id, 'sell', :stock_code, :operation_time, 'pending', 
                :message
            )
            """
            
            operation_params = {
                'account_id': account_id,
                'stock_code': stock_code,
                'operation_time': now,
                'message': f"卖出股票 {stock_code}"
            }
            
            self._execute_database_operation(operation_query, operation_params)
            
            # 获取账户信息
            account_info = self._get_account_info(account_id)
            if not account_info['success']:
                return account_info
            
            account_data = account_info['account_data']
            
            # 检查是否持有该股票
            holding_query = f"""
            SELECT * FROM simulation_holding 
            WHERE account_id = '{account_id}' AND stock_code = '{stock_code}'
            """
            holding = self._read_sql(holding_query)
            
            if holding.empty:
                return {"success": False, "message": f"账户未持有股票 {stock_code}，无法卖出"}
            
            holding_data = holding.iloc[0]
            
            # 确定交易日期和价格
            today = now.strftime('%Y-%m-%d')
            latest_trade_date = self._get_latest_trade_date()
            
            # 判断卖出执行时间
            is_after_close = self._is_after_close(now)
            trade_date = today if not is_after_close else self._get_next_trade_date(today)
            price_type = 'close'  # 按收盘价交易
            
            # 获取股票价格
            price = self._get_stock_price(stock_code, trade_date, price_type)
            
            # 如果获取不到当日收盘价，使用最新交易日的收盘价
            if price is None:
                price = self._get_stock_price(stock_code, latest_trade_date, 'close')
                if price is None:
                    price = float(holding_data['current_price'])  # 使用当前价格
            
            # 计算交易金额和盈亏
            quantity = int(holding_data['quantity'])
            cost_price = float(holding_data['cost_price'])
            
            trade_amount = quantity * price
            profit_loss = (price - cost_price) * quantity
            
            # 更新操作日志
            update_log_query = """
            UPDATE simulation_operation_log SET
                execution_time = :execution_time,
                execution_price = :execution_price,
                status = 'executed',
                message = :message
            WHERE account_id = :account_id AND operation_type = 'sell' AND stock_code = :stock_code
            ORDER BY id DESC LIMIT 1
            """
            
            update_log_params = {
                'execution_time': now,
                'execution_price': price,
                'message': f"卖出股票 {stock_code}, 数量: {quantity}, 价格: {price}, 金额: {trade_amount}, 盈亏: {profit_loss}",
                'account_id': account_id,
                'stock_code': stock_code
            }
            
            self._execute_database_operation(update_log_query, update_log_params)
            
            # 添加交易记录
            transaction_query = """
            INSERT INTO simulation_transaction (
                account_id, stock_code, stock_name, transaction_type, 
                transaction_price, quantity, transaction_amount, profit_loss, trade_time
            ) VALUES (
                :account_id, :stock_code, :stock_name, 'sell',
                :transaction_price, :quantity, :transaction_amount, :profit_loss, :trade_time
            )
            """
            
            transaction_params = {
                'account_id': account_id,
                'stock_code': stock_code,
                'stock_name': holding_data['stock_name'],
                'transaction_price': price,
                'quantity': quantity,
                'transaction_amount': trade_amount,
                'profit_loss': profit_loss,
                'trade_time': now
            }
            
            self._execute_database_operation(transaction_query, transaction_params)
            
            # 删除持仓记录
            delete_holding_query = f"""
            DELETE FROM simulation_holding 
            WHERE account_id = '{account_id}' AND stock_code = '{stock_code}'
            """
            
            self._execute_database_operation(delete_holding_query)
            
            # 更新账户信息
            available_capital = float(account_data['available_capital']) + trade_amount
            holding_value = float(account_data['holding_value']) - float(holding_data['market_value'])
            total_profit_loss = float(account_data['profit_loss']) + profit_loss
            
            # 更新盈亏统计
            win_count = int(account_data['win_count'])
            loss_count = int(account_data['loss_count'])
            
            if profit_loss > 0:
                win_count += 1
            else:
                loss_count += 1
            
            update_account_query = """
            UPDATE simulation_account SET
                available_capital = :available_capital,
                holding_value = :holding_value,
                profit_loss = :profit_loss,
                win_count = :win_count,
                loss_count = :loss_count,
                update_time = :update_time
            WHERE id = :account_id
            """
            
            update_account_params = {
                'available_capital': available_capital,
                'holding_value': holding_value,
                'profit_loss': total_profit_loss,
                'win_count': win_count,
                'loss_count': loss_count,
                'update_time': now,
                'account_id': account_id
            }
            
            self._execute_database_operation(update_account_query, update_account_params)
            
            # 更新净值记录
            net_value_date = datetime.strptime(trade_date, '%Y-%m-%d').date()
            self._update_net_value(account_id, net_value_date)
            
            return {
                "success": True,
                "message": f"卖出股票 {stock_code} 成功",
                "stock_code": stock_code,
                "stock_name": holding_data['stock_name'],
                "quantity": quantity,
                "price": price,
                "amount": trade_amount,
                "profit_loss": profit_loss,
                "trade_date": trade_date
            }
            
        except Exception as e:
            logger.error(f"卖出股票出错: {str(e)}")
            return {"success": False, "message": f"卖出股票出错: {str(e)}"}
    
    def _update_net_value(self, account_id: str, trade_date: datetime.date) -> bool:
        """更新账户净值"""
        try:
            # 获取账户信息
            account_info = self._get_account_info(account_id)
            if not account_info['success']:
                return False
            
            account_data = account_info['account_data']
            
            # 获取持仓信息
            holdings_query = f"""
            SELECT * FROM simulation_holding WHERE account_id = '{account_id}'
            """
            holdings = self._read_sql(holdings_query)
            
            # 计算持仓市值和持仓盈亏
            holding_value = 0
            holding_profit_loss = 0
            
            for _, holding in holdings.iterrows():
                stock_code = holding['stock_code']
                cost_price = float(holding['cost_price'])
                quantity = int(holding['quantity'])
                
                # 获取当前价格
                current_price = self._get_stock_price(
                    stock_code, 
                    trade_date.strftime('%Y-%m-%d'), 
                    'close'
                )
                
                if current_price is None:
                    # 如果获取不到，使用成本价
                    current_price = cost_price
                
                market_value = current_price * quantity
                profit_loss = (current_price - cost_price) * quantity
                profit_loss_percent = (current_price - cost_price) / cost_price if cost_price > 0 else 0
                
                # 更新持仓信息
                update_holding_query = """
                UPDATE simulation_holding SET
                    current_price = :current_price,
                    market_value = :market_value,
                    profit_loss = :profit_loss,
                    profit_loss_percent = :profit_loss_percent,
                    update_time = :update_time
                WHERE account_id = :account_id AND stock_code = :stock_code
                """
                
                update_holding_params = {
                    'current_price': current_price,
                    'market_value': market_value,
                    'profit_loss': profit_loss,
                    'profit_loss_percent': profit_loss_percent,
                    'update_time': datetime.now(),
                    'account_id': account_id,
                    'stock_code': stock_code
                }
                
                self._execute_database_operation(update_holding_query, update_holding_params)
                
                holding_value += market_value
                holding_profit_loss += profit_loss
            
            # 计算账户净值和收益率
            total_capital = float(account_data['total_capital'])
            available_capital = float(account_data['available_capital'])
            profit_loss = float(account_data['profit_loss'])  # 已清算盈亏
            
            net_value = available_capital + holding_value
            accumulated_profit_loss = profit_loss + holding_profit_loss
            yield_rate = accumulated_profit_loss / total_capital if total_capital > 0 else 0
            
            # 查询是否已有当日净值记录
            check_query = f"""
            SELECT * FROM simulation_net_value 
            WHERE account_id = '{account_id}' AND trade_date = '{trade_date}'
            """
            existing_record = self._read_sql(check_query)
            
            if not existing_record.empty:
                # 如果已有记录，更新
                daily_profit_loss = net_value - float(existing_record.iloc[0]['net_value'])
                
                update_query = """
                UPDATE simulation_net_value SET
                    net_value = :net_value,
                    available_capital = :available_capital,
                    holding_value = :holding_value,
                    daily_profit_loss = :daily_profit_loss,
                    accumulated_profit_loss = :accumulated_profit_loss,
                    yield_rate = :yield_rate,
                    create_time = :create_time
                WHERE account_id = :account_id AND trade_date = :trade_date
                """
                
                update_params = {
                    'net_value': net_value,
                    'available_capital': available_capital,
                    'holding_value': holding_value,
                    'daily_profit_loss': daily_profit_loss,
                    'accumulated_profit_loss': accumulated_profit_loss,
                    'yield_rate': yield_rate,
                    'create_time': datetime.now(),
                    'account_id': account_id,
                    'trade_date': trade_date
                }
                
                self._execute_database_operation(update_query, update_params)
            else:
                # 如果没有记录，创建新记录
                # 查询前一天的净值
                prev_date = trade_date - timedelta(days=1)
                prev_query = f"""
                SELECT * FROM simulation_net_value 
                WHERE account_id = '{account_id}' AND trade_date <= '{prev_date}'
                ORDER BY trade_date DESC LIMIT 1
                """
                prev_record = self._read_sql(prev_query)
                
                daily_profit_loss = 0
                if not prev_record.empty:
                    daily_profit_loss = net_value - float(prev_record.iloc[0]['net_value'])
                
                insert_query = """
                INSERT INTO simulation_net_value (
                    account_id, trade_date, net_value, available_capital, holding_value,
                    daily_profit_loss, accumulated_profit_loss, yield_rate
                ) VALUES (
                    :account_id, :trade_date, :net_value, :available_capital, :holding_value,
                    :daily_profit_loss, :accumulated_profit_loss, :yield_rate
                )
                """
                
                insert_params = {
                    'account_id': account_id,
                    'trade_date': trade_date,
                    'net_value': net_value,
                    'available_capital': available_capital,
                    'holding_value': holding_value,
                    'daily_profit_loss': daily_profit_loss,
                    'accumulated_profit_loss': accumulated_profit_loss,
                    'yield_rate': yield_rate
                }
                
                self._execute_database_operation(insert_query, insert_params)
            
            # 更新账户表的数据
            update_account_query = """
            UPDATE simulation_account SET
                holding_value = :holding_value,
                holding_profit_loss = :holding_profit_loss,
                strategy_yield = :strategy_yield,
                update_time = :update_time
            WHERE id = :account_id
            """
            
            update_account_params = {
                'holding_value': holding_value,
                'holding_profit_loss': holding_profit_loss,
                'strategy_yield': yield_rate,
                'update_time': datetime.now(),
                'account_id': account_id
            }
            
            self._execute_database_operation(update_account_query, update_account_params)
            
            return True
            
        except Exception as e:
            logger.error(f"更新净值出错: {str(e)}")
            return False
    
    def clear_account(self, account_id: str) -> Dict:
        """
        清仓账户所有持仓
        :param account_id: 账户ID
        :return: 操作结果
        """
        try:
            now = datetime.now()
            
            # 记录操作
            operation_query = """
            INSERT INTO simulation_operation_log (
                account_id, operation_type, operation_time, status, message
            ) VALUES (
                :account_id, 'clear', :operation_time, 'pending', 
                :message
            )
            """
            
            operation_params = {
                'account_id': account_id,
                'operation_time': now,
                'message': f"清仓账户 {account_id} 所有持仓"
            }
            
            self._execute_database_operation(operation_query, operation_params)
            
            # 获取账户信息
            account_info = self._get_account_info(account_id)
            if not account_info['success']:
                return account_info
            
            account_data = account_info['account_data']
            
            # 获取所有持仓
            holdings_query = f"""
            SELECT * FROM simulation_holding WHERE account_id = '{account_id}'
            """
            holdings = self._read_sql(holdings_query)
            
            if holdings.empty:
                return {"success": False, "message": f"账户 {account_id} 无持仓，无需清仓"}
            
            # 确定交易日期和价格
            today = now.strftime('%Y-%m-%d')
            latest_trade_date = self._get_latest_trade_date()
            
            # 判断清仓执行时间
            is_after_close = self._is_after_close(now)
            trade_date = today if not is_after_close else self._get_next_trade_date(today)
            price_type = 'close'  # 按收盘价交易
            
            total_profit_loss = 0
            clear_summary = []
            
            # 逐个处理持仓
            for _, holding in holdings.iterrows():
                stock_code = holding['stock_code']
                stock_name = holding['stock_name']
                quantity = int(holding['quantity'])
                cost_price = float(holding['cost_price'])
                
                # 获取股票价格
                price = self._get_stock_price(stock_code, trade_date, price_type)
                
                # 如果获取不到当日收盘价，使用最新交易日的收盘价
                if price is None:
                    price = self._get_stock_price(stock_code, latest_trade_date, 'close')
                    if price is None:
                        price = float(holding['current_price'])  # 使用当前价格
                
                # 计算交易金额和盈亏
                trade_amount = quantity * price
                profit_loss = (price - cost_price) * quantity
                
                # 添加交易记录
                transaction_query = """
                INSERT INTO simulation_transaction (
                    account_id, stock_code, stock_name, transaction_type, 
                    transaction_price, quantity, transaction_amount, profit_loss, trade_time
                ) VALUES (
                    :account_id, :stock_code, :stock_name, 'clear',
                    :transaction_price, :quantity, :transaction_amount, :profit_loss, :trade_time
                )
                """
                
                transaction_params = {
                    'account_id': account_id,
                    'stock_code': stock_code,
                    'stock_name': stock_name,
                    'transaction_price': price,
                    'quantity': quantity,
                    'transaction_amount': trade_amount,
                    'profit_loss': profit_loss,
                    'trade_time': now
                }
                
                self._execute_database_operation(transaction_query, transaction_params)
                
                total_profit_loss += profit_loss
                
                clear_summary.append({
                    'stock_code': stock_code,
                    'stock_name': stock_name,
                    'quantity': quantity,
                    'cost_price': cost_price,
                    'price': price,
                    'amount': trade_amount,
                    'profit_loss': profit_loss
                })
            
            # 删除所有持仓记录
            delete_holdings_query = f"""
            DELETE FROM simulation_holding WHERE account_id = '{account_id}'
            """
            
            self._execute_database_operation(delete_holdings_query)
            
            # 更新账户信息
            available_capital = float(account_data['available_capital']) + float(account_data['holding_value'])
            account_profit_loss = float(account_data['profit_loss']) + total_profit_loss
            
            # 统计盈亏情况
            win_count = int(account_data['win_count'])
            loss_count = int(account_data['loss_count'])
            
            for item in clear_summary:
                if item['profit_loss'] > 0:
                    win_count += 1
                else:
                    loss_count += 1
            
            # 计算策略收益率
            strategy_yield = account_profit_loss / float(account_data['total_capital'])
            
            update_account_query = """
            UPDATE simulation_account SET
                available_capital = :available_capital,
                holding_value = 0,
                holding_profit_loss = 0,
                profit_loss = :profit_loss,
                strategy_yield = :strategy_yield,
                win_count = :win_count,
                loss_count = :loss_count,
                status = 'closed',
                update_time = :update_time
            WHERE id = :account_id
            """
            
            update_account_params = {
                'available_capital': available_capital,
                'profit_loss': account_profit_loss,
                'strategy_yield': strategy_yield,
                'win_count': win_count,
                'loss_count': loss_count,
                'update_time': now,
                'account_id': account_id
            }
            
            self._execute_database_operation(update_account_query, update_account_params)
            
            # 更新操作日志
            update_log_query = """
            UPDATE simulation_operation_log SET
                execution_time = :execution_time,
                status = 'executed',
                message = :message
            WHERE account_id = :account_id AND operation_type = 'clear'
            ORDER BY id DESC LIMIT 1
            """
            
            update_log_params = {
                'execution_time': now,
                'message': f"成功清仓账户 {account_id} 所有持仓，总盈亏: {total_profit_loss}",
                'account_id': account_id
            }
            
            self._execute_database_operation(update_log_query, update_log_params)
            
            # 更新净值记录
            net_value_date = datetime.strptime(trade_date, '%Y-%m-%d').date()
            self._update_net_value(account_id, net_value_date)
            
            return {
                "success": True,
                "message": f"清仓账户 {account_id} 成功",
                "total_profit_loss": total_profit_loss,
                "strategy_yield": strategy_yield,
                "clear_summary": clear_summary,
                "trade_date": trade_date
            }
            
        except Exception as e:
            logger.error(f"清仓账户出错: {str(e)}")
            return {"success": False, "message": f"清仓账户出错: {str(e)}"}
    
    def get_all_accounts(self) -> Dict:
        """
        获取所有模拟账户状态
        :return: 所有账户信息
        """
        try:
            query = """
            SELECT 
                id, total_capital, available_capital, holding_value, 
                profit_loss, holding_profit_loss, 
                strategy_yield, win_count, loss_count, status,
                create_time, update_time
            FROM simulation_account
            """
            
            accounts = self._read_sql(query)
            
            if accounts.empty:
                return {"success": True, "message": "没有模拟账户", "accounts": []}
            
            # 转换为字典列表
            accounts_list = []
            for _, account in accounts.iterrows():
                # 计算总统计数据
                total_trades = account['win_count'] + account['loss_count']
                win_rate = account['win_count'] / total_trades * 100 if total_trades > 0 else 0
                
                account_dict = {
                    'account_id': account['id'],
                    'total_capital': float(account['total_capital']),
                    'available_capital': float(account['available_capital']),
                    'holding_value': float(account['holding_value']),
                    'total_value': float(account['available_capital']) + float(account['holding_value']),
                    'profit_loss': float(account['profit_loss']),
                    'holding_profit_loss': float(account['holding_profit_loss']),
                    'total_profit_loss': float(account['profit_loss']) + float(account['holding_profit_loss']),
                    'strategy_yield': float(account['strategy_yield']) * 100,  # 转为百分比
                    'win_count': account['win_count'],
                    'loss_count': account['loss_count'],
                    'total_trades': total_trades,
                    'win_rate': win_rate,
                    'status': account['status'],
                    'create_time': account['create_time'].strftime('%Y-%m-%d %H:%M:%S'),
                    'update_time': account['update_time'].strftime('%Y-%m-%d %H:%M:%S')
                }
                accounts_list.append(account_dict)
            
            return {
                "success": True,
                "message": f"获取到 {len(accounts_list)} 个模拟账户",
                "accounts": accounts_list
            }
            
        except Exception as e:
            logger.error(f"获取所有账户出错: {str(e)}")
            return {"success": False, "message": f"获取所有账户出错: {str(e)}"}
    
    def get_account_detail(self, account_id: str) -> Dict:
        """
        获取账户详细信息
        :param account_id: 账户ID
        :return: 账户详细信息
        """
        try:
            # 获取账户基本信息
            account_info = self._get_account_info(account_id)
            if not account_info['success']:
                return account_info
            
            account_data = account_info['account_data']
            
            # 获取持仓信息
            holdings_query = f"""
            SELECT * FROM simulation_holding WHERE account_id = '{account_id}'
            """
            holdings = self._read_sql(holdings_query)
            
            holdings_list = []
            for _, holding in holdings.iterrows():
                holding_dict = {
                    'stock_code': holding['stock_code'],
                    'stock_name': holding['stock_name'],
                    'quantity': int(holding['quantity']),
                    'cost_price': float(holding['cost_price']),
                    'current_price': float(holding['current_price']),
                    'market_value': float(holding['market_value']),
                    'profit_loss': float(holding['profit_loss']),
                    'profit_loss_percent': float(holding['profit_loss_percent']) * 100  # 转为百分比
                }
                holdings_list.append(holding_dict)
            
            # 获取净值变动
            net_value_query = f"""
            SELECT * FROM simulation_net_value 
            WHERE account_id = '{account_id}'
            ORDER BY trade_date
            """
            net_values = self._read_sql(net_value_query)
            
            net_values_list = []
            for _, net_value in net_values.iterrows():
                net_value_dict = {
                    'trade_date': net_value['trade_date'].strftime('%Y-%m-%d'),
                    'net_value': float(net_value['net_value']),
                    'available_capital': float(net_value['available_capital']),
                    'holding_value': float(net_value['holding_value']),
                    'daily_profit_loss': float(net_value['daily_profit_loss']),
                    'accumulated_profit_loss': float(net_value['accumulated_profit_loss']),
                    'yield_rate': float(net_value['yield_rate']) * 100  # 转为百分比
                }
                net_values_list.append(net_value_dict)
            
            # 获取交易记录
            transactions_query = f"""
            SELECT * FROM simulation_transaction 
            WHERE account_id = '{account_id}'
            ORDER BY trade_time
            """
            transactions = self._read_sql(transactions_query)
            
            transactions_list = []
            for _, transaction in transactions.iterrows():
                transaction_dict = {
                    'stock_code': transaction['stock_code'],
                    'stock_name': transaction['stock_name'],
                    'transaction_type': transaction['transaction_type'],
                    'transaction_price': float(transaction['transaction_price']),
                    'quantity': int(transaction['quantity']),
                    'transaction_amount': float(transaction['transaction_amount']),
                    'profit_loss': float(transaction['profit_loss']) if pd.notna(transaction['profit_loss']) else None,
                    'trade_time': transaction['trade_time'].strftime('%Y-%m-%d %H:%M:%S')
                }
                transactions_list.append(transaction_dict)
            
            # 计算统计数据
            total_trades = account_data['win_count'] + account_data['loss_count']
            win_rate = account_data['win_count'] / total_trades * 100 if total_trades > 0 else 0
            
            # 准备返回数据
            result = {
                "success": True,
                "account_id": account_id,
                "total_capital": float(account_data['total_capital']),
                "available_capital": float(account_data['available_capital']),
                "holding_value": float(account_data['holding_value']),
                "total_value": float(account_data['available_capital']) + float(account_data['holding_value']),
                "profit_loss": float(account_data['profit_loss']),  # 已清算盈亏
                "holding_profit_loss": float(account_data['holding_profit_loss']),  # 持仓盈亏
                "total_profit_loss": float(account_data['profit_loss']) + float(account_data['holding_profit_loss']),
                "strategy_yield": float(account_data['strategy_yield']) * 100,  # 转为百分比
                "win_count": account_data['win_count'],
                "loss_count": account_data['loss_count'],
                "total_trades": total_trades,
                "win_rate": win_rate,
                "status": account_data['status'],
                "holdings": holdings_list,
                "net_values": net_values_list,
                "transactions": transactions_list,
                "create_time": account_data['create_time'].strftime('%Y-%m-%d %H:%M:%S'),
                "update_time": account_data['update_time'].strftime('%Y-%m-%d %H:%M:%S')
            }
            
            return result
            
        except Exception as e:
            logger.error(f"获取账户详情出错: {str(e)}")
            return {"success": False, "message": f"获取账户详情出错: {str(e)}"}


def main():
    """主函数，用于测试"""
    # 数据库连接配置
    db_config = {
        'host': '192.168.18.199',
        'port': 3306,
        'user': 'root',
        'password': 'Chlry#$.8',
        'database': 'db_gp_cj'
    }
    
    # 创建数据库连接字符串
    connection_string = f"mysql+pymysql://{db_config['user']}:{db_config['password']}@{db_config['host']}:{db_config['port']}/{db_config['database']}"
    
    # 创建模拟器实例
    simulator = StockSimulator(connection_string)
    
    # 测试初始化账户
    # result = simulator.init_simulation_account(5000000, 200000)
    # print("初始化账户结果:", result)
    #
    # if result['success']:
    account_id = 'a111336c-b77c-47b2-9ea9-2717827200ba'

    # 测试买入股票
    buy_result = simulator.buy_stock(account_id, 'SH600522')
    print("买入股票结果:", buy_result)
    #
    #     # 测试获取账户详情
    #     detail_result = simulator.get_account_detail(account_id)
    #     print("账户详情:", detail_result)
    #
    #     # 测试卖出股票
    #     sell_result = simulator.sell_stock(account_id, 'SH600522')
    #     print("卖出股票结果:", sell_result)
    #
    #     # 测试再次买入股票
    #     buy_result = simulator.buy_stock(account_id, 'SH601187')
    #     print("再次买入股票结果:", buy_result)
    #
    #     # 测试清仓账户
    #     clear_result = simulator.clear_account(account_id)
    #     print("清仓账户结果:", clear_result)
    #
    # # 测试获取所有账户
    # all_accounts = simulator.get_all_accounts()
    # print("所有账户:", all_accounts)


if __name__ == "__main__":
    main() 