ruff F401 failed the deploy: `import pytest` in test_event_study.py outlived the pytest.approx assertion it was added for. Compiling the migration for Postgres while checking that turned up a second defect worth fixing while the table is still empty. It created a unique constraint *and* a plain index on effective_date, while the model declares `unique=True, index=True` -- one unique index. Both enforce uniqueness, but the pairing left a redundant second index on the column and a permanent diff for autogenerate to keep trying to reconcile. Now renders byte-for-byte what the model declares, matching RegimeSnapshot.date. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
71 lines
3.0 KiB
Python
71 lines
3.0 KiB
Python
"""Point-in-time history for the sourced fundamental observation
|
|
|
|
Revision ID: 033
|
|
Revises: 032
|
|
Create Date: 2026-08-12 00:00:00.000000
|
|
|
|
The hyperscaler capex / "good news, stock down" read lived in a single
|
|
``SystemSetting`` slot, so each refresh overwrote the last and no history
|
|
existed. The read is now a categorical channel reported alongside State and
|
|
Warning (never a term in either), and a channel with no history cannot be
|
|
replayed: a snapshot rebuild would record every historical session as if nothing
|
|
had ever been observed, and the event study could not measure the channel at all.
|
|
|
|
Keyed on ``effective_date`` (the session the observation becomes usable on,
|
|
normally the next weekday) rather than ``fetched_at``, because that is the gate
|
|
that stops a rebuild stamping today's reading onto historical rows.
|
|
|
|
The table starts empty. ``update_regime_monitor`` records the currently stored
|
|
observation on its next run, so a deployment does not lose the live reading —
|
|
but genuine history does not exist and cannot be invented here. Backfilling it
|
|
from the SEC capex line and earnings-date reactions is separate work; until then
|
|
every historical session reads ``unknown``, which is the honest value rather than
|
|
a guessed one.
|
|
"""
|
|
from typing import Sequence, Union
|
|
|
|
from alembic import op
|
|
import sqlalchemy as sa
|
|
|
|
|
|
revision: str = "033"
|
|
down_revision: Union[str, None] = "032"
|
|
branch_labels: Union[str, Sequence[str], None] = None
|
|
depends_on: Union[str, Sequence[str], None] = None
|
|
|
|
|
|
def upgrade() -> None:
|
|
op.create_table(
|
|
"regime_fundamental_observations",
|
|
sa.Column("id", sa.Integer(), nullable=False),
|
|
sa.Column("effective_date", sa.Date(), nullable=False),
|
|
sa.Column("f1_score", sa.Float(), nullable=True),
|
|
sa.Column("f3_score", sa.Float(), nullable=True),
|
|
sa.Column("capex_json", sa.Text(), nullable=False),
|
|
sa.Column("good_news_stock_down", sa.String(length=10), nullable=False),
|
|
sa.Column("reasoning", sa.Text(), nullable=True),
|
|
sa.Column("source", sa.String(length=30), nullable=False),
|
|
sa.Column("fetched_at", sa.DateTime(timezone=True), nullable=False),
|
|
sa.Column("created_at", sa.DateTime(timezone=True), nullable=False),
|
|
sa.PrimaryKeyConstraint("id"),
|
|
)
|
|
# One unique index, not a unique constraint plus a plain index: the model
|
|
# declares `unique=True, index=True`, which SQLAlchemy renders as exactly
|
|
# this. The constraint-plus-index pairing worked but left a redundant second
|
|
# index on the column and a permanent metadata diff for autogenerate to keep
|
|
# trying to reconcile. Matches RegimeSnapshot.date, the sibling table.
|
|
op.create_index(
|
|
"ix_regime_fundamental_observations_effective_date",
|
|
"regime_fundamental_observations",
|
|
["effective_date"],
|
|
unique=True,
|
|
)
|
|
|
|
|
|
def downgrade() -> None:
|
|
op.drop_index(
|
|
"ix_regime_fundamental_observations_effective_date",
|
|
table_name="regime_fundamental_observations",
|
|
)
|
|
op.drop_table("regime_fundamental_observations")
|