| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144 |
- """
- 智能股票分析助手 — 用户偏好数据模型
- 定义用户投资偏好、风控参数、界面偏好等持久化存储结构。
- """
- from sqlalchemy import Column, Integer, String, Float, Text, DateTime, Boolean, func
- from app.models.database import Base
- class UserPreference(Base):
- """用户偏好模型"""
- __tablename__ = "user_preferences"
- # 主键
- id = Column(Integer, primary_key=True, autoincrement=True)
- # 关联用户(当前简化:单用户模式,后续可扩展多用户)
- user_id = Column(String(64), default="default", unique=True, nullable=False, comment="用户ID")
- # =========================================================================
- # 投资偏好
- # =========================================================================
- risk_tolerance = Column(
- String(20), default="moderate", nullable=False,
- comment="风险承受度: conservative / moderate / aggressive"
- )
- investment_style = Column(
- String(20), default="blend", nullable=False,
- comment="投资风格: value / growth / momentum / dividend / blend"
- )
- preferred_sectors = Column(
- Text, default="[]",
- comment="偏好行业 (JSON数组)"
- )
- excluded_sectors = Column(
- Text, default="[]",
- comment="排除行业 (JSON数组)"
- )
- investment_horizon = Column(
- String(20), default="medium",
- comment="投资期限: short / medium / long"
- )
- target_return_rate = Column(
- Float, default=10.0, nullable=False,
- comment="目标年化收益率(%)"
- )
- # =========================================================================
- # 风控参数
- # =========================================================================
- max_position_ratio = Column(
- Float, default=30.0, nullable=False,
- comment="单只股票最大仓位比例(%)"
- )
- max_drawdown_limit = Column(
- Float, default=-15.0, nullable=False,
- comment="最大回撤预警线(%)"
- )
- # =========================================================================
- # 通知设置
- # =========================================================================
- notification_enabled = Column(
- Boolean, default=True, nullable=False,
- comment="是否启用通知"
- )
- notification_channels = Column(
- Text, default='["push"]',
- comment="通知渠道 (JSON: email/sms/push)"
- )
- market_alert_threshold = Column(
- Float, default=5.0, nullable=False,
- comment="行情异动提醒阈值(%)"
- )
- # =========================================================================
- # 界面偏好
- # =========================================================================
- language = Column(
- String(10), default="zh", nullable=False,
- comment="界面语言: zh / en"
- )
- theme = Column(
- String(10), default="auto", nullable=False,
- comment="主题: light / dark / auto"
- )
- default_view = Column(
- String(20), default="dashboard", nullable=False,
- comment="默认首页: dashboard / watchlist"
- )
- # =========================================================================
- # 时间戳
- # =========================================================================
- created_at = Column(DateTime, server_default=func.now(), comment="创建时间")
- updated_at = Column(DateTime, server_default=func.now(), onupdate=func.now(), comment="更新时间")
- def to_dict(self) -> dict:
- """转为字典(用于API响应)"""
- import json
- return {
- "id": self.id,
- "user_id": self.user_id,
- "risk_tolerance": self.risk_tolerance,
- "investment_style": self.investment_style,
- "preferred_sectors": json.loads(self.preferred_sectors),
- "excluded_sectors": json.loads(self.excluded_sectors),
- "investment_horizon": self.investment_horizon,
- "target_return_rate": self.target_return_rate,
- "max_position_ratio": self.max_position_ratio,
- "max_drawdown_limit": self.max_drawdown_limit,
- "notification_enabled": self.notification_enabled,
- "notification_channels": json.loads(self.notification_channels),
- "market_alert_threshold": self.market_alert_threshold,
- "language": self.language,
- "theme": self.theme,
- "default_view": self.default_view,
- "created_at": self.created_at.isoformat() if self.created_at else None,
- "updated_at": self.updated_at.isoformat() if self.updated_at else None,
- }
- @classmethod
- def create_default(cls, user_id: str = "default") -> "UserPreference":
- """创建默认偏好实例"""
- return cls(
- user_id=user_id,
- risk_tolerance="moderate",
- investment_style="blend",
- preferred_sectors="[]",
- excluded_sectors="[]",
- investment_horizon="medium",
- target_return_rate=10.0,
- max_position_ratio=30.0,
- max_drawdown_limit=-15.0,
- notification_enabled=True,
- notification_channels='["push"]',
- market_alert_threshold=5.0,
- language="zh",
- theme="auto",
- default_view="dashboard",
- )
|