167 lines
6.5 KiB
Python
167 lines
6.5 KiB
Python
"""数据库表定义"""
|
||
|
||
from sqlalchemy import (
|
||
MetaData, Table, Column, Integer, Float, Text, Boolean, DateTime,
|
||
func
|
||
)
|
||
|
||
metadata = MetaData()
|
||
|
||
recommendations_table = Table(
|
||
"recommendations", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("ts_code", Text, nullable=False),
|
||
Column("name", Text, nullable=False),
|
||
Column("sector", Text),
|
||
Column("score", Float),
|
||
Column("market_temp_score", Float),
|
||
Column("sector_score", Float),
|
||
Column("capital_score", Float),
|
||
Column("technical_score", Float),
|
||
Column("supply_demand_score", Float, default=0),
|
||
Column("price_action_score", Float, default=0),
|
||
Column("position_score", Float),
|
||
Column("valuation_score", Float),
|
||
Column("signal", Text),
|
||
Column("entry_price", Float),
|
||
Column("target_price", Float),
|
||
Column("stop_loss", Float),
|
||
Column("reasons", Text),
|
||
Column("risk_note", Text, default=""),
|
||
Column("action_plan", Text, default="观察"),
|
||
Column("trigger_condition", Text, default=""),
|
||
Column("invalidation_condition", Text, default=""),
|
||
Column("suggested_position_pct", Float, default=0),
|
||
Column("review_after_days", Integer, default=3),
|
||
Column("lifecycle_status", Text, default="candidate"),
|
||
Column("data_freshness", Text, default=""),
|
||
Column("llm_analysis", Text, default=""),
|
||
Column("strategy", Text, default="trend_breakout"),
|
||
Column("entry_signal_type", Text, default="none"),
|
||
Column("entry_timing", Text, default=""),
|
||
Column("llm_score", Float, default=None),
|
||
Column("recall_tags", Text, default="[]"),
|
||
Column("prefilter_decision", Text, default=""),
|
||
Column("prefilter_reason", Text, default=""),
|
||
Column("focus_points", Text, default="[]"),
|
||
Column("scan_session", Text),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
sector_heat_table = Table(
|
||
"sector_heat", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("sector_code", Text, nullable=False),
|
||
Column("sector_name", Text, nullable=False),
|
||
Column("pct_change", Float),
|
||
Column("capital_inflow", Float),
|
||
Column("limit_up_count", Integer),
|
||
Column("heat_score", Float),
|
||
Column("stage", Text),
|
||
Column("days_continuous", Integer),
|
||
Column("member_count", Integer),
|
||
Column("leading_stocks", Text), # JSON string
|
||
Column("pct_trend", Text), # JSON string
|
||
Column("turnover_avg", Float),
|
||
Column("main_force_ratio", Float),
|
||
Column("trade_date", Text, nullable=False),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
market_temperature_table = Table(
|
||
"market_temperature", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("trade_date", Text, nullable=False, unique=True),
|
||
Column("up_count", Integer),
|
||
Column("down_count", Integer),
|
||
Column("limit_up_count", Integer),
|
||
Column("limit_down_count", Integer),
|
||
Column("max_streak", Integer),
|
||
Column("broken_rate", Float),
|
||
Column("temperature", Float),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
recommendation_tracking_table = Table(
|
||
"recommendation_tracking", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("recommendation_id", Integer),
|
||
Column("track_date", Text, nullable=False),
|
||
Column("current_price", Float),
|
||
Column("pct_from_entry", Float),
|
||
Column("max_price", Float),
|
||
Column("min_price", Float),
|
||
Column("max_return_pct", Float),
|
||
Column("max_drawdown_pct", Float),
|
||
Column("days_since_recommendation", Integer, default=0),
|
||
Column("hit_target", Boolean, default=False),
|
||
Column("hit_stop_loss", Boolean, default=False),
|
||
Column("close_reason", Text, default=""),
|
||
Column("review_note", Text, default=""),
|
||
Column("status", Text, default="active"),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
users_table = Table(
|
||
"users", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("username", Text, nullable=False, unique=True),
|
||
Column("password_hash", Text, nullable=False),
|
||
Column("role", Text, default="user"),
|
||
Column("is_active", Boolean, default=True),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
Column("updated_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
stock_diagnoses_table = Table(
|
||
"stock_diagnoses", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("ts_code", Text, nullable=False),
|
||
Column("name", Text, nullable=False),
|
||
Column("diagnosis_mode", Text, default="entry"),
|
||
Column("diagnosis", Text, nullable=False),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
user_watchlists_table = Table(
|
||
"user_watchlists", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("user_id", Integer, nullable=False),
|
||
Column("ts_code", Text, nullable=False),
|
||
Column("name", Text, nullable=False),
|
||
Column("note", Text, default=""),
|
||
Column("watch_group", Text, default="observe"),
|
||
Column("cost_price", Float, default=None),
|
||
Column("is_active", Boolean, default=True),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
Column("updated_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
watchlist_analyses_table = Table(
|
||
"watchlist_analyses", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("user_id", Integer, nullable=False),
|
||
Column("watchlist_id", Integer, nullable=False),
|
||
Column("ts_code", Text, nullable=False),
|
||
Column("name", Text, nullable=False),
|
||
Column("conclusion", Text, default="观察"),
|
||
Column("advice", Text, default=""),
|
||
Column("trigger_condition", Text, default=""),
|
||
Column("risk_note", Text, default=""),
|
||
Column("summary", Text, default=""),
|
||
Column("full_analysis", Text, default=""),
|
||
Column("score_reference", Float, default=0),
|
||
Column("analysis_mode", Text, default="scheduled"),
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|
||
|
||
error_logs_table = Table(
|
||
"error_logs", metadata,
|
||
Column("id", Integer, primary_key=True, autoincrement=True),
|
||
Column("source", Text, nullable=False), # 模块来源,如 "recommender", "screener"
|
||
Column("level", Text, default="error"), # error / warning
|
||
Column("message", Text, nullable=False), # 错误消息
|
||
Column("detail", Text, default=""), # 完整异常信息(traceback)
|
||
Column("created_at", DateTime, server_default=func.now()),
|
||
)
|