From e971d19678a7ce94666e5887909823cdd2a6cab2 Mon Sep 17 00:00:00 2001 From: TheSiahxyz <164138827+TheSiahxyz@users.noreply.github.com> Date: Wed, 1 Apr 2026 16:52:03 +0900 Subject: fix: resolve critical deployment blockers - Add Alembic initial migration (6 tables: candles, signals, orders, trades, positions, portfolio_snapshots) - Expose health ports (8080-8083) in docker-compose with healthchecks - Add numpy dependency to strategy-engine pyproject.toml --- shared/alembic/versions/001_initial_schema.py | 96 +++++++++++++++++++++++++++ 1 file changed, 96 insertions(+) create mode 100644 shared/alembic/versions/001_initial_schema.py (limited to 'shared/alembic/versions/001_initial_schema.py') diff --git a/shared/alembic/versions/001_initial_schema.py b/shared/alembic/versions/001_initial_schema.py new file mode 100644 index 0000000..2bdaafc --- /dev/null +++ b/shared/alembic/versions/001_initial_schema.py @@ -0,0 +1,96 @@ +"""Initial schema + +Revision ID: 001 +Revises: +Create Date: 2026-04-01 +""" + +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + +# 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 + + +def upgrade() -> None: + op.create_table( + "candles", + sa.Column("symbol", sa.Text, primary_key=True), + sa.Column("timeframe", sa.Text, primary_key=True), + sa.Column("open_time", sa.DateTime(timezone=True), primary_key=True), + sa.Column("open", sa.Numeric, nullable=False), + sa.Column("high", sa.Numeric, nullable=False), + sa.Column("low", sa.Numeric, nullable=False), + sa.Column("close", sa.Numeric, nullable=False), + sa.Column("volume", sa.Numeric, nullable=False), + ) + + op.create_table( + "signals", + sa.Column("id", sa.Text, primary_key=True), + sa.Column("strategy", sa.Text, nullable=False), + sa.Column("symbol", sa.Text, nullable=False), + sa.Column("side", sa.Text, nullable=False), + sa.Column("price", sa.Numeric, nullable=False), + sa.Column("quantity", sa.Numeric, nullable=False), + sa.Column("reason", sa.Text), + sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), + ) + + op.create_table( + "orders", + sa.Column("id", sa.Text, primary_key=True), + sa.Column("signal_id", sa.Text, sa.ForeignKey("signals.id")), + sa.Column("symbol", sa.Text, nullable=False), + sa.Column("side", sa.Text, nullable=False), + sa.Column("type", sa.Text, nullable=False), + sa.Column("price", sa.Numeric, nullable=False), + sa.Column("quantity", sa.Numeric, nullable=False), + sa.Column("status", sa.Text, nullable=False, server_default="PENDING"), + sa.Column("created_at", sa.DateTime(timezone=True), nullable=False), + sa.Column("filled_at", sa.DateTime(timezone=True)), + ) + + op.create_table( + "trades", + sa.Column("id", sa.Text, primary_key=True), + sa.Column("order_id", sa.Text, sa.ForeignKey("orders.id")), + sa.Column("symbol", sa.Text, nullable=False), + sa.Column("side", sa.Text, nullable=False), + sa.Column("price", sa.Numeric, nullable=False), + sa.Column("quantity", sa.Numeric, nullable=False), + sa.Column("fee", sa.Numeric, nullable=False, server_default="0"), + sa.Column("traded_at", sa.DateTime(timezone=True), nullable=False), + ) + + op.create_table( + "positions", + sa.Column("symbol", sa.Text, primary_key=True), + sa.Column("quantity", sa.Numeric, nullable=False), + sa.Column("avg_entry_price", sa.Numeric, nullable=False), + sa.Column("current_price", sa.Numeric, nullable=False), + sa.Column("updated_at", sa.DateTime(timezone=True), nullable=False), + ) + + op.create_table( + "portfolio_snapshots", + sa.Column("id", sa.Integer, primary_key=True, autoincrement=True), + sa.Column("total_value", sa.Numeric, nullable=False), + sa.Column("realized_pnl", sa.Numeric, nullable=False), + sa.Column("unrealized_pnl", sa.Numeric, nullable=False), + sa.Column("snapshot_at", sa.DateTime(timezone=True), nullable=False), + ) + + +def downgrade() -> None: + op.drop_table("portfolio_snapshots") + op.drop_table("positions") + op.drop_table("trades") + op.drop_table("orders") + op.drop_table("signals") + op.drop_table("candles") -- cgit v1.2.3