commit;
This commit is contained in:
		
							parent
							
								
									ed2758532e
								
							
						
					
					
						commit
						ae9b2f2fcf
					
				
							
								
								
									
										23
									
								
								src/app.py
								
								
								
								
							
							
						
						
									
										23
									
								
								src/app.py
								
								
								
								
							|  | @ -1,6 +1,8 @@ | |||
| import sys | ||||
| import os | ||||
| 
 | ||||
| from src.fundamentals_llm.fundamental_analysis_database import get_analysis_result, get_db | ||||
| 
 | ||||
| # 添加项目根目录到 Python 路径 | ||||
| sys.path.append(os.path.dirname(os.path.dirname(os.path.abspath(__file__)))) | ||||
| 
 | ||||
|  | @ -25,6 +27,9 @@ CORS(app)  # 启用跨域请求支持 | |||
| # 创建企业筛选器实例 | ||||
| screener = EnterpriseScreener() | ||||
| 
 | ||||
| # 获取数据库连接 | ||||
| db = next(get_db()) | ||||
| 
 | ||||
| @app.route('/api/health', methods=['GET']) | ||||
| def health_check(): | ||||
|     """健康检查接口""" | ||||
|  | @ -752,9 +757,25 @@ def comprehensive_analysis(): | |||
|                 # 筛选出传入列表中符合条件的股票 | ||||
|                 for code, name in all_stocks: | ||||
|                     if code in input_stock_codes: | ||||
|                         # 获取各个维度的分析结果 | ||||
|                         investment_advice_result = get_analysis_result(db, code, "investment_advice") | ||||
|                         industry_competition_result = get_analysis_result(db, code, "industry_competition") | ||||
|                         financial_report_result = get_analysis_result(db, code, "financial_report") | ||||
|                         valuation_level_result = get_analysis_result(db, code, "valuation_level") | ||||
|                          | ||||
|                         # 从ai_response和extra_info中提取所需的值 | ||||
|                         investment_advice = investment_advice_result.ai_response if investment_advice_result else None | ||||
|                         industry_space = industry_competition_result.extra_info.get("industry_space") if industry_competition_result else 0 | ||||
|                         financial_report_level = financial_report_result.extra_info.get("financial_report_level") if financial_report_result else 0 | ||||
|                         pe_industry = valuation_level_result.extra_info.get("pe_industry") if valuation_level_result else 0 | ||||
|                          | ||||
|                         filtered_stocks.append({ | ||||
|                             "code": code, | ||||
|                             "name": name | ||||
|                             "name": name, | ||||
|                             "investment_advice": investment_advice,  # 投资建议(从ai_response获取) | ||||
|                             "industry_space": industry_space,  # 行业发展空间(2:高速增长, 1:稳定经营, 0:不确定性大, -1:不利经营) | ||||
|                             "financial_report_level": financial_report_level,  # 经营质量(2:优秀, 1:较好, 0:一般, -1:存在隐患,-2:较大隐患) | ||||
|                             "pe_industry": pe_industry  # 个股在行业的PE水平(-1:高于行业, 0:接近行业, 1:低于行业) | ||||
|                         }) | ||||
|                  | ||||
|                 logger.info(f"筛选出 {len(filtered_stocks)} 个符合条件的股票") | ||||
|  |  | |||
|  | @ -66,7 +66,7 @@ class FundamentalAnalyzer: | |||
|         # 使用联网模型进行基本面分析 | ||||
|         self.chat_bot = ChatBot(model_type="online_bot") | ||||
|         # 使用离线模型进行其他分析 | ||||
|         self.offline_bot = OfflineChatBot(platform="volc", model_type="offline_model") | ||||
|         self.offline_bot = OfflineChatBot(platform="tl_private", model_type="ds-v1") | ||||
|         # 千问打杂 | ||||
|         self.offline_bot_tl_qw = OfflineChatBot(platform="tl_qw_private", model_type="qwq") | ||||
|         self.db = next(get_db()) | ||||
|  | @ -366,25 +366,25 @@ class FundamentalAnalyzer: | |||
|         try: | ||||
|             prompt = f"""请对{stock_name}({stock_code})的财报情况进行简要分析,严格要求最新财报情况200字以内,最新业绩预告情况100字以内,近三年变化趋势150字以内,请严格按照以下格式输出: | ||||
| 
 | ||||
| 1. 最新财报情况 | ||||
| - 营业收入及同比变化 | ||||
| - 主要成本构成及变化 | ||||
| - 净利润及同比变化 | ||||
| - 毛利率和净利率变化 | ||||
| - 其他重要财务指标(如ROE、资产负债率等) | ||||
|                     1. 最新财报情况 | ||||
|                     - 营业收入及同比变化 | ||||
|                     - 主要成本构成及变化 | ||||
|                     - 净利润及同比变化 | ||||
|                     - 毛利率和净利率变化 | ||||
|                     - 其他重要财务指标(如ROE、资产负债率等) | ||||
|                      | ||||
| 2. 最新业绩预告情况(没有就不要提) | ||||
| - 预告类型(预增/预减/扭亏/续亏) | ||||
| - 预计业绩区间 | ||||
| - 变动原因 | ||||
|                     2. 最新业绩预告情况(没有就不要提) | ||||
|                     - 预告类型(预增/预减/扭亏/续亏) | ||||
|                     - 预计业绩区间 | ||||
|                     - 变动原因 | ||||
|                      | ||||
| 3. 近三年变化趋势 | ||||
| - 收入增长趋势 | ||||
| - 利润变化趋势 | ||||
| - 盈利能力变化 | ||||
| - 经营质量变化 | ||||
|                     3. 近三年变化趋势 | ||||
|                     - 收入增长趋势 | ||||
|                     - 利润变化趋势 | ||||
|                     - 盈利能力变化 | ||||
|                     - 经营质量变化 | ||||
|                      | ||||
| 请提供专业、客观的分析,突出关键信息,避免冗长描述。""" | ||||
|                     请提供专业、客观的分析,突出关键信息,避免冗长描述。""" | ||||
|             # 获取AI分析结果 | ||||
|             result = self.chat_bot.chat(prompt) | ||||
|              | ||||
|  | @ -425,16 +425,16 @@ class FundamentalAnalyzer: | |||
|             # 使用在线模型分析财报水平 | ||||
|             prompt = f"""请对{stock_name}({stock_code})的财报水平进行专业分析,并返回对应的数值评级: | ||||
| 
 | ||||
