347 lines
12 KiB
Python
347 lines
12 KiB
Python
import openai
|
||
import json
|
||
from typing import Dict, List, Any, Optional
|
||
import config
|
||
|
||
class DeepSeekClient:
|
||
"""DeepSeek API客户端"""
|
||
|
||
def __init__(self, model="deepseek-chat"):
|
||
self.model = model
|
||
self.client = openai.OpenAI(
|
||
api_key=config.DEEPSEEK_API_KEY,
|
||
base_url=config.DEEPSEEK_BASE_URL
|
||
)
|
||
|
||
def call_api(self, messages: List[Dict[str, str]], model: Optional[str] = None,
|
||
temperature: float = 0.7, max_tokens: int = 2000) -> str:
|
||
"""调用DeepSeek API"""
|
||
# 使用实例的模型,如果没有传入则使用默认模型
|
||
model_to_use = model or self.model
|
||
|
||
# 对于 reasoner 模型,自动增加 max_tokens
|
||
if "reasoner" in model_to_use.lower() and max_tokens <= 2000:
|
||
max_tokens = 8000 # reasoner 模型需要更多 tokens 来输出推理过程
|
||
|
||
try:
|
||
response = self.client.chat.completions.create(
|
||
model=model_to_use,
|
||
messages=messages,
|
||
temperature=temperature,
|
||
max_tokens=max_tokens
|
||
)
|
||
|
||
# 处理 reasoner 模型的响应
|
||
message = response.choices[0].message
|
||
|
||
# reasoner 模型可能包含 reasoning_content(推理过程)和 content(最终答案)
|
||
# 我们返回完整内容,包括推理过程(如果有的话)
|
||
result = ""
|
||
|
||
# 检查是否有推理内容
|
||
if hasattr(message, 'reasoning_content') and message.reasoning_content:
|
||
result += f"【推理过程】\n{message.reasoning_content}\n\n"
|
||
|
||
# 添加最终内容
|
||
if message.content:
|
||
result += message.content
|
||
|
||
return result if result else "API返回空响应"
|
||
|
||
except Exception as e:
|
||
return f"API调用失败: {str(e)}"
|
||
|
||
def technical_analysis(self, stock_info: Dict, stock_data: Any, indicators: Dict) -> str:
|
||
"""技术面分析"""
|
||
prompt = f"""
|
||
你是一名资深的技术分析师。请基于以下股票数据进行专业的技术面分析:
|
||
|
||
股票信息:
|
||
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
||
- 股票名称:{stock_info.get('name', 'N/A')}
|
||
- 当前价格:{stock_info.get('current_price', 'N/A')}
|
||
- 涨跌幅:{stock_info.get('change_percent', 'N/A')}%
|
||
|
||
最新技术指标:
|
||
- 收盘价:{indicators.get('price', 'N/A')}
|
||
- MA5:{indicators.get('ma5', 'N/A')}
|
||
- MA10:{indicators.get('ma10', 'N/A')}
|
||
- MA20:{indicators.get('ma20', 'N/A')}
|
||
- MA60:{indicators.get('ma60', 'N/A')}
|
||
- RSI:{indicators.get('rsi', 'N/A')}
|
||
- MACD:{indicators.get('macd', 'N/A')}
|
||
- MACD信号线:{indicators.get('macd_signal', 'N/A')}
|
||
- 布林带上轨:{indicators.get('bb_upper', 'N/A')}
|
||
- 布林带下轨:{indicators.get('bb_lower', 'N/A')}
|
||
- K值:{indicators.get('k_value', 'N/A')}
|
||
- D值:{indicators.get('d_value', 'N/A')}
|
||
- 量比:{indicators.get('volume_ratio', 'N/A')}
|
||
|
||
请从以下角度进行分析:
|
||
1. 趋势分析(均线系统、价格走势)
|
||
2. 超买超卖分析(RSI、KDJ)
|
||
3. 动量分析(MACD)
|
||
4. 支撑阻力分析(布林带)
|
||
5. 成交量分析
|
||
6. 短期、中期、长期技术判断
|
||
7. 关键技术位分析
|
||
|
||
请给出专业、详细的技术分析报告,包含风险提示。
|
||
"""
|
||
|
||
messages = [
|
||
{"role": "system", "content": "你是一名经验丰富的股票技术分析师,具有深厚的技术分析功底。"},
|
||
{"role": "user", "content": prompt}
|
||
]
|
||
|
||
return self.call_api(messages)
|
||
|
||
def fundamental_analysis(self, stock_info: Dict, financial_data: Dict = None) -> str:
|
||
"""基本面分析"""
|
||
|
||
# 构建财务数据部分
|
||
financial_section = ""
|
||
if financial_data and not financial_data.get('error'):
|
||
ratios = financial_data.get('financial_ratios', {})
|
||
if ratios:
|
||
financial_section = f"""
|
||
详细财务指标:
|
||
【盈利能力】
|
||
- 净资产收益率(ROE):{ratios.get('净资产收益率ROE', ratios.get('ROE', 'N/A'))}
|
||
- 总资产收益率(ROA):{ratios.get('总资产收益率ROA', ratios.get('ROA', 'N/A'))}
|
||
- 销售毛利率:{ratios.get('销售毛利率', ratios.get('毛利率', 'N/A'))}
|
||
- 销售净利率:{ratios.get('销售净利率', ratios.get('净利率', 'N/A'))}
|
||
|
||
【偿债能力】
|
||
- 资产负债率:{ratios.get('资产负债率', 'N/A')}
|
||
- 流动比率:{ratios.get('流动比率', 'N/A')}
|
||
- 速动比率:{ratios.get('速动比率', 'N/A')}
|
||
|
||
【运营能力】
|
||
- 存货周转率:{ratios.get('存货周转率', 'N/A')}
|
||
- 应收账款周转率:{ratios.get('应收账款周转率', 'N/A')}
|
||
- 总资产周转率:{ratios.get('总资产周转率', 'N/A')}
|
||
|
||
【成长能力】
|
||
- 营业收入同比增长:{ratios.get('营业收入同比增长', ratios.get('收入增长', 'N/A'))}
|
||
- 净利润同比增长:{ratios.get('净利润同比增长', ratios.get('盈利增长', 'N/A'))}
|
||
|
||
【每股指标】
|
||
- 每股收益(EPS):{ratios.get('EPS', 'N/A')}
|
||
- 每股账面价值:{ratios.get('每股账面价值', 'N/A')}
|
||
- 股息率:{ratios.get('股息率', stock_info.get('dividend_yield', 'N/A'))}
|
||
- 派息率:{ratios.get('派息率', 'N/A')}
|
||
"""
|
||
|
||
# 添加报告期信息
|
||
if ratios.get('报告期'):
|
||
financial_section = f"\n财务数据报告期:{ratios.get('报告期')}\n" + financial_section
|
||
|
||
prompt = f"""
|
||
你是一名资深的基本面分析师,拥有CFA资格和10年以上的证券分析经验。请基于以下详细信息进行深入的基本面分析:
|
||
|
||
【基本信息】
|
||
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
||
- 股票名称:{stock_info.get('name', 'N/A')}
|
||
- 当前价格:{stock_info.get('current_price', 'N/A')}
|
||
- 市值:{stock_info.get('market_cap', 'N/A')}
|
||
- 行业:{stock_info.get('sector', 'N/A')}
|
||
- 细分行业:{stock_info.get('industry', 'N/A')}
|
||
|
||
【估值指标】
|
||
- 市盈率(PE):{stock_info.get('pe_ratio', 'N/A')}
|
||
- 市净率(PB):{stock_info.get('pb_ratio', 'N/A')}
|
||
- 市销率(PS):{stock_info.get('ps_ratio', 'N/A')}
|
||
- Beta系数:{stock_info.get('beta', 'N/A')}
|
||
- 52周最高:{stock_info.get('52_week_high', 'N/A')}
|
||
- 52周最低:{stock_info.get('52_week_low', 'N/A')}
|
||
{financial_section}
|
||
|
||
请从以下维度进行专业、深入的分析:
|
||
|
||
1. **公司质地分析**
|
||
- 业务模式和核心竞争力
|
||
- 行业地位和市场份额
|
||
- 护城河分析(品牌、技术、规模等)
|
||
|
||
2. **盈利能力分析**
|
||
- ROE和ROA水平评估
|
||
- 毛利率和净利率趋势
|
||
- 与行业平均水平对比
|
||
- 盈利质量和持续性
|
||
|
||
3. **财务健康度分析**
|
||
- 资产负债结构
|
||
- 偿债能力评估
|
||
- 现金流状况
|
||
- 财务风险识别
|
||
|
||
4. **成长性分析**
|
||
- 收入和利润增长趋势
|
||
- 增长驱动因素
|
||
- 未来成长空间
|
||
- 行业发展前景
|
||
|
||
5. **估值分析**
|
||
- 当前估值水平(PE、PB)
|
||
- 历史估值区间对比
|
||
- 行业估值对比
|
||
- 合理估值区间判断
|
||
|
||
6. **投资价值判断**
|
||
- 综合评分(0-100分)
|
||
- 投资亮点
|
||
- 投资风险
|
||
- 适合的投资者类型
|
||
|
||
请给出专业、详细的基本面分析报告,数据分析要深入,结论要有依据。
|
||
|
||
请结合当前市场环境和行业发展趋势,给出专业的基本面分析报告。
|
||
"""
|
||
|
||
messages = [
|
||
{"role": "system", "content": "你是一名经验丰富的股票基本面分析师,擅长公司财务分析和行业研究。"},
|
||
{"role": "user", "content": prompt}
|
||
]
|
||
|
||
return self.call_api(messages)
|
||
|
||
def fund_flow_analysis(self, stock_info: Dict, indicators: Dict) -> str:
|
||
"""资金面分析"""
|
||
prompt = f"""
|
||
你是一名资深的资金面分析师。请基于以下信息进行专业的资金面分析:
|
||
|
||
股票信息:
|
||
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
||
- 股票名称:{stock_info.get('name', 'N/A')}
|
||
- 当前价格:{stock_info.get('current_price', 'N/A')}
|
||
- 市值:{stock_info.get('market_cap', 'N/A')}
|
||
|
||
资金相关指标:
|
||
- 量比:{indicators.get('volume_ratio', 'N/A')}
|
||
- 当前成交量与5日均量比:{indicators.get('volume_ratio', 'N/A')}
|
||
|
||
请从以下角度进行分析:
|
||
1. 成交量变化分析
|
||
2. 资金流入流出趋势
|
||
3. 大单、中单、小单资金行为
|
||
4. 主力资金动向分析
|
||
5. 市场情绪和资金偏好
|
||
6. 流动性分析
|
||
7. 资金面对股价的支撑或压力
|
||
|
||
请结合当前市场资金环境,给出专业的资金面分析报告。
|
||
"""
|
||
|
||
messages = [
|
||
{"role": "system", "content": "你是一名经验丰富的资金面分析师,擅长市场资金流向和主力行为分析。"},
|
||
{"role": "user", "content": prompt}
|
||
]
|
||
|
||
return self.call_api(messages)
|
||
|
||
def comprehensive_discussion(self, technical_report: str, fundamental_report: str,
|
||
fund_flow_report: str, stock_info: Dict) -> str:
|
||
"""综合讨论"""
|
||
prompt = f"""
|
||
现在需要进行一场投资决策会议,你作为首席分析师,需要综合各位分析师的报告进行讨论。
|
||
|
||
股票基本信息:
|
||
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
||
- 股票名称:{stock_info.get('name', 'N/A')}
|
||
- 当前价格:{stock_info.get('current_price', 'N/A')}
|
||
|
||
技术面分析报告:
|
||
{technical_report}
|
||
|
||
基本面分析报告:
|
||
{fundamental_report}
|
||
|
||
资金面分析报告:
|
||
{fund_flow_report}
|
||
|
||
请作为首席分析师,综合以上三个维度的分析报告,进行深入讨论:
|
||
|
||
1. 各个分析维度的一致性和分歧点
|
||
2. 不同分析结论的权重考量
|
||
3. 当前市场环境下的投资逻辑
|
||
4. 潜在风险和机会识别
|
||
5. 不同投资周期的考量(短期、中期、长期)
|
||
6. 市场情绪和预期管理
|
||
|
||
请模拟一场专业的投资讨论会议,体现不同观点的碰撞和融合。
|
||
"""
|
||
|
||
messages = [
|
||
{"role": "system", "content": "你是一名资深的首席投资分析师,擅长综合不同维度的分析形成投资判断。"},
|
||
{"role": "user", "content": prompt}
|
||
]
|
||
|
||
return self.call_api(messages, max_tokens=6000)
|
||
|
||
def final_decision(self, comprehensive_discussion: str, stock_info: Dict,
|
||
indicators: Dict) -> Dict[str, Any]:
|
||
"""最终投资决策"""
|
||
prompt = f"""
|
||
基于前期的综合分析讨论,现在需要做出最终的投资决策。
|
||
|
||
股票信息:
|
||
- 股票代码:{stock_info.get('symbol', 'N/A')}
|
||
- 股票名称:{stock_info.get('name', 'N/A')}
|
||
- 当前价格:{stock_info.get('current_price', 'N/A')}
|
||
|
||
综合分析讨论结果:
|
||
{comprehensive_discussion}
|
||
|
||
当前关键技术位:
|
||
- MA20:{indicators.get('ma20', 'N/A')}
|
||
- 布林带上轨:{indicators.get('bb_upper', 'N/A')}
|
||
- 布林带下轨:{indicators.get('bb_lower', 'N/A')}
|
||
|
||
请给出最终投资决策,必须包含以下内容:
|
||
|
||
1. 投资评级:买入/持有/卖出
|
||
2. 目标价位(具体数字)
|
||
3. 操作建议(具体的买入/卖出策略)
|
||
4. 进场位置(具体价位区间)
|
||
5. 止盈位置(具体价位)
|
||
6. 止损位置(具体价位)
|
||
7. 持有周期建议
|
||
8. 风险提示
|
||
9. 仓位建议(轻仓/中等仓位/重仓)
|
||
|
||
请以JSON格式输出决策结果,格式如下:
|
||
{{
|
||
"rating": "买入/持有/卖出",
|
||
"target_price": "目标价位数字",
|
||
"operation_advice": "具体操作建议",
|
||
"entry_range": "进场价位区间",
|
||
"take_profit": "止盈价位",
|
||
"stop_loss": "止损价位",
|
||
"holding_period": "持有周期",
|
||
"position_size": "仓位建议",
|
||
"risk_warning": "风险提示",
|
||
"confidence_level": "信心度(1-10分)"
|
||
}}
|
||
"""
|
||
|
||
messages = [
|
||
{"role": "system", "content": "你是一名专业的投资决策专家,需要给出明确、可执行的投资建议。"},
|
||
{"role": "user", "content": prompt}
|
||
]
|
||
|
||
response = self.call_api(messages, temperature=0.3, max_tokens=4000)
|
||
|
||
try:
|
||
# 尝试解析JSON响应
|
||
import re
|
||
json_match = re.search(r'\{.*\}', response, re.DOTALL)
|
||
if json_match:
|
||
decision_json = json.loads(json_match.group())
|
||
return decision_json
|
||
else:
|
||
# 如果无法解析JSON,返回文本响应
|
||
return {"decision_text": response}
|
||
except:
|
||
return {"decision_text": response}
|