commit;
This commit is contained in:
parent
6986259726
commit
ed2758532e
|
@ -1,5 +1,7 @@
|
|||
import logging
|
||||
from typing import Dict, List, Optional, Callable, Tuple
|
||||
import os
|
||||
from datetime import datetime
|
||||
from typing import Dict, List, Optional, Tuple, Callable
|
||||
# 修改导入路径,使用相对导入
|
||||
try:
|
||||
# 尝试相对导入
|
||||
|
@ -26,6 +28,36 @@ import re
|
|||
# 设置日志记录
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
# 获取项目根目录的绝对路径
|
||||
ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||
|
||||
# 创建logs目录(如果不存在)
|
||||
LOGS_DIR = os.path.join(ROOT_DIR, "logs")
|
||||
os.makedirs(LOGS_DIR, exist_ok=True)
|
||||
|
||||
# 配置日志格式
|
||||
log_format = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
|
||||
date_format = '%Y-%m-%d %H:%M:%S'
|
||||
|
||||
# 创建文件处理器
|
||||
log_file = os.path.join(LOGS_DIR, f"fundamental_analysis_{datetime.now().strftime('%Y%m%d')}.log")
|
||||
file_handler = logging.FileHandler(log_file, encoding='utf-8')
|
||||
file_handler.setLevel(logging.INFO)
|
||||
file_handler.setFormatter(logging.Formatter(log_format, date_format))
|
||||
|
||||
# 创建控制台处理器
|
||||
console_handler = logging.StreamHandler()
|
||||
console_handler.setLevel(logging.INFO)
|
||||
console_handler.setFormatter(logging.Formatter(log_format, date_format))
|
||||
|
||||
# 配置根日志记录器
|
||||
logging.basicConfig(
|
||||
level=logging.INFO,
|
||||
handlers=[file_handler, console_handler],
|
||||
format=log_format,
|
||||
datefmt=date_format
|
||||
)
|
||||
|
||||
class FundamentalAnalyzer:
|
||||
"""基本面分析器"""
|
||||
|
||||
|
@ -35,6 +67,8 @@ class FundamentalAnalyzer:
|
|||
self.chat_bot = ChatBot(model_type="online_bot")
|
||||
# 使用离线模型进行其他分析
|
||||
self.offline_bot = OfflineChatBot(platform="volc", model_type="offline_model")
|
||||
# 千问打杂
|
||||
self.offline_bot_tl_qw = OfflineChatBot(platform="tl_qw_private", model_type="qwq")
|
||||
self.db = next(get_db())
|
||||
|
||||
# 定义维度映射
|
||||
|
@ -47,6 +81,7 @@ class FundamentalAnalyzer:
|
|||
"stock_discussion": self.analyze_stock_discussion,
|
||||
"industry_cooperation": self.analyze_industry_cooperation,
|
||||
"target_price": self.analyze_target_price,
|
||||
"valuation_level": self.analyze_valuation_level,
|
||||
"investment_advice": self.generate_investment_advice
|
||||
}
|
||||
|
||||
|
@ -517,10 +552,10 @@ class FundamentalAnalyzer:
|
|||
{industry_text}
|
||||
|
||||
请仅返回一个数值:2、1、0或-1,不要包含任何解释或说明。"""
|
||||
|
||||
self.offline_bot_tl_qw.clear_history()
|
||||
# 使用离线模型进行分析
|
||||
space_value_str = self.offline_bot.chat(prompt).strip()
|
||||
|
||||
space_value_str = self.offline_bot_tl_qw.chat(prompt)
|
||||
space_value_str = self._clean_model_output(space_value_str)
|
||||
# 提取数值
|
||||
space_value = 0 # 默认值
|
||||
|
||||
|
@ -613,18 +648,19 @@ class FundamentalAnalyzer:
|
|||
try:
|
||||
# 使用离线模型分析项目进展情况
|
||||
prompt = f"""请分析以下{stock_name}({stock_code})的重大订单和项目进展情况,并返回对应的数值:
|
||||
- 如果项目进展顺利,且订单交付/建厂等超预期,返回数值"1"
|
||||
- 如果进展顺利,但没有超预期,返回数值"0"
|
||||
- 如果进展不顺利,或者按照进度进行但仍然在验证中,返回数值"-1"
|
||||
|
||||
重大订单和项目进展内容:
|
||||
{projects_text}
|
||||
|
||||
请仅返回一个数值:1、0或-1,不要包含任何解释或说明。"""
|
||||
|
||||
- 如果项目进展顺利,且订单交付/建厂等超预期,返回数值"1"
|
||||
- 如果进展顺利,但没有超预期,返回数值"0"
|
||||
- 如果进展不顺利,或者按照进度进行但仍然在验证中,返回数值"-1"
|
||||
|
||||
重大订单和项目进展内容:
|
||||
{projects_text}
|
||||
|
||||
请仅返回一个数值:1、0或-1,不要包含任何解释或说明。"""
|
||||
self.offline_bot_tl_qw.clear_history()
|
||||
# 使用离线模型进行分析
|
||||
events_value_str = self.offline_bot.chat(prompt).strip()
|
||||
|
||||
events_value_str = self.offline_bot_tl_qw.chat(prompt)
|
||||
# 数据清洗
|
||||
events_value_str = self._clean_model_output(events_value_str)
|
||||
# 提取数值
|
||||
events_value = 0 # 默认值
|
||||
|
||||
|
@ -724,10 +760,12 @@ class FundamentalAnalyzer:
|
|||
{discussion_text}
|
||||
|
||||
请仅返回一个数值:1、0或-1,不要包含任何解释或说明。"""
|
||||
|
||||
self.offline_bot_tl_qw.clear_history()
|
||||
# 使用离线模型进行分析
|
||||
emotion_value_str = self.offline_bot.chat(prompt).strip()
|
||||
|
||||
emotion_value_str = self.offline_bot_tl_qw.chat(prompt)
|
||||
|
||||
# 数据清洗
|
||||
emotion_value_str = self._clean_model_output(emotion_value_str)
|
||||
# 提取数值
|
||||
emotion_value = 0 # 默认值
|
||||
|
||||
|
@ -965,30 +1003,33 @@ class FundamentalAnalyzer:
|
|||
try:
|
||||
# 使用离线模型提取评级
|
||||
prompt = f"""请仔细分析以下目标股价文本,判断半年内券商评级的主要倾向,并返回对应的数值:
|
||||
- 如果半年内券商评级以"买入"居多,返回数值"2"
|
||||
- 如果半年内券商评级以"增持"居多,返回数值"1"
|
||||
- 如果半年内券商评级以"中性"居多,返回数值"0"
|
||||
- 如果半年内券商评级以"减持"居多,返回数值"-1"
|
||||
- 如果半年内券商评级以"卖出"居多,返回数值"-2"
|
||||
- 如果半年内没有券商评级信息,返回数值"0"
|
||||
|
||||
目标股价文本:
|
||||
{price_text}
|
||||
|
||||
只需要输出一个数值,不要输出任何说明或解释。只输出:2,1,0,-1或-2。"""
|
||||
- 如果半年内券商评级以"买入"居多,返回数值"2"
|
||||
- 如果半年内券商评级以"增持"居多,返回数值"1"
|
||||
- 如果半年内券商评级以"中性"居多,返回数值"0"
|
||||
- 如果半年内券商评级以"减持"居多,返回数值"-1"
|
||||
- 如果半年内券商评级以"卖出"居多,返回数值"-2"
|
||||
- 如果半年内没有券商评级信息,返回数值"0"
|
||||
|
||||
目标股价文本:
|
||||
{price_text}
|
||||
|
||||
只需要输出一个数值,不要输出任何说明或解释。只输出:2,1,0,-1或-2。"""
|
||||
|
||||
response = self.chat_bot.chat(prompt)
|
||||
|
||||
# 提取数值
|
||||
rating_str = self._extract_numeric_value_from_response(response)
|
||||
|
||||
# 尝试将响应转换为整数
|
||||
try:
|
||||
rating = int(response)
|
||||
rating = int(rating_str)
|
||||
# 确保评级在有效范围内
|
||||
if rating < -2 or rating > 2:
|
||||
logger.warning(f"提取的券商评级值超出范围: {rating},设置为默认值0")
|
||||
return 0
|
||||
return rating
|
||||
except ValueError:
|
||||
logger.warning(f"无法将提取的券商评级值转换为整数: {response},设置为默认值0")
|
||||
logger.warning(f"无法将提取的券商评级值转换为整数: {rating_str},设置为默认值0")
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
|
@ -1018,27 +1059,196 @@ class FundamentalAnalyzer:
|
|||
|
||||
response = self.chat_bot.chat(prompt)
|
||||
|
||||
# 检查是否是错误响应
|
||||
if isinstance(response, str) and "抱歉,发生错误" in response:
|
||||
logger.warning(f"获取上涨/下跌空间失败: {response}")
|
||||
return 0
|
||||
# 提取数值
|
||||
odds_str = self._extract_numeric_value_from_response(response)
|
||||
|
||||
# 尝试将响应转换为整数
|
||||
try:
|
||||
odds = int(response)
|
||||
odds = int(odds_str)
|
||||
# 确保值在有效范围内
|
||||
if odds < -1 or odds > 1:
|
||||
logger.warning(f"提取的上涨/下跌空间值超出范围: {odds},设置为默认值0")
|
||||
return 0
|
||||
return odds
|
||||
except ValueError:
|
||||
logger.warning(f"无法将提取的上涨/下跌空间值转换为整数: {response},设置为默认值0")
|
||||
logger.warning(f"无法将提取的上涨/下跌空间值转换为整数: {odds_str},设置为默认值0")
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"提取上涨/下跌空间失败: {str(e)}")
|
||||
return 0
|
||||
|
||||
def analyze_valuation_level(self, stock_code: str, stock_name: str) -> bool:
|
||||
"""分析企业PE和PB在历史分位水平和行业平均水平的对比情况"""
|
||||
try:
|
||||
prompt = f"""请对{stock_name}({stock_code})的估值水平进行简要分析,要求输出控制在300字以内,请严格按照以下格式输出:
|
||||
|
||||
1. 历史估值水平(150字左右):
|
||||
- 当前PE和PB值
|
||||
- PE在历史分位水平的位置(高于/接近/低于历史平均分位)
|
||||
- PB在历史分位水平的位置(高于/接近/低于历史平均分位)
|
||||
- 历史估值变化趋势简要分析
|
||||
|
||||
2. 行业估值对比(150字左右):
|
||||
- 所在行业平均PE和PB
|
||||
- PE与行业平均的比较(高于/接近/低于行业平均)
|
||||
- PB与行业平均的比较(高于/接近/低于行业平均)
|
||||
- 与可比公司估值的简要对比
|
||||
|
||||
请提供专业、客观的分析,突出关键信息,避免冗长描述。如果无法获取某项数据,请直接说明。"""
|
||||
# 获取AI分析结果
|
||||
result = self.chat_bot.chat(prompt)
|
||||
|
||||
# 保存到数据库
|
||||
success = save_analysis_result(
|
||||
self.db,
|
||||
stock_code=stock_code,
|
||||
stock_name=stock_name,
|
||||
dimension="valuation_level",
|
||||
ai_response=self._remove_references_from_response(result["response"]),
|
||||
reasoning_process=result["reasoning_process"],
|
||||
references=result["references"]
|
||||
)
|
||||
|
||||
# 提取估值水平分类并更新结果
|
||||
if success:
|
||||
self.extract_valuation_classification(result["response"], stock_code, stock_name)
|
||||
return True
|
||||
|
||||
return success
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"分析估值水平失败: {str(e)}")
|
||||
return False
|
||||
|
||||
def extract_valuation_classification(self, valuation_text: str, stock_code: str, stock_name: str) -> Dict[str, int]:
|
||||
"""从估值水平分析中提取历史和行业估值分类并更新数据库
|
||||
|
||||
Args:
|
||||
valuation_text: 完整的估值水平分析文本
|
||||
stock_code: 股票代码
|
||||
stock_name: 股票名称
|
||||
|
||||
Returns:
|
||||
Dict[str, int]: 包含历史估值和行业估值分类的字典
|
||||
"""
|
||||
try:
|
||||
# 提取历史估值分类
|
||||
historical_classification = self._extract_historical_valuation(valuation_text)
|
||||
|
||||
# 提取行业估值分类
|
||||
industry_classification = self._extract_industry_valuation(valuation_text)
|
||||
|
||||
# 更新数据库中的记录
|
||||
result = get_analysis_result(self.db, stock_code, "valuation_level")
|
||||
if result:
|
||||
update_analysis_result(
|
||||
self.db,
|
||||
stock_code=stock_code,
|
||||
dimension="valuation_level",
|
||||
ai_response=result.ai_response,
|
||||
reasoning_process=result.reasoning_process,
|
||||
references=result.references,
|
||||
extra_info={
|
||||
"historical_valuation": historical_classification,
|
||||
"industry_valuation": industry_classification
|
||||
}
|
||||
)
|
||||
|
||||
logger.info(f"已更新估值分类到数据库: historical_valuation={historical_classification}, industry_valuation={industry_classification}")
|
||||
|
||||
return {"historical_valuation": historical_classification, "industry_valuation": industry_classification}
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"提取估值分类失败: {str(e)}")
|
||||
return {"historical_valuation": 0, "industry_valuation": 0}
|
||||
|
||||
def _extract_historical_valuation(self, valuation_text: str) -> int:
|
||||
"""从估值水平分析中提取历史估值分类
|
||||
|
||||
Args:
|
||||
valuation_text: 完整的估值水平分析文本
|
||||
|
||||
Returns:
|
||||
int: 历史估值分类值 (高于历史:-1, 接近历史:0, 低于历史:1)
|
||||
"""
|
||||
try:
|
||||
# 使用在线模型提取历史估值分类
|
||||
prompt = f"""请仔细分析以下估值水平文本,判断当前PE和PB在历史分位的位置,并返回对应的数值:
|
||||
- 如果当前估值明显高于历史平均水平(高估),返回数值"-1"
|
||||
- 如果当前估值接近历史平均水平,返回数值"0"
|
||||
- 如果当前估值明显低于历史平均水平(低估),返回数值"1"
|
||||
- 如果文本中没有相关信息,返回数值"0"
|
||||
|
||||
估值水平文本:
|
||||
{valuation_text}
|
||||
|
||||
只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。"""
|
||||
|
||||
# 使用千问离线模型提取数值
|
||||
response = self.offline_bot_tl_qw.chat(prompt)
|
||||
# 清理模型输出
|
||||
hist_val_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")
|
||||
return 0
|
||||
return hist_val
|
||||
except ValueError:
|
||||
logger.warning(f"无法将提取的历史估值分类值转换为整数: {hist_val_str},设置为默认值0")
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"提取历史估值分类失败: {str(e)}")
|
||||
return 0
|
||||
|
||||
def _extract_industry_valuation(self, valuation_text: str) -> int:
|
||||
"""从估值水平分析中提取行业估值对比分类
|
||||
|
||||
Args:
|
||||
valuation_text: 完整的估值水平分析文本
|
||||
|
||||
Returns:
|
||||
int: 行业估值对比分类值 (高于行业:-1, 接近行业:0, 低于行业:1)
|
||||
"""
|
||||
try:
|
||||
# 使用在线模型提取行业估值对比分类
|
||||
prompt = f"""请仔细分析以下估值水平文本,判断当前企业的PE和PB与行业平均水平的对比情况,并返回对应的数值:
|
||||
- 如果当前企业估值明显高于行业平均水平,返回数值"-1"
|
||||
- 如果当前企业估值接近行业平均水平,返回数值"0"
|
||||
- 如果当前企业估值明显低于行业平均水平,返回数值"1"
|
||||
- 如果文本中没有相关信息,返回数值"0"
|
||||
|
||||
估值水平文本:
|
||||
{valuation_text}
|
||||
|
||||
只需要输出一个数值,不要输出任何说明或解释。只输出:-1、0或1。"""
|
||||
|
||||
# 使用千问离线模型提取数值
|
||||
response = self.offline_bot_tl_qw.chat(prompt)
|
||||
# 清理模型输出
|
||||
ind_val_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")
|
||||
return 0
|
||||
return ind_val
|
||||
except ValueError:
|
||||
logger.warning(f"无法将提取的行业估值对比分类值转换为整数: {ind_val_str},设置为默认值0")
|
||||
return 0
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"提取行业估值对比分类失败: {str(e)}")
|
||||
return 0
|
||||
|
||||
def generate_investment_advice(self, stock_code: str, stock_name: str) -> bool:
|
||||
"""生成最终投资建议"""
|
||||
try:
|
||||
|
@ -1076,7 +1286,8 @@ class FundamentalAnalyzer:
|
|||
self.offline_bot.clear_history()
|
||||
# 使用离线模型生成建议
|
||||
result = self.offline_bot.chat(prompt)
|
||||
|
||||
# 清理模型输出
|
||||
result = self._clean_model_output(result)
|
||||
# 保存到数据库
|
||||
success = save_analysis_result(
|
||||
self.db,
|
||||
|
@ -1175,6 +1386,60 @@ class FundamentalAnalyzer:
|
|||
logger.error(f"清理模型输出失败: {str(e)}")
|
||||
return output.strip()
|
||||
|
||||
def _extract_numeric_value_from_response(self, response: str) -> str:
|
||||
"""从模型响应中提取数值,移除参考资料和推理过程
|
||||
|
||||
Args:
|
||||
response: 模型原始响应文本或响应对象
|
||||
|
||||
Returns:
|
||||
str: 提取的数值字符串
|
||||
"""
|
||||
try:
|
||||
# 处理响应对象(包含response字段的字典)
|
||||
if isinstance(response, dict) and "response" in response:
|
||||
response = response["response"]
|
||||
|
||||
# 确保响应是字符串
|
||||
if not isinstance(response, str):
|
||||
logger.warning(f"响应不是字符串类型: {type(response)}")
|
||||
return "0"
|
||||
|
||||
# 移除推理过程部分
|
||||
reasoning_start = response.find("推理过程:")
|
||||
if reasoning_start != -1:
|
||||
response = response[:reasoning_start].strip()
|
||||
|
||||
# 移除参考资料部分(通常以 [数字] 开头的行)
|
||||
lines = response.split("\n")
|
||||
cleaned_lines = []
|
||||
|
||||
for line in lines:
|
||||
# 跳过参考资料行(通常以 [数字] 开头)
|
||||
if re.match(r'\[\d+\]', line.strip()):
|
||||
continue
|
||||
cleaned_lines.append(line)
|
||||
|
||||
response = "\n".join(cleaned_lines).strip()
|
||||
|
||||
# 提取数值
|
||||
# 先尝试直接将整个响应转换为数值
|
||||
if response.strip() in ["-2", "-1", "0", "1", "2"]:
|
||||
return response.strip()
|
||||
|
||||
# 如果整个响应不是数值,尝试匹配第一个数值
|
||||
match = re.search(r'([-]?[0-9])', response)
|
||||
if match:
|
||||
return match.group(1)
|
||||
|
||||
# 如果没有找到数值,返回默认值
|
||||
logger.warning(f"未能从响应中提取数值: {response}")
|
||||
return "0"
|
||||
|
||||
except Exception as e:
|
||||
logger.error(f"从响应中提取数值失败: {str(e)}")
|
||||
return "0"
|
||||
|
||||
def _try_extract_advice_type(self, advice_text: str, max_attempts: int = 3) -> Optional[str]:
|
||||
"""尝试多次从投资建议中提取建议类型
|
||||
|
||||
|
@ -1195,8 +1460,8 @@ class FundamentalAnalyzer:
|
|||
prompt = self._get_extract_prompt_by_attempt(advice_text, attempt)
|
||||
|
||||
# 使用千问离线模型提取建议类型
|
||||
offline_bot_tl_qw = OfflineChatBot(platform="tl_qw_private", model_type="qwq")
|
||||
result = offline_bot_tl_qw.chat(prompt)
|
||||
|
||||
result = self.offline_bot_tl_qw.chat(prompt)
|
||||
|
||||
# 检查是否是错误响应
|
||||
if isinstance(result, str) and "抱歉,发生错误" in result:
|
||||
|
@ -1301,6 +1566,7 @@ class FundamentalAnalyzer:
|
|||
"stock_discussion": "市场讨论",
|
||||
"industry_cooperation": "产业合作",
|
||||
"target_price": "目标股价",
|
||||
"valuation_level": "估值水平",
|
||||
"investment_advice": "投资建议"
|
||||
}
|
||||
|
||||
|
|
|
@ -14,10 +14,10 @@ ROOT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
|||
|
||||
# 数据库配置
|
||||
DB_CONFIG = {
|
||||
'host': '192.168.1.82',
|
||||
'host': '192.168.18.199',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'Chlry$%.8',
|
||||
'password': 'Chlry#$.8',
|
||||
'database': 'db_gp_cj'
|
||||
}
|
||||
|
||||
|
|
|
@ -6,10 +6,10 @@ from sqlalchemy import create_engine, Table, Column, String, DECIMAL, MetaData,
|
|||
|
||||
# 数据库连接配置
|
||||
DB_CONFIG = {
|
||||
'host': '192.168.1.82',
|
||||
'host': '192.168.18.199',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'Chlry$%.8',
|
||||
'password': 'Chlry#$.8',
|
||||
'database': 'db_gp_cj'
|
||||
}
|
||||
|
||||
|
|
|
@ -17,10 +17,10 @@ MODEL = "doubao-1-5-pro-32k-250115" # 请填入火山引擎的模型名称
|
|||
|
||||
# 数据库配置
|
||||
DB_CONFIG = {
|
||||
'host': '192.168.1.82',
|
||||
'host': '192.168.18.199',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'Chlry$%.8',
|
||||
'password': 'Chlry#$.8',
|
||||
'database': 'db_gp_cj'
|
||||
}
|
||||
|
||||
|
|
|
@ -121,5 +121,5 @@ def fetch_convertible_bonds(db_url):
|
|||
print(f"错误类型: {type(e).__name__}")
|
||||
|
||||
if __name__ == "__main__":
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
fetch_convertible_bonds(db_url)
|
|
@ -41,5 +41,5 @@ def import_concept_sectors(file_path, db_url, table_name):
|
|||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
file_path = "C:/Users/xy/Desktop/temp/概念板块.csv"
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
import_concept_sectors(file_path, db_url, "gp_gnbk")
|
|
@ -109,5 +109,5 @@ def clean_historical_data(engine):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
fetch_hk_hot_stocks(db_url)
|
|
@ -185,5 +185,5 @@ def analyze_limitup_stocks_main(db_url):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
analyze_limitup_stocks_main(db_url)
|
|
@ -131,7 +131,7 @@ def collect_stock_daily_data(db_url, date=None):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
|
||||
# 方法1:使用快捷函数获取当天数据
|
||||
collect_stock_daily_data(db_url)
|
||||
|
|
|
@ -125,7 +125,7 @@ def get_todays_filtered_stocks(db_url):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
|
||||
# 方法1:使用快捷函数获取今日数据
|
||||
# today_stocks = get_todays_filtered_stocks(db_url)
|
||||
|
|
|
@ -124,7 +124,7 @@ def collect_stock_minute_data(db_url, date=None):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
|
||||
# 方法1:使用快捷函数获取当天数据
|
||||
collect_stock_minute_data(db_url)
|
||||
|
|
|
@ -276,5 +276,5 @@ def main(db_url):
|
|||
print("9:24:00数据失败")
|
||||
|
||||
if __name__ == "__main__":
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
main(db_url)
|
|
@ -324,7 +324,7 @@ def clean_historical_data(engine):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
|
||||
# 创建数据库连接
|
||||
engine = create_engine(db_url)
|
||||
|
|
|
@ -68,6 +68,6 @@ def fetch_and_store_stock_data(db_url, table_name, page_size=100):
|
|||
|
||||
if __name__ == "__main__":
|
||||
# 示例调用
|
||||
db_url = 'mysql+pymysql://root:Chlry$%.8@192.168.1.82:3306/db_gp_cj'
|
||||
db_url = 'mysql+pymysql://root:Chlry#$.8@192.168.18.199:3306/db_gp_cj'
|
||||
table_name = 'stock_changes'
|
||||
fetch_and_store_stock_data(db_url, table_name)
|
|
@ -756,10 +756,10 @@ class StockAnalyzer:
|
|||
def main():
|
||||
# 数据库连接配置
|
||||
db_config = {
|
||||
'host': '192.168.1.82',
|
||||
'host': '192.168.18.199',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'Chlry$%.8',
|
||||
'password': 'Chlry#$.8',
|
||||
'database': 'db_gp_cj'
|
||||
}
|
||||
|
||||
|
|
|
@ -386,10 +386,10 @@ class StockAnalyzer:
|
|||
def main():
|
||||
# 数据库连接配置
|
||||
db_config = {
|
||||
'host': '192.168.1.82',
|
||||
'host': '192.168.18.199',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'Chlry$%.8',
|
||||
'password': 'Chlry#$.8',
|
||||
'database': 'db_gp_cj'
|
||||
}
|
||||
|
||||
|
|
|
@ -1413,10 +1413,10 @@ class StockAnalyzer:
|
|||
def main():
|
||||
# 数据库连接配置
|
||||
db_config = {
|
||||
'host': '192.168.1.82',
|
||||
'host': '192.168.18.199',
|
||||
'port': 3306,
|
||||
'user': 'root',
|
||||
'password': 'Chlry$%.8',
|
||||
'password': 'Chlry#$.8',
|
||||
'database': 'db_gp_cj'
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue