Files
GoFundBot/Backend/models.py
2026-01-27 15:13:10 +08:00

246 lines
9.6 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
from sqlalchemy import Column, String, Float, Text, DateTime, Integer
from sqlalchemy.ext.declarative import declarative_base
from datetime import datetime
Base = declarative_base()
"""
数据库表结构设计说明
====================
核心原则:一份数据只存储一次,通过 JOIN 关联查询
数据表分类:
1. 原始数据表 - 存储从API获取的原始数据
- FundBasicInfo: 基本信息、业绩数据
- FundTrend: 净值走势、排名趋势
- FundExtraData: 持有人结构、资产配置、基金经理
- FundEstimate: 实时估值
- FundPortfolio: 持仓信息
2. 计算指标表 - 基于原始数据计算
- FundRiskMetrics: 风险指标(回撤、波动率、夏普等)
3. 筛选专用表 - 存储同类排名等筛选特有数据
- FundScreeningRank: 同类排名百分位、4433标记
4. 用户数据表
- FundWatchlist: 自选基金
- FundWatchlistGroup: 自选分组
使用方式:
- 基金详情FundBasicInfo + FundTrend + FundExtraData + FundRiskMetrics
- 基金对比:同上
- 基金筛选FundBasicInfo + FundRiskMetrics + FundScreeningRank
"""
# ==================== 原始数据表 ====================
class FundBasicInfo(Base):
"""
基金基础信息表
数据来源: pingzhongdata.js API
"""
__tablename__ = 'fund_basic_info'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
fund_name = Column(String(100), nullable=False)
fund_type = Column(String(50), index=True) # 基金类型
original_rate = Column(Float) # 原始费率
current_rate = Column(Float) # 当前费率
min_subscription_amount = Column(String(50)) # 最低申购金额
is_hb = Column(String(10)) # 是否货币基金
return_1y = Column(Float) # 近1年收益率用于排序
basic_json = Column(Text) # 完整基本信息JSON
performance_json = Column(Text) # 业绩数据JSON (收益率)
created_time = Column(DateTime, default=datetime.now)
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
class FundTrend(Base):
"""
基金走势数据表
数据来源: pingzhongdata.js API
"""
__tablename__ = 'fund_trend'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
net_worth_trend_json = Column(Text) # 单位净值走势
accumulated_net_worth_json = Column(Text) # 累计净值走势
position_trend_json = Column(Text) # 仓位变动趋势
total_return_trend_json = Column(Text) # 总收益率走势
ranking_trend_json = Column(Text) # 同类排名走势
ranking_percentage_json = Column(Text) # 排名百分位走势
scale_fluctuation_json = Column(Text) # 规模变动数据
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
class FundEstimate(Base):
"""
基金实时估值表
数据来源: fundgz.js API
"""
__tablename__ = 'fund_estimate'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
name = Column(String(100))
net_worth = Column(String(50)) # 最新净值
net_worth_date = Column(String(50)) # 净值日期
estimate_value = Column(String(50)) # 估算净值
estimate_change = Column(String(50)) # 估算涨跌幅
estimate_time = Column(String(50)) # 估算时间
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
class FundPortfolio(Base):
"""
基金持仓表
数据来源: pingzhongdata.js API
"""
__tablename__ = 'fund_portfolio'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
stock_codes_json = Column(Text) # 股票持仓
bond_codes_json = Column(Text) # 债券持仓
stock_codes_new_json = Column(Text) # 最新股票持仓
bond_codes_new_json = Column(Text) # 最新债券持仓
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
class FundExtraData(Base):
"""
基金扩展数据表
数据来源: pingzhongdata.js API
"""
__tablename__ = 'fund_extra_data'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
holder_structure_json = Column(Text) # 持有人结构
asset_allocation_json = Column(Text) # 资产配置
performance_evaluation_json = Column(Text) # 业绩评价
fund_managers_json = Column(Text) # 基金经理信息
subscription_redemption_json = Column(Text) # 申购赎回状态
same_type_funds_json = Column(Text) # 同类型基金
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
# ==================== 计算指标表 ====================
class FundRiskMetrics(Base):
"""
基金风险指标表
数据来源: 根据 FundTrend.net_worth_trend 计算
"""
__tablename__ = 'fund_risk_metrics'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
# 最大回撤(百分比)
max_drawdown_3m = Column(Float) # 近3月
max_drawdown_6m = Column(Float) # 近6月
max_drawdown_1y = Column(Float) # 近1年
max_drawdown_3y = Column(Float) # 近3年
max_drawdown_all = Column(Float) # 成立以来
# 夏普比率
sharpe_ratio_1y = Column(Float) # 近1年
sharpe_ratio_3y = Column(Float) # 近3年
# 年化波动率(百分比)
volatility_1y = Column(Float) # 近1年
volatility_3y = Column(Float) # 近3年
# 年化收益率(百分比)
annual_return_1y = Column(Float) # 近1年
annual_return_3y = Column(Float) # 近3年
# 卡玛比率
calmar_ratio_1y = Column(Float) # 近1年
calmar_ratio_3y = Column(Float) # 近3年
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
# ==================== 筛选专用表 ====================
class FundScreeningRank(Base):
"""
基金筛选排名表
只存储筛选功能特有的数据同类排名百分位、4433标记
其他数据通过 JOIN 查询 FundBasicInfo、FundRiskMetrics
"""
__tablename__ = 'fund_screening_rank'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
# 同类排名百分位值越小越好前10%=10
rank_pct_1m = Column(Float) # 近1月
rank_pct_3m = Column(Float) # 近3月
rank_pct_6m = Column(Float) # 近6月
rank_pct_1y = Column(Float) # 近1年
rank_pct_2y = Column(Float) # 近2年
rank_pct_3y = Column(Float) # 近3年
# 筛选标记
pass_4433 = Column(Integer, default=0) # 是否通过4433法则
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
# ==================== 用户数据表 ====================
class FundWatchlistGroup(Base):
"""自选分组表"""
__tablename__ = 'fund_watchlist_group'
id = Column(Integer, primary_key=True, autoincrement=True)
name = Column(String(50), nullable=False)
sort_order = Column(Integer, default=0)
created_time = Column(DateTime, default=datetime.now)
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
class FundWatchlist(Base):
"""基金自选表"""
__tablename__ = 'fund_watchlist'
id = Column(Integer, primary_key=True, autoincrement=True)
fund_code = Column(String(6), unique=True, nullable=False, index=True)
fund_name = Column(String(100), nullable=False)
fund_type = Column(String(50))
group_id = Column(Integer, default=None)
sort_order = Column(Integer, default=0)
created_time = Column(DateTime, default=datetime.now)
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)
class DailyMarketSummary(Base):
"""
每日市场行情摘要缓存表
用于存储AI生成的市场分析报告避免重复调用LLM
"""
__tablename__ = 'daily_market_summary'
id = Column(Integer, primary_key=True, autoincrement=True)
date = Column(String(10), unique=True, nullable=False, index=True) # 日期: YYYY-MM-DD
status = Column(String(20), default='pending') # pending / step_1_search / step_2_llm / completed / error
current_step = Column(Integer, default=0) # 当前步骤: 0-未开始, 1-搜索新闻, 2-AI分析, 3-完成
step_message = Column(String(200)) # 当前步骤描述
market_sentiment = Column(String(50)) # 市场情绪
summary = Column(Text) # 市场总结
indices_json = Column(Text) # 指数数据 JSON
hot_sectors_json = Column(Text) # 热门板块 JSON
key_news_json = Column(Text) # 关键新闻 JSON
outlook = Column(Text) # 后市展望
error_message = Column(Text) # 错误信息(如有)
created_time = Column(DateTime, default=datetime.now)
updated_time = Column(DateTime, default=datetime.now, onupdate=datetime.now)