| - 如果财报水平边际向好,最新财报没有任何风险,返回数值"2" | ||||
| - 如果边际变化波动不高较为稳定,并且风险很小,返回数值"1" | ||||
| - 如果波动不高较为稳定,但其中存在一定财报隐患,返回数值"0" | ||||
| - 如果财报波动较大(亏损或者盈利),并且存在一定财报隐患,返回数值"-1" | ||||
| - 如果财报波动较大(亏损或者盈利),并且存在较大财报隐患,返回数值"-2" | ||||
|                     - 如果财报水平边际向好,最新财报没有任何风险,返回数值"2" | ||||
|                     - 如果边际变化波动不高较为稳定,并且风险很小,返回数值"1" | ||||
|                     - 如果波动不高较为稳定,但其中存在一定财报隐患,返回数值"0" | ||||
|                     - 如果财报波动较大(亏损或者盈利),并且存在一定财报隐患,返回数值"-1" | ||||
|                     - 如果财报波动较大(亏损或者盈利),并且存在较大财报隐患,返回数值"-2" | ||||
|                      | ||||
| 财报分析内容: | ||||
| {report_text} | ||||
|                     财报分析内容: | ||||
|                     {report_text} | ||||
|                      | ||||
| 请仅返回一个数值:2、1、0、-1或-2,不要包含任何解释或说明。""" | ||||
|                     请仅返回一个数值:2、1、0、-1或-2,不要包含任何解释或说明。""" | ||||
| 
 | ||||
