astock-agent/backend/app/db/tables.py
2026-05-19 11:25:21 +08:00

326 lines
13 KiB
Python
Raw 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 (
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("decision_trace", 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("board_type", Text, default="theme"),
Column("theme_id", Text, default=""),
Column("theme_name", Text, default=""),
Column("theme_aliases", Text, default="[]"),
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("email", Text, nullable=False, unique=True),
Column("password_hash", Text, nullable=False),
Column("role", Text, default="user"),
Column("is_active", Boolean, default=True),
Column("invite_code_used", Text, default=""),
Column("created_at", DateTime, server_default=func.now()),
Column("updated_at", DateTime, server_default=func.now()),
)
email_verification_codes_table = Table(
"email_verification_codes", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("email", Text, nullable=False),
Column("code", Text, nullable=False),
Column("purpose", Text, nullable=False, default="register"),
Column("expires_at", DateTime, nullable=False),
Column("used", Boolean, default=False),
Column("created_at", DateTime, server_default=func.now()),
)
invite_codes_table = Table(
"invite_codes", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("code", Text, nullable=False, unique=True),
Column("description", Text, default=""),
Column("is_active", Boolean, default=True),
Column("max_uses", Integer, default=1),
Column("used_count", Integer, default=0),
Column("expires_at", DateTime, default=None),
Column("created_by", Integer, default=None),
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()),
)
scan_process_logs_table = Table(
"scan_process_logs", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("scan_session", Text, nullable=False),
Column("scan_mode", Text, default=""),
Column("stage", Text, nullable=False),
Column("stage_label", Text, nullable=False),
Column("status", Text, default="ok"),
Column("input_count", Integer, default=0),
Column("output_count", Integer, default=0),
Column("filtered_count", Integer, default=0),
Column("summary", Text, default=""),
Column("detail_json", Text, default="{}"),
Column("created_at", DateTime, server_default=func.now()),
)
research_observations_table = Table(
"research_observations", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("scan_session", Text, nullable=False),
Column("scan_mode", Text, default=""),
Column("ts_code", Text, nullable=False),
Column("name", Text, nullable=False),
Column("theme_name", Text, default=""),
Column("stock_role", Text, default=""),
Column("action_plan", Text, default="观察"),
Column("final_score", Float, default=0),
Column("catalyst_score", Float, default=0),
Column("theme_money_score", Float, default=0),
Column("stock_money_score", Float, default=0),
Column("emotion_role_score", Float, default=0),
Column("timing_score", Float, default=0),
Column("entry_signal_type", Text, default="none"),
Column("elimination_reason", Text, default=""),
Column("detail_json", Text, default="{}"),
Column("created_at", DateTime, server_default=func.now()),
)
strategy_configs_table = Table(
"strategy_configs", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("strategy_id", Text, nullable=False),
Column("version", Integer, nullable=False, default=1),
Column("config_json", Text, nullable=False),
Column("is_active", Boolean, default=True),
Column("source", Text, default="manual"), # manual / auto_review / rollback / default_seed
Column("change_reason", Text, default=""),
Column("evidence_json", Text, default="{}"),
Column("effective_from", DateTime, server_default=func.now()),
Column("created_at", DateTime, server_default=func.now()),
)
prompt_configs_table = Table(
"prompt_configs", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("prompt_key", Text, nullable=False),
Column("version", Integer, nullable=False, default=1),
Column("content", Text, nullable=False),
Column("is_active", Boolean, default=True),
Column("source", Text, default="manual"), # manual / candidate / rollback / default_seed
Column("change_reason", Text, default=""),
Column("evidence_json", Text, default="{}"),
Column("created_at", DateTime, server_default=func.now()),
)
strategy_config_changes_table = Table(
"strategy_config_changes", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("change_type", Text, nullable=False), # auto_applied / pending / rollback / manual
Column("status", Text, default="pending"), # pending / applied / rejected
Column("strategy_id", Text, default=""),
Column("prompt_key", Text, default=""),
Column("base_version", Integer, default=0),
Column("new_version", Integer, default=0),
Column("diff_json", Text, default="{}"),
Column("evidence_json", Text, default="{}"),
Column("reason", Text, default=""),
Column("created_at", DateTime, server_default=func.now()),
Column("applied_at", DateTime),
)
news_items_table = Table(
"news_items", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("title", Text, nullable=False),
Column("content", Text, default=""),
Column("summary", Text, default=""),
Column("source", Text, default=""),
Column("url", Text, default=""),
Column("published_at", DateTime),
Column("dedup_key", Text, nullable=False, unique=True),
Column("status", Text, default="pending"), # pending / analyzed / skipped / failed
Column("catalyst_id", Integer),
Column("error", Text, default=""),
Column("created_at", DateTime, server_default=func.now()),
Column("analyzed_at", DateTime),
)
catalysts_table = Table(
"catalysts", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("title", Text, nullable=False),
Column("summary", Text, default=""),
Column("source", Text, default="manual"),
Column("url", Text, default=""),
Column("published_at", DateTime),
Column("catalyst_type", Text, default="news"),
Column("strength", Float, default=0),
Column("freshness", Float, default=0),
Column("confidence", Float, default=0),
Column("is_active", Boolean, default=True),
Column("raw_text", Text, default=""),
Column("llm_reason", Text, default=""),
Column("created_at", DateTime, server_default=func.now()),
)
theme_catalysts_table = Table(
"theme_catalysts", metadata,
Column("id", Integer, primary_key=True, autoincrement=True),
Column("catalyst_id", Integer, nullable=False),
Column("theme_id", Text, nullable=False),
Column("theme_name", Text, nullable=False),
Column("relevance", Float, default=0),
Column("reason", Text, default=""),
Column("created_at", DateTime, server_default=func.now()),
)