Initial commit

This commit is contained in:
freedakgmail
2026-07-17 18:49:07 +08:00
commit 9c7d7abdd4
100 changed files with 41337 additions and 0 deletions
+253
View File
@@ -0,0 +1,253 @@
"""
豆包AI服务模块
用于股票分析的AI对话(流式输出版本)
"""
import requests
import json
# API配置
API_KEY = "9fd8383f-5776-4366-855d-c6f40e867940"
API_URL = "https://ark.cn-beijing.volces.com/api/v3/chat/completions"
MODEL = "doubao-seed-1-6-251015"
def analyze_stock(stock_code, stock_name, stock_data):
"""
使用豆包AI分析股票(流式输出,获取思考和结论)
"""
# 构建分析提示词(基于推荐模型v3.0)
fund_flow_str = format_fund_flow(stock_data.get('fund_flow_3days', []))
prompt = f"""分析{stock_name}({stock_code})投资价值。
数据:价格{stock_data.get('price', 'N/A')}元,PE={stock_data.get('pe', 'N/A')}PB={stock_data.get('pb', 'N/A')}ROE={stock_data.get('roe', 'N/A')}%,市值{format_market_cap(stock_data.get('total_market_cap'))}
资金流向:{fund_flow_str}
评分模型:价格位置(30分,低于50%为低位)、资金流向(25分,主力净流入占比)、趋势(15分)、连续性(15分,≥3天强连续)、涨跌配合(10分)、量能(5分)
推荐率:80-100强买/卖,60-79可操作,40-59观望,0-39不建议
按以下格式输出:
## 技术面分析
分析资金流向趋势和连续性
## 基本面分析
分析PE/ROE估值和盈利能力
## 操作建议
明确建议买入/持有/卖出,给出预估推荐率(0-100)
## 风险提示
列出2-3个风险点"""
try:
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
payload = {
"model": MODEL,
"max_completion_tokens": 2048,
"stream": True, # 启用流式输出
"messages": [
{
"role": "user",
"content": prompt
}
]
}
# 流式请求
response = requests.post(API_URL, headers=headers, json=payload, timeout=120, stream=True)
if response.status_code == 200:
reasoning_content = "" # 思考过程
content = "" # 最终结论
for line in response.iter_lines():
if line:
line_str = line.decode('utf-8')
if line_str.startswith('data: '):
data_str = line_str[6:]
if data_str == '[DONE]':
break
try:
data = json.loads(data_str)
if 'choices' in data and len(data['choices']) > 0:
delta = data['choices'][0].get('delta', {})
# 获取思考过程
if 'reasoning_content' in delta and delta['reasoning_content']:
reasoning_content += delta['reasoning_content']
# 获取最终内容
if 'content' in delta and delta['content']:
content += delta['content']
except json.JSONDecodeError:
continue
# 组合思考过程和结论
full_analysis = ""
if reasoning_content:
full_analysis += "## 💭 AI思考过程\n" + reasoning_content + "\n\n---\n\n"
if content:
full_analysis += content
if full_analysis:
return {'success': True, 'analysis': full_analysis}
else:
return {'success': False, 'error': 'AI返回内容为空'}
else:
return {'success': False, 'error': f'API请求失败: {response.status_code}'}
except requests.exceptions.Timeout:
return {'success': False, 'error': 'AI分析超时,请稍后重试'}
except Exception as e:
return {'success': False, 'error': f'AI分析失败: {str(e)}'}
def analyze_stock_stream(stock_code, stock_name, stock_data):
"""
使用豆包AI分析股票(流式生成器,用于SSE)
"""
# 构建分析提示词
fund_flow_str = format_fund_flow(stock_data.get('fund_flow_3days', []))
signal_status = stock_data.get('signal_status', [])
indicators = stock_data.get('indicators', {})
signal_lines = []
triggered_names = []
for s in signal_status:
status = '✅已触发' if s.get('triggered') else '○未触发'
signal_lines.append(f" {s.get('name','')}: {status} (胜率{s.get('strength',0)}%) — {s.get('description','')}")
if s.get('triggered'):
triggered_names.append(s.get('name', ''))
signal_text = '\n'.join(signal_lines) if signal_lines else ' 暂无扫描数据'
triggered_text = ''.join(triggered_names) if triggered_names else ''
macd = indicators.get('macd', {})
skdj = indicators.get('skdj', {})
ema = indicators.get('ema', {})
indicator_text = f"MACD: DIF={macd.get('dif','N/A')}, DEA={macd.get('dea','N/A')} | SKDJ: K={skdj.get('k','N/A')}, D={skdj.get('d','N/A')} | EMA: EMA3={ema.get('ema3','N/A')}, EMA21={ema.get('ema21','N/A')}"
prompt = f"""基于"交易信号实战体系"分析{stock_name}({stock_code})。
【基本面数据】
价格{stock_data.get('price', 'N/A')}元,PE={stock_data.get('pe', 'N/A')}PB={stock_data.get('pb', 'N/A')}ROE={stock_data.get('roe', 'N/A')}%,市值{format_market_cap(stock_data.get('total_market_cap'))}
资金流向:{fund_flow_str}
【技术指标】
{indicator_text}
【7大交易信号状态】(当前已触发: {triggered_text}
{signal_text}
【交易信号体系规则】
信号胜率排行: ★主升浪85% > 日线底背离80% > 龙抬头75% > 真龙70% > 短底背离65% > 老鼠仓60% > 反弹55%
标准牛股启动顺序: 日线底背离→龙抬头→真龙→★主升浪→反弹
体系最强战法: 1)日线底背离出现→关注 2)龙抬头出现→买入 3)真龙/★主升浪→持有加仓 4)不见主升浪→不出场
请按以下格式分析:
## 交易信号分析
根据7大信号的触发状态,判断该股在"底部→拉升"流程中处于哪个阶段。已触发的信号说明什么?距离下一个关键信号还有多远?
## 基本面分析
简要分析PE/ROE估值水平和盈利能力(2-3句话)
## 操作建议
基于体系最强战法规则,给出明确建议(关注/买入/持有加仓/减仓/观望),并解释理由。给出推荐率(0-100)
## 风险提示
列出2-3个关键风险点"""
try:
headers = {
"Content-Type": "application/json",
"Authorization": f"Bearer {API_KEY}"
}
payload = {
"model": MODEL,
"max_completion_tokens": 2048,
"stream": True,
"messages": [
{"role": "user", "content": prompt}
]
}
response = requests.post(API_URL, headers=headers, json=payload, timeout=120, stream=True)
if response.status_code == 200:
in_reasoning = False
for line in response.iter_lines():
if line:
line_str = line.decode('utf-8')
if line_str.startswith('data: '):
data_str = line_str[6:]
if data_str == '[DONE]':
break
try:
data = json.loads(data_str)
if 'choices' in data and len(data['choices']) > 0:
delta = data['choices'][0].get('delta', {})
# 思考过程
if 'reasoning_content' in delta and delta['reasoning_content']:
if not in_reasoning:
yield {'type': 'reasoning_start'}
in_reasoning = True
yield {'type': 'reasoning', 'content': delta['reasoning_content']}
# 最终内容
if 'content' in delta and delta['content']:
if in_reasoning:
yield {'type': 'reasoning_end'}
in_reasoning = False
yield {'type': 'content', 'content': delta['content']}
except json.JSONDecodeError:
continue
if in_reasoning:
yield {'type': 'reasoning_end'}
else:
yield {'type': 'error', 'content': f'API请求失败: {response.status_code}'}
except requests.exceptions.Timeout:
yield {'type': 'error', 'content': 'AI分析超时,请稍后重试'}
except Exception as e:
yield {'type': 'error', 'content': f'AI分析失败: {str(e)}'}
def format_market_cap(value):
"""格式化市值"""
if not value:
return 'N/A'
try:
value = float(value)
if value >= 100000000000: # 千亿
return f"{value/100000000000:.2f}千亿"
elif value >= 100000000: # 亿
return f"{value/100000000:.2f}亿"
else:
return f"{value/10000:.2f}"
except:
return str(value)
def format_fund_flow(fund_flow_list):
"""格式化资金流向数据"""
if not fund_flow_list:
return "暂无数据"
lines = []
for item in fund_flow_list:
date = item.get('date', '')
change = item.get('change_pct', 0)
main = item.get('main_pct', 0)
super_pct = item.get('super_pct', 0)
lines.append(f"- {date}: 涨跌{change:+.2f}%, 主力{main:+.2f}%, 超大单{super_pct:+.2f}%")
return '\n'.join(lines)