|             # 使用在线模型进行分析 | ||||
|             response = self.chat_bot.chat(prompt) | ||||
|  | @ -484,26 +484,26 @@ class FundamentalAnalyzer: | |||
|         try: | ||||
|             prompt = f"""请对{stock_name}({stock_code})所在行业的发展趋势和竞争格局进行简要分析,要求输出控制在400字以内,请严格按照以下格式输出: | ||||
| 
 | ||||
| 1. 市场需求: | ||||
| - 主要下游应用领域 | ||||
| - 需求增长驱动因素 | ||||
| - 市场规模和增速 | ||||
|                     1. 市场需求: | ||||
|                     - 主要下游应用领域 | ||||
|                     - 需求增长驱动因素 | ||||
|                     - 市场规模和增速 | ||||
|                      | ||||
| 2. 竞争格局: | ||||
| - 主要竞争对手及特点 | ||||
| - 行业集中度 | ||||
| - 竞争壁垒 | ||||
|                     2. 竞争格局: | ||||
|                     - 主要竞争对手及特点 | ||||
|                     - 行业集中度 | ||||
|                     - 竞争壁垒 | ||||
|                      | ||||
| 3. 行业环境: | ||||
| - 行业平均利润率 | ||||
| - 政策环境影响 | ||||
| - 技术发展趋势 | ||||
| - 市场阶段结论:新兴市场、成熟市场、衰退市场 | ||||
|                     3. 行业环境: | ||||
|                     - 行业平均利润率 | ||||
|                     - 政策环境影响 | ||||
|                     - 技术发展趋势 | ||||
|                     - 市场阶段结论:新兴市场、成熟市场、衰退市场 | ||||
|                      | ||||
| 4. 小结: | ||||
| - 简要说明当前市场是否有利于企业经营 | ||||
|                     4. 小结: | ||||
|                     - 简要说明当前市场是否有利于企业经营 | ||||
|                      | ||||
| 请提供专业、客观的分析,突出关键信息,避免冗长描述。""" | ||||
|                     请提供专业、客观的分析,突出关键信息,避免冗长描述。""" | ||||
|             # 获取AI分析结果 | ||||
|             result = self.chat_bot.chat(prompt) | ||||
|              | ||||
|  | @ -543,15 +543,15 @@ class FundamentalAnalyzer: | |||
|         try: | ||||
|             # 使用离线模型分析行业发展空间 | ||||
|             prompt = f"""请分析以下{stock_name}({stock_code})的行业发展趋势和竞争格局文本,评估当前市场环境、阶段和竞争格局对企业未来的影响,并返回对应的数值: | ||||
| - 如果当前市场环境、阶段和竞争格局符合未来企业高速增长,返回数值"2" | ||||
| - 如果当前市场环境、阶段和竞争格局符合未来企业稳定经营,返回数值"1" | ||||
| - 如果当前市场环境、阶段和竞争格局存在较大不确定性,返回数值"0" | ||||
| - 如果当前市场环境、阶段和竞争格局不利于企业正常经营,返回数值"-1" | ||||
|                     - 如果当前市场环境、阶段和竞争格局符合未来企业高速增长,返回数值"2" | ||||
|                     - 如果当前市场环境、阶段和竞争格局符合未来企业稳定经营,返回数值"1" | ||||
|                     - 如果当前市场环境、阶段和竞争格局存在较大不确定性,返回数值"0" | ||||
|                     - 如果当前市场环境、阶段和竞争格局不利于企业正常经营,返回数值"-1" | ||||
|                      | ||||
| 行业发展趋势和竞争格局文本: | ||||
| {industry_text} | ||||
|                     行业发展趋势和竞争格局文本: | ||||
|                     {industry_text} | ||||
|                      | ||||
| 请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。""" | ||||
|                     请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。""" | ||||
|             self.offline_bot_tl_qw.clear_history() | ||||
|             # 使用离线模型进行分析 | ||||
|             space_value_str = self.offline_bot_tl_qw.chat(prompt) | ||||
|  | @ -702,17 +702,17 @@ class FundamentalAnalyzer: | |||
|         try: | ||||
|             prompt = f"""请对{stock_name}({stock_code})的股吧讨论内容进行简要分析,要求输出控制在300字以内,请严格按照以下格式输出: | ||||
| 
 | ||||
| 1. 主要讨论话题(150字左右): | ||||
| - 近期热点事件 | ||||
| - 投资者关注焦点 | ||||
| - 市场情绪倾向 | ||||
|                     1. 主要讨论话题(150字左右): | ||||
|                     - 近期热点事件 | ||||
|                     - 投资者关注焦点 | ||||
|                     - 市场情绪倾向 | ||||
|                      | ||||
| 2. 重要信息汇总(150字左右): | ||||
| - 公司相关动态 | ||||
| - 行业政策变化 | ||||
| - 市场预期变化 | ||||
|                     2. 重要信息汇总(150字左右): | ||||
|                     - 公司相关动态 | ||||
|                     - 行业政策变化 | ||||
|                     - 市场预期变化 | ||||
|                      | ||||
| 请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注投资者普遍关注的话题和重要市场信息。""" | ||||
|                     请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注投资者普遍关注的话题和重要市场信息。""" | ||||
|             # 获取AI分析结果 | ||||
|             result = self.chat_bot.chat(prompt) | ||||
|              | ||||
|  | @ -752,14 +752,14 @@ class FundamentalAnalyzer: | |||
|         try: | ||||
|             # 使用离线模型分析市场情绪 | ||||
|             prompt = f"""请分析以下{stock_name}({stock_code})的股吧讨论内容分析,判断整体市场情绪倾向,并返回对应的数值: | ||||
| - 如果股吧讨论情绪偏乐观,返回数值"1" | ||||
| - 如果股吧讨论情绪偏中性,返回数值"0" | ||||
| - 如果股吧讨论情绪偏悲观,返回数值"-1" | ||||
|                     - 如果股吧讨论情绪偏乐观,返回数值"1" | ||||
|                     - 如果股吧讨论情绪偏中性,返回数值"0" | ||||
|                     - 如果股吧讨论情绪偏悲观,返回数值"-1" | ||||
|                      | ||||
| 股吧讨论内容分析: | ||||
| {discussion_text} | ||||
|                     股吧讨论内容分析: | ||||
|                     {discussion_text} | ||||
|                      | ||||
| 请仅返回一个数值:1、0或-1,不要包含任何解释或说明。""" | ||||
|                     请仅返回一个数值:1、0或-1,不要包含任何解释或说明。""" | ||||
|             self.offline_bot_tl_qw.clear_history() | ||||
|             # 使用离线模型进行分析 | ||||
|             emotion_value_str = self.offline_bot_tl_qw.chat(prompt) | ||||
|  | @ -807,17 +807,17 @@ class FundamentalAnalyzer: | |||
|         try: | ||||
|             prompt = f"""请对{stock_name}({stock_code})最近半年内的产业链上下游合作动态进行简要分析,要求输出控制在400字以内,请严格按照以下格式输出: | ||||
| 
 | ||||
| 1. 重要客户合作(200字左右): | ||||
| - 主要客户合作进展 | ||||
| - 产品供应情况 | ||||
| - 合作深度和规模 | ||||
|                     1. 重要客户合作(200字左右): | ||||
|                     - 主要客户合作进展 | ||||
|                     - 产品供应情况 | ||||
|                     - 合作深度和规模 | ||||
|                      | ||||
| 2. 产业链布局(200字左右): | ||||
| - 上下游合作动态 | ||||
| - 新业务领域拓展 | ||||
| - 战略合作项目 | ||||
|                     2. 产业链布局(200字左右): | ||||
|                     - 上下游合作动态 | ||||
|                     - 新业务领域拓展 | ||||
|                     - 战略合作项目 | ||||
|                      | ||||
| 请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注最近半年内的合作动态,如果没有相关动态,请直接说明。""" | ||||
|                     请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注最近半年内的合作动态,如果没有相关动态,请直接说明。""" | ||||
|             # 获取AI分析结果 | ||||
|             result = self.chat_bot.chat(prompt) | ||||
|              | ||||
|  | @ -858,15 +858,15 @@ class FundamentalAnalyzer: | |||
|             # 使用在线模型分析合作动态质量 | ||||
|             prompt = f"""请评估{stock_name}({stock_code})的产业链上下游合作动态质量,并返回相应数值: | ||||
| 
 | ||||
