#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
是固态电池、人形机器人、通信设备、算力租赁四个赛道的筛选。
结合个股历史基本面，以及个股波动情况，这里波动指标是一个波动越大，分数越高的指标
v2并不是科技主题选股！！！！！！--这里就是入口--请执行这个文件！
整合企业生命周期、财务指标和平均距离因子分析
"""

import sys
import pandas as pd
import numpy as np
import logging
from typing import Dict, List, Tuple
from pathlib import Path
from sqlalchemy import create_engine, text
from datetime import datetime
import math

# 添加项目根路径到Python路径
project_root = Path(__file__).parent.parent.parent
sys.path.append(str(project_root))

# 导入依赖的工具类
from src.quantitative_analysis.company_lifecycle_factor import CompanyLifecycleFactor
from src.quantitative_analysis.financial_indicator_analyzer import FinancialIndicatorAnalyzer
from src.quantitative_analysis.average_distance_factor import AverageDistanceFactor
from src.valuation_analysis.config import MONGO_CONFIG2, DB_URL

# 设置日志
logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
)
logger = logging.getLogger(__name__)


class TechFundamentalFactorStrategy:
    """科技主题基本面因子选股策略"""
    
    def __init__(self):
        """初始化策略"""
        self.lifecycle_calculator = CompanyLifecycleFactor()
        self.financial_analyzer = FinancialIndicatorAnalyzer()
        self.distance_calculator = AverageDistanceFactor(DB_URL)
        
        # MySQL连接
        self.mysql_engine = create_engine(
            DB_URL,
            pool_size=5,
            max_overflow=10,
            pool_recycle=3600
        )
        
        # 科技概念板块列表
        self.tech_concepts = [
            "固态电池", "人形机器人", "通信设备", "算力租赁"
        ]
        logger.info("科技主题基本面因子选股策略初始化完成")
    
    def get_tech_stocks(self) -> pd.DataFrame:
        """
        获取科技概念板块的股票列表
        
        Returns:
            pd.DataFrame: 包含股票代码和名称的DataFrame
        """
        try:
            # 构建查询条件
            concepts_str = "', '".join(self.tech_concepts)
            query = text(f"""
                SELECT DISTINCT gp_code as stock_code, gp_name as stock_name, bk_name as concept_name
                FROM gp_gnbk 
                WHERE bk_name IN ('{concepts_str}')
                UNION
                SELECT DISTINCT gp_code as stock_code, gp_name as stock_name, bk_name as concept_name
                FROM gp_hybk
                WHERE bk_name = '通信设备'
                ORDER BY stock_code
            """)

            with self.mysql_engine.connect() as conn:
                df = pd.read_sql(query, conn)
            
            logger.info(f"获取到 {len(df)} 只科技概念股票")
            return df
            
        except Exception as e:
            logger.error(f"获取科技概念股票失败: {str(e)}")
            return pd.DataFrame()
    
    def filter_by_lifecycle(self, stock_codes: List[str], year: int = 2024) -> Dict[str, List[str]]:
        """
        根据企业生命周期筛选股票
        
        Args:
            stock_codes: 股票代码列表
            year: 分析年份
            
        Returns:
            Dict: 包含成长期和成熟期股票的字典
        """
        try:
            logger.info(f"开始分析 {len(stock_codes)} 只股票的企业生命周期")
            
            # 批量计算生命周期
            lifecycle_df = self.lifecycle_calculator.batch_calculate_lifecycle_factors(stock_codes, year)
            
            # 筛选目标阶段的股票
            # 引入期(1)和成长期(2)合并为成长期，成熟期(3)保持不变
            growth_stage_stocks = lifecycle_df[
                lifecycle_df['stage_id'].isin([1, 2])
            ]['stock_code'].tolist()
            
            mature_stage_stocks = lifecycle_df[
                lifecycle_df['stage_id'] == 3
            ]['stock_code'].tolist()
            
            result = {
                'growth': growth_stage_stocks,
                'mature': mature_stage_stocks
            }
            
            logger.info(f"成长期股票: {len(growth_stage_stocks)} 只")
            logger.info(f"成熟期股票: {len(mature_stage_stocks)} 只")
            
            return result
            
        except Exception as e:
            logger.error(f"生命周期筛选失败: {str(e)}")
            return {'growth': [], 'mature': []}
    
    def calculate_distance_factors(self, growth_stocks: List[str], mature_stocks: List[str]) -> Tuple[pd.DataFrame, pd.DataFrame]:
        """
        分别计算成长期和成熟期股票的平均距离因子
        
        Args:
            growth_stocks: 成长期股票列表
            mature_stocks: 成熟期股票列表
            
        Returns:
            Tuple: (成长期距离因子DataFrame, 成熟期距离因子DataFrame)
        """
        try:
            growth_distance_df = pd.DataFrame()
            mature_distance_df = pd.DataFrame()
            
            # 计算成长期股票距离因子
            if growth_stocks:
                logger.info(f"计算 {len(growth_stocks)} 只成长期股票的距离因子")
                growth_data = self.distance_calculator.get_stock_data(growth_stocks)
                if not growth_data.empty:
                    growth_indicators = self.distance_calculator.calculate_technical_indicators(growth_data)
                    growth_distance_df = self.distance_calculator.calculate_distance_factor(growth_indicators)
            
            # 计算成熟期股票距离因子
            if mature_stocks:
                logger.info(f"计算 {len(mature_stocks)} 只成熟期股票的距离因子")
                mature_data = self.distance_calculator.get_stock_data(mature_stocks)
                if not mature_data.empty:
                    mature_indicators = self.distance_calculator.calculate_technical_indicators(mature_data)
                    mature_distance_df = self.distance_calculator.calculate_distance_factor(mature_indicators)
            
            return growth_distance_df, mature_distance_df
            
        except Exception as e:
            logger.error(f"计算距离因子失败: {str(e)}")
            return pd.DataFrame(), pd.DataFrame()
    
    def calculate_common_factors(self, stock_codes: List[str]) -> pd.DataFrame:
        """
        计算通用因子
        
        Args:
            stock_codes: 股票代码列表
            
        Returns:
            pd.DataFrame: 包含通用因子的DataFrame
        """
        try:
            logger.info(f"计算 {len(stock_codes)} 只股票的通用因子")
            
            results = []
            latest_date = "2025-06-30"  # 最新季度数据
            annual_date = "2024-12-31"  # 年报数据
            
            for stock_code in stock_codes:
                try:

                    factor_data = {'stock_code': stock_code}
                    
                    # 1. 毛利率（使用最新数据）
                    gross_margin = self.financial_analyzer.analyze_gross_profit_margin(stock_code, latest_date)
                    factor_data['gross_profit_margin'] = gross_margin
                    
                    # 2. 成长能力指标
                    growth_capability = self.financial_analyzer.analyze_growth_capability(stock_code)
                    if growth_capability is not None:
                        # 成长能力越高越好，使用sigmoid函数映射到0-1
                        growth_score = 1 / (1 + math.exp(-growth_capability))
                    else:
                        growth_score = 0.5  # 默认中性评分
                    factor_data['growth_score'] = growth_score
                    
                    # 3. 前五大供应商占比（使用年报数据）
                    supplier_conc = self.financial_analyzer.analyze_supplier_concentration(stock_code, annual_date)
                    factor_data['supplier_concentration'] = supplier_conc

                    # 4. 前五大客户占比（使用年报数据）
                    customer_conc = self.financial_analyzer.analyze_customer_concentration(stock_code, annual_date)
                    factor_data['customer_concentration'] = customer_conc
                    
                    results.append(factor_data)
                    
                except Exception as e:
                    logger.warning(f"计算股票 {stock_code} 通用因子失败: {str(e)}")
                    continue
            
            df = pd.DataFrame(results)
            logger.info(f"成功计算 {len(df)} 只股票的通用因子")
            return df
            
        except Exception as e:
            logger.error(f"计算通用因子失败: {str(e)}")
            return pd.DataFrame()
    
    def calculate_growth_specific_factors(self, stock_codes: List[str]) -> pd.DataFrame:
        """
        计算成长期特色因子
        
        Args:
            stock_codes: 成长期股票代码列表
            
        Returns:
            pd.DataFrame: 包含成长期特色因子的DataFrame
        """
        try:
            logger.info(f"计算 {len(stock_codes)} 只成长期股票的特色因子")
            
            results = []
            latest_date = "2025-06-30"  # 使用最新数据
            annual_date = "2024-12-31"  # 使用年度数据

            for stock_code in stock_codes:
                try:

                    factor_data = {'stock_code': stock_code}
                    
                    # 1. 管理费用率（使用最新数据）
                    admin_ratio = self.financial_analyzer.analyze_admin_expense_ratio(stock_code, latest_date)
                    factor_data['admin_expense_ratio'] = admin_ratio
                    
                    # 2. 研发费用折旧摊销占比（使用年度数据）
                    # financial_data = self.financial_analyzer.get_financial_data(stock_code, latest_date)
                    financial_data = self.financial_analyzer.get_financial_data(stock_code, annual_date)
                    if financial_data:
                        intangible_amortize = financial_data.get('cash_flow_statement', {}).get('IA_AMORTIZE', 0)
                        rd_expense = financial_data.get('profit_statement', {}).get('RESEARCH_EXPENSE', 0)
                        
                        if rd_expense and rd_expense != 0:
                            rd_amortize_ratio = intangible_amortize / rd_expense if intangible_amortize else 0
                        else:
                            rd_amortize_ratio = None  # 使用None而不是0，避免这些股票获得最高分
                        
                        factor_data['rd_amortize_ratio'] = rd_amortize_ratio
                    else:
                        factor_data['rd_amortize_ratio'] = None
                    
                    # 3. 资产负债率（使用最新数据）
                    asset_liability_ratio = self.financial_analyzer.analyze_asset_liability_ratio(stock_code, latest_date)
                    factor_data['asset_liability_ratio'] = asset_liability_ratio
                    
                    results.append(factor_data)
                    
                except Exception as e:
                    logger.warning(f"计算股票 {stock_code} 成长期特色因子失败: {str(e)}")
                    continue
            
            df = pd.DataFrame(results)
            logger.info(f"成功计算 {len(df)} 只成长期股票的特色因子")
            return df
            
        except Exception as e:
            logger.error(f"计算成长期特色因子失败: {str(e)}")
            return pd.DataFrame()
    
    def calculate_mature_specific_factors(self, stock_codes: List[str]) -> pd.DataFrame:
        """
        计算成熟期特色因子
        
        Args:
            stock_codes: 成熟期股票代码列表
            
        Returns:
            pd.DataFrame: 包含成熟期特色因子的DataFrame
        """
        try:
            logger.info(f"计算 {len(stock_codes)} 只成熟期股票的特色因子")
            
            latest_date = "2025-06-30"  # 使用最新数据
            
            # 在循环外获取全A股PB和ROE数据，避免重复查询
            logger.info("获取全A股PB数据...")
            all_pb_data = self.financial_analyzer.get_all_stocks_pb_data()
            
            logger.info("获取全A股ROE数据...")
            all_roe_data = self.financial_analyzer.get_all_stocks_roe_data(latest_date)
            
            results = []
            
            for stock_code in stock_codes:
                try:
                    factor_data = {'stock_code': stock_code}
                    
                    # 1. 应收账款周转率（使用最新数据）
                    formatted_stock_code = self.financial_analyzer.code_formatter.to_dot_format(stock_code)
                    financial_data = self.financial_analyzer.get_financial_data(formatted_stock_code, latest_date)
                    if financial_data:
                        revenue = financial_data.get('profit_statement', {}).get('OPERATE_INCOME', 0)
                        accounts_rece = financial_data.get('balance_sheet', {}).get('ACCOUNTS_RECE', 0)
                        
                        if accounts_rece and accounts_rece != 0:
                            turnover_ratio = revenue / accounts_rece if revenue else 0
                        else:
                            turnover_ratio = None  # 使用None而不是0
                        
                        factor_data['accounts_receivable_turnover'] = turnover_ratio
                    else:
                        factor_data['accounts_receivable_turnover'] = None
                    
                    # 2. 研发强度（使用最新数据）
                    rd_intensity = self.financial_analyzer.analyze_rd_expense_ratio(stock_code, latest_date)
                    factor_data['rd_intensity'] = rd_intensity
                    
                    # 3. PB-ROE排名因子：使用预获取的全A股数据
                    if all_pb_data and all_roe_data:
                        pb_roe_rank_factor = self.financial_analyzer.calculate_pb_roe_rank_factor(
                            stock_code, all_pb_data, all_roe_data
                        )
                        factor_data['pb_roe_rank_factor'] = pb_roe_rank_factor
                    else:
                        factor_data['pb_roe_rank_factor'] = None
                    
                    results.append(factor_data)
                    
                except Exception as e:
                    logger.warning(f"计算股票 {stock_code} 成熟期特色因子失败: {str(e)}")
                    continue
            
            df = pd.DataFrame(results)
            logger.info(f"成功计算 {len(df)} 只成熟期股票的特色因子")
            return df
            
        except Exception as e:
            logger.error(f"计算成熟期特色因子失败: {str(e)}")
            return pd.DataFrame()
    
    def run_strategy(self, year: int = 2024) -> Dict[str, pd.DataFrame]:
        """
        运行完整的选股策略
        
        Args:
            year: 分析年份
            
        Returns:
            Dict: 包含成长期和成熟期股票分析结果的字典
        """
        try:
            logger.info("开始运行科技主题基本面因子选股策略")
            
            # 1. 获取科技概念股票
            tech_stocks_df = self.get_tech_stocks()
            if tech_stocks_df.empty:
                logger.error("未获取到科技概念股票")
                return {}
            
            stock_codes = tech_stocks_df['stock_code'].unique().tolist()
            logger.info(f"共获取到 {len(stock_codes)} 只科技概念股票")
            
            # 2. 按企业生命周期筛选
            lifecycle_result = self.filter_by_lifecycle(stock_codes, year)
            growth_stocks = lifecycle_result['growth']
            mature_stocks = lifecycle_result['mature']
            
            if not growth_stocks and not mature_stocks:
                logger.warning("未找到符合条件的成长期或成熟期股票")
                return {}
            
            # 3. 计算平均距离因子
            growth_distance_df, mature_distance_df = self.calculate_distance_factors(growth_stocks, mature_stocks)
            
            # 4. 计算通用因子
            all_qualified_stocks = growth_stocks + mature_stocks
            common_factors_df = self.calculate_common_factors(all_qualified_stocks)
            
            # 5. 计算特色因子
            growth_specific_df = self.calculate_growth_specific_factors(growth_stocks) if growth_stocks else pd.DataFrame()
            mature_specific_df = self.calculate_mature_specific_factors(mature_stocks) if mature_stocks else pd.DataFrame()
            
            # 6. 合并结果并计算分数
            result = {}
            
            # 处理成长期股票
            if not growth_specific_df.empty:
                # 成长期结果合并
                growth_result = growth_specific_df.copy()
                
                # 合并距离因子
                if not growth_distance_df.empty:
                    growth_result = growth_result.merge(
                        growth_distance_df[['symbol', 'avg_distance_factor']], 
                        left_on='stock_code', right_on='symbol', how='left'
                    ).drop('symbol', axis=1)
                
                # 合并通用因子
                if not common_factors_df.empty:
                    growth_result = growth_result.merge(
                        common_factors_df, on='stock_code', how='left'
                    )
                
                # 计算因子分数
                growth_result = self.calculate_factor_scores(growth_result, 'growth')
                
                # 计算总分并排序
                growth_result = self.calculate_total_score(growth_result, 'growth')
                
                result['growth'] = growth_result
                logger.info(f"成长期结果: {len(growth_result)} 只股票")
            
            # 处理成熟期股票
            if not mature_specific_df.empty:
                # 成熟期结果合并
                mature_result = mature_specific_df.copy()
                
                # 合并距离因子
                if not mature_distance_df.empty:
                    mature_result = mature_result.merge(
                        mature_distance_df[['symbol', 'avg_distance_factor']], 
                        left_on='stock_code', right_on='symbol', how='left'
                    ).drop('symbol', axis=1)
                
                # 合并通用因子
                if not common_factors_df.empty:
                    mature_result = mature_result.merge(
                        common_factors_df, on='stock_code', how='left'
                    )
                
                # 计算因子分数
                mature_result = self.calculate_factor_scores(mature_result, 'mature')
                
                # 计算总分并排序
                mature_result = self.calculate_total_score(mature_result, 'mature')
                
                result['mature'] = mature_result
                logger.info(f"成熟期结果: {len(mature_result)} 只股票")
            
            logger.info("科技主题基本面因子选股策略运行完成")
            return result
            
        except Exception as e:
            logger.error(f"策略运行失败: {str(e)}")
            return {}
    
    def calculate_factor_scores(self, df: pd.DataFrame, stage: str) -> pd.DataFrame:
        """
        计算单因子打分（0-100分位数）
        
        Args:
            df: 包含因子数据的DataFrame
            stage: 阶段类型 ('growth' 或 'mature')
            
        Returns:
            pd.DataFrame: 包含因子分数的DataFrame
        """
        try:
            if df.empty:
                return df
            
            df_scored = df.copy()
            
            # 定义因子方向（正向为True，负向为False）
            factor_directions = {
                # 通用因子
                'gross_profit_margin': True,  # 毛利率_环比增量 - 正向
                'growth_score': True,       # 成长能力 - 正向
                'supplier_concentration': False,  # 前5大供应商金额占比合计 - 负向
                'customer_concentration': False,  # 前5大客户收入金额占比合计 - 负向
                'avg_distance_factor': True,     # 平均距离因子 - 负向
                
                # 成长期特色因子
                'admin_expense_ratio': False,     # 管理费用/营业总收入_环比增量 - 负向
                'rd_amortize_ratio': False,       # 研发费用折旧摊销占比_环比增量 - 负向
                'asset_liability_ratio': True,    # 资产负债率 - 正向
                
                # 成熟期特色因子
                'accounts_receivable_turnover': True,  # 应收账款周转率 - 正向
                'rd_intensity': True,                  # 研发费用直接投入占比_环比增量 - 正向
                'pb_roe_rank_factor': False            # PB-ROE排名因子 - 负向（越小越好）
            }
            
            # 为每个因子计算分位数分数
            for column in df.columns:
                if column == 'stock_code':
                    continue
                
                # 只对有效值进行排名计算
                values = df_scored[column].dropna()
                if len(values) <= 1:
                    # 如果只有一个值或没有值，所有股票都得50分或0分
                    if len(values) == 1:
                        df_scored[f'{column}_score'] = df_scored[column].apply(lambda x: 50 if pd.notna(x) else 0)
                    else:
                        df_scored[f'{column}_score'] = 0
                    continue
                
                # 根据因子方向确定排序方式
                is_positive = factor_directions.get(column, True)
                
                # 计算排名分数
                if is_positive:
                    # 正向因子：值越大分数越高
                    ranked_values = values.rank(pct=True) * 100
                else:
                    # 负向因子：值越小分数越高
                    ranked_values = (1 - values.rank(pct=True)) * 100
                
                # 初始化分数列
                df_scored[f'{column}_score'] = 0.0
                
                # 将分数赋值给对应的行
                for idx in ranked_values.index:
                    df_scored.loc[idx, f'{column}_score'] = ranked_values[idx]
            
            logger.info(f"完成 {stage} 阶段 {len(df_scored)} 只股票的因子打分")
            return df_scored
            
        except Exception as e:
            logger.error(f"计算因子分数失败: {str(e)}")
            import traceback
            traceback.print_exc()
            return df
    
    def calculate_total_score(self, df: pd.DataFrame, stage: str) -> pd.DataFrame:
        """
        计算总分
        使用公式：总分 = 1/8 * Mean(Si) + Mean(Si)/Std(Si)
        
        Args:
            df: 包含因子分数的DataFrame
            stage: 阶段类型 ('growth' 或 'mature')
            
        Returns:
            pd.DataFrame: 包含总分的DataFrame
        """
        try:
            if df.empty:
                return df
            
            df_result = df.copy()
            
            # 定义因子权重（注意：这里是factor_score而不是factor）
            if stage == 'growth':
                factor_weights = {
                    # 通用因子
                    'gross_profit_margin_score': 1/8,
                    'growth_score_score': 1/8,  # 注意这里是growth_score_score
                    'supplier_concentration_score': 1/8,
                    'customer_concentration_score': 1/8,
                    'avg_distance_factor_score': 2/8,
                    
                    # 成长期特色因子
                    'admin_expense_ratio_score': 1/8,
                    'rd_amortize_ratio_score': 1/8,
                    'asset_liability_ratio_score': 1/8
                }
            else:  # mature
                factor_weights = {
                    # 通用因子
                    'gross_profit_margin_score': 1/8,
                    'growth_score_score': 1/8,  # 注意这里是growth_score_score
                    'supplier_concentration_score': 1/8,
                    'customer_concentration_score': 1/8,
                    'avg_distance_factor_score': 2/8,
                    
                    # 成熟期特色因子
                    'accounts_receivable_turnover_score': 1/8,
                    'rd_intensity_score': 1/8,
                    'pb_roe_rank_factor_score': 1/8
                }
            
            # 计算每只股票的总分
            total_scores = []
            
            for index, row in df_result.iterrows():
                # 获取该股票的所有因子分数
                factor_scores = []
                valid_weights = []
                
                for factor, weight in factor_weights.items():
                    if factor in row and pd.notna(row[factor]) and row[factor] > 0:
                        factor_scores.append(row[factor])
                        valid_weights.append(weight)
                
                if len(factor_scores) == 0:
                    total_scores.append(0)
                    continue
                
                factor_scores = np.array(factor_scores)
                valid_weights = np.array(valid_weights)
                
                # 重新标准化权重
                valid_weights = valid_weights / valid_weights.sum()
                
                # 计算加权平均分数
                mean_score = np.average(factor_scores, weights=valid_weights)
                
                # 计算调整项 Mean(Si)/Std(Si)
                if len(factor_scores) > 1 and np.std(factor_scores) > 0:
                    adjustment = np.mean(factor_scores) / np.std(factor_scores)
                else:
                    adjustment = 0
                
                # 计算总分：1/8 * Mean(Si) + Mean(Si)/Std(Si)
                total_score = (1/8) * mean_score + adjustment
                total_scores.append(total_score)
            
            df_result['total_score'] = total_scores
            
            # 按总分降序排列
            df_result = df_result.sort_values('total_score', ascending=False).reset_index(drop=True)
            df_result['rank'] = range(1, len(df_result) + 1)
            
            logger.info(f"完成 {stage} 阶段 {len(df_result)} 只股票的总分计算")
            return df_result
            
        except Exception as e:
            logger.error(f"计算总分失败: {str(e)}")
            import traceback
            traceback.print_exc()
            return df
    
    def close_connections(self):
        """关闭所有数据库连接"""
        try:
            if hasattr(self, 'lifecycle_calculator'):
                del self.lifecycle_calculator
            if hasattr(self, 'financial_analyzer'):
                self.financial_analyzer.close_connection()
            if hasattr(self, 'distance_calculator'):
                del self.distance_calculator
            if hasattr(self, 'mysql_engine'):
                self.mysql_engine.dispose()
            logger.info("数据库连接已关闭")
        except Exception as e:
            logger.error(f"关闭连接失败: {str(e)}")


def main():
    """主函数 - 科技主题基本面因子选股策略"""
    strategy = None
    try:
        print("=== 科技主题基本面因子选股策略 ===")
        print("数据说明:")
        print("- 毛利率、净利润增长率等：使用最新数据 (2025-06-30)")
        print("- 供应商客户集中度、折旧摊销、研发费用：使用年报数据 (2024-12-31)")
        print()
        
        # 创建策略实例
        strategy = TechFundamentalFactorStrategy()
        logger.info("策略实例创建成功")
        
        # 运行策略
        results = strategy.run_strategy(year=2024)
        
        # 输出结果
        if not results:
            print("未获得分析结果")
            return
            
        for stage, df in results.items():
            print(f"\n=== {stage.upper()} 阶段股票分析结果 ===")
            print(f"股票数量: {len(df)}")
            
            if not df.empty:
                # 调试：显示所有列名
                print(f"数据列: {list(df.columns)}")
                # 显示前5只股票的关键指标
                print("\n前5只股票:")
                display_columns = [
                    'stock_code', 'gross_profit_margin', 'growth_score', 
                    'supplier_concentration', 'customer_concentration', 
                    'total_score', 'rank'
                ]
                available_columns = [col for col in display_columns if col in df.columns]
                print(df[available_columns].head(5).to_string(index=False))

                # 保存完整结果
                output_file = f"tech_fundamental_factor_{stage}_{datetime.now().strftime('%Y%m%d_%H%M')}.csv"
                df.to_csv(output_file, index=False, encoding='utf-8-sig')
                print(f"\n完整结果已保存到: {output_file}")
                
                # 显示统计信息
                print(f"\n统计信息:")
                print(f"  平均总分: {df['total_score'].mean():.2f}")
                print(f"  最高总分: {df['total_score'].max():.2f}")
                print(f"  最低总分: {df['total_score'].min():.2f}")
        
        # 生成成长+成熟合并的简表（仅三列：股票代码、总分、排名）
        combined_parts = []
        for stage, df in results.items():
            if isinstance(df, pd.DataFrame) and not df.empty:
                if 'stock_code' in df.columns and 'total_score' in df.columns:
                    combined_parts.append(df[['stock_code', 'total_score']].copy())
        
        if combined_parts:
            combined_df = pd.concat(combined_parts, ignore_index=True)
            # 去除总分为空的数据
            combined_df = combined_df.dropna(subset=['total_score'])
            # 按总分降序并重新排名
            combined_df = combined_df.sort_values('total_score', ascending=False).reset_index(drop=True)
            combined_df['rank'] = range(1, len(combined_df) + 1)
            # 追加概念列：获取每个股票所属概念（若多概念则以逗号分隔）
            try:
                concept_df = strategy.get_tech_stocks()
                if not concept_df.empty and 'stock_code' in concept_df.columns and 'concept_name' in concept_df.columns:
                    concept_map = (
                        concept_df.groupby('stock_code')['concept_name']
                        .apply(lambda s: ','.join(sorted(set([str(x) for x in s if pd.notna(x)]))))
                        .to_dict()
                    )
                    combined_df['concepts'] = combined_df['stock_code'].map(concept_map)
                else:
                    combined_df['concepts'] = None
            except Exception:
                combined_df['concepts'] = None
            # 保存文件
            combined_file = f"tech_fundamental_factor_all_{datetime.now().strftime('%Y%m%d_%H%M')}.csv"
            combined_df.to_csv(combined_file, index=False, encoding='utf-8-sig')
            print(f"\n=== 合并结果（成长+成熟） ===")
            print(f"总股票数量: {len(combined_df)}")
            print(combined_df.head(10).to_string(index=False))
            print(f"\n合并简表已保存到: {combined_file}")
        
        print(f"\n=== 策略运行完成 ===")
        
    except Exception as e:
        logger.error(f"程序执行失败: {str(e)}")
        import traceback
        traceback.print_exc()
    finally:
        if strategy:
            strategy.close_connections()


if __name__ == "__main__":
    main()