AI股票分析师daily_stock_analysis与MySQL数据库集成教程
AI股票分析师daily_stock_analysis与MySQL数据库集成教程
1. 引言
你是不是也遇到过这样的情况:每天使用AI股票分析师生成大量有价值的分析数据,但每次重启程序后历史记录就消失了?或者想要对过去一段时间的股票分析结果进行统计和对比,却发现数据分散在各个地方?
这就是为什么我们需要将AI股票分析师与数据库集成。通过MySQL数据库,我们可以把每天的分析结果持久化保存,建立自己的股票分析数据库,方便后续的查询、分析和回溯。
今天我就来手把手教你如何将daily_stock_analysis项目与MySQL数据库完美集成,让你拥有一个真正属于自己的智能股票分析系统。
2. 环境准备与依赖安装
在开始之前,我们需要确保系统已经准备好所有必要的组件。这个过程很简单,跟着步骤走就行。
2.1 系统要求
首先确认你的系统满足以下要求:
- Python 3.8 或更高版本
- MySQL 5.7 或更高版本(MySQL 8.0推荐)
- 足够的内存和存储空间来运行数据库和分析程序
2.2 安装MySQL数据库
如果你还没有安装MySQL,可以选择以下方式之一:
在本地安装MySQL:
# Ubuntu/Debian系统
sudo apt update
sudo apt install mysql-server
# CentOS/RHEL系统
sudo yum install mysql-server
# macOS使用Homebrew
brew install mysql
使用Docker运行MySQL:
docker run --name mysql-stock -e MYSQL_ROOT_PASSWORD=your_password -p 3306:3306 -d mysql:8.0
2.3 安装Python依赖
进入daily_stock_analysis项目目录,安装必要的数据库依赖:
cd daily_stock_analysis
pip install mysql-connector-python sqlalchemy pymysql
这些包分别用于MySQL连接、数据库操作和SQLAlchemy集成。
3. 数据库设计与创建
好的数据库设计是成功集成的关键。我们来设计一个既实用又高效的数据库结构。
3.1 数据库表设计
我们需要创建几个核心表来存储不同类型的分析数据:
-- 创建数据库
CREATE DATABASE IF NOT EXISTS stock_analysis DEFAULT CHARSET utf8mb4 COLLATE utf8mb4_unicode_ci;
USE stock_analysis;
-- 股票基本信息表
CREATE TABLE stocks (
id INT AUTO_INCREMENT PRIMARY KEY,
symbol VARCHAR(20) NOT NULL UNIQUE,
name VARCHAR(100),
market VARCHAR(10),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
-- 每日分析结果表
CREATE TABLE daily_analysis (
id INT AUTO_INCREMENT PRIMARY KEY,
stock_id INT NOT NULL,
analysis_date DATE NOT NULL,
decision VARCHAR(10), -- 买入/观望/卖出
confidence VARCHAR(10), -- 高/中/低
current_price DECIMAL(10, 2),
buy_price DECIMAL(10, 2),
stop_loss DECIMAL(10, 2),
target_price DECIMAL(10, 2),
analysis_text TEXT,
technical_analysis TEXT,
sentiment_analysis TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (stock_id) REFERENCES stocks(id),
UNIQUE KEY unique_stock_date (stock_id, analysis_date)
);
-- 新闻舆情表
CREATE TABLE news_sentiment (
id INT AUTO_INCREMENT PRIMARY KEY,
stock_id INT NOT NULL,
news_date DATE NOT NULL,
sentiment_score DECIMAL(3, 2),
news_summary TEXT,
source VARCHAR(50),
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,
FOREIGN KEY (stock_id) REFERENCES stocks(id)
);
-- 大盘复盘数据表
CREATE TABLE market_summary (
id INT AUTO_INCREMENT PRIMARY KEY,
summary_date DATE NOT NULL UNIQUE,
shanghai_index DECIMAL(10, 2),
shenzhen_index DECIMAL(10, 2),
chuangye_index DECIMAL(10, 2),
rising_stocks INT,
falling_stocks INT,
limit_up INT,
limit_down INT,
summary_text TEXT,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
3.2 创建数据库用户
为了安全起见,我们创建一个专用的数据库用户:
CREATE USER 'stock_analyzer'@'%' IDENTIFIED BY 'strong_password_here';
GRANT ALL PRIVILEGES ON stock_analysis.* TO 'stock_analyzer'@'%';
FLUSH PRIVILEGES;
记得把'strong_password_here'换成你自己的强密码。
4. 数据库连接配置
现在我们来配置daily_stock_analysis项目连接到MySQL数据库。
4.1 修改环境配置文件
打开项目中的.env文件,添加数据库配置:
# MySQL数据库配置
DB_HOST=localhost
DB_PORT=3306
DB_NAME=stock_analysis
DB_USER=stock_analyzer
DB_PASSWORD=your_secure_password_here
DB_CHARSET=utf8mb4
# 是否启用数据库存储
ENABLE_DB_STORAGE=true
# 数据库连接池配置
DB_POOL_SIZE=5
DB_MAX_OVERFLOW=10
DB_POOL_RECYCLE=3600
4.2 创建数据库连接工具类
在项目中创建一个新的Python文件database/db_connector.py:
import mysql.connector
from mysql.connector import pooling
import os
from dotenv import load_dotenv
import logging
# 加载环境变量
load_dotenv()
logger = logging.getLogger(__name__)
class DatabaseConnector:
_connection_pool = None
@classmethod
def initialize_pool(cls):
"""初始化数据库连接池"""
try:
cls._connection_pool = pooling.MySQLConnectionPool(
pool_name="stock_analysis_pool",
pool_size=int(os.getenv('DB_POOL_SIZE', 5)),
pool_reset_session=True,
host=os.getenv('DB_HOST', 'localhost'),
port=int(os.getenv('DB_PORT', 3306)),
database=os.getenv('DB_NAME', 'stock_analysis'),
user=os.getenv('DB_USER', 'stock_analyzer'),
password=os.getenv('DB_PASSWORD', ''),
charset=os.getenv('DB_CHARSET', 'utf8mb4')
)
logger.info("数据库连接池初始化成功")
except Exception as e:
logger.error(f"数据库连接池初始化失败: {str(e)}")
raise
@classmethod
def get_connection(cls):
"""从连接池获取数据库连接"""
if cls._connection_pool is None:
cls.initialize_pool()
try:
connection = cls._connection_pool.get_connection()
return connection
except Exception as e:
logger.error(f"获取数据库连接失败: {str(e)}")
raise
@staticmethod
def test_connection():
"""测试数据库连接是否正常"""
try:
conn = DatabaseConnector.get_connection()
cursor = conn.cursor()
cursor.execute("SELECT 1")
result = cursor.fetchone()
cursor.close()
conn.close()
return result[0] == 1
except Exception as e:
logger.error(f"数据库连接测试失败: {str(e)}")
return False
5. 数据存储功能实现
现在我们来实现将分析结果保存到数据库的核心功能。
5.1 创建数据访问层
新建database/dao.py文件:
from .db_connector import DatabaseConnector
from datetime import datetime, date
import logging
from typing import Optional, List, Dict, Any
logger = logging.getLogger(__name__)
class StockAnalysisDAO:
@staticmethod
def save_stock_analysis(analysis_data: Dict[str, Any]):
"""保存股票分析结果到数据库"""
conn = None
try:
conn = DatabaseConnector.get_connection()
cursor = conn.cursor()
# 首先确保股票信息存在
stock_id = StockAnalysisDAO._ensure_stock_exists(
cursor,
analysis_data['symbol'],
analysis_data.get('name')
)
# 插入分析结果
insert_query = """
INSERT INTO daily_analysis (
stock_id, analysis_date, decision, confidence,
current_price, buy_price, stop_loss, target_price,
analysis_text, technical_analysis, sentiment_analysis
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
decision = VALUES(decision),
confidence = VALUES(confidence),
current_price = VALUES(current_price),
buy_price = VALUES(buy_price),
stop_loss = VALUES(stop_loss),
target_price = VALUES(target_price),
analysis_text = VALUES(analysis_text),
technical_analysis = VALUES(technical_analysis),
sentiment_analysis = VALUES(sentiment_analysis)
"""
cursor.execute(insert_query, (
stock_id,
analysis_data.get('analysis_date', date.today()),
analysis_data.get('decision'),
analysis_data.get('confidence'),
analysis_data.get('current_price'),
analysis_data.get('buy_price'),
analysis_data.get('stop_loss'),
analysis_data.get('target_price'),
analysis_data.get('analysis_text', ''),
analysis_data.get('technical_analysis', ''),
analysis_data.get('sentiment_analysis', '')
))
conn.commit()
logger.info(f"成功保存股票 {analysis_data['symbol']} 的分析结果")
except Exception as e:
logger.error(f"保存股票分析结果失败: {str(e)}")
if conn:
conn.rollback()
raise
finally:
if conn:
conn.close()
@staticmethod
def _ensure_stock_exists(cursor, symbol: str, name: Optional[str] = None) -> int:
"""确保股票信息存在,返回股票ID"""
# 首先查询是否已存在
cursor.execute("SELECT id FROM stocks WHERE symbol = %s", (symbol,))
result = cursor.fetchone()
if result:
return result[0]
# 不存在则插入
insert_query = "INSERT INTO stocks (symbol, name) VALUES (%s, %s)"
cursor.execute(insert_query, (symbol, name))
return cursor.lastrowid
@staticmethod
def save_market_summary(summary_data: Dict[str, Any]):
"""保存大盘复盘数据"""
conn = None
try:
conn = DatabaseConnector.get_connection()
cursor = conn.cursor()
insert_query = """
INSERT INTO market_summary (
summary_date, shanghai_index, shenzhen_index, chuangye_index,
rising_stocks, falling_stocks, limit_up, limit_down, summary_text
) VALUES (%s, %s, %s, %s, %s, %s, %s, %s, %s)
ON DUPLICATE KEY UPDATE
shanghai_index = VALUES(shanghai_index),
shenzhen_index = VALUES(shenzhen_index),
chuangye_index = VALUES(chuangye_index),
rising_stocks = VALUES(rising_stocks),
falling_stocks = VALUES(falling_stocks),
limit_up = VALUES(limit_up),
limit_down = VALUES(limit_down),
summary_text = VALUES(summary_text)
"""
cursor.execute(insert_query, (
summary_data.get('summary_date', date.today()),
summary_data.get('shanghai_index'),
summary_data.get('shenzhen_index'),
summary_data.get('chuangye_index'),
summary_data.get('rising_stocks'),
summary_data.get('falling_stocks'),
summary_data.get('limit_up'),
summary_data.get('limit_down'),
summary_data.get('summary_text', '')
))
conn.commit()
logger.info("成功保存大盘复盘数据")
except Exception as e:
logger.error(f"保存大盘复盘数据失败: {str(e)}")
if conn:
conn.rollback()
raise
finally:
if conn:
conn.close()
@staticmethod
def get_recent_analysis(symbol: str, days: int = 7) -> List[Dict]:
"""获取最近几天的分析结果"""
conn = None
try:
conn = DatabaseConnector.get_connection()
cursor = conn.cursor(dictionary=True)
query = """
SELECT da.*, s.symbol, s.name
FROM daily_analysis da
JOIN stocks s ON da.stock_id = s.id
WHERE s.symbol = %s
ORDER BY da.analysis_date DESC
LIMIT %s
"""
cursor.execute(query, (symbol, days))
results = cursor.fetchall()
return results
except Exception as e:
logger.error(f"获取近期分析结果失败: {str(e)}")
return []
finally:
if conn:
conn.close()
5.2 集成到主分析流程
修改主分析文件(通常是main.py或analyzer.py),添加数据库存储功能:
import os
from database.db_connector import DatabaseConnector
from database.dao import StockAnalysisDAO
from dotenv import load_dotenv
# 在文件开头添加
load_dotenv()
def setup_database():
"""初始化数据库连接"""
if os.getenv('ENABLE_DB_STORAGE', 'false').lower() == 'true':
try:
DatabaseConnector.initialize_pool()
if DatabaseConnector.test_connection():
print("数据库连接测试成功")
return True
else:
print("数据库连接测试失败")
return False
except Exception as e:
print(f"数据库初始化失败: {e}")
return False
return False
# 在分析函数中添加保存逻辑
def save_analysis_to_db(analysis_result):
"""将分析结果保存到数据库"""
if not hasattr(save_analysis_to_db, 'db_enabled'):
save_analysis_to_db.db_enabled = setup_database()
if save_analysis_to_db.db_enabled:
try:
# 转换分析结果为数据库格式
db_data = {
'symbol': analysis_result.get('symbol'),
'name': analysis_result.get('name'),
'decision': analysis_result.get('decision'),
'confidence': analysis_result.get('confidence'),
'current_price': analysis_result.get('current_price'),
'buy_price': analysis_result.get('buy_price'),
'stop_loss': analysis_result.get('stop_loss'),
'target_price': analysis_result.get('target_price'),
'analysis_text': analysis_result.get('analysis_text', ''),
'technical_analysis': analysis_result.get('technical_analysis', ''),
'sentiment_analysis': analysis_result.get('sentiment_analysis', ''),
'analysis_date': analysis_result.get('analysis_date')
}
StockAnalysisDAO.save_stock_analysis(db_data)
except Exception as e:
print(f"保存分析结果到数据库失败: {e}")
# 在大盘复盘函数中同样添加保存逻辑
def save_market_summary_to_db(summary_data):
"""保存大盘复盘的数据库"""
if not hasattr(save_market_summary_to_db, 'db_enabled'):
save_market_summary_to_db.db_enabled = setup_database()
if save_market_summary_to_db.db_enabled:
try:
StockAnalysisDAO.save_market_summary(summary_data)
except Exception as e:
print(f"保存大盘复盘数据到数据库失败: {e}")
6. 数据查询与展示功能
现在我们来添加一些实用的数据查询功能,让你可以方便地查看历史分析结果。
6.1 添加查询接口
创建database/query_service.py文件:
from .dao import StockAnalysisDAO
from datetime import datetime, timedelta
from typing import List, Dict, Any
class StockQueryService:
@staticmethod
def get_stock_performance(symbol: str, period_days: int = 30) -> Dict[str, Any]:
"""获取股票近期表现统计"""
recent_analysis = StockAnalysisDAO.get_recent_analysis(symbol, period_days)
if not recent_analysis:
return {}
# 计算各种统计指标
buy_signals = sum(1 for a in recent_analysis if a.get('decision') == '买入')
watch_signals = sum(1 for a in recent_analysis if a.get('decision') == '观望')
sell_signals = sum(1 for a in recent_analysis if a.get('decision') == '卖出')
# 计算价格变化
latest = recent_analysis[0]
oldest = recent_analysis[-1]
price_change = ((latest.get('current_price', 0) - oldest.get('current_price', 0)) /
oldest.get('current_price', 1)) * 100 if oldest.get('current_price') else 0
return {
'symbol': symbol,
'analysis_count': len(recent_analysis),
'buy_signals': buy_signals,
'watch_signals': watch_signals,
'sell_signals': sell_signals,
'price_change_percent': round(price_change, 2),
'latest_analysis': latest,
'period_days': period_days
}
@staticmethod
def get_decision_history(symbol: str) -> List[Dict]:
"""获取股票决策历史"""
return StockAnalysisDAO.get_recent_analysis(symbol, 365) # 最近一年
@staticmethod
def generate_performance_report(symbol: str) -> str:
"""生成股票表现报告"""
performance = StockQueryService.get_stock_performance(symbol)
if not performance:
return f"没有找到股票 {symbol} 的历史数据"
report = f"""
📊 股票 {symbol} 近期表现报告
───────────────────────
分析周期: 最近 {performance['analysis_count']} 个交易日
买入信号: {performance['buy_signals']} 次
观望信号: {performance['watch_signals']} 次
卖出信号: {performance['sell_signals']} 次
价格变化: {performance['price_change_percent']}%
最新分析结果:
决策: {performance['latest_analysis'].get('decision', 'N/A')}
信心度: {performance['latest_analysis'].get('confidence', 'N/A')}
当前价: {performance['latest_analysis'].get('current_price', 'N/A')}
目标价: {performance['latest_analysis'].get('target_price', 'N/A')}
"""
return report
6.2 添加查询命令行接口
你可以在项目中添加一个简单的命令行查询工具:
import argparse
from database.query_service import StockQueryService
def setup_query_cli():
"""设置命令行查询接口"""
parser = argparse.ArgumentParser(description='股票分析数据库查询工具')
parser.add_argument('--symbol', '-s', required=True, help='股票代码')
parser.add_argument('--report', '-r', action='store_true', help='生成详细报告')
parser.add_argument('--days', '-d', type=int, default=30, help='分析天数')
return parser
def main():
parser = setup_query_cli()
args = parser.parse_args()
if args.report:
report = StockQueryService.generate_performance_report(args.symbol)
print(report)
else:
performance = StockQueryService.get_stock_performance(args.symbol, args.days)
print(performance)
if __name__ == "__main__":
main()
7. 性能优化与最佳实践
为了保证数据库集成的性能和稳定性,这里有一些实用的优化建议。
7.1 数据库索引优化
为常用查询字段添加索引:
-- 添加索引以提高查询性能
CREATE INDEX idx_daily_analysis_date ON daily_analysis(analysis_date);
CREATE INDEX idx_daily_analysis_stock_date ON daily_analysis(stock_id, analysis_date);
CREATE INDEX idx_stocks_symbol ON stocks(symbol);
CREATE INDEX idx_market_summary_date ON market_summary(summary_date);
7.2 连接池配置优化
在.env中调整连接池参数:
# 根据你的服务器配置调整
DB_POOL_SIZE=10
DB_MAX_OVERFLOW=20
DB_POOL_RECYCLE=1800 # 30分钟回收连接
DB_POOL_TIMEOUT=30 # 30秒超时
7.3 批量处理优化
对于大量数据的处理,使用批量操作:
def batch_save_analyses(analyses_list):
"""批量保存分析结果"""
if not analyses_list:
return
conn = None
try:
conn = DatabaseConnector.get_connection()
cursor = conn.cursor()
for analysis_data in analyses_list:
# 批量处理逻辑...
pass
conn.commit()
except Exception as e:
logger.error(f"批量保存失败: {str(e)}")
if conn:
conn.rollback()
finally:
if conn:
conn.close()
8. 常见问题解决
在实际集成过程中,你可能会遇到一些问题,这里提供一些解决方案。
8.1 连接问题排查
如果遇到数据库连接问题,可以运行测试脚本:
# test_db_connection.py
from database.db_connector import DatabaseConnector
def test_connection():
try:
if DatabaseConnector.test_connection():
print("✅ 数据库连接正常")
else:
print("❌ 数据库连接失败")
except Exception as e:
print(f"❌ 连接测试异常: {e}")
if __name__ == "__main__":
test_connection()
8.2 字符编码问题
确保数据库和连接都使用utf8mb4编码以支持中文:
-- 检查数据库编码
SHOW VARIABLES LIKE 'character_set%';
SHOW VARIABLES LIKE 'collation%';
-- 修改连接编码
SET NAMES utf8mb4;
8.3 性能问题排查
如果发现数据库操作变慢,可以检查:
-- 查看慢查询日志
SHOW VARIABLES LIKE 'slow_query_log';
SHOW VARIABLES LIKE 'long_query_time';
-- 分析查询性能
EXPLAIN SELECT * FROM daily_analysis WHERE stock_id = 1;
9. 总结
通过这个教程,我们成功将AI股票分析师daily_stock_analysis与MySQL数据库进行了深度集成。现在你的分析结果会自动保存到数据库中,可以随时查询历史数据、生成统计报告,甚至进行更深入的数据分析。
实际使用下来,这个集成方案运行稳定,数据存储和查询都很顺畅。特别是历史数据分析功能,让你能够更好地跟踪股票表现和AI分析的准确性。如果你在实施过程中遇到任何问题,或者有更好的优化建议,欢迎交流讨论。
记得定期备份你的数据库,这些分析数据可是很有价值的资产呢!
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。
更多推荐

所有评论(0)