commit;
This commit is contained in:
parent
8f73099e18
commit
03450116ce
23
src/app.py
23
src/app.py
|
@ -241,7 +241,7 @@ def initialize_stock_price_schedule():
|
|||
scheduler.add_job(
|
||||
func=update_stock_price,
|
||||
trigger='interval',
|
||||
minutes=5,
|
||||
minutes=60,
|
||||
id='stock_price_update',
|
||||
name='实时股价数据采集',
|
||||
replace_existing=True
|
||||
|
@ -249,7 +249,7 @@ def initialize_stock_price_schedule():
|
|||
|
||||
# 启动调度器
|
||||
scheduler.start()
|
||||
logger.info("实时股价数据采集定时任务已初始化,将在交易时间内每5分钟执行一次")
|
||||
logger.info("实时股价数据采集定时任务已初始化,将在交易时间内每60分钟执行一次")
|
||||
return scheduler
|
||||
|
||||
except Exception as e:
|
||||
|
@ -1452,6 +1452,22 @@ def comprehensive_analysis():
|
|||
if 'db_session2' in locals() and db_session2 is not None: # 确保 db_session 已定义
|
||||
db_session2.close() # <--- 关闭会话
|
||||
|
||||
# 获取企业市值信息
|
||||
market_value_results = {}
|
||||
try:
|
||||
from src.valuation_analysis.stock_price_collector import StockPriceCollector
|
||||
price_collector = StockPriceCollector()
|
||||
|
||||
for stock_code in input_stock_codes:
|
||||
price_data = price_collector.get_stock_price_data(stock_code)
|
||||
if price_data and 'total_market_value' in price_data:
|
||||
market_value_results[stock_code] = price_data['total_market_value']
|
||||
else:
|
||||
market_value_results[stock_code] = None
|
||||
except Exception as e:
|
||||
logger.error(f"获取企业市值信息失败: {str(e)}")
|
||||
market_value_results = {}
|
||||
|
||||
db_session = next(get_db())
|
||||
# 筛选出传入列表中符合条件的股票
|
||||
for code, name in all_stocks:
|
||||
|
@ -1475,7 +1491,8 @@ def comprehensive_analysis():
|
|||
"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:低于行业)
|
||||
"tracks": track_results.get(code, []) # 添加赛道信息
|
||||
"tracks": track_results.get(code, []), # 添加赛道信息
|
||||
"market_value": market_value_results.get(code) # 添加企业市值信息
|
||||
})
|
||||
|
||||
logger.info(f"筛选出 {len(filtered_stocks)} 个符合条件的股票")
|
||||
|
|
|
@ -1477,6 +1477,13 @@ class FundamentalAnalyzer:
|
|||
- 长期持有:公司具备长期稳定的盈利能力、行业地位稳固、长期成长性好
|
||||
- 不建议投资:存在明显风险因素、基本面恶化、估值过高、行业前景不佳或者存在退市风险
|
||||
|
||||
请注意:
|
||||
1. 请完全基于提供的分析结果中的最新数据进行分析,不要使用任何历史数据或过时信息
|
||||
2. 如果分析结果中包含2024年或2025年的数据,请优先使用这些最新数据
|
||||
3. 避免使用"2023年"等历史时间点的数据,除非分析结果中明确提供了这些数据
|
||||
4. 重点关注公司最新的业务发展、财务表现和市场定位
|
||||
5. 在分析行业环境时,请使用最新的行业数据和竞争格局信息
|
||||
|
||||
请提供专业、客观的分析,突出关键信息,避免冗长描述。重点关注投资价值和风险。在输出投资建议时,请明确指出是短期持有、中期持有、长期持有还是不建议投资。
|
||||
|
||||
各维度分析结果:
|
||||
|
|
|
@ -11,7 +11,7 @@ XUEQIU_HEADERS = {
|
|||
'Accept-Encoding': 'gzip, deflate, br, zstd',
|
||||
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8',
|
||||
'Client-Version': 'v2.44.75',
|
||||
'Cookie': 'cookiesu=811743062689927; device_id=33fa3c7fca4a65f8f4354e10ed6b7470; HMACCOUNT=8B64A2E3C307C8C0; s=c611ttmqlj; xq_is_login=1; u=8493411634; bid=4065a77ca57a69c83405d6e591ab5449_m8r2nhs8; Hm_lvt_1db88642e346389874251b5a1eded6e3=1746410725; xq_a_token=660fb18cf1d15162da76deedc46b649370124dca; xqat=660fb18cf1d15162da76deedc46b649370124dca; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOjg0OTM0MTE2MzQsImlzcyI6InVjIiwiZXhwIjoxNzQ5ODYxNjY5LCJjdG0iOjE3NDcyNjk2Njk0NDgsImNpZCI6ImQ5ZDBuNEFadXAifQ.jc_E9qvguLwBDASn1Z-KjGtU89pNJRwJq_hIaiR3r2re7-_xiXH8qhuhC3Se8rlfKGZ8sHsb3rSND_vnF7yMp90QQHdK_brSmlgd6_ltHmJfWSFNJvMk7F3s0yPjcpeMqeUTPFnZwKmoWwZVKEwdVBN8f25z6e9M2JjtSTZ2huADH_FdEn1rb9IU-H35z_MLWW1M7vB5xc2rh57yFIBnQoxu9OLfeETpeIpASP1UBeZXoQZ_v1gIWiFYItwuudIz0tPYzB-o2duRe31G0S_hNvEGl3HH4M5FjTyaPAq2PRuiZCyRF-25gHXBZnLcxyavZ1VAURfHng_377_IJNSXsw; xq_r_token=8a5dec9c93caf88d0e1f98f1d23ea1bb60eb6225; is_overseas=0; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1747356850; ssxmod_itna=eqGxBDnGKYuxcD4kDRgxYq7ueYKS8DBP01Dp2xQyP08D60DB40QuHhqDyGGdVmpmghQehYtDDsqze4GzDiLPGhDBWAFdYCdqt4NKWooqCWKCwdUme9Ill25QAClcymm=0Iil4OAe8oGLDY=DCTKK420iDYAEDBYD74G+DDeDiO3Dj4GmDGY=aeDFIQutVCRKdxDwDB=DmqG23ObDm4DfDDLorBD4Il2YDDtDAkaGNPDADA3doDDlYD84edb4DYpogQ0FdgahphuXIeDMixGXzAlzx9CnoiWtV/LfNf2aHPGuDG=OcC0Hh2bmRT3f8hGxYBY5QeOhx+BxorKq0DW7HRYqexx=CD=WKK7oQ7YBGxPG4KiKy7hAQd5dpOodYYrcqsMkbZMshieygdyhxogYO2deGd46DAQ5MA5VBxiT5/h4WB++l=Eet4D; ssxmod_itna2=eqGxBDnGKYuxcD4kDRgxYq7ueYKS8DBP01Dp2xQyP08D60DB40QuHhqDyGGdVmpmghQehY4Dfie4pCoTp35CT5NsKziGGtvkoYD',
|
||||
'Cookie': 'cookiesu=811743062689927; device_id=33fa3c7fca4a65f8f4354e10ed6b7470; HMACCOUNT=8B64A2E3C307C8C0; s=c611ttmqlj; xq_is_login=1; u=8493411634; bid=4065a77ca57a69c83405d6e591ab5449_m8r2nhs8; Hm_lvt_1db88642e346389874251b5a1eded6e3=1746410725; xq_a_token=660fb18cf1d15162da76deedc46b649370124dca; xqat=660fb18cf1d15162da76deedc46b649370124dca; xq_id_token=eyJ0eXAiOiJKV1QiLCJhbGciOiJSUzI1NiJ9.eyJ1aWQiOjg0OTM0MTE2MzQsImlzcyI6InVjIiwiZXhwIjoxNzQ5ODYxNjY5LCJjdG0iOjE3NDcyNjk2Njk0NDgsImNpZCI6ImQ5ZDBuNEFadXAifQ.jc_E9qvguLwBDASn1Z-KjGtU89pNJRwJq_hIaiR3r2re7-_xiXH8qhuhC3Se8rlfKGZ8sHsb3rSND_vnF7yMp90QQHdK_brSmlgd6_ltHmJfWSFNJvMk7F3s0yPjcpeMqeUTPFnZwKmoWwZVKEwdVBN8f25z6e9M2JjtSTZ2huADH_FdEn1rb9IU-H35z_MLWW1M7vB5xc2rh57yFIBnQoxu9OLfeETpeIpASP1UBeZXoQZ_v1gIWiFYItwuudIz0tPYzB-o2duRe31G0S_hNvEGl3HH4M5FjTyaPAq2PRuiZCyRF-25gHXBZnLcxyavZ1VAURfHng_377_IJNSXsw; xq_r_token=8a5dec9c93caf88d0e1f98f1d23ea1bb60eb6225; snbim_minify=true; is_overseas=0; Hm_lpvt_1db88642e346389874251b5a1eded6e3=1747905410; ssxmod_itna=eqGxBDnGKYuxcD4kDRgxYq7ueYKS8DBP01Dp2xQyP08D60DB40QuHhqDyGGTrlGiGbtOh01qDsqze4GzDiLPGhDBWAFdYCdqtsqfmmxXxyB+doh6odserKO5sg=EiqfqztqpiexCPGnD0=O77N4xYAEDBYD74G+DDeDiO3Dj4GmDGYd=eDFzjRQyl2edxDwDB=DmqG23grDm4DfDDL5xRD4zC2YDDtDAMWz5PDADA3ooDDlYGO44Lr4DYp52nXWdOaspxTXzeDMixGXzYlCgaCRo0TQy9LAN32TNPGuDG=H6e0ahrbicn0AP4KGGwQ0imPKY+5meOQDqixGYwQGGiGGetGe3qqjeKYw10G4ixqim2mpbK+h1iaIPeQAieNS1X5pXZP4rQ04Iv4zmQWvplG40P4Gw4CqRjwzlwGjPwlD3iho+qKlD4hi3YD; ssxmod_itna2=eqGxBDnGKYuxcD4kDRgxYq7ueYKS8DBP01Dp2xQyP08D60DB40QuHhqDyGGTrlGiGbtOh0P4DWhYebouIdHtBItz/DboqtwisfWD',
|
||||
'Referer': 'https://weibo.com/u/7735765253',
|
||||
'Sec-Ch-Ua': '"Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"',
|
||||
'Sec-Ch-Ua-Mobile': '?0',
|
||||
|
|
|
@ -11,6 +11,7 @@ from pymongo import MongoClient
|
|||
import logging
|
||||
from typing import Dict, List, Optional, Union, Tuple
|
||||
import json
|
||||
import requests
|
||||
|
||||
from .config import DB_URL, MONGO_CONFIG, LOG_FILE
|
||||
from .stock_price_collector import StockPriceCollector
|
||||
|
@ -394,6 +395,69 @@ class FinancialAnalyzer:
|
|||
'message': f'查询失败: {str(e)}'
|
||||
}
|
||||
|
||||
def get_momentum_indicators(self, stock_code: str, industry_codes: List[str]) -> Dict:
|
||||
"""
|
||||
获取动量指标数据
|
||||
|
||||
Args:
|
||||
stock_code: 目标股票代码
|
||||
industry_codes: 行业股票代码列表
|
||||
|
||||
Returns:
|
||||
动量指标数据字典
|
||||
"""
|
||||
try:
|
||||
url = "http://192.168.18.42:5000/api/dify/getStockMomentumIndex"
|
||||
payload = {
|
||||
"code_list": industry_codes,
|
||||
"target_code": stock_code
|
||||
}
|
||||
|
||||
response = requests.post(url, json=payload)
|
||||
if response.status_code != 200:
|
||||
return {
|
||||
'success': False,
|
||||
'message': f'获取动量指标失败: HTTP {response.status_code}'
|
||||
}
|
||||
|
||||
data = response.json()
|
||||
|
||||
# 计算OBV和NATR的rank_score
|
||||
obv_rank_score = round((1 - data['obv_rank'] / len(industry_codes)) * 10, 3)
|
||||
natr_rank_score = round((1 - data['natr_rank'] / len(industry_codes)) * 10, 3)
|
||||
|
||||
return {
|
||||
'success': True,
|
||||
'indicators': [
|
||||
{
|
||||
'key': 'obv',
|
||||
'desc': '能量',
|
||||
'value': round(data['OBV'], 3),
|
||||
'rank_score': obv_rank_score
|
||||
},
|
||||
{
|
||||
'key': 'form',
|
||||
'desc': f'技术形态-{data["form"]}',
|
||||
'value': round(data['form_probability'], 3),
|
||||
'rank_score': round(data['form_probability'] * 10, 3) # 将概率转换为0-10的分数
|
||||
},
|
||||
{
|
||||
'key': 'natr',
|
||||
'desc': '阶段位置',
|
||||
'value': round(data['NATR'], 3),
|
||||
'rank_score': natr_rank_score
|
||||
}
|
||||
],
|
||||
'avg_score': round((obv_rank_score + natr_rank_score + round(data['form_probability'] * 10, 3)) / 3, 3)
|
||||
}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"获取动量指标失败: {str(e)}")
|
||||
return {
|
||||
'success': False,
|
||||
'message': f'获取动量指标失败: {str(e)}'
|
||||
}
|
||||
|
||||
def analyze_financial_data(self, stock_code: str) -> Dict:
|
||||
"""
|
||||
分析财务数据
|
||||
|
@ -413,6 +477,12 @@ class FinancialAnalyzer:
|
|||
industry_analyzer = IndustryAnalyzer()
|
||||
concepts = industry_analyzer.get_stock_concepts(stock_code)
|
||||
|
||||
# 获取同行业股票列表
|
||||
industry_stocks = self.get_industry_stocks(stock_code)
|
||||
|
||||
# 获取动量指标数据
|
||||
momentum_result = self.get_momentum_indicators(stock_code, industry_stocks)
|
||||
|
||||
# 获取基础财务指标
|
||||
base_result = self.extract_financial_indicators(stock_code)
|
||||
if not base_result.get('success'):
|
||||
|
@ -578,6 +648,7 @@ class FinancialAnalyzer:
|
|||
'growth': growth_data,
|
||||
'value_rating': process_indicators(value_rating_indicators),
|
||||
'liquidity': process_indicators(liquidity_indicators),
|
||||
'momentum': momentum_result.get('indicators', []), # 添加动量指标数据
|
||||
'concepts': concepts, # 添加概念板块数据
|
||||
'price_data': price_data # 添加实时股价数据
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue