You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

127 lines
4.8 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

"""
数据库模型 - SQLAlchemy Models
"""
from datetime import datetime
from sqlalchemy import Column, Integer, String, Numeric, BigInteger, DateTime, Boolean, Text, ForeignKey
from sqlalchemy.orm import declarative_base, relationship
# TimescaleDB 基础类 (时序数据)
TimescaleBase = declarative_base()
# SQLite 基础类 (配置数据)
SQLiteBase = declarative_base()
# ==================== SQLite Models (配置数据) ====================
class User(SQLiteBase):
"""用户模型"""
__tablename__ = "users"
id = Column(Integer, primary_key=True, index=True)
username = Column(String(50), unique=True, nullable=False, index=True)
password_hash = Column(String(255), nullable=False)
email = Column(String(100))
role = Column(String(20), default="user") # admin, user
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关系
api_keys = relationship("APIKey", back_populates="user", cascade="all, delete-orphan")
alerts = relationship("Alert", back_populates="user", cascade="all, delete-orphan")
subscriptions = relationship("Subscription", back_populates="user", cascade="all, delete-orphan")
class APIKey(SQLiteBase):
"""API Key 模型"""
__tablename__ = "api_keys"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
key_hash = Column(String(255), unique=True, nullable=False, index=True)
name = Column(String(100))
permissions = Column(Text) # JSON 格式存储权限
expires_at = Column(DateTime)
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
last_used_at = Column(DateTime)
# 关系
user = relationship("User", back_populates="api_keys")
class Alert(SQLiteBase):
"""告警配置模型"""
__tablename__ = "alerts"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
symbol = Column(String(20), nullable=False, index=True)
condition_type = Column(String(20), nullable=False) # greater_than, less_than, equals
condition_value = Column(Numeric(20, 8), nullable=False)
alert_type = Column(String(20), default="price") # price, percent_change
status = Column(String(20), default="active") # active, triggered, disabled
triggered_at = Column(DateTime)
created_at = Column(DateTime, default=datetime.utcnow)
updated_at = Column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)
# 关系
user = relationship("User", back_populates="alerts")
class Subscription(SQLiteBase):
"""数据订阅模型"""
__tablename__ = "subscriptions"
id = Column(Integer, primary_key=True, index=True)
user_id = Column(Integer, ForeignKey("users.id"), nullable=False)
symbol = Column(String(20), nullable=False, index=True)
period = Column(String(10)) # 1m, 5m, 1h, 1d 等
subscription_type = Column(String(20), default="kline") # kline, realtime
is_active = Column(Boolean, default=True)
created_at = Column(DateTime, default=datetime.utcnow)
# 关系
user = relationship("User", back_populates="subscriptions")
# ==================== TimescaleDB Models (时序数据) ====================
# 注意TimescaleDB 表使用原生 SQL 操作,这里仅作为参考
class KlineData(TimescaleBase):
"""K 线数据模型 (TimescaleDB hypertable)"""
__tablename__ = "kline_data"
time = Column(DateTime, primary_key=True)
symbol = Column(String(20), primary_key=True)
period = Column(String(10), primary_key=True)
open = Column(Numeric(20, 8), nullable=False)
high = Column(Numeric(20, 8), nullable=False)
low = Column(Numeric(20, 8), nullable=False)
close = Column(Numeric(20, 8), nullable=False)
volume = Column(BigInteger, nullable=False)
amount = Column(Numeric(30, 8), default=0)
open_interest = Column(BigInteger, default=0)
created_at = Column(DateTime, default=datetime.utcnow)
class RealtimeQuote(TimescaleBase):
"""实时行情模型 (TimescaleDB hypertable)"""
__tablename__ = "realtime_quotes"
time = Column(DateTime, primary_key=True)
symbol = Column(String(20), primary_key=True)
last_price = Column(Numeric(20, 8), nullable=False)
open_price = Column(Numeric(20, 8))
high_price = Column(Numeric(20, 8))
low_price = Column(Numeric(20, 8))
prev_close = Column(Numeric(20, 8))
volume = Column(BigInteger)
amount = Column(Numeric(30, 8))
bid_price_1 = Column(Numeric(20, 8))
bid_volume_1 = Column(BigInteger)
ask_price_1 = Column(Numeric(20, 8))
ask_volume_1 = Column(BigInteger)
position = Column(BigInteger, default=0)