| - 如果企业近期有较多且质量高的新合作动态(具备新业务拓展能力,以及可以体现在近一年财报中),返回数值"2" | ||||
| - 如果企业半年内合作动态频率低或质量一般(在原有业务上合作关系的衍生,对财报影响一般),返回数值"1" | ||||
| - 如果企业没有合作动态或质量低,返回数值"0" | ||||
| - 如果企业有负面合作关系(解除合作,或业务被其他厂商瓜分),返回数值"-1" | ||||
|                     - 如果企业近期有较多且质量高的新合作动态(具备新业务拓展能力,以及可以体现在近一年财报中),返回数值"2" | ||||
|                     - 如果企业半年内合作动态频率低或质量一般(在原有业务上合作关系的衍生,对财报影响一般),返回数值"1" | ||||
|                     - 如果企业没有合作动态或质量低,返回数值"0" | ||||
|                     - 如果企业有负面合作关系(解除合作,或业务被其他厂商瓜分),返回数值"-1" | ||||
|                      | ||||
| 以下是合作动态相关信息: | ||||
| {cooperation_text} | ||||
|                     以下是合作动态相关信息: | ||||
|                     {cooperation_text} | ||||
|                      | ||||
| 请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。""" | ||||
|                     请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。""" | ||||
| 
 | ||||
