Files
zhixing-system/zhixing-server/migrations/versions/0002_selection_results.py
T

113 lines
4.3 KiB
Python
Raw Normal View History

"""Create persisted selection run and signal result tables."""
from collections.abc import Sequence
import sqlalchemy as sa
from alembic import op
from sqlalchemy.dialects.postgresql import JSONB
revision: str = "0002_selection_results"
down_revision: str | None = "0001_market_data"
branch_labels: str | Sequence[str] | None = None
depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
"""Create the current selection-run result model."""
op.create_table(
"selection_run",
sa.Column("id", sa.String(36), primary_key=True),
sa.Column("strategy", sa.String(64), nullable=False),
sa.Column("target_trade_date", sa.Date(), nullable=False),
sa.Column("market_sync_batch_id", sa.String(36), nullable=False),
sa.Column("status", sa.String(24), nullable=False),
sa.Column("target_count", sa.Integer(), nullable=False),
sa.Column("eligible_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("evaluated_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("selected_stock_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("signal_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("failed_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("coverage", sa.Numeric(8, 6), nullable=False, server_default="0"),
sa.Column("error_type", sa.String(64)),
sa.Column("error_message", sa.Text()),
sa.Column(
"created_at",
sa.DateTime(timezone=True),
nullable=False,
server_default=sa.text("now()"),
),
sa.Column("finished_at", sa.DateTime(timezone=True)),
sa.UniqueConstraint(
"strategy",
"target_trade_date",
name="uq_selection_run_strategy_date",
),
)
op.create_index(
"ix_selection_run_status_date",
"selection_run",
["strategy", "status", "target_trade_date"],
)
op.create_table(
"selection_run_item",
sa.Column(
"run_id",
sa.String(36),
sa.ForeignKey("selection_run.id", ondelete="CASCADE"),
nullable=False,
),
sa.Column("ts_code", sa.String(12), nullable=False),
sa.Column("name", sa.String(128), nullable=False),
sa.Column("status", sa.String(32), nullable=False),
sa.Column("signal_count", sa.Integer(), nullable=False, server_default="0"),
sa.Column("reason", sa.Text()),
sa.Column(
"created_at",
sa.DateTime(timezone=True),
nullable=False,
server_default=sa.text("now()"),
),
sa.PrimaryKeyConstraint("run_id", "ts_code"),
)
op.create_index("ix_selection_run_item_status", "selection_run_item", ["run_id", "status"])
op.create_table(
"selection_signal",
sa.Column(
"run_id",
sa.String(36),
sa.ForeignKey("selection_run.id", ondelete="CASCADE"),
nullable=False,
),
sa.Column("ts_code", sa.String(12), nullable=False),
sa.Column("name", sa.String(128), nullable=False),
sa.Column("target_trade_date", sa.Date(), nullable=False),
sa.Column("strategy", sa.String(64), nullable=False),
sa.Column("category", sa.String(64), nullable=False),
sa.Column("close", sa.Numeric(20, 6), nullable=False),
sa.Column("details", JSONB, nullable=False),
sa.Column(
"created_at",
sa.DateTime(timezone=True),
nullable=False,
server_default=sa.text("now()"),
),
sa.PrimaryKeyConstraint("run_id", "ts_code", "category"),
)
op.create_index(
"ix_selection_signal_strategy_date",
"selection_signal",
["strategy", "target_trade_date", "ts_code"],
)
def downgrade() -> None:
"""Drop selection result tables in dependency-safe order."""
op.drop_index("ix_selection_signal_strategy_date", table_name="selection_signal")
op.drop_table("selection_signal")
op.drop_index("ix_selection_run_item_status", table_name="selection_run_item")
op.drop_table("selection_run_item")
op.drop_index("ix_selection_run_status_date", table_name="selection_run")
op.drop_table("selection_run")