summaryrefslogtreecommitdiff
path: root/shared/alembic
diff options
context:
space:
mode:
Diffstat (limited to 'shared/alembic')
-rw-r--r--shared/alembic/versions/001_initial_schema.py10
-rw-r--r--shared/alembic/versions/002_news_sentiment_tables.py84
-rw-r--r--shared/alembic/versions/003_add_missing_indexes.py35
-rw-r--r--shared/alembic/versions/004_add_signal_detail_columns.py25
4 files changed, 149 insertions, 5 deletions
diff --git a/shared/alembic/versions/001_initial_schema.py b/shared/alembic/versions/001_initial_schema.py
index 2bdaafc..7b744ee 100644
--- a/shared/alembic/versions/001_initial_schema.py
+++ b/shared/alembic/versions/001_initial_schema.py
@@ -5,16 +5,16 @@ Revises:
Create Date: 2026-04-01
"""
-from typing import Sequence, Union
+from collections.abc import Sequence
-from alembic import op
import sqlalchemy as sa
+from alembic import op
# revision identifiers, used by Alembic.
revision: str = "001"
-down_revision: Union[str, None] = None
-branch_labels: Union[str, Sequence[str], None] = None
-depends_on: Union[str, Sequence[str], None] = None
+down_revision: str | None = None
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
def upgrade() -> None:
diff --git a/shared/alembic/versions/002_news_sentiment_tables.py b/shared/alembic/versions/002_news_sentiment_tables.py
new file mode 100644
index 0000000..d85a634
--- /dev/null
+++ b/shared/alembic/versions/002_news_sentiment_tables.py
@@ -0,0 +1,84 @@
+"""Add news, sentiment, and stock selection tables
+
+Revision ID: 002
+Revises: 001
+Create Date: 2026-04-02
+"""
+
+from collections.abc import Sequence
+
+import sqlalchemy as sa
+from alembic import op
+
+revision: str = "002"
+down_revision: str | None = "001"
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
+
+
+def upgrade() -> None:
+ op.create_table(
+ "news_items",
+ sa.Column("id", sa.Text, primary_key=True),
+ sa.Column("source", sa.Text, nullable=False),
+ sa.Column("headline", sa.Text, nullable=False),
+ sa.Column("summary", sa.Text),
+ sa.Column("url", sa.Text),
+ sa.Column("published_at", sa.DateTime(timezone=True), nullable=False),
+ sa.Column("symbols", sa.Text),
+ sa.Column("sentiment", sa.Float, nullable=False),
+ sa.Column("category", sa.Text, nullable=False),
+ sa.Column("raw_data", sa.Text),
+ sa.Column(
+ "created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()
+ ),
+ )
+ op.create_index("idx_news_items_published", "news_items", ["published_at"])
+ op.create_index("idx_news_items_source", "news_items", ["source"])
+
+ op.create_table(
+ "symbol_scores",
+ sa.Column("id", sa.Text, primary_key=True),
+ sa.Column("symbol", sa.Text, nullable=False, unique=True),
+ sa.Column("news_score", sa.Float, nullable=False, server_default="0"),
+ sa.Column("news_count", sa.Integer, nullable=False, server_default="0"),
+ sa.Column("social_score", sa.Float, nullable=False, server_default="0"),
+ sa.Column("policy_score", sa.Float, nullable=False, server_default="0"),
+ sa.Column("filing_score", sa.Float, nullable=False, server_default="0"),
+ sa.Column("composite", sa.Float, nullable=False, server_default="0"),
+ sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
+ )
+
+ op.create_table(
+ "market_sentiment",
+ sa.Column("id", sa.Text, primary_key=True),
+ sa.Column("fear_greed", sa.Integer, nullable=False),
+ sa.Column("fear_greed_label", sa.Text, nullable=False),
+ sa.Column("vix", sa.Float),
+ sa.Column("fed_stance", sa.Text, nullable=False, server_default="neutral"),
+ sa.Column("market_regime", sa.Text, nullable=False, server_default="neutral"),
+ sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False),
+ )
+
+ op.create_table(
+ "stock_selections",
+ sa.Column("id", sa.Text, primary_key=True),
+ sa.Column("trade_date", sa.Date, nullable=False),
+ sa.Column("symbol", sa.Text, nullable=False),
+ sa.Column("side", sa.Text, nullable=False),
+ sa.Column("conviction", sa.Float, nullable=False),
+ sa.Column("reason", sa.Text, nullable=False),
+ sa.Column("key_news", sa.Text),
+ sa.Column("sentiment_snapshot", sa.Text),
+ sa.Column(
+ "created_at", sa.DateTime(timezone=True), nullable=False, server_default=sa.func.now()
+ ),
+ )
+ op.create_index("idx_stock_selections_date", "stock_selections", ["trade_date"])
+
+
+def downgrade() -> None:
+ op.drop_table("stock_selections")
+ op.drop_table("market_sentiment")
+ op.drop_table("symbol_scores")
+ op.drop_table("news_items")
diff --git a/shared/alembic/versions/003_add_missing_indexes.py b/shared/alembic/versions/003_add_missing_indexes.py
new file mode 100644
index 0000000..7a252d4
--- /dev/null
+++ b/shared/alembic/versions/003_add_missing_indexes.py
@@ -0,0 +1,35 @@
+"""Add missing indexes for common query patterns.
+
+Revision ID: 003
+Revises: 002
+Create Date: 2026-04-02
+"""
+
+from collections.abc import Sequence
+
+from alembic import op
+
+revision: str = "003"
+down_revision: str | None = "002"
+branch_labels: str | Sequence[str] | None = None
+depends_on: str | Sequence[str] | None = None
+
+
+def upgrade() -> None:
+ op.create_index("idx_signals_symbol_created", "signals", ["symbol", "created_at"])
+ op.create_index(
+ "idx_orders_symbol_status_created", "orders", ["symbol", "status", "created_at"]
+ )
+ op.create_index("idx_trades_order_id", "trades", ["order_id"])
+ op.create_index("idx_trades_symbol_traded", "trades", ["symbol", "traded_at"])
+ op.create_index("idx_portfolio_snapshots_at", "portfolio_snapshots", ["snapshot_at"])
+ op.create_index("idx_symbol_scores_symbol", "symbol_scores", ["symbol"], unique=True)
+
+
+def downgrade() -> None:
+ op.drop_index("idx_symbol_scores_symbol", table_name="symbol_scores")
+ op.drop_index("idx_portfolio_snapshots_at", table_name="portfolio_snapshots")
+ op.drop_index("idx_trades_symbol_traded", table_name="trades")
+ op.drop_index("idx_trades_order_id", table_name="trades")
+ op.drop_index("idx_orders_symbol_status_created", table_name="orders")
+ op.drop_index("idx_signals_symbol_created", table_name="signals")
diff --git a/shared/alembic/versions/004_add_signal_detail_columns.py b/shared/alembic/versions/004_add_signal_detail_columns.py
new file mode 100644
index 0000000..4009b6e
--- /dev/null
+++ b/shared/alembic/versions/004_add_signal_detail_columns.py
@@ -0,0 +1,25 @@
+"""Add conviction, stop_loss, take_profit columns to signals table.
+
+Revision ID: 004
+Revises: 003
+"""
+
+import sqlalchemy as sa
+from alembic import op
+
+revision = "004"
+down_revision = "003"
+
+
+def upgrade():
+ op.add_column(
+ "signals", sa.Column("conviction", sa.Float, nullable=False, server_default="1.0")
+ )
+ op.add_column("signals", sa.Column("stop_loss", sa.Numeric, nullable=True))
+ op.add_column("signals", sa.Column("take_profit", sa.Numeric, nullable=True))
+
+
+def downgrade():
+ op.drop_column("signals", "take_profit")
+ op.drop_column("signals", "stop_loss")
+ op.drop_column("signals", "conviction")