|             # 使用在线模型进行分析 | ||||
|             response = self.chat_bot.chat(prompt) | ||||
|  | @ -1084,15 +1084,13 @@ class FundamentalAnalyzer: | |||
|             prompt = f"""请对{stock_name}({stock_code})的估值水平进行简要分析,要求输出控制在300字以内,请严格按照以下格式输出: | ||||
| 
 | ||||
| 1. 历史估值水平(150字左右): | ||||
| - 当前PE和PB值 | ||||
| - PE在历史分位水平的位置(高于/接近/低于历史平均分位) | ||||
| - PB在历史分位水平的位置(高于/接近/低于历史平均分位) | ||||
| - 当前PE值及其在历史分位水平的位置(高于/接近/低于历史平均分位) | ||||
| - 当前PB值及其在历史分位水平的位置(高于/接近/低于历史平均分位) | ||||
| - 历史估值变化趋势简要分析 | ||||
| 
 | ||||
| 2. 行业估值对比(150字左右): | ||||
| - 所在行业平均PE和PB | ||||
| - PE与行业平均的比较(高于/接近/低于行业平均) | ||||
| - PB与行业平均的比较(高于/接近/低于行业平均) | ||||
| - 当前PE值与行业平均水平的比较(高于/接近/低于行业平均) | ||||
| - 当前PB值与行业平均水平的比较(高于/接近/低于行业平均) | ||||
| - 与可比公司估值的简要对比 | ||||
| 
 | ||||
| 请提供专业、客观的分析,突出关键信息,避免冗长描述。如果无法获取某项数据,请直接说明。""" | ||||
|  | @ -1130,14 +1128,18 @@ class FundamentalAnalyzer: | |||
|             stock_name: 股票名称 | ||||
|              | ||||
|         Returns: | ||||
|             Dict[str, int]: 包含历史估值和行业估值分类的字典 | ||||
|             Dict[str, int]: 包含四个分类值的字典: | ||||
|                 - pe_historical: PE历史分位分类 (-1:高于历史, 0:接近历史, 1:低于历史) | ||||
|                 - pb_historical: PB历史分位分类 (-1:高于历史, 0:接近历史, 1:低于历史) | ||||
|                 - pe_industry: PE行业对比分类 (-1:高于行业, 0:接近行业, 1:低于行业) | ||||
|                 - pb_industry: PB行业对比分类 (-1:高于行业, 0:接近行业, 1:低于行业) | ||||
|         """ | ||||
|         try: | ||||
|             # 提取历史估值分类 | ||||
|             historical_classification = self._extract_historical_valuation(valuation_text) | ||||
|              | ||||
|             # 提取行业估值分类 | ||||
|             industry_classification = self._extract_industry_valuation(valuation_text) | ||||
|             # 直接提取四个分类值 | ||||
|             pe_historical = self._extract_pe_historical(valuation_text) | ||||
|             pb_historical = self._extract_pb_historical(valuation_text) | ||||
|             pe_industry = self._extract_pe_industry(valuation_text) | ||||
|             pb_industry = self._extract_pb_industry(valuation_text) | ||||
|              | ||||
|             # 更新数据库中的记录 | ||||
|             result = get_analysis_result(self.db, stock_code, "valuation_level") | ||||
|  | @ -1150,34 +1152,46 @@ class FundamentalAnalyzer: | |||
|                     reasoning_process=result.reasoning_process, | ||||
|                     references=result.references, | ||||
|                     extra_info={ | ||||
|                         "historical_valuation": historical_classification, | ||||
|                         "industry_valuation": industry_classification | ||||
|                         "pe_historical": pe_historical, | ||||
|                         "pb_historical": pb_historical, | ||||
|                         "pe_industry": pe_industry, | ||||
|                         "pb_industry": pb_industry | ||||
|                     } | ||||
|                 ) | ||||
|                  | ||||
|                 logger.info(f"已更新估值分类到数据库: historical_valuation={historical_classification}, industry_valuation={industry_classification}") | ||||
|                 logger.info(f"已更新估值分类到数据库: pe_historical={pe_historical}, pb_historical={pb_historical}, pe_industry={pe_industry}, pb_industry={pb_industry}") | ||||
|              | ||||
|             return {"historical_valuation": historical_classification, "industry_valuation": industry_classification} | ||||
|             return { | ||||
|                 "pe_historical": pe_historical, | ||||
|                 "pb_historical": pb_historical, | ||||
|                 "pe_industry": pe_industry, | ||||
|                 "pb_industry": pb_industry | ||||
|             } | ||||
|              | ||||
|         except Exception as e: | ||||
|             logger.error(f"提取估值分类失败: {str(e)}") | ||||
|             return {"historical_valuation": 0, "industry_valuation": 0} | ||||
|             return { | ||||
|                 "pe_historical": 0, | ||||
|                 "pb_historical": 0, | ||||
|                 "pe_industry": 0, | ||||
|                 "pb_industry": 0 | ||||
|             } | ||||
| 
 | ||||
|     def _extract_historical_valuation(self, valuation_text: str) -> int: | ||||
|         """从估值水平分析中提取历史估值分类 | ||||
|     def _extract_pe_historical(self, valuation_text: str) -> int: | ||||
|         """从估值水平分析中提取PE历史分位分类 | ||||
|          | ||||
|         Args: | ||||
|             valuation_text: 完整的估值水平分析文本 | ||||
|              | ||||
|         Returns: | ||||
|             int: 历史估值分类值 (高于历史:-1, 接近历史:0, 低于历史:1) | ||||
|             int: PE历史分位分类值 (-1:高于历史, 0:接近历史, 1:低于历史) | ||||
|         """ | ||||
|         try: | ||||
|             # 使用在线模型提取历史估值分类 | ||||
|             prompt = f"""请仔细分析以下估值水平文本,判断当前PE和PB在历史分位的位置,并返回对应的数值: | ||||
|                     - 如果当前估值明显高于历史平均水平(高估),返回数值"-1" | ||||
|                     - 如果当前估值接近历史平均水平,返回数值"0" | ||||
|                     - 如果当前估值明显低于历史平均水平(低估),返回数值"1" | ||||
|             prompt = f"""请仔细分析以下估值水平文本,判断当前PE在历史分位的位置,并返回对应的数值: | ||||
|                     - 如果当前PE为负数,返回数值"-1" | ||||
|                     - 如果当前PE明显高于历史平均水平,返回数值"-1" | ||||
|                     - 如果当前PE接近历史平均水平,返回数值"0" | ||||
|                     - 如果当前PE明显低于历史平均水平,返回数值"1" | ||||
|                     - 如果文本中没有相关信息,返回数值"0" | ||||
|                      | ||||
|                     估值水平文本: | ||||
|  | @ -1185,42 +1199,39 @@ class FundamentalAnalyzer: | |||
|                      | ||||
|                     只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。""" | ||||
|              | ||||
|             # 使用千问离线模型提取数值 | ||||
|             self.offline_bot_tl_qw.clear_history() | ||||
|             response = self.offline_bot_tl_qw.chat(prompt) | ||||
|             # 清理模型输出 | ||||
|             hist_val_str = self._clean_model_output(response) | ||||
|             pe_hist_str = self._clean_model_output(response) | ||||
|              | ||||
|             # 尝试将响应转换为整数 | ||||
|             try: | ||||
|                 hist_val = int(hist_val_str) | ||||
|                 # 确保值在有效范围内 | ||||
|                 if hist_val < -1 or hist_val > 1: | ||||
|                     logger.warning(f"提取的历史估值分类值超出范围: {hist_val},设置为默认值0") | ||||
|                 pe_hist = int(pe_hist_str) | ||||
|                 if pe_hist < -1 or pe_hist > 1: | ||||
|                     logger.warning(f"提取的PE历史分位分类值超出范围: {pe_hist},设置为默认值0") | ||||
|                     return 0 | ||||
|                 return hist_val | ||||
|                 return pe_hist | ||||
|             except ValueError: | ||||
|                 logger.warning(f"无法将提取的历史估值分类值转换为整数: {hist_val_str},设置为默认值0") | ||||
|                 logger.warning(f"无法将提取的PE历史分位分类值转换为整数: {pe_hist_str},设置为默认值0") | ||||
|                 return 0 | ||||
|              | ||||
|         except Exception as e: | ||||
|             logger.error(f"提取历史估值分类失败: {str(e)}") | ||||
|             logger.error(f"提取PE历史分位分类失败: {str(e)}") | ||||
|             return 0 | ||||
| 
 | ||||
|     def _extract_industry_valuation(self, valuation_text: str) -> int: | ||||
|         """从估值水平分析中提取行业估值对比分类 | ||||
|     def _extract_pb_historical(self, valuation_text: str) -> int: | ||||
|         """从估值水平分析中提取PB历史分位分类 | ||||
|          | ||||
|         Args: | ||||
|             valuation_text: 完整的估值水平分析文本 | ||||
|              | ||||
|         Returns: | ||||
|             int: 行业估值对比分类值 (高于行业:-1, 接近行业:0, 低于行业:1) | ||||
|             int: PB历史分位分类值 (-1:高于历史, 0:接近历史, 1:低于历史) | ||||
|         """ | ||||
|         try: | ||||
|             # 使用在线模型提取行业估值对比分类 | ||||
|             prompt = f"""请仔细分析以下估值水平文本,判断当前企业的PE和PB与行业平均水平的对比情况,并返回对应的数值: | ||||
|                     - 如果当前企业估值明显高于行业平均水平,返回数值"-1" | ||||
|                     - 如果当前企业估值接近行业平均水平,返回数值"0" | ||||
|                     - 如果当前企业估值明显低于行业平均水平,返回数值"1" | ||||
|             prompt = f"""请仔细分析以下估值水平文本,判断当前PB在历史分位的位置,并返回对应的数值: | ||||
|                     - 如果当前PB为负数,返回数值"-1" | ||||
|                     - 如果当前PB明显高于历史平均水平,返回数值"-1" | ||||
|                     - 如果当前PB接近历史平均水平,返回数值"0" | ||||
|                     - 如果当前PB明显低于历史平均水平,返回数值"1" | ||||
|                     - 如果文本中没有相关信息,返回数值"0" | ||||
|                      | ||||
|                     估值水平文本: | ||||
|  | @ -1228,25 +1239,102 @@ class FundamentalAnalyzer: | |||
|                      | ||||
|                     只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。""" | ||||
|              | ||||
|             # 使用千问离线模型提取数值 | ||||
|             self.offline_bot_tl_qw.clear_history() | ||||
|             response = self.offline_bot_tl_qw.chat(prompt) | ||||
|             # 清理模型输出 | ||||
|             ind_val_str = self._clean_model_output(response) | ||||
|             pb_hist_str = self._clean_model_output(response) | ||||
|              | ||||
|             # 尝试将响应转换为整数 | ||||
|             try: | ||||
|                 ind_val = int(ind_val_str) | ||||
|                 # 确保值在有效范围内 | ||||
|                 if ind_val < -1 or ind_val > 1: | ||||
|                     logger.warning(f"提取的行业估值对比分类值超出范围: {ind_val},设置为默认值0") | ||||
|                 pb_hist = int(pb_hist_str) | ||||
|                 if pb_hist < -1 or pb_hist > 1: | ||||
|                     logger.warning(f"提取的PB历史分位分类值超出范围: {pb_hist},设置为默认值0") | ||||
|                     return 0 | ||||
|                 return ind_val | ||||
|                 return pb_hist | ||||
|             except ValueError: | ||||
|                 logger.warning(f"无法将提取的行业估值对比分类值转换为整数: {ind_val_str},设置为默认值0") | ||||
|                 logger.warning(f"无法将提取的PB历史分位分类值转换为整数: {pb_hist_str},设置为默认值0") | ||||
|                 return 0 | ||||
|              | ||||
|         except Exception as e: | ||||
|             logger.error(f"提取行业估值对比分类失败: {str(e)}") | ||||
|             logger.error(f"提取PB历史分位分类失败: {str(e)}") | ||||
|             return 0 | ||||
| 
 | ||||
|     def _extract_pe_industry(self, valuation_text: str) -> int: | ||||
|         """从估值水平分析中提取PE行业对比分类 | ||||
|          | ||||
|         Args: | ||||
|             valuation_text: 完整的估值水平分析文本 | ||||
|              | ||||
|         Returns: | ||||
|             int: PE行业对比分类值 (-1:高于行业, 0:接近行业, 1:低于行业) | ||||
|         """ | ||||
|         try: | ||||
|             prompt = f"""请仔细分析以下估值水平文本,判断当前PE与行业平均水平的对比情况,并返回对应的数值: | ||||
|                     - 如果当前PE为负数,返回数值"-1" | ||||
|                     - 如果当前PE明显高于行业平均水平,返回数值"-1" | ||||
|                     - 如果当前PE接近行业平均水平,返回数值"0" | ||||
|                     - 如果当前PE明显低于行业平均水平,返回数值"1" | ||||
|                     - 如果文本中没有相关信息,返回数值"0" | ||||
|                      | ||||
|                     估值水平文本: | ||||
|                     {valuation_text} | ||||
|                      | ||||
|                     只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。""" | ||||
|              | ||||
|             self.offline_bot_tl_qw.clear_history() | ||||
|             response = self.offline_bot_tl_qw.chat(prompt) | ||||
|             pe_ind_str = self._clean_model_output(response) | ||||
|              | ||||
|             try: | ||||
|                 pe_ind = int(pe_ind_str) | ||||
|                 if pe_ind < -1 or pe_ind > 1: | ||||
|                     logger.warning(f"提取的PE行业对比分类值超出范围: {pe_ind},设置为默认值0") | ||||
|                     return 0 | ||||
|                 return pe_ind | ||||
|             except ValueError: | ||||
|                 logger.warning(f"无法将提取的PE行业对比分类值转换为整数: {pe_ind_str},设置为默认值0") | ||||
|                 return 0 | ||||
|              | ||||
|         except Exception as e: | ||||
|             logger.error(f"提取PE行业对比分类失败: {str(e)}") | ||||
|             return 0 | ||||
| 
 | ||||
|     def _extract_pb_industry(self, valuation_text: str) -> int: | ||||
|         """从估值水平分析中提取PB行业对比分类 | ||||
|          | ||||
|         Args: | ||||
|             valuation_text: 完整的估值水平分析文本 | ||||
|              | ||||
|         Returns: | ||||
|             int: PB行业对比分类值 (-1:高于行业, 0:接近行业, 1:低于行业) | ||||
|         """ | ||||
|         try: | ||||
|             prompt = f"""请仔细分析以下估值水平文本,判断当前PB与行业平均水平的对比情况,并返回对应的数值: | ||||
|                     - 如果当前PB为负数,返回数值"-1" | ||||
|                     - 如果当前PB明显高于行业平均水平,返回数值"-1" | ||||
|                     - 如果当前PB接近行业平均水平,返回数值"0" | ||||
|                     - 如果当前PB明显低于行业平均水平,返回数值"1" | ||||
|                     - 如果文本中没有相关信息,返回数值"0" | ||||
|                      | ||||
|                     估值水平文本: | ||||
|                     {valuation_text} | ||||
|                      | ||||
|                     只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。""" | ||||
|              | ||||
|             self.offline_bot_tl_qw.clear_history() | ||||
|             response = self.offline_bot_tl_qw.chat(prompt) | ||||
|             pb_ind_str = self._clean_model_output(response) | ||||
|              | ||||
|             try: | ||||
|                 pb_ind = int(pb_ind_str) | ||||
|                 if pb_ind < -1 or pb_ind > 1: | ||||
|                     logger.warning(f"提取的PB行业对比分类值超出范围: {pb_ind},设置为默认值0") | ||||
|                     return 0 | ||||
|                 return pb_ind | ||||
|             except ValueError: | ||||
|                 logger.warning(f"无法将提取的PB行业对比分类值转换为整数: {pb_ind_str},设置为默认值0") | ||||
|                 return 0 | ||||
|              | ||||
|         except Exception as e: | ||||
|             logger.error(f"提取PB行业对比分类失败: {str(e)}") | ||||
|             return 0 | ||||
| 
 | ||||
|     def generate_investment_advice(self, stock_code: str, stock_name: str) -> bool: | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue