"""instrument_map — T212 shortcode → Yahoo ticker mapping Revision ID: 0006 Revises: 0005 Create Date: 2026-05-16 """ from typing import Sequence, Union import sqlalchemy as sa from alembic import op revision: str = "0006" down_revision: Union[str, None] = "0005" branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: op.create_table( "instrument_map", sa.Column("id", sa.BigInteger, primary_key=True, autoincrement=True), # T212's internal ticker (e.g. "SGLNl_EQ", "EQNR_US_EQ"). Unique # globally because each T212 ticker is one listing. sa.Column("t212_ticker", sa.String(64), nullable=False), # T212's short name (e.g. "SGLN") — the value in the CSV's "Slice" # column. Not unique: many tickers share a shortName across listings. sa.Column("t212_shortname", sa.String(32), nullable=False), # Computed Yahoo Finance symbol. Nullable so unmappable rows still # land in the table (we may add manual mappings later). sa.Column("yahoo_ticker", sa.String(32)), sa.Column("name", sa.String(128), nullable=False), # T212's currencyCode (GBP, GBX, USD, EUR, CHF, …). sa.Column("currency", sa.String(8)), sa.Column("isin", sa.String(16)), sa.Column("instrument_type", sa.String(16)), # STOCK, ETF, … # True when the row was hand-edited; auto-sync won't overwrite. sa.Column("manual", sa.Boolean, nullable=False, server_default=sa.text("0")), sa.Column("last_verified_at", sa.DateTime(timezone=True), nullable=False), sa.UniqueConstraint("t212_ticker", name="uq_imap_t212_ticker"), ) op.create_index("ix_imap_shortname", "instrument_map", ["t212_shortname"]) op.create_index("ix_imap_isin", "instrument_map", ["isin"]) def downgrade() -> None: op.drop_index("ix_imap_isin", table_name="instrument_map") op.drop_index("ix_imap_shortname", table_name="instrument_map") op.drop_table("instrument_map")