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、资产负债率等)
|
||||
|
||||
2. 最新业绩预告情况(没有就不要提)
|
||||
- 预告类型(预增/预减/扭亏/续亏)
|
||||
- 预计业绩区间
|
||||
- 变动原因
|
||||
|
||||
3. 近三年变化趋势
|
||||
- 收入增长趋势
|
||||
- 利润变化趋势
|
||||
- 盈利能力变化
|
||||
- 经营质量变化
|
||||
|
||||
请提供专业、客观的分析,突出关键信息,避免冗长描述。"""
|
||||
1. 最新财报情况
|
||||
- 营业收入及同比变化
|
||||
- 主要成本构成及变化
|
||||
- 净利润及同比变化
|
||||
- 毛利率和净利率变化
|
||||
- 其他重要财务指标(如ROE、资产负债率等)
|
||||
|
||||
2. 最新业绩预告情况(没有就不要提)
|
||||
- 预告类型(预增/预减/扭亏/续亏)
|
||||
- 预计业绩区间
|
||||
- 变动原因
|
||||
|
||||
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"
|
||||
|
||||
财报分析内容:
|
||||
{report_text}
|
||||
|
||||
请仅返回一个数值:2、1、0、-1或-2,不要包含任何解释或说明。"""
|
||||
- 如果财报水平边际向好,最新财报没有任何风险,返回数值"2"
|
||||
- 如果边际变化波动不高较为稳定,并且风险很小,返回数值"1"
|
||||
- 如果波动不高较为稳定,但其中存在一定财报隐患,返回数值"0"
|
||||
- 如果财报波动较大(亏损或者盈利),并且存在一定财报隐患,返回数值"-1"
|
||||
- 如果财报波动较大(亏损或者盈利),并且存在较大财报隐患,返回数值"-2"
|
||||
|
||||
财报分析内容:
|
||||
{report_text}
|
||||
|
||||
请仅返回一个数值: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. 市场需求:
|
||||
- 主要下游应用领域
|
||||
- 需求增长驱动因素
|
||||
- 市场规模和增速
|
||||
|
||||
2. 竞争格局:
|
||||
- 主要竞争对手及特点
|
||||
- 行业集中度
|
||||
- 竞争壁垒
|
||||
|
||||
3. 行业环境:
|
||||
- 行业平均利润率
|
||||
- 政策环境影响
|
||||
- 技术发展趋势
|
||||
- 市场阶段结论:新兴市场、成熟市场、衰退市场
|
||||
|
||||
4. 小结:
|
||||
- 简要说明当前市场是否有利于企业经营
|
||||
|
||||
请提供专业、客观的分析,突出关键信息,避免冗长描述。"""
|
||||
1. 市场需求:
|
||||
- 主要下游应用领域
|
||||
- 需求增长驱动因素
|
||||
- 市场规模和增速
|
||||
|
||||
2. 竞争格局:
|
||||
- 主要竞争对手及特点
|
||||
- 行业集中度
|
||||
- 竞争壁垒
|
||||
|
||||
3. 行业环境:
|
||||
- 行业平均利润率
|
||||
- 政策环境影响
|
||||
- 技术发展趋势
|
||||
- 市场阶段结论:新兴市场、成熟市场、衰退市场
|
||||
|
||||
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"
|
||||
|
||||
行业发展趋势和竞争格局文本:
|
||||
{industry_text}
|
||||
|
||||
请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。"""
|
||||
- 如果当前市场环境、阶段和竞争格局符合未来企业高速增长,返回数值"2"
|
||||
- 如果当前市场环境、阶段和竞争格局符合未来企业稳定经营,返回数值"1"
|
||||
- 如果当前市场环境、阶段和竞争格局存在较大不确定性,返回数值"0"
|
||||
- 如果当前市场环境、阶段和竞争格局不利于企业正常经营,返回数值"-1"
|
||||
|
||||
行业发展趋势和竞争格局文本:
|
||||
{industry_text}
|
||||
|
||||
请仅返回一个数值: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字左右):
|
||||
- 近期热点事件
|
||||
- 投资者关注焦点
|
||||
- 市场情绪倾向
|
||||
|
||||
2. 重要信息汇总(150字左右):
|
||||
- 公司相关动态
|
||||
- 行业政策变化
|
||||
- 市场预期变化
|
||||
|
||||
请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注投资者普遍关注的话题和重要市场信息。"""
|
||||
1. 主要讨论话题(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"
|
||||
|
||||
股吧讨论内容分析:
|
||||
{discussion_text}
|
||||
|
||||
请仅返回一个数值:1、0或-1,不要包含任何解释或说明。"""
|
||||
- 如果股吧讨论情绪偏乐观,返回数值"1"
|
||||
- 如果股吧讨论情绪偏中性,返回数值"0"
|
||||
- 如果股吧讨论情绪偏悲观,返回数值"-1"
|
||||
|
||||
股吧讨论内容分析:
|
||||
{discussion_text}
|
||||
|
||||
请仅返回一个数值: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字左右):
|
||||
- 主要客户合作进展
|
||||
- 产品供应情况
|
||||
- 合作深度和规模
|
||||
|
||||
2. 产业链布局(200字左右):
|
||||
- 上下游合作动态
|
||||
- 新业务领域拓展
|
||||
- 战略合作项目
|
||||
|
||||
请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注最近半年内的合作动态,如果没有相关动态,请直接说明。"""
|
||||
1. 重要客户合作(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"
|
||||
|
||||
以下是合作动态相关信息:
|
||||
{cooperation_text}
|
||||
|
||||
请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。"""
|
||||
- 如果企业近期有较多且质量高的新合作动态(具备新业务拓展能力,以及可以体现在近一年财报中),返回数值"2"
|
||||
- 如果企业半年内合作动态频率低或质量一般(在原有业务上合作关系的衍生,对财报影响一般),返回数值"1"
|
||||
- 如果企业没有合作动态或质量低,返回数值"0"
|
||||
- 如果企业有负面合作关系(解除合作,或业务被其他厂商瓜分),返回数值"-1"
|
||||
|
||||
以下是合作动态相关信息:
|
||||
{cooperation_text}
|
||||
|
||||
请仅返回一个数值: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,103 +1152,189 @@ 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"
|
||||
|
||||
估值水平文本:
|
||||
{valuation_text}
|
||||
|
||||
只需要输出一个数值,不要输出任何说明或解释。只输出:-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"
|
||||
|
||||
估值水平文本:
|
||||
{valuation_text}
|
||||
|
||||
只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。"""
|
||||
|
||||
# 使用千问离线模型提取数值
|
||||
response = self.offline_bot_tl_qw.chat(prompt)
|
||||
# 清理模型输出
|
||||
ind_val_str = self._clean_model_output(response)
|
||||
|
||||
# 尝试将响应转换为整数
|
||||
self.offline_bot_tl_qw.clear_history()
|
||||
response = self.offline_bot_tl_qw.chat(prompt)
|
||||
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