""" 投资分析引擎 提供基本面分析、技术面分析和估值分析功能 """ import pandas as pd import numpy as np from typing import Dict, List, Tuple, Optional from dataclasses import dataclass from enum import Enum class InvestmentRating(Enum): """投资评级""" BUY = "买入" ACCUMULATE = "增持" HOLD = "持有" REDUCE = "减持" SELL = "卖出" class RiskLevel(Enum): """风险等级""" LOW = "低风险" LOW_MEDIUM = "中低风险" MEDIUM = "中等风险" MEDIUM_HIGH = "中高风险" HIGH = "高风险" @dataclass class TechnicalAnalysis: """技术分析结果""" trend: str # 趋势判断 support_level: float # 支撑位 resistance_level: float # 阻力位 volatility: float # 波动率 ma_status: str # 均线状态 technical_summary: str # 技术总结 @dataclass class FundamentalAnalysis: """基本面分析结果""" roe: float # 净资产收益率 roe_comment: str # ROE评价 pe_ttm: float # 市盈率TTM pb_lf: float # 市净率LF valuation_comment: str # 估值评价 fundamental_summary: str # 基本面总结 @dataclass class InvestmentRecommendation: """投资建议""" rating: InvestmentRating target_price: float risk_level: RiskLevel recommendation_text: str key_factors: List[str] class AnalysisEngine: """ 投资分析引擎 """ # ROE评价标准 ROE_THRESHOLDS = { 'excellent': 20, 'good': 15, 'average': 10, 'poor': 5 } # PE评价标准(参考值,实际应根据行业调整) PE_THRESHOLDS = { 'undervalued': 15, 'fair': 25, 'overvalued': 35 } # PB评价标准 PB_THRESHOLDS = { 'undervalued': 1.5, 'fair': 3.0, 'overvalued': 5.0 } def __init__(self, price_df: pd.DataFrame, financial_data: Dict): """ 初始化分析引擎 Args: price_df: 价格数据DataFrame financial_data: 财务数据字典 """ self.price_df = price_df.copy() self.financial_data = financial_data # 计算涨跌幅和收益率 if 'pct_chg' not in self.price_df.columns and 'close' in self.price_df.columns: self.price_df['pct_chg'] = self.price_df['close'].pct_change() * 100 def analyze_technical(self) -> TechnicalAnalysis: """ 技术分析 Returns: TechnicalAnalysis对象 """ df = self.price_df # 计算均线 if 'ma5' not in df.columns: df['ma5'] = df['close'].rolling(window=5).mean() if 'ma10' not in df.columns: df['ma10'] = df['close'].rolling(window=10).mean() if 'ma20' not in df.columns: df['ma20'] = df['close'].rolling(window=20).mean() latest = df.iloc[-1] # 趋势判断 if latest['close'] > latest['ma5'] > latest['ma10'] > latest['ma20']: trend = "强势上涨" elif latest['close'] > latest['ma5'] > latest['ma10']: trend = "震荡上行" elif latest['close'] < latest['ma5'] < latest['ma10'] < latest['ma20']: trend = "强势下跌" elif latest['close'] < latest['ma5'] < latest['ma10']: trend = "震荡下行" else: trend = "震荡整理" # 计算支撑位和阻力位(基于近期高低点) recent_data = df.tail(20) support_level = recent_data['low'].min() resistance_level = recent_data['high'].max() # 计算波动率 returns = df['close'].pct_change().dropna() volatility = returns.std() * np.sqrt(52) * 100 # 年化波动率 # 均线状态 if latest['ma5'] > latest['ma20']: ma_status = "多头排列" elif latest['ma5'] < latest['ma20']: ma_status = "空头排列" else: ma_status = "均线粘合" # 技术总结 if trend in ["强势上涨", "震荡上行"] and ma_status == "多头排列": technical_summary = "技术面呈上升趋势,建议关注回调买入机会。" elif trend in ["强势下跌", "震荡下行"]: technical_summary = "技术面呈下降趋势,建议观望或减仓。" else: technical_summary = "技术面呈震荡格局,建议高抛低吸。" return TechnicalAnalysis( trend=trend, support_level=round(support_level, 2), resistance_level=round(resistance_level, 2), volatility=round(volatility, 2), ma_status=ma_status, technical_summary=technical_summary ) def analyze_fundamental(self) -> FundamentalAnalysis: """ 基本面分析 Returns: FundamentalAnalysis对象 """ # 获取ROE roe = self.financial_data.get('roe_wgt', 0) or self.financial_data.get('roe', 0) # ROE评价 if roe >= self.ROE_THRESHOLDS['excellent']: roe_comment = "ROE表现优异,公司盈利能力强劲" elif roe >= self.ROE_THRESHOLDS['good']: roe_comment = "ROE表现良好,盈利能力较强" elif roe >= self.ROE_THRESHOLDS['average']: roe_comment = "ROE处于行业平均水平" else: roe_comment = "ROE偏低,需关注盈利能力改善" # 获取PE和PB pe_ttm = self.financial_data.get('pe_ttm', 0) or self.price_df['pe_ttm'].iloc[-1] if 'pe_ttm' in self.price_df.columns else 0 pb_lf = self.financial_data.get('pb_lf', 0) or self.price_df['pb_lf'].iloc[-1] if 'pb_lf' in self.price_df.columns else 0 # 估值评价 if pe_ttm <= self.PE_THRESHOLDS['undervalued'] and pb_lf <= self.PB_THRESHOLDS['undervalued']: valuation_comment = "估值处于历史低位,具备较高安全边际" elif pe_ttm <= self.PE_THRESHOLDS['fair']: valuation_comment = "估值处于合理区间" elif pe_ttm <= self.PE_THRESHOLDS['overvalued']: valuation_comment = "估值略高,需关注业绩成长性" else: valuation_comment = "估值偏高,注意追高风险" # 基本面总结 if roe >= self.ROE_THRESHOLDS['good'] and pe_ttm <= self.PE_THRESHOLDS['fair']: fundamental_summary = "公司基本面健康,盈利能力强,估值合理,具备投资价值。" elif roe >= self.ROE_THRESHOLDS['good']: fundamental_summary = "公司盈利能力较强,但估值偏高,建议等待回调机会。" else: fundamental_summary = "公司基本面一般,建议谨慎观望。" return FundamentalAnalysis( roe=round(roe, 2) if roe else 0, roe_comment=roe_comment, pe_ttm=round(pe_ttm, 2) if pe_ttm else 0, pb_lf=round(pb_lf, 2) if pb_lf else 0, valuation_comment=valuation_comment, fundamental_summary=fundamental_summary ) def generate_recommendation(self, current_price: float, fundamental: FundamentalAnalysis = None, technical: TechnicalAnalysis = None) -> InvestmentRecommendation: """ 生成投资建议 Args: current_price: 当前价格 fundamental: 基本面分析结果 technical: 技术面分析结果 Returns: InvestmentRecommendation对象 """ if fundamental is None: fundamental = self.analyze_fundamental() if technical is None: technical = self.analyze_technical() # 综合评分 score = 0 # 基本面评分 if fundamental.roe >= self.ROE_THRESHOLDS['excellent']: score += 3 elif fundamental.roe >= self.ROE_THRESHOLDS['good']: score += 2 elif fundamental.roe >= self.ROE_THRESHOLDS['average']: score += 1 # 估值评分 if fundamental.pe_ttm <= self.PE_THRESHOLDS['undervalued']: score += 3 elif fundamental.pe_ttm <= self.PE_THRESHOLDS['fair']: score += 2 elif fundamental.pe_ttm <= self.PE_THRESHOLDS['overvalued']: score += 1 # 技术面评分 if technical.trend in ["强势上涨", "震荡上行"]: score += 2 elif technical.trend == "震荡整理": score += 1 # 风险等级 if technical.volatility > 50: risk_level = RiskLevel.HIGH elif technical.volatility > 35: risk_level = RiskLevel.MEDIUM_HIGH elif technical.volatility > 25: risk_level = RiskLevel.MEDIUM elif technical.volatility > 15: risk_level = RiskLevel.LOW_MEDIUM else: risk_level = RiskLevel.LOW # 目标价格计算(基于PE和支撑阻力) target_price_pe = current_price * (self.PE_THRESHOLDS['fair'] / max(fundamental.pe_ttm, 1)) target_price_resistance = technical.resistance_level * 1.1 target_price = round((target_price_pe + target_price_resistance) / 2, 2) # 投资建议 key_factors = [] if score >= 6: rating = InvestmentRating.BUY recommendation_text = f"综合基本面和技术面分析,该股投资价值较高。目标价{target_price}元,建议逢低买入。" key_factors.append("盈利能力强劲,ROE表现优异") elif score >= 4: rating = InvestmentRating.ACCUMULATE recommendation_text = f"公司基本面良好,建议关注回调机会逐步建仓。目标价{target_price}元。" key_factors.append("基本面稳健,估值合理") elif score >= 2: rating = InvestmentRating.HOLD recommendation_text = "公司基本面一般,当前估值合理,建议持有观望。" key_factors.append("基本面中性,估值合理") else: rating = InvestmentRating.REDUCE recommendation_text = "公司基本面较弱或估值偏高,建议谨慎或减仓。" key_factors.append("基本面一般或估值偏高") if technical.trend in ["强势上涨", "震荡上行"]: key_factors.append("技术面呈上升趋势") elif technical.trend in ["强势下跌", "震荡下行"]: key_factors.append("技术面呈下降趋势") if fundamental.pe_ttm <= self.PE_THRESHOLDS['undervalued']: key_factors.append("估值处于历史低位") return InvestmentRecommendation( rating=rating, target_price=target_price, risk_level=risk_level, recommendation_text=recommendation_text, key_factors=key_factors ) def generate_core_summary(self, fundamental: FundamentalAnalysis = None, technical: TechnicalAnalysis = None, recommendation: InvestmentRecommendation = None) -> List[str]: """ 生成核心提要要点 Returns: 要点列表 """ if fundamental is None: fundamental = self.analyze_fundamental() if technical is None: technical = self.analyze_technical() if recommendation is None: # 获取最新价格 latest_price = self.price_df['close'].iloc[-1] if 'close' in self.price_df.columns else 0 recommendation = self.generate_recommendation(latest_price, fundamental, technical) summary_points = [] # ROE要点 if fundamental.roe > 0: summary_points.append( f"该公司最新净资产收益率(ROE)为{fundamental.roe}%,{fundamental.roe_comment}" ) # 估值要点 if fundamental.pe_ttm > 0: summary_points.append( f"当前市盈率(TTM)为{fundamental.pe_ttm}倍,{fundamental.valuation_comment}" ) # 技术面要点 summary_points.append( f"技术面显示股价呈现{technical.trend}趋势,{technical.technical_summary}" ) # 投资建议要点 summary_points.append( f"给予\"{recommendation.rating.value}\"评级,目标价格{recommendation.target_price}元,风险等级为{recommendation.risk_level.value}" ) return summary_points def get_price_statistics(self) -> Dict: """ 获取价格统计数据 Returns: 统计数据字典 """ df = self.price_df if len(df) == 0: return {} return { 'latest_price': round(df['close'].iloc[-1], 2), 'highest_price': round(df['high'].max(), 2), 'lowest_price': round(df['low'].min(), 2), 'avg_price': round(df['close'].mean(), 2), 'total_change': round(((df['close'].iloc[-1] / df['close'].iloc[0]) - 1) * 100, 2), 'max_daily_gain': round(df['pct_chg'].max(), 2) if 'pct_chg' in df.columns else 0, 'max_daily_loss': round(df['pct_chg'].min(), 2) if 'pct_chg' in df.columns else 0, 'volatility': round(df['close'].pct_change().std() * np.sqrt(52) * 100, 2) } def perform_comprehensive_analysis(price_df: pd.DataFrame, financial_data: Dict, current_price: float = None) -> Dict: """ 执行综合分析并返回所有结果 Args: price_df: 价格数据 financial_data: 财务数据 current_price: 当前价格(可选) Returns: 包含所有分析结果的字典 """ engine = AnalysisEngine(price_df, financial_data) if current_price is None: current_price = price_df['close'].iloc[-1] technical = engine.analyze_technical() fundamental = engine.analyze_fundamental() recommendation = engine.generate_recommendation(current_price, fundamental, technical) summary_points = engine.generate_core_summary(fundamental, technical, recommendation) price_stats = engine.get_price_statistics() return { 'technical': technical, 'fundamental': fundamental, 'recommendation': recommendation, 'summary_points': summary_points, 'price_stats': price_stats } if __name__ == '__main__': # 测试代码 import numpy as np # 创建模拟数据 dates = pd.date_range(start='2025-01-01', periods=60, freq='W') np.random.seed(42) prices = 30 + np.cumsum(np.random.randn(60) * 0.5) price_df = pd.DataFrame({ 'date': dates, 'open': prices * 0.98, 'high': prices * 1.03, 'low': prices * 0.97, 'close': prices, 'volume': np.random.randint(1000000, 5000000, 60), 'pe_ttm': 25 + np.random.randn(60) * 2, 'pb_lf': 3 + np.random.randn(60) * 0.2 }) financial_data = { 'roe_wgt': 16.5, 'pe_ttm': 25.3, 'pb_lf': 3.1, 'sec_name': '测试公司' } # 执行分析 results = perform_comprehensive_analysis(price_df, financial_data) print("=== 技术分析 ===") print(f"趋势: {results['technical'].trend}") print(f"支撑位: {results['technical'].support_level}") print(f"阻力位: {results['technical'].resistance_level}") print("\n=== 基本面分析 ===") print(f"ROE: {results['fundamental'].roe}%") print(f"PE TTM: {results['fundamental'].pe_ttm}") print(f"PB LF: {results['fundamental'].pb_lf}") print("\n=== 投资建议 ===") print(f"评级: {results['recommendation'].rating.value}") print(f"目标价: {results['recommendation'].target_price}元") print(f"风险等级: {results['recommendation'].risk_level.value}") print("\n=== 核心提要 ===") for i, point in enumerate(results['summary_points'], 1): print(f"{i}. {point}")