增强风险管理师分析功能
This commit is contained in:
+1
-9
@@ -21,14 +21,6 @@ DEEPSEEK_BASE_URL=https://api.deepseek.com/v1
|
|||||||
# 获取地址:https://tushare.pro/register
|
# 获取地址:https://tushare.pro/register
|
||||||
TUSHARE_TOKEN=
|
TUSHARE_TOKEN=
|
||||||
|
|
||||||
# ========== AI服务商配置 ==========
|
|
||||||
AI_PROVIDER="siliconflow"
|
|
||||||
|
|
||||||
# ========== 硅基流动 API配置 ==========
|
|
||||||
SILICONFLOW_API_KEY="YOUR_API_KEY_FROM_CLOUD_SILICONFLOW_CN"
|
|
||||||
SILICONFLOW_BASE_URL="https://api.siliconflow.cn/v1"
|
|
||||||
SILICONFLOW_MODEL="Qwen/Qwen2.5-72B-Instruct"
|
|
||||||
|
|
||||||
|
|
||||||
# ========== MiniQMT量化交易配置(可选)==========
|
# ========== MiniQMT量化交易配置(可选)==========
|
||||||
# 是否启用MiniQMT量化交易接口
|
# 是否启用MiniQMT量化交易接口
|
||||||
@@ -58,7 +50,7 @@ SMTP_SERVER=smtp.163.com
|
|||||||
|
|
||||||
# SMTP服务器端口
|
# SMTP服务器端口
|
||||||
# 常用端口:
|
# 常用端口:
|
||||||
# - 465:SSL加密连接(推荐)
|
# - 465:SSL加密连接163邮箱常用(推荐)
|
||||||
# - 587:TLS加密连接
|
# - 587:TLS加密连接
|
||||||
SMTP_PORT=465
|
SMTP_PORT=465
|
||||||
|
|
||||||
|
|||||||
+113
-19
@@ -73,13 +73,34 @@ class StockAnalysisAgents:
|
|||||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
}
|
}
|
||||||
|
|
||||||
def risk_management_agent(self, stock_info: Dict, indicators: Dict) -> Dict[str, Any]:
|
def risk_management_agent(self, stock_info: Dict, indicators: Dict, risk_data: Dict = None) -> Dict[str, Any]:
|
||||||
"""风险管理智能体"""
|
"""风险管理智能体(增强版)"""
|
||||||
print("⚠️ 风险管理师正在评估中...")
|
print("⚠️ 风险管理师正在评估中...")
|
||||||
|
|
||||||
|
# 如果有风险数据,显示数据来源
|
||||||
|
if risk_data and risk_data.get('data_success'):
|
||||||
|
print(" ✓ 已获取问财风险数据(限售解禁、大股东减持、重要事件)")
|
||||||
|
else:
|
||||||
|
print(" ⚠ 未获取到风险数据,将基于基本信息分析")
|
||||||
|
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
|
||||||
|
# 构建风险数据文本
|
||||||
|
risk_data_text = ""
|
||||||
|
if risk_data and risk_data.get('data_success'):
|
||||||
|
# 使用格式化的风险数据
|
||||||
|
from risk_data_fetcher import RiskDataFetcher
|
||||||
|
fetcher = RiskDataFetcher()
|
||||||
|
risk_data_text = f"""
|
||||||
|
|
||||||
|
【实际风险数据】(来自问财)
|
||||||
|
{fetcher.format_risk_data_for_ai(risk_data)}
|
||||||
|
|
||||||
|
以上是通过问财(pywencai)获取的实际风险数据,请重点关注这些数据进行深度风险分析。
|
||||||
|
"""
|
||||||
|
|
||||||
risk_prompt = f"""
|
risk_prompt = f"""
|
||||||
作为风险管理专家,请基于以下信息进行风险评估:
|
作为资深风险管理专家,请基于以下信息进行全面深度的风险评估:
|
||||||
|
|
||||||
股票信息:
|
股票信息:
|
||||||
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
||||||
@@ -93,32 +114,105 @@ class StockAnalysisAgents:
|
|||||||
- RSI:{indicators.get('rsi', 'N/A')}
|
- RSI:{indicators.get('rsi', 'N/A')}
|
||||||
- 布林带位置:当前价格相对于上下轨的位置
|
- 布林带位置:当前价格相对于上下轨的位置
|
||||||
- 波动率指标等
|
- 波动率指标等
|
||||||
|
{risk_data_text}
|
||||||
|
|
||||||
请从以下角度进行风险评估:
|
⚠️ 重要提示:以上风险数据是从问财(pywencai)实时查询的完整原始数据,请你:
|
||||||
1. 市场风险(系统性风险)
|
1. 仔细解析每一条记录的所有字段信息
|
||||||
2. 个股风险(非系统性风险)
|
2. 识别数据中的关键风险点(时间、规模、频率、股东身份等)
|
||||||
3. 流动性风险
|
3. 对数据进行深度分析,不要遗漏任何重要信息
|
||||||
4. 波动性风险
|
4. 如果数据中有日期字段,要特别关注最近的记录和即将发生的事件
|
||||||
5. 估值风险
|
5. 如果数据中有金额/比例字段,要评估其规模和影响力
|
||||||
6. 行业风险
|
6. 基于实际数据给出量化的风险评估,而不是空泛的描述
|
||||||
7. 风险等级评定(低/中/高)
|
|
||||||
8. 风险控制建议
|
|
||||||
|
|
||||||
给出专业的风险评估报告。
|
请从以下角度进行全面的风险评估:
|
||||||
|
|
||||||
|
1. **限售解禁风险分析** ⭐ 重点
|
||||||
|
- 解禁时间和规模评估
|
||||||
|
- 解禁对股价的潜在冲击
|
||||||
|
- 解禁股东类型分析(创始人/投资机构/其他)
|
||||||
|
- 历史解禁后股价走势参考
|
||||||
|
- 风险等级评定和应对建议
|
||||||
|
|
||||||
|
2. **股东减持风险分析** ⭐ 重点
|
||||||
|
- 减持频率和力度评估
|
||||||
|
- 减持股东身份和意图分析
|
||||||
|
- 减持对市场信心的影响
|
||||||
|
- 是否存在连续减持或集中减持
|
||||||
|
- 风险警示和投资建议
|
||||||
|
|
||||||
|
3. **重要事件风险分析** ⭐ 重点
|
||||||
|
- 识别可能影响股价的重大事件
|
||||||
|
- 事件性质判断(利好/利空/中性)
|
||||||
|
- 事件影响的时间维度(短期/中期/长期)
|
||||||
|
- 事件的确定性和不确定性
|
||||||
|
- 风险提示和关注要点
|
||||||
|
|
||||||
|
4. **市场风险(系统性风险)**
|
||||||
|
- 宏观经济环境风险
|
||||||
|
- 市场整体走势风险
|
||||||
|
- Beta系数反映的市场敏感度
|
||||||
|
- 系统性风险应对策略
|
||||||
|
|
||||||
|
5. **个股风险(非系统性风险)**
|
||||||
|
- 公司基本面风险
|
||||||
|
- 经营管理风险
|
||||||
|
- 竞争力风险
|
||||||
|
- 行业地位风险
|
||||||
|
|
||||||
|
6. **流动性风险**
|
||||||
|
- 成交量和换手率分析
|
||||||
|
- 买卖盘深度评估
|
||||||
|
- 流动性枯竭风险
|
||||||
|
- 大额交易影响评估
|
||||||
|
|
||||||
|
7. **波动性风险**
|
||||||
|
- 价格波动幅度分析
|
||||||
|
- 52周最高最低位分析
|
||||||
|
- RSI等技术指标的风险提示
|
||||||
|
- 波动率对投资的影响
|
||||||
|
|
||||||
|
8. **估值风险**
|
||||||
|
- 当前估值水平评估
|
||||||
|
- 市场预期和估值偏差
|
||||||
|
- 估值过高风险警示
|
||||||
|
|
||||||
|
9. **行业风险**
|
||||||
|
- 行业周期阶段
|
||||||
|
- 行业竞争格局
|
||||||
|
- 行业政策风险
|
||||||
|
- 行业技术变革风险
|
||||||
|
|
||||||
|
10. **综合风险评定**
|
||||||
|
- 风险等级评定(低/中/高)
|
||||||
|
- 主要风险因素排序
|
||||||
|
- 风险暴露时间窗口
|
||||||
|
- 风险演变趋势判断
|
||||||
|
|
||||||
|
11. **风险控制建议** ⭐ 核心
|
||||||
|
- 仓位控制建议(具体比例)
|
||||||
|
- 止损位设置建议(具体价位)
|
||||||
|
- 风险规避策略(什么情况下不建议投资)
|
||||||
|
- 风险对冲方案(如果适用)
|
||||||
|
- 持仓时间建议
|
||||||
|
- 重点关注指标和信号
|
||||||
|
|
||||||
|
请基于实际数据进行客观、专业、严谨的风险评估,给出可操作的风险控制建议。
|
||||||
|
如果某些风险数据缺失,也要指出数据缺失本身可能带来的风险。
|
||||||
"""
|
"""
|
||||||
|
|
||||||
messages = [
|
messages = [
|
||||||
{"role": "system", "content": "你是一名专业的风险管理专家,具有丰富的风险识别和控制经验。"},
|
{"role": "system", "content": "你是一名资深的风险管理专家,具有20年以上的风险识别和控制经验,擅长全面评估各类投资风险,特别关注限售解禁、股东减持、重要事件等可能影响股价的风险因素。你擅长从海量原始数据中提取关键信息,进行深度解析和量化评估。"},
|
||||||
{"role": "user", "content": risk_prompt}
|
{"role": "user", "content": risk_prompt}
|
||||||
]
|
]
|
||||||
|
|
||||||
analysis = self.deepseek_client.call_api(messages)
|
analysis = self.deepseek_client.call_api(messages, max_tokens=6000)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
"agent_name": "风险管理师",
|
"agent_name": "风险管理师",
|
||||||
"agent_role": "负责风险识别、风险评估、风险控制策略制定",
|
"agent_role": "负责风险识别、风险评估、风险控制策略制定",
|
||||||
"analysis": analysis,
|
"analysis": analysis,
|
||||||
"focus_areas": ["风险识别", "风险量化", "风险控制", "资产配置"],
|
"focus_areas": ["限售解禁风险", "股东减持风险", "重要事件风险", "风险识别", "风险量化", "风险控制", "资产配置"],
|
||||||
|
"risk_data": risk_data, # 保存风险数据以供后续使用
|
||||||
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
"timestamp": time.strftime("%Y-%m-%d %H:%M:%S")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -313,7 +407,7 @@ class StockAnalysisAgents:
|
|||||||
def run_multi_agent_analysis(self, stock_info: Dict, stock_data: Any, indicators: Dict,
|
def run_multi_agent_analysis(self, stock_info: Dict, stock_data: Any, indicators: Dict,
|
||||||
financial_data: Dict = None, fund_flow_data: Dict = None,
|
financial_data: Dict = None, fund_flow_data: Dict = None,
|
||||||
sentiment_data: Dict = None, news_data: Dict = None,
|
sentiment_data: Dict = None, news_data: Dict = None,
|
||||||
quarterly_data: Dict = None,
|
quarterly_data: Dict = None, risk_data: Dict = None,
|
||||||
enabled_analysts: Dict = None) -> Dict[str, Any]:
|
enabled_analysts: Dict = None) -> Dict[str, Any]:
|
||||||
"""运行多智能体分析
|
"""运行多智能体分析
|
||||||
|
|
||||||
@@ -356,9 +450,9 @@ class StockAnalysisAgents:
|
|||||||
if enabled_analysts.get('fund_flow', True):
|
if enabled_analysts.get('fund_flow', True):
|
||||||
agents_results["fund_flow"] = self.fund_flow_analyst_agent(stock_info, indicators, fund_flow_data)
|
agents_results["fund_flow"] = self.fund_flow_analyst_agent(stock_info, indicators, fund_flow_data)
|
||||||
|
|
||||||
# 风险管理分析
|
# 风险管理分析(传入风险数据)
|
||||||
if enabled_analysts.get('risk', True):
|
if enabled_analysts.get('risk', True):
|
||||||
agents_results["risk_management"] = self.risk_management_agent(stock_info, indicators)
|
agents_results["risk_management"] = self.risk_management_agent(stock_info, indicators, risk_data)
|
||||||
|
|
||||||
# 市场情绪分析(传入市场情绪数据)
|
# 市场情绪分析(传入市场情绪数据)
|
||||||
if enabled_analysts.get('sentiment', False):
|
if enabled_analysts.get('sentiment', False):
|
||||||
|
|||||||
@@ -636,9 +636,21 @@ def main():
|
|||||||
|
|
||||||
st.info(f"📊 准备分析 {len(stock_list)} 只股票: {', '.join(stock_list)}")
|
st.info(f"📊 准备分析 {len(stock_list)} 只股票: {', '.join(stock_list)}")
|
||||||
|
|
||||||
# 清除之前的批量分析结果
|
# 清除之前的分析结果(包括单个和批量)
|
||||||
if 'batch_analysis_results' in st.session_state:
|
if 'batch_analysis_results' in st.session_state:
|
||||||
del st.session_state.batch_analysis_results
|
del st.session_state.batch_analysis_results
|
||||||
|
if 'analysis_completed' in st.session_state:
|
||||||
|
del st.session_state.analysis_completed
|
||||||
|
if 'stock_info' in st.session_state:
|
||||||
|
del st.session_state.stock_info
|
||||||
|
if 'agents_results' in st.session_state:
|
||||||
|
del st.session_state.agents_results
|
||||||
|
if 'discussion_result' in st.session_state:
|
||||||
|
del st.session_state.discussion_result
|
||||||
|
if 'final_decision' in st.session_state:
|
||||||
|
del st.session_state.final_decision
|
||||||
|
if 'just_completed' in st.session_state:
|
||||||
|
del st.session_state.just_completed
|
||||||
|
|
||||||
# 获取批量模式
|
# 获取批量模式
|
||||||
batch_mode = st.session_state.get('batch_mode', '顺序分析')
|
batch_mode = st.session_state.get('batch_mode', '顺序分析')
|
||||||
@@ -646,8 +658,12 @@ def main():
|
|||||||
# 运行批量分析
|
# 运行批量分析
|
||||||
run_batch_analysis(stock_list, period, batch_mode)
|
run_batch_analysis(stock_list, period, batch_mode)
|
||||||
|
|
||||||
|
# 检查是否有已完成的批量分析结果(优先显示批量结果)
|
||||||
|
if 'batch_analysis_results' in st.session_state and st.session_state.batch_analysis_results:
|
||||||
|
display_batch_analysis_results(st.session_state.batch_analysis_results, period)
|
||||||
|
|
||||||
# 检查是否有已完成的单个分析结果(但不是刚刚完成的,避免重复显示)
|
# 检查是否有已完成的单个分析结果(但不是刚刚完成的,避免重复显示)
|
||||||
if 'analysis_completed' in st.session_state and st.session_state.analysis_completed:
|
elif 'analysis_completed' in st.session_state and st.session_state.analysis_completed:
|
||||||
# 如果是刚刚完成的分析,清除标志,避免重复显示
|
# 如果是刚刚完成的分析,清除标志,避免重复显示
|
||||||
if st.session_state.get('just_completed', False):
|
if st.session_state.get('just_completed', False):
|
||||||
st.session_state.just_completed = False
|
st.session_state.just_completed = False
|
||||||
@@ -677,10 +693,6 @@ def main():
|
|||||||
# 显示最终决策
|
# 显示最终决策
|
||||||
display_final_decision(final_decision, stock_info, agents_results, discussion_result)
|
display_final_decision(final_decision, stock_info, agents_results, discussion_result)
|
||||||
|
|
||||||
# 检查是否有已完成的批量分析结果
|
|
||||||
elif 'batch_analysis_results' in st.session_state and st.session_state.batch_analysis_results:
|
|
||||||
display_batch_analysis_results(st.session_state.batch_analysis_results, period)
|
|
||||||
|
|
||||||
# 示例和说明
|
# 示例和说明
|
||||||
elif not stock_input:
|
elif not stock_input:
|
||||||
show_example_interface()
|
show_example_interface()
|
||||||
@@ -832,6 +844,15 @@ def analyze_single_stock_for_batch(symbol, period, enabled_analysts_config=None,
|
|||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
# 5.5 获取风险数据(限售解禁、大股东减持、重要事件,可选)
|
||||||
|
risk_data = None
|
||||||
|
enable_risk = enabled_analysts_config.get('risk', True)
|
||||||
|
if enable_risk and fetcher._is_chinese_stock(symbol):
|
||||||
|
try:
|
||||||
|
risk_data = fetcher.get_risk_data(symbol)
|
||||||
|
except:
|
||||||
|
pass
|
||||||
|
|
||||||
# 6. 初始化AI分析系统
|
# 6. 初始化AI分析系统
|
||||||
agents = StockAnalysisAgents(model=selected_model)
|
agents = StockAnalysisAgents(model=selected_model)
|
||||||
|
|
||||||
@@ -841,7 +862,7 @@ def analyze_single_stock_for_batch(symbol, period, enabled_analysts_config=None,
|
|||||||
# 7. 运行多智能体分析
|
# 7. 运行多智能体分析
|
||||||
agents_results = agents.run_multi_agent_analysis(
|
agents_results = agents.run_multi_agent_analysis(
|
||||||
stock_info, stock_data, indicators, financial_data,
|
stock_info, stock_data, indicators, financial_data,
|
||||||
fund_flow_data, sentiment_data, news_data, quarterly_data,
|
fund_flow_data, sentiment_data, news_data, quarterly_data, risk_data,
|
||||||
enabled_analysts=enabled_analysts_config
|
enabled_analysts=enabled_analysts_config
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -1137,6 +1158,36 @@ def run_stock_analysis(symbol, period):
|
|||||||
news_data = None
|
news_data = None
|
||||||
elif enable_news and not fetcher._is_chinese_stock(symbol):
|
elif enable_news and not fetcher._is_chinese_stock(symbol):
|
||||||
st.info("ℹ️ 美股暂不支持新闻数据")
|
st.info("ℹ️ 美股暂不支持新闻数据")
|
||||||
|
progress_bar.progress(45)
|
||||||
|
|
||||||
|
# 5.5 获取风险数据(仅在选择了风险管理师时,使用问财数据源)
|
||||||
|
enable_risk = st.session_state.get('enable_risk', True)
|
||||||
|
risk_data = None
|
||||||
|
if enable_risk and fetcher._is_chinese_stock(symbol):
|
||||||
|
status_text.text("⚠️ 正在获取风险数据(限售解禁、大股东减持、重要事件)...")
|
||||||
|
try:
|
||||||
|
risk_data = fetcher.get_risk_data(symbol)
|
||||||
|
if risk_data and risk_data.get('data_success'):
|
||||||
|
# 统计获取到的风险数据类型
|
||||||
|
risk_types = []
|
||||||
|
if risk_data.get('lifting_ban') and risk_data['lifting_ban'].get('has_data'):
|
||||||
|
risk_types.append("限售解禁")
|
||||||
|
if risk_data.get('shareholder_reduction') and risk_data['shareholder_reduction'].get('has_data'):
|
||||||
|
risk_types.append("大股东减持")
|
||||||
|
if risk_data.get('important_events') and risk_data['important_events'].get('has_data'):
|
||||||
|
risk_types.append("重要事件")
|
||||||
|
|
||||||
|
if risk_types:
|
||||||
|
st.info(f"✅ 成功获取风险数据:{', '.join(risk_types)}")
|
||||||
|
else:
|
||||||
|
st.info("ℹ️ 暂无风险相关数据")
|
||||||
|
else:
|
||||||
|
st.info("ℹ️ 暂无风险相关数据,将基于基本信息进行风险分析")
|
||||||
|
except Exception as e:
|
||||||
|
st.warning(f"⚠️ 获取风险数据时出错: {str(e)}")
|
||||||
|
risk_data = None
|
||||||
|
elif enable_risk and not fetcher._is_chinese_stock(symbol):
|
||||||
|
st.info("ℹ️ 美股暂不支持风险数据(限售解禁、大股东减持等)")
|
||||||
progress_bar.progress(50)
|
progress_bar.progress(50)
|
||||||
|
|
||||||
# 6. 初始化AI分析系统
|
# 6. 初始化AI分析系统
|
||||||
@@ -1165,7 +1216,7 @@ def run_stock_analysis(symbol, period):
|
|||||||
status_text.text("🔍 AI分析师团队正在分析,请耐心等待几分钟...")
|
status_text.text("🔍 AI分析师团队正在分析,请耐心等待几分钟...")
|
||||||
agents_results = agents.run_multi_agent_analysis(
|
agents_results = agents.run_multi_agent_analysis(
|
||||||
stock_info, stock_data, indicators, financial_data,
|
stock_info, stock_data, indicators, financial_data,
|
||||||
fund_flow_data, sentiment_data, news_data, quarterly_data,
|
fund_flow_data, sentiment_data, news_data, quarterly_data, risk_data,
|
||||||
enabled_analysts=enabled_analysts
|
enabled_analysts=enabled_analysts
|
||||||
)
|
)
|
||||||
progress_bar.progress(75)
|
progress_bar.progress(75)
|
||||||
@@ -2504,22 +2555,16 @@ def display_comparison_table(results):
|
|||||||
df = pd.DataFrame(comparison_data)
|
df = pd.DataFrame(comparison_data)
|
||||||
|
|
||||||
# 应用样式
|
# 应用样式
|
||||||
def highlight_rating(val):
|
# 显示表格(不使用样式,避免matplotlib导入问题)
|
||||||
if val == '买入' or val == '强烈买入':
|
|
||||||
return 'background-color: #c8e6c9; color: #2e7d32;'
|
|
||||||
elif val == '持有':
|
|
||||||
return 'background-color: #fff9c4; color: #f57f17;'
|
|
||||||
elif val == '卖出' or val == '强烈卖出':
|
|
||||||
return 'background-color: #ffcdd2; color: #c62828;'
|
|
||||||
return ''
|
|
||||||
|
|
||||||
# 显示表格
|
|
||||||
st.dataframe(
|
st.dataframe(
|
||||||
df.style.applymap(highlight_rating, subset=['投资评级']),
|
df,
|
||||||
use_container_width=True,
|
use_container_width=True,
|
||||||
height=400
|
height=400
|
||||||
)
|
)
|
||||||
|
|
||||||
|
# 添加评级说明
|
||||||
|
st.caption("💡 投资评级说明:强烈买入 > 买入 > 持有 > 卖出 > 强烈卖出")
|
||||||
|
|
||||||
# 添加筛选功能
|
# 添加筛选功能
|
||||||
st.markdown("---")
|
st.markdown("---")
|
||||||
st.subheader("🔍 快速筛选")
|
st.subheader("🔍 快速筛选")
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -0,0 +1,469 @@
|
|||||||
|
"""
|
||||||
|
风险数据获取模块
|
||||||
|
使用pywencai获取股票风险相关信息:
|
||||||
|
1. 限售解禁数据
|
||||||
|
2. 大股东减持公告
|
||||||
|
3. 近期重要事件
|
||||||
|
"""
|
||||||
|
|
||||||
|
import pywencai
|
||||||
|
import pandas as pd
|
||||||
|
from typing import Dict, Any
|
||||||
|
import time
|
||||||
|
import warnings
|
||||||
|
import os
|
||||||
|
|
||||||
|
# 屏蔽pywencai的Node.js警告信息(不影响功能)
|
||||||
|
warnings.filterwarnings('ignore', category=DeprecationWarning)
|
||||||
|
os.environ['PYTHONWARNINGS'] = 'ignore::DeprecationWarning'
|
||||||
|
os.environ['NODE_NO_WARNINGS'] = '1' # 屏蔽Node.js警告
|
||||||
|
|
||||||
|
|
||||||
|
class RiskDataFetcher:
|
||||||
|
"""风险数据获取类"""
|
||||||
|
|
||||||
|
def __init__(self):
|
||||||
|
"""初始化"""
|
||||||
|
pass
|
||||||
|
|
||||||
|
def get_risk_data(self, symbol: str) -> Dict[str, Any]:
|
||||||
|
"""
|
||||||
|
获取股票风险相关数据
|
||||||
|
|
||||||
|
Args:
|
||||||
|
symbol: 股票代码(如:600000)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
包含风险数据的字典
|
||||||
|
"""
|
||||||
|
print(f"\n正在获取 {symbol} 的风险数据...")
|
||||||
|
|
||||||
|
risk_data = {
|
||||||
|
'symbol': symbol,
|
||||||
|
'data_success': False,
|
||||||
|
'lifting_ban': None, # 限售解禁数据
|
||||||
|
'shareholder_reduction': None, # 大股东减持数据
|
||||||
|
'important_events': None, # 重要事件数据
|
||||||
|
'error': None
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. 获取限售解禁数据
|
||||||
|
print(" 查询限售解禁数据...")
|
||||||
|
lifting_ban = self._get_lifting_ban_data(symbol)
|
||||||
|
risk_data['lifting_ban'] = lifting_ban
|
||||||
|
if lifting_ban and lifting_ban.get('has_data'):
|
||||||
|
print(f" 获取到限售解禁数据")
|
||||||
|
else:
|
||||||
|
print(f" 暂无限售解禁数据")
|
||||||
|
|
||||||
|
time.sleep(1) # 避免请求过快
|
||||||
|
|
||||||
|
# 2. 获取大股东减持公告
|
||||||
|
print(" 查询大股东减持公告...")
|
||||||
|
reduction = self._get_shareholder_reduction_data(symbol)
|
||||||
|
risk_data['shareholder_reduction'] = reduction
|
||||||
|
if reduction and reduction.get('has_data'):
|
||||||
|
print(f" 获取到大股东减持数据")
|
||||||
|
else:
|
||||||
|
print(f" 暂无大股东减持数据")
|
||||||
|
|
||||||
|
time.sleep(1) # 避免请求过快
|
||||||
|
|
||||||
|
# 3. 获取近期重要事件
|
||||||
|
print(" 查询近期重要事件...")
|
||||||
|
events = self._get_important_events_data(symbol)
|
||||||
|
risk_data['important_events'] = events
|
||||||
|
if events and events.get('has_data'):
|
||||||
|
print(f" 获取到重要事件数据")
|
||||||
|
else:
|
||||||
|
print(f" 暂无重要事件数据")
|
||||||
|
|
||||||
|
# 如果至少有一个数据源成功,则认为获取成功
|
||||||
|
if (lifting_ban and lifting_ban.get('has_data')) or \
|
||||||
|
(reduction and reduction.get('has_data')) or \
|
||||||
|
(events and events.get('has_data')):
|
||||||
|
risk_data['data_success'] = True
|
||||||
|
print(f"风险数据获取完成")
|
||||||
|
else:
|
||||||
|
print(f"未获取到风险相关数据")
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"风险数据获取失败: {str(e)}")
|
||||||
|
risk_data['error'] = str(e)
|
||||||
|
|
||||||
|
return risk_data
|
||||||
|
|
||||||
|
def _get_lifting_ban_data(self, symbol: str) -> Dict[str, Any]:
|
||||||
|
"""获取限售解禁数据"""
|
||||||
|
result = {
|
||||||
|
'has_data': False,
|
||||||
|
'query': f"{symbol}限售解禁",
|
||||||
|
'data': None,
|
||||||
|
'summary': None
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 构建问句
|
||||||
|
query = f"{symbol}限售解禁"
|
||||||
|
|
||||||
|
# 使用pywencai查询
|
||||||
|
response = pywencai.get(query=query, loop=True)
|
||||||
|
|
||||||
|
if response is None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# 处理返回结果
|
||||||
|
df_result = self._convert_to_dataframe(response)
|
||||||
|
|
||||||
|
if df_result is None or df_result.empty:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# 提取有用的信息
|
||||||
|
result['has_data'] = True
|
||||||
|
result['data'] = df_result
|
||||||
|
|
||||||
|
# 生成摘要
|
||||||
|
summary = []
|
||||||
|
|
||||||
|
# 尝试提取关键字段
|
||||||
|
if '解禁时间' in df_result.columns or '限售解禁日' in df_result.columns:
|
||||||
|
time_col = '解禁时间' if '解禁时间' in df_result.columns else '限售解禁日'
|
||||||
|
summary.append(f"发现 {len(df_result)} 条解禁记录")
|
||||||
|
|
||||||
|
# 提取最近的解禁记录
|
||||||
|
recent_records = df_result.head(5)
|
||||||
|
for idx, row in recent_records.iterrows():
|
||||||
|
record_info = []
|
||||||
|
if time_col in row.index:
|
||||||
|
record_info.append(f"日期: {row[time_col]}")
|
||||||
|
if '解禁股数' in row.index:
|
||||||
|
record_info.append(f"解禁股数: {row['解禁股数']}")
|
||||||
|
if '解禁市值' in row.index:
|
||||||
|
record_info.append(f"解禁市值: {row['解禁市值']}")
|
||||||
|
if '股东名称' in row.index:
|
||||||
|
record_info.append(f"股东: {row['股东名称']}")
|
||||||
|
|
||||||
|
if record_info:
|
||||||
|
summary.append(" | ".join(record_info))
|
||||||
|
else:
|
||||||
|
# 如果没有标准字段,只记录有数据
|
||||||
|
summary.append(f"获取到 {len(df_result)} 条相关记录")
|
||||||
|
|
||||||
|
result['summary'] = "\n".join(summary) if summary else "有限售解禁数据"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['error'] = str(e)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _get_shareholder_reduction_data(self, symbol: str) -> Dict[str, Any]:
|
||||||
|
"""获取大股东减持公告数据"""
|
||||||
|
result = {
|
||||||
|
'has_data': False,
|
||||||
|
'query': f"{symbol}大股东减持公告",
|
||||||
|
'data': None,
|
||||||
|
'summary': None
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 构建问句
|
||||||
|
query = f"{symbol}大股东减持公告"
|
||||||
|
|
||||||
|
# 使用pywencai查询
|
||||||
|
response = pywencai.get(query=query, loop=True)
|
||||||
|
|
||||||
|
if response is None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# 处理返回结果
|
||||||
|
df_result = self._convert_to_dataframe(response)
|
||||||
|
|
||||||
|
if df_result is None or df_result.empty:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# 提取有用的信息
|
||||||
|
result['has_data'] = True
|
||||||
|
result['data'] = df_result
|
||||||
|
|
||||||
|
# 生成摘要
|
||||||
|
summary = []
|
||||||
|
|
||||||
|
# 尝试提取关键字段
|
||||||
|
if '公告日期' in df_result.columns or '减持日期' in df_result.columns:
|
||||||
|
date_col = '公告日期' if '公告日期' in df_result.columns else '减持日期'
|
||||||
|
summary.append(f"发现 {len(df_result)} 条减持公告")
|
||||||
|
|
||||||
|
# 提取最近的减持记录
|
||||||
|
recent_records = df_result.head(5)
|
||||||
|
for idx, row in recent_records.iterrows():
|
||||||
|
record_info = []
|
||||||
|
if date_col in row.index:
|
||||||
|
record_info.append(f"日期: {row[date_col]}")
|
||||||
|
if '股东名称' in row.index:
|
||||||
|
record_info.append(f"股东: {row['股东名称']}")
|
||||||
|
if '减持股数' in row.index:
|
||||||
|
record_info.append(f"减持股数: {row['减持股数']}")
|
||||||
|
if '减持比例' in row.index:
|
||||||
|
record_info.append(f"减持比例: {row['减持比例']}")
|
||||||
|
|
||||||
|
if record_info:
|
||||||
|
summary.append(" | ".join(record_info))
|
||||||
|
else:
|
||||||
|
# 如果没有标准字段,只记录有数据
|
||||||
|
summary.append(f"获取到 {len(df_result)} 条相关记录")
|
||||||
|
|
||||||
|
result['summary'] = "\n".join(summary) if summary else "有大股东减持数据"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['error'] = str(e)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _get_important_events_data(self, symbol: str) -> Dict[str, Any]:
|
||||||
|
"""获取近期重要事件数据"""
|
||||||
|
result = {
|
||||||
|
'has_data': False,
|
||||||
|
'query': f"{symbol}近期重要事件",
|
||||||
|
'data': None,
|
||||||
|
'summary': None
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 构建问句
|
||||||
|
query = f"{symbol}近期重要事件"
|
||||||
|
|
||||||
|
# 使用pywencai查询
|
||||||
|
response = pywencai.get(query=query, loop=True)
|
||||||
|
|
||||||
|
if response is None:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# 处理返回结果
|
||||||
|
df_result = self._convert_to_dataframe(response)
|
||||||
|
|
||||||
|
if df_result is None or df_result.empty:
|
||||||
|
return result
|
||||||
|
|
||||||
|
# 提取有用的信息
|
||||||
|
result['has_data'] = True
|
||||||
|
result['data'] = df_result
|
||||||
|
|
||||||
|
# 生成摘要
|
||||||
|
summary = []
|
||||||
|
|
||||||
|
# 尝试提取关键字段
|
||||||
|
if '事件时间' in df_result.columns or '公告日期' in df_result.columns:
|
||||||
|
time_col = '事件时间' if '事件时间' in df_result.columns else '公告日期'
|
||||||
|
summary.append(f"发现 {len(df_result)} 条重要事件")
|
||||||
|
|
||||||
|
# 提取最近的事件
|
||||||
|
recent_events = df_result.head(10)
|
||||||
|
for idx, row in recent_events.iterrows():
|
||||||
|
event_info = []
|
||||||
|
if time_col in row.index:
|
||||||
|
event_info.append(f"时间: {row[time_col]}")
|
||||||
|
if '事件类型' in row.index:
|
||||||
|
event_info.append(f"类型: {row['事件类型']}")
|
||||||
|
if '事件内容' in row.index:
|
||||||
|
content = str(row['事件内容'])[:100] # 限制长度
|
||||||
|
event_info.append(f"内容: {content}")
|
||||||
|
elif '标题' in row.index:
|
||||||
|
title = str(row['标题'])[:100]
|
||||||
|
event_info.append(f"标题: {title}")
|
||||||
|
|
||||||
|
if event_info:
|
||||||
|
summary.append(" | ".join(event_info))
|
||||||
|
else:
|
||||||
|
# 如果没有标准字段,只记录有数据
|
||||||
|
summary.append(f"获取到 {len(df_result)} 条相关记录")
|
||||||
|
|
||||||
|
result['summary'] = "\n".join(summary) if summary else "有重要事件数据"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
result['error'] = str(e)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _convert_to_dataframe(self, result) -> pd.DataFrame:
|
||||||
|
"""将pywencai返回结果转换为DataFrame"""
|
||||||
|
try:
|
||||||
|
if result is None:
|
||||||
|
return None
|
||||||
|
|
||||||
|
df_result = None
|
||||||
|
|
||||||
|
if isinstance(result, dict):
|
||||||
|
try:
|
||||||
|
df_result = pd.DataFrame([result])
|
||||||
|
except Exception:
|
||||||
|
return None
|
||||||
|
elif isinstance(result, pd.DataFrame):
|
||||||
|
df_result = result
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
if df_result is None or df_result.empty:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 处理嵌套结构(tableV1)
|
||||||
|
if 'tableV1' in df_result.columns and len(df_result.columns) == 1:
|
||||||
|
table_v1_data = df_result.iloc[0]['tableV1']
|
||||||
|
if isinstance(table_v1_data, pd.DataFrame):
|
||||||
|
df_result = table_v1_data
|
||||||
|
elif isinstance(table_v1_data, list) and len(table_v1_data) > 0:
|
||||||
|
df_result = pd.DataFrame(table_v1_data)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
|
||||||
|
# 处理嵌套结构(title_content等单列嵌套)
|
||||||
|
# 如果只有一列,且该列的值是DataFrame,则展开
|
||||||
|
if len(df_result.columns) == 1:
|
||||||
|
col_name = df_result.columns[0]
|
||||||
|
first_value = df_result.iloc[0][col_name]
|
||||||
|
if isinstance(first_value, pd.DataFrame):
|
||||||
|
print(f" 检测到嵌套DataFrame(列名: {col_name}),正在展开...")
|
||||||
|
df_result = first_value
|
||||||
|
|
||||||
|
return df_result if not df_result.empty else None
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f" 转换DataFrame时出错: {str(e)}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
def format_risk_data_for_ai(self, risk_data: Dict[str, Any]) -> str:
|
||||||
|
"""格式化风险数据供AI分析使用 - 直接转换DataFrame为字符串"""
|
||||||
|
if not risk_data or not risk_data.get('data_success'):
|
||||||
|
return "未获取到风险数据"
|
||||||
|
|
||||||
|
formatted_text = []
|
||||||
|
|
||||||
|
try:
|
||||||
|
# 1. 限售解禁数据
|
||||||
|
lifting_ban = risk_data.get('lifting_ban')
|
||||||
|
if lifting_ban and lifting_ban.get('has_data') and lifting_ban.get('data') is not None:
|
||||||
|
formatted_text.append("=" * 80)
|
||||||
|
formatted_text.append("【限售解禁数据】")
|
||||||
|
formatted_text.append("=" * 80)
|
||||||
|
formatted_text.append(f"查询语句: {lifting_ban.get('query', '')}")
|
||||||
|
formatted_text.append("")
|
||||||
|
|
||||||
|
# 直接将DataFrame转换为字符串(最多50行)
|
||||||
|
df = lifting_ban.get('data')
|
||||||
|
try:
|
||||||
|
df_str = df.head(50).to_string(index=False, max_rows=50, max_cols=20)
|
||||||
|
formatted_text.append(f"共 {len(df)} 条记录,显示前50条:")
|
||||||
|
formatted_text.append(df_str)
|
||||||
|
except Exception as e:
|
||||||
|
formatted_text.append(f"数据转换失败: {str(e)}")
|
||||||
|
formatted_text.append("")
|
||||||
|
|
||||||
|
# 2. 大股东减持数据
|
||||||
|
reduction = risk_data.get('shareholder_reduction')
|
||||||
|
if reduction and reduction.get('has_data') and reduction.get('data') is not None:
|
||||||
|
formatted_text.append("=" * 80)
|
||||||
|
formatted_text.append("【大股东减持数据】")
|
||||||
|
formatted_text.append("=" * 80)
|
||||||
|
formatted_text.append(f"查询语句: {reduction.get('query', '')}")
|
||||||
|
formatted_text.append("")
|
||||||
|
|
||||||
|
# 直接将DataFrame转换为字符串(最多50行)
|
||||||
|
df = reduction.get('data')
|
||||||
|
try:
|
||||||
|
df_str = df.head(50).to_string(index=False, max_rows=50, max_cols=20)
|
||||||
|
formatted_text.append(f"共 {len(df)} 条记录,显示前50条:")
|
||||||
|
formatted_text.append(df_str)
|
||||||
|
except Exception as e:
|
||||||
|
formatted_text.append(f"数据转换失败: {str(e)}")
|
||||||
|
formatted_text.append("")
|
||||||
|
|
||||||
|
# 3. 重要事件数据
|
||||||
|
events = risk_data.get('important_events')
|
||||||
|
if events and events.get('has_data') and events.get('data') is not None:
|
||||||
|
formatted_text.append("=" * 80)
|
||||||
|
formatted_text.append("【重要事件数据】")
|
||||||
|
formatted_text.append("=" * 80)
|
||||||
|
formatted_text.append(f"查询语句: {events.get('query', '')}")
|
||||||
|
formatted_text.append("")
|
||||||
|
|
||||||
|
# 直接将DataFrame转换为字符串(最多50行)
|
||||||
|
df = events.get('data')
|
||||||
|
try:
|
||||||
|
df_str = df.head(50).to_string(index=False, max_rows=50, max_cols=20)
|
||||||
|
formatted_text.append(f"共 {len(df)} 条记录,显示前50条:")
|
||||||
|
formatted_text.append(df_str)
|
||||||
|
except Exception as e:
|
||||||
|
formatted_text.append(f"数据转换失败: {str(e)}")
|
||||||
|
formatted_text.append("")
|
||||||
|
|
||||||
|
return "\n".join(formatted_text) if formatted_text else "暂无风险数据"
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
print(f"格式化风险数据时出错: {str(e)}")
|
||||||
|
import traceback
|
||||||
|
traceback.print_exc()
|
||||||
|
return f"格式化风险数据时出错: {str(e)}"
|
||||||
|
|
||||||
|
def _format_dataframe_for_ai(self, df: pd.DataFrame, data_type: str) -> str:
|
||||||
|
"""将DataFrame格式化为AI易读的文本格式"""
|
||||||
|
lines = []
|
||||||
|
|
||||||
|
# 显示数据总数
|
||||||
|
lines.append(f"共 {len(df)} 条{data_type}记录")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# 显示列名
|
||||||
|
lines.append(f"数据字段:{', '.join(df.columns.tolist())}")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
# 逐行显示数据(最多显示50条,避免数据过大)
|
||||||
|
max_rows = min(50, len(df))
|
||||||
|
|
||||||
|
for idx, row in df.head(max_rows).iterrows():
|
||||||
|
lines.append(f"【记录 {idx + 1}】")
|
||||||
|
|
||||||
|
# 显示每个字段的值
|
||||||
|
for col in df.columns:
|
||||||
|
value = row[col]
|
||||||
|
|
||||||
|
# 处理不同类型的值
|
||||||
|
if pd.isna(value):
|
||||||
|
value_str = "无数据"
|
||||||
|
elif isinstance(value, (int, float)):
|
||||||
|
value_str = str(value)
|
||||||
|
else:
|
||||||
|
value_str = str(value)
|
||||||
|
# 限制过长的字符串
|
||||||
|
if len(value_str) > 200:
|
||||||
|
value_str = value_str[:200] + "..."
|
||||||
|
|
||||||
|
lines.append(f" {col}: {value_str}")
|
||||||
|
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
if len(df) > max_rows:
|
||||||
|
lines.append(f"... 还有 {len(df) - max_rows} 条记录(已省略)")
|
||||||
|
lines.append("")
|
||||||
|
|
||||||
|
return "\n".join(lines)
|
||||||
|
|
||||||
|
|
||||||
|
# 测试代码
|
||||||
|
if __name__ == "__main__":
|
||||||
|
fetcher = RiskDataFetcher()
|
||||||
|
|
||||||
|
# 测试获取风险数据
|
||||||
|
test_symbol = "600000"
|
||||||
|
print(f"测试获取 {test_symbol} 的风险数据...")
|
||||||
|
|
||||||
|
risk_data = fetcher.get_risk_data(test_symbol)
|
||||||
|
|
||||||
|
print("\n" + "=" * 60)
|
||||||
|
print("获取结果:")
|
||||||
|
print("=" * 60)
|
||||||
|
print(f"数据获取成功: {risk_data['data_success']}")
|
||||||
|
|
||||||
|
if risk_data['data_success']:
|
||||||
|
print("\n格式化的风险数据:")
|
||||||
|
print(fetcher.format_risk_data_for_ai(risk_data))
|
||||||
|
|
||||||
@@ -816,6 +816,34 @@ class StockDataFetcher:
|
|||||||
# - 新方案:使用 akshare 的 stock_individual_fund_flow 接口
|
# - 新方案:使用 akshare 的 stock_individual_fund_flow 接口
|
||||||
# - 新方案优势:数据标准化、准确获取最近20个交易日、6类资金详细分类
|
# - 新方案优势:数据标准化、准确获取最近20个交易日、6类资金详细分类
|
||||||
|
|
||||||
|
def get_risk_data(self, symbol):
|
||||||
|
"""
|
||||||
|
获取股票风险数据(限售解禁、大股东减持、重要事件)
|
||||||
|
只支持中国A股
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 只有中国A股才支持风险数据查询
|
||||||
|
if not self._is_chinese_stock(symbol):
|
||||||
|
return {
|
||||||
|
'symbol': symbol,
|
||||||
|
'data_success': False,
|
||||||
|
'error': '仅支持中国A股风险数据查询'
|
||||||
|
}
|
||||||
|
|
||||||
|
# 使用风险数据获取器
|
||||||
|
from risk_data_fetcher import RiskDataFetcher
|
||||||
|
fetcher = RiskDataFetcher()
|
||||||
|
risk_data = fetcher.get_risk_data(symbol)
|
||||||
|
|
||||||
|
return risk_data
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
return {
|
||||||
|
'symbol': symbol,
|
||||||
|
'data_success': False,
|
||||||
|
'error': f'获取风险数据失败: {str(e)}'
|
||||||
|
}
|
||||||
|
|
||||||
def _safe_convert(self, value):
|
def _safe_convert(self, value):
|
||||||
"""安全地转换数值"""
|
"""安全地转换数值"""
|
||||||
if value is None or value == '' or (isinstance(value, float) and np.isnan(value)):
|
if value is None or value == '' or (isinstance(value, float) and np.isnan(value)):
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
"""
|
||||||
|
风险数据获取功能测试脚本
|
||||||
|
测试pywencai获取限售解禁、大股东减持、重要事件数据
|
||||||
|
"""
|
||||||
|
|
||||||
|
from risk_data_fetcher import RiskDataFetcher
|
||||||
|
|
||||||
|
|
||||||
|
def test_risk_data_fetcher():
|
||||||
|
"""测试风险数据获取器"""
|
||||||
|
|
||||||
|
print("=" * 80)
|
||||||
|
print("风险数据获取功能测试")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
# 初始化获取器
|
||||||
|
fetcher = RiskDataFetcher()
|
||||||
|
|
||||||
|
# 测试股票列表(建议使用大盘股,数据更全)
|
||||||
|
test_symbols = [
|
||||||
|
"600000", # 浦发银行
|
||||||
|
"000001", # 平安银行
|
||||||
|
"600519", # 茅台
|
||||||
|
]
|
||||||
|
|
||||||
|
for symbol in test_symbols:
|
||||||
|
print(f"\n{'=' * 80}")
|
||||||
|
print(f"测试股票: {symbol}")
|
||||||
|
print(f"{'=' * 80}")
|
||||||
|
|
||||||
|
# 获取风险数据
|
||||||
|
risk_data = fetcher.get_risk_data(symbol)
|
||||||
|
|
||||||
|
# 显示结果
|
||||||
|
print(f"\n数据获取成功: {risk_data.get('data_success', False)}")
|
||||||
|
|
||||||
|
if risk_data.get('error'):
|
||||||
|
print(f"错误信息: {risk_data['error']}")
|
||||||
|
continue
|
||||||
|
|
||||||
|
# 显示限售解禁数据
|
||||||
|
lifting_ban = risk_data.get('lifting_ban')
|
||||||
|
if lifting_ban and lifting_ban.get('has_data'):
|
||||||
|
print(f"\n✅ 限售解禁数据:")
|
||||||
|
print(f" 查询语句: {lifting_ban.get('query')}")
|
||||||
|
df_data = lifting_ban.get('data')
|
||||||
|
if df_data is not None and not df_data.empty:
|
||||||
|
print(f" 记录数: {len(df_data)}")
|
||||||
|
print(f" 字段: {', '.join(df_data.columns.tolist())}")
|
||||||
|
print(f" 前3条记录:")
|
||||||
|
print(df_data.head(3).to_string(index=False))
|
||||||
|
else:
|
||||||
|
print(f"\nℹ️ 暂无限售解禁数据")
|
||||||
|
|
||||||
|
# 显示股东减持数据
|
||||||
|
reduction = risk_data.get('shareholder_reduction')
|
||||||
|
if reduction and reduction.get('has_data'):
|
||||||
|
print(f"\n✅ 大股东减持数据:")
|
||||||
|
print(f" 查询语句: {reduction.get('query')}")
|
||||||
|
df_data = reduction.get('data')
|
||||||
|
if df_data is not None and not df_data.empty:
|
||||||
|
print(f" 记录数: {len(df_data)}")
|
||||||
|
print(f" 字段: {', '.join(df_data.columns.tolist())}")
|
||||||
|
print(f" 前3条记录:")
|
||||||
|
print(df_data.head(3).to_string(index=False))
|
||||||
|
else:
|
||||||
|
print(f"\nℹ️ 暂无大股东减持数据")
|
||||||
|
|
||||||
|
# 显示重要事件数据
|
||||||
|
events = risk_data.get('important_events')
|
||||||
|
if events and events.get('has_data'):
|
||||||
|
print(f"\n✅ 重要事件数据:")
|
||||||
|
print(f" 查询语句: {events.get('query')}")
|
||||||
|
df_data = events.get('data')
|
||||||
|
if df_data is not None and not df_data.empty:
|
||||||
|
print(f" 记录数: {len(df_data)}")
|
||||||
|
print(f" 字段: {', '.join(df_data.columns.tolist())}")
|
||||||
|
print(f" 前3条记录:")
|
||||||
|
print(df_data.head(3).to_string(index=False))
|
||||||
|
else:
|
||||||
|
print(f"\nℹ️ 暂无重要事件数据")
|
||||||
|
|
||||||
|
# 显示格式化后的数据
|
||||||
|
print(f"\n{'=' * 80}")
|
||||||
|
print("格式化供AI分析的数据:")
|
||||||
|
print(f"{'=' * 80}")
|
||||||
|
formatted_data = fetcher.format_risk_data_for_ai(risk_data)
|
||||||
|
print(formatted_data)
|
||||||
|
|
||||||
|
print(f"\n{'=' * 80}")
|
||||||
|
print("测试完成!")
|
||||||
|
print(f"{'=' * 80}")
|
||||||
|
|
||||||
|
|
||||||
|
def test_risk_management_agent():
|
||||||
|
"""测试风险管理师功能"""
|
||||||
|
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("风险管理师AI分析测试")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
# 需要配置API Key才能测试
|
||||||
|
try:
|
||||||
|
from ai_agents import StockAnalysisAgents
|
||||||
|
from risk_data_fetcher import RiskDataFetcher
|
||||||
|
|
||||||
|
# 测试股票
|
||||||
|
test_symbol = "600000"
|
||||||
|
|
||||||
|
print(f"\n测试股票: {test_symbol}")
|
||||||
|
|
||||||
|
# 获取风险数据
|
||||||
|
fetcher = RiskDataFetcher()
|
||||||
|
risk_data = fetcher.get_risk_data(test_symbol)
|
||||||
|
|
||||||
|
if not risk_data.get('data_success'):
|
||||||
|
print("未获取到风险数据,跳过AI分析测试")
|
||||||
|
return
|
||||||
|
|
||||||
|
# 模拟股票信息和指标
|
||||||
|
stock_info = {
|
||||||
|
'symbol': test_symbol,
|
||||||
|
'name': '测试股票',
|
||||||
|
'current_price': 10.5,
|
||||||
|
'beta': 1.2,
|
||||||
|
'52_week_high': 12.0,
|
||||||
|
'52_week_low': 8.5
|
||||||
|
}
|
||||||
|
|
||||||
|
indicators = {
|
||||||
|
'rsi': 65.5,
|
||||||
|
'macd': 0.15
|
||||||
|
}
|
||||||
|
|
||||||
|
# 初始化AI分析系统
|
||||||
|
print("\n初始化AI分析系统...")
|
||||||
|
agents = StockAnalysisAgents()
|
||||||
|
|
||||||
|
# 运行风险管理师分析
|
||||||
|
print("\n运行风险管理师分析...")
|
||||||
|
result = agents.risk_management_agent(stock_info, indicators, risk_data)
|
||||||
|
|
||||||
|
# 显示分析结果
|
||||||
|
print(f"\n{'=' * 80}")
|
||||||
|
print(f"分析师: {result['agent_name']}")
|
||||||
|
print(f"职责: {result['agent_role']}")
|
||||||
|
print(f"关注领域: {', '.join(result['focus_areas'])}")
|
||||||
|
print(f"{'=' * 80}")
|
||||||
|
print("\n分析报告:")
|
||||||
|
print(result['analysis'])
|
||||||
|
|
||||||
|
except ImportError as e:
|
||||||
|
print(f"⚠️ 导入模块失败: {e}")
|
||||||
|
print("提示:请确保已安装所有依赖并配置API Key")
|
||||||
|
except Exception as e:
|
||||||
|
print(f"❌ 测试失败: {e}")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
# 测试1:风险数据获取
|
||||||
|
test_risk_data_fetcher()
|
||||||
|
|
||||||
|
# 测试2:AI分析(需要API Key)
|
||||||
|
print("\n\n是否测试AI分析功能?(需要配置DeepSeek API Key)")
|
||||||
|
user_input = input("输入 y 继续,其他键跳过: ")
|
||||||
|
|
||||||
|
if user_input.lower() == 'y':
|
||||||
|
test_risk_management_agent()
|
||||||
|
else:
|
||||||
|
print("\n跳过AI分析测试")
|
||||||
|
|
||||||
|
print("\n✅ 所有测试完成!")
|
||||||
|
|
||||||
@@ -0,0 +1,146 @@
|
|||||||
|
"""
|
||||||
|
调试风险数据获取和格式化
|
||||||
|
检查数据是否真的传递给AI
|
||||||
|
"""
|
||||||
|
|
||||||
|
from risk_data_fetcher import RiskDataFetcher
|
||||||
|
import json
|
||||||
|
|
||||||
|
|
||||||
|
def test_full_data_flow(symbol="300433"):
|
||||||
|
"""测试完整数据流程"""
|
||||||
|
|
||||||
|
print("=" * 80)
|
||||||
|
print(f"测试股票: {symbol}")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
fetcher = RiskDataFetcher()
|
||||||
|
|
||||||
|
# 1. 获取原始数据
|
||||||
|
print("\n【步骤1】获取原始风险数据...")
|
||||||
|
risk_data = fetcher.get_risk_data(symbol)
|
||||||
|
|
||||||
|
print(f"\n数据获取成功: {risk_data.get('data_success', False)}")
|
||||||
|
|
||||||
|
# 2. 查看每类数据的详情
|
||||||
|
print("\n【步骤2】查看原始数据详情...")
|
||||||
|
|
||||||
|
# 限售解禁
|
||||||
|
lifting_ban = risk_data.get('lifting_ban')
|
||||||
|
if lifting_ban:
|
||||||
|
print(f"\n限售解禁数据:")
|
||||||
|
print(f" has_data: {lifting_ban.get('has_data')}")
|
||||||
|
df = lifting_ban.get('data')
|
||||||
|
if df is not None:
|
||||||
|
print(f" 记录数: {len(df)}")
|
||||||
|
print(f" 列名: {list(df.columns)}")
|
||||||
|
print(f"\n 前3条数据:")
|
||||||
|
print(df.head(3))
|
||||||
|
else:
|
||||||
|
print(f" data字段为None")
|
||||||
|
|
||||||
|
# 大股东减持
|
||||||
|
reduction = risk_data.get('shareholder_reduction')
|
||||||
|
if reduction:
|
||||||
|
print(f"\n大股东减持数据:")
|
||||||
|
print(f" has_data: {reduction.get('has_data')}")
|
||||||
|
df = reduction.get('data')
|
||||||
|
if df is not None:
|
||||||
|
print(f" 记录数: {len(df)}")
|
||||||
|
print(f" 列名: {list(df.columns)}")
|
||||||
|
print(f"\n 前3条数据:")
|
||||||
|
print(df.head(3))
|
||||||
|
print(f"\n 完整第1条数据:")
|
||||||
|
if len(df) > 0:
|
||||||
|
first_row = df.iloc[0]
|
||||||
|
for col in df.columns:
|
||||||
|
print(f" {col}: {first_row[col]}")
|
||||||
|
else:
|
||||||
|
print(f" data字段为None")
|
||||||
|
|
||||||
|
# 重要事件
|
||||||
|
events = risk_data.get('important_events')
|
||||||
|
if events:
|
||||||
|
print(f"\n重要事件数据:")
|
||||||
|
print(f" has_data: {events.get('has_data')}")
|
||||||
|
df = events.get('data')
|
||||||
|
if df is not None:
|
||||||
|
print(f" 记录数: {len(df)}")
|
||||||
|
print(f" 列名: {list(df.columns)}")
|
||||||
|
print(f"\n 前3条数据:")
|
||||||
|
print(df.head(3))
|
||||||
|
else:
|
||||||
|
print(f" data字段为None")
|
||||||
|
|
||||||
|
# 3. 测试格式化后的数据
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("【步骤3】测试格式化后传给AI的数据")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
formatted_data = fetcher.format_risk_data_for_ai(risk_data)
|
||||||
|
|
||||||
|
print("\n格式化后的数据长度:", len(formatted_data), "字符")
|
||||||
|
print("\n格式化后的数据内容:")
|
||||||
|
print(formatted_data)
|
||||||
|
|
||||||
|
# 4. 保存到文件供查看
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("【步骤4】保存数据到文件")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
with open("risk_data_debug_output.txt", "w", encoding="utf-8") as f:
|
||||||
|
f.write("=" * 80 + "\n")
|
||||||
|
f.write("原始数据结构\n")
|
||||||
|
f.write("=" * 80 + "\n\n")
|
||||||
|
|
||||||
|
# 保存原始数据(不包含DataFrame,只保存基本信息)
|
||||||
|
f.write("data_success: " + str(risk_data.get('data_success')) + "\n\n")
|
||||||
|
|
||||||
|
for key in ['lifting_ban', 'shareholder_reduction', 'important_events']:
|
||||||
|
data = risk_data.get(key)
|
||||||
|
if data:
|
||||||
|
f.write(f"\n{key}:\n")
|
||||||
|
f.write(f" has_data: {data.get('has_data')}\n")
|
||||||
|
f.write(f" query: {data.get('query')}\n")
|
||||||
|
df = data.get('data')
|
||||||
|
if df is not None:
|
||||||
|
f.write(f" 记录数: {len(df)}\n")
|
||||||
|
f.write(f" 列名: {list(df.columns)}\n")
|
||||||
|
|
||||||
|
f.write("\n" + "=" * 80 + "\n")
|
||||||
|
f.write("格式化后传给AI的数据\n")
|
||||||
|
f.write("=" * 80 + "\n\n")
|
||||||
|
f.write(formatted_data)
|
||||||
|
|
||||||
|
print("✓ 数据已保存到 risk_data_debug_output.txt")
|
||||||
|
|
||||||
|
# 5. 检查数据是否完整
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("【步骤5】数据完整性检查")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
if "【大股东减持数据】" in formatted_data:
|
||||||
|
print("✓ 格式化数据中包含大股东减持数据")
|
||||||
|
|
||||||
|
# 检查是否有实际内容
|
||||||
|
reduction_section = formatted_data.split("【大股东减持数据】")[1].split("=" * 80)[0]
|
||||||
|
if len(reduction_section.strip()) > 100:
|
||||||
|
print(f"✓ 减持数据部分有 {len(reduction_section)} 字符")
|
||||||
|
else:
|
||||||
|
print(f"⚠️ 减持数据部分只有 {len(reduction_section)} 字符,可能数据不完整")
|
||||||
|
else:
|
||||||
|
print("❌ 格式化数据中未找到大股东减持数据")
|
||||||
|
|
||||||
|
print("\n" + "=" * 80)
|
||||||
|
print("测试完成!请查看 risk_data_debug_output.txt 文件")
|
||||||
|
print("=" * 80)
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
import sys
|
||||||
|
|
||||||
|
# 默认测试300433,也可以通过命令行参数指定其他股票
|
||||||
|
symbol = sys.argv[1] if len(sys.argv) > 1 else "300433"
|
||||||
|
|
||||||
|
test_full_data_flow(symbol)
|
||||||
|
|
||||||
+371
@@ -0,0 +1,371 @@
|
|||||||
|
# 风险管理师增强功能说明 ⚠️
|
||||||
|
|
||||||
|
## 📋 功能概述
|
||||||
|
|
||||||
|
风险管理师功能已全面增强,现在使用**问财(pywencai)**实时获取三大类风险数据,为投资决策提供更全面的风险评估。
|
||||||
|
|
||||||
|
## ✨ 新增功能
|
||||||
|
|
||||||
|
### 1. 三大风险数据源 🔍
|
||||||
|
|
||||||
|
风险管理师现在会自动查询以下三类关键风险信息:
|
||||||
|
|
||||||
|
| 风险类型 | 查询问句 | 数据内容 |
|
||||||
|
|---------|---------|---------|
|
||||||
|
| **限售解禁** | `股票代码限售解禁` | 解禁时间、解禁股数、解禁市值、股东名称 |
|
||||||
|
| **大股东减持** | `股票代码大股东减持公告` | 减持日期、股东名称、减持股数、减持比例 |
|
||||||
|
| **重要事件** | `股票代码近期重要事件` | 事件时间、事件类型、事件内容 |
|
||||||
|
|
||||||
|
### 2. 完整数据传递 📊
|
||||||
|
|
||||||
|
系统会将pywencai返回的**完整原始数据**喂给AI,包括:
|
||||||
|
|
||||||
|
- **所有字段**:不遗漏任何信息
|
||||||
|
- **所有记录**:最多传递50条记录(避免过载)
|
||||||
|
- **结构化格式**:AI易于解析的格式
|
||||||
|
- **详细信息**:时间、金额、比例、股东名称等
|
||||||
|
|
||||||
|
**数据传递示例:**
|
||||||
|
|
||||||
|
```
|
||||||
|
================================================================================
|
||||||
|
【限售解禁完整数据】
|
||||||
|
================================================================================
|
||||||
|
查询语句: 600000限售解禁
|
||||||
|
|
||||||
|
共 10 条限售解禁记录
|
||||||
|
|
||||||
|
数据字段:股票代码, 股票简称, 解禁时间, 解禁股数, 解禁市值, 股东名称, ...
|
||||||
|
|
||||||
|
【记录 1】
|
||||||
|
股票代码: 600000
|
||||||
|
股票简称: 浦发银行
|
||||||
|
解禁时间: 2024-03-15
|
||||||
|
解禁股数: 500000000
|
||||||
|
解禁市值: 5000000000
|
||||||
|
股东名称: 某某投资公司
|
||||||
|
...
|
||||||
|
|
||||||
|
【记录 2】
|
||||||
|
...
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. 智能风险分析 🧠
|
||||||
|
|
||||||
|
风险管理师会**深度解析所有原始数据**,进行**11个维度**的全面风险评估:
|
||||||
|
|
||||||
|
#### ⭐ 三大重点风险分析
|
||||||
|
|
||||||
|
1. **限售解禁风险分析**
|
||||||
|
- 解禁时间和规模评估
|
||||||
|
- 解禁对股价的潜在冲击
|
||||||
|
- 解禁股东类型分析(创始人/投资机构/其他)
|
||||||
|
- 历史解禁后股价走势参考
|
||||||
|
- 风险等级评定和应对建议
|
||||||
|
|
||||||
|
2. **股东减持风险分析**
|
||||||
|
- 减持频率和力度评估
|
||||||
|
- 减持股东身份和意图分析
|
||||||
|
- 减持对市场信心的影响
|
||||||
|
- 是否存在连续减持或集中减持
|
||||||
|
- 风险警示和投资建议
|
||||||
|
|
||||||
|
3. **重要事件风险分析**
|
||||||
|
- 识别可能影响股价的重大事件
|
||||||
|
- 事件性质判断(利好/利空/中性)
|
||||||
|
- 事件影响的时间维度(短期/中期/长期)
|
||||||
|
- 事件的确定性和不确定性
|
||||||
|
- 风险提示和关注要点
|
||||||
|
|
||||||
|
#### 📊 其他风险维度
|
||||||
|
|
||||||
|
4. **市场风险**(系统性风险)
|
||||||
|
5. **个股风险**(非系统性风险)
|
||||||
|
6. **流动性风险**
|
||||||
|
7. **波动性风险**
|
||||||
|
8. **估值风险**
|
||||||
|
9. **行业风险**
|
||||||
|
10. **综合风险评定**
|
||||||
|
11. **风险控制建议** ⭐
|
||||||
|
|
||||||
|
### 4. AI深度解析能力 🤖
|
||||||
|
|
||||||
|
AI会对每条原始记录进行深度分析:
|
||||||
|
|
||||||
|
- **时间识别**:自动识别日期字段,关注最近和即将发生的事件
|
||||||
|
- **金额量化**:评估解禁市值、减持金额的规模和影响
|
||||||
|
- **股东分析**:识别股东类型(创始人/机构/高管)
|
||||||
|
- **频率统计**:分析减持频率,判断是否连续减持
|
||||||
|
- **趋势预判**:基于历史数据预测未来风险
|
||||||
|
|
||||||
|
### 5. 可操作的风险控制建议 📋
|
||||||
|
|
||||||
|
风险管理师会提供具体的风险控制建议:
|
||||||
|
|
||||||
|
- **仓位控制建议**:具体的仓位比例建议
|
||||||
|
- **止损位设置**:具体的止损价位建议
|
||||||
|
- **风险规避策略**:明确什么情况下不建议投资
|
||||||
|
- **风险对冲方案**:如果适用,提供对冲策略
|
||||||
|
- **持仓时间建议**:建议的持仓周期
|
||||||
|
- **重点关注指标**:需要持续监控的关键指标
|
||||||
|
|
||||||
|
## 🎯 使用方法
|
||||||
|
|
||||||
|
### 自动获取(推荐)✅
|
||||||
|
|
||||||
|
风险管理师默认启用,系统会自动获取风险数据:
|
||||||
|
|
||||||
|
1. 在股票分析界面,确保**风险管理师**处于勾选状态
|
||||||
|
2. 输入股票代码(仅支持**A股6位代码**)
|
||||||
|
3. 点击"开始分析"
|
||||||
|
4. 系统自动获取风险数据并进行分析
|
||||||
|
|
||||||
|
### 数据获取流程 🔄
|
||||||
|
|
||||||
|
```
|
||||||
|
1. 查询限售解禁数据 → 2秒延迟
|
||||||
|
2. 查询大股东减持数据 → 2秒延迟
|
||||||
|
3. 查询重要事件数据 → 完成
|
||||||
|
4. 综合所有数据进行AI分析
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📊 数据展示
|
||||||
|
|
||||||
|
### 获取成功提示
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ 成功获取风险数据:限售解禁, 大股东减持, 重要事件
|
||||||
|
```
|
||||||
|
|
||||||
|
### 部分数据提示
|
||||||
|
|
||||||
|
```
|
||||||
|
ℹ️ 成功获取风险数据:大股东减持
|
||||||
|
ℹ️ 暂无限售解禁和重要事件数据
|
||||||
|
```
|
||||||
|
|
||||||
|
### 无数据提示
|
||||||
|
|
||||||
|
```
|
||||||
|
ℹ️ 暂无风险相关数据,将基于基本信息进行风险分析
|
||||||
|
```
|
||||||
|
|
||||||
|
### 美股提示
|
||||||
|
|
||||||
|
```
|
||||||
|
ℹ️ 美股暂不支持风险数据(限售解禁、大股东减持等)
|
||||||
|
```
|
||||||
|
|
||||||
|
## 💡 使用场景
|
||||||
|
|
||||||
|
### 场景1:发现解禁风险 🚨
|
||||||
|
|
||||||
|
**案例**:某股票即将迎来大规模限售解禁
|
||||||
|
|
||||||
|
**风险管理师分析**:
|
||||||
|
- 识别解禁时间窗口
|
||||||
|
- 评估解禁规模对股价的压力
|
||||||
|
- 分析解禁股东类型(创始人vs机构)
|
||||||
|
- 建议:解禁前减仓,解禁后观察
|
||||||
|
|
||||||
|
### 场景2:监控股东减持 ⚠️
|
||||||
|
|
||||||
|
**案例**:大股东连续减持
|
||||||
|
|
||||||
|
**风险管理师分析**:
|
||||||
|
- 识别减持频率和强度
|
||||||
|
- 分析减持股东身份(实际控制人/财务投资者)
|
||||||
|
- 评估对市场信心的影响
|
||||||
|
- 建议:降低仓位,设置止损位
|
||||||
|
|
||||||
|
### 场景3:追踪重要事件 📰
|
||||||
|
|
||||||
|
**案例**:公司面临重大诉讼或政策变动
|
||||||
|
|
||||||
|
**风险管理师分析**:
|
||||||
|
- 识别事件性质和影响范围
|
||||||
|
- 评估短中长期影响
|
||||||
|
- 判断事件的不确定性
|
||||||
|
- 建议:谨慎持仓,关注后续进展
|
||||||
|
|
||||||
|
## 🔧 技术实现
|
||||||
|
|
||||||
|
### 核心模块
|
||||||
|
|
||||||
|
```
|
||||||
|
risk_data_fetcher.py # 风险数据获取模块
|
||||||
|
├── RiskDataFetcher # 风险数据获取类
|
||||||
|
│ ├── get_risk_data() # 主函数:获取所有风险数据
|
||||||
|
│ ├── _get_lifting_ban_data() # 获取限售解禁
|
||||||
|
│ ├── _get_shareholder_reduction_data() # 获取股东减持
|
||||||
|
│ ├── _get_important_events_data() # 获取重要事件
|
||||||
|
│ ├── format_risk_data_for_ai() # 格式化供AI分析(完整数据)
|
||||||
|
│ └── _format_dataframe_for_ai() # DataFrame转文本格式
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据处理流程
|
||||||
|
|
||||||
|
```
|
||||||
|
pywencai查询 → DataFrame原始数据 → 格式化为文本 → 喂给AI
|
||||||
|
↓ ↓ ↓ ↓
|
||||||
|
问句查询 保留所有字段 逐行格式化 深度解析
|
||||||
|
实时数据 完整记录 AI可读 量化评估
|
||||||
|
```
|
||||||
|
|
||||||
|
### 数据流程
|
||||||
|
|
||||||
|
```
|
||||||
|
用户输入股票代码
|
||||||
|
↓
|
||||||
|
stock_data.py → get_risk_data()
|
||||||
|
↓
|
||||||
|
risk_data_fetcher.py → 调用pywencai
|
||||||
|
↓
|
||||||
|
获取三类风险数据
|
||||||
|
↓
|
||||||
|
ai_agents.py → risk_management_agent()
|
||||||
|
↓
|
||||||
|
DeepSeek AI 深度分析
|
||||||
|
↓
|
||||||
|
生成风险评估报告
|
||||||
|
```
|
||||||
|
|
||||||
|
## 📈 数据来源
|
||||||
|
|
||||||
|
- **数据源**:问财(pywencai)
|
||||||
|
- **更新频率**:实时查询
|
||||||
|
- **查询语法**:自然语言问句
|
||||||
|
- **数据类型**:结构化表格数据
|
||||||
|
|
||||||
|
## ⚙️ 配置说明
|
||||||
|
|
||||||
|
### 默认配置
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 风险管理师默认启用
|
||||||
|
enable_risk = True
|
||||||
|
|
||||||
|
# 仅支持A股
|
||||||
|
supported_markets = ["中国A股(6位代码)"]
|
||||||
|
|
||||||
|
# 查询延迟(避免频繁请求)
|
||||||
|
query_delay = 1秒
|
||||||
|
```
|
||||||
|
|
||||||
|
### 在批量分析中使用
|
||||||
|
|
||||||
|
```python
|
||||||
|
# 批量分析也支持风险管理功能
|
||||||
|
enabled_analysts_config = {
|
||||||
|
'technical': True,
|
||||||
|
'fundamental': True,
|
||||||
|
'fund_flow': True,
|
||||||
|
'risk': True, # 启用风险管理师
|
||||||
|
'sentiment': False,
|
||||||
|
'news': False
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
## 🎓 最佳实践
|
||||||
|
|
||||||
|
### 1. 结合其他分析师 👥
|
||||||
|
|
||||||
|
风险管理师的分析应该与其他分析师综合判断:
|
||||||
|
|
||||||
|
- **技术分析师**:识别技术面风险信号
|
||||||
|
- **基本面分析师**:评估基本面恶化风险
|
||||||
|
- **资金面分析师**:监控主力资金流出
|
||||||
|
- **风险管理师**:识别特定风险事件
|
||||||
|
|
||||||
|
### 2. 重点关注时间窗口 ⏰
|
||||||
|
|
||||||
|
特别关注以下时间窗口的风险:
|
||||||
|
|
||||||
|
- 解禁前1个月:提前规避风险
|
||||||
|
- 减持公告后:评估市场反应
|
||||||
|
- 重大事件发生时:及时调整策略
|
||||||
|
|
||||||
|
### 3. 设置风险预警 🔔
|
||||||
|
|
||||||
|
可以结合监测功能,设置风险预警:
|
||||||
|
|
||||||
|
- 解禁预警:提前30天预警
|
||||||
|
- 减持预警:出现减持公告时预警
|
||||||
|
- 事件预警:重大负面事件预警
|
||||||
|
|
||||||
|
## 📝 注意事项
|
||||||
|
|
||||||
|
### 支持范围
|
||||||
|
|
||||||
|
✅ **支持**:中国A股(6位数字代码)
|
||||||
|
❌ **不支持**:美股、港股
|
||||||
|
|
||||||
|
### 数据时效性
|
||||||
|
|
||||||
|
- 数据来自问财实时查询
|
||||||
|
- 可能存在1-2个交易日的延迟
|
||||||
|
- 建议定期刷新分析
|
||||||
|
|
||||||
|
### 网络依赖
|
||||||
|
|
||||||
|
- 需要稳定的网络连接
|
||||||
|
- 查询可能需要5-10秒
|
||||||
|
- 失败时会自动降级到基础分析
|
||||||
|
|
||||||
|
### 数据准确性
|
||||||
|
|
||||||
|
- 数据来源于公开信息
|
||||||
|
- 建议交叉验证重要信息
|
||||||
|
- 以官方公告为准
|
||||||
|
|
||||||
|
## 🚀 未来规划
|
||||||
|
|
||||||
|
### 计划新增功能
|
||||||
|
|
||||||
|
- [ ] 风险评分量化模型
|
||||||
|
- [ ] 风险历史对比分析
|
||||||
|
- [ ] 风险预警阈值设置
|
||||||
|
- [ ] 风险事件影响回测
|
||||||
|
- [ ] 多股票风险对比分析
|
||||||
|
|
||||||
|
### 优化方向
|
||||||
|
|
||||||
|
- 增加更多风险数据源
|
||||||
|
- 优化数据查询速度
|
||||||
|
- 提升AI分析准确度
|
||||||
|
- 增强可视化展示
|
||||||
|
|
||||||
|
## 📞 问题反馈
|
||||||
|
|
||||||
|
如果在使用过程中遇到问题:
|
||||||
|
|
||||||
|
1. **数据获取失败**:检查网络连接,稍后重试
|
||||||
|
2. **分析结果异常**:确认股票代码正确(6位A股代码)
|
||||||
|
3. **其他问题**:查看控制台错误信息
|
||||||
|
|
||||||
|
## 📚 相关文档
|
||||||
|
|
||||||
|
- `主力选股使用指南.md` - 了解主力资金分析
|
||||||
|
- `分析师团队选择功能说明.md` - 了解如何选择分析师
|
||||||
|
- `智瞰龙虎功能说明.md` - 了解龙虎榜风险分析
|
||||||
|
|
||||||
|
## 🎯 总结
|
||||||
|
|
||||||
|
风险管理师增强功能通过**问财实时数据**和**完整数据传递**,为投资者提供:
|
||||||
|
|
||||||
|
✅ **三大风险数据**:限售解禁、大股东减持、重要事件
|
||||||
|
✅ **完整原始数据**:所有字段、所有记录,不遗漏任何信息
|
||||||
|
✅ **AI深度解析**:自动识别关键风险点,量化评估
|
||||||
|
✅ **11维度分析**:全面评估各类风险
|
||||||
|
✅ **可操作建议**:具体的风险控制策略
|
||||||
|
✅ **实时更新**:基于最新公开信息
|
||||||
|
✅ **智能分析**:DeepSeek AI从海量数据中提取关键信息
|
||||||
|
|
||||||
|
**核心优势:**
|
||||||
|
- 不再是摘要或概括,而是**完整原始数据**
|
||||||
|
- AI自主解析每条记录的**每个字段**
|
||||||
|
- 基于实际数据给出**量化风险评估**
|
||||||
|
- 让AI的分析更准确、更深入、更可靠
|
||||||
|
|
||||||
|
让投资决策更安全、更可靠!⚠️📊💡
|
||||||
|
|
||||||
Reference in New Issue
Block a user