""" Seed the company_aliases table with canonical names + common short forms for the TOP_50 watchlist. Idempotent — re-running is safe. Usage: docker exec stock_oracle_api python -m scripts.seed_company_aliases """ import asyncio import logging import sys from sqlalchemy import select from app.core.database import AsyncSessionLocal from app.models.overlay_registry import CompanyAlias logging.basicConfig(level=logging.INFO, format="%(message)s") logger = logging.getLogger(__name__) # (symbol, [(alias, alias_type, confidence), ...]) # Confidence ≥ 0.7 is required for the EntityResolver to apply Stage 3 # (alias-based) matches. _SEEDS = { "AAPL": [("Apple", "short", 0.95), ("Apple Inc", "canonical", 1.0)], "MSFT": [("Microsoft", "short", 0.95), ("Microsoft Corporation", "canonical", 1.0)], "NVDA": [("Nvidia", "short", 0.95), ("NVIDIA", "alias", 0.95), ("NVIDIA Corporation", "canonical", 1.0)], "AMZN": [("Amazon", "short", 0.9), ("Amazon.com", "canonical", 1.0)], "GOOGL": [("Google", "short", 0.85), ("Alphabet", "alias", 0.9), ("Alphabet Inc", "canonical", 1.0)], "META": [("Meta", "short", 0.8), ("Meta Platforms", "canonical", 1.0), ("Facebook", "alias", 0.8)], "TSLA": [("Tesla", "short", 0.95), ("Tesla Inc", "canonical", 1.0), ("Tesla Motors", "alias", 0.9)], "BRK.B": [("Berkshire Hathaway", "canonical", 1.0), ("Berkshire", "short", 0.9)], "JPM": [("JPMorgan", "short", 0.9), ("JPMorgan Chase", "canonical", 1.0), ("JP Morgan", "alias", 0.9)], "JNJ": [("Johnson & Johnson", "canonical", 1.0), ("J&J", "short", 0.9)], "V": [("Visa", "short", 0.9), ("Visa Inc", "canonical", 1.0)], "UNH": [("UnitedHealth", "short", 0.9), ("UnitedHealth Group", "canonical", 1.0)], "XOM": [("Exxon", "short", 0.9), ("ExxonMobil", "alias", 0.95), ("Exxon Mobil", "canonical", 1.0)], "PG": [("Procter & Gamble", "canonical", 1.0), ("P&G", "short", 0.9)], "MA": [("Mastercard", "short", 0.95), ("Mastercard Inc", "canonical", 1.0)], "HD": [("Home Depot", "short", 0.9), ("The Home Depot", "canonical", 1.0)], "CVX": [("Chevron", "short", 0.95), ("Chevron Corporation", "canonical", 1.0)], "LLY": [("Eli Lilly", "short", 0.95), ("Eli Lilly and Company", "canonical", 1.0), ("Lilly", "alias", 0.75)], "ABBV": [("AbbVie", "short", 0.95), ("AbbVie Inc", "canonical", 1.0)], "BAC": [("Bank of America", "canonical", 1.0), ("BofA", "short", 0.9)], "KO": [("Coca-Cola", "short", 0.9), ("The Coca-Cola Company", "canonical", 1.0), ("Coca Cola", "alias", 0.85)], "PEP": [("Pepsi", "short", 0.85), ("PepsiCo", "canonical", 1.0)], "AVGO": [("Broadcom", "short", 0.95), ("Broadcom Inc", "canonical", 1.0)], "COST": [("Costco", "short", 0.95), ("Costco Wholesale", "canonical", 1.0)], "WMT": [("Walmart", "short", 0.95), ("Wal-Mart", "alias", 0.9)], "MRK": [("Merck", "short", 0.85), ("Merck & Co", "canonical", 1.0)], "TMO": [("Thermo Fisher", "short", 0.9), ("Thermo Fisher Scientific", "canonical", 1.0)], "DIS": [("Disney", "short", 0.9), ("Walt Disney", "alias", 0.9), ("The Walt Disney Company", "canonical", 1.0)], "ACN": [("Accenture", "short", 0.95), ("Accenture plc", "canonical", 1.0)], "ABT": [("Abbott", "short", 0.85), ("Abbott Laboratories", "canonical", 1.0)], "VZ": [("Verizon", "short", 0.95), ("Verizon Communications", "canonical", 1.0)], "ADBE": [("Adobe", "short", 0.9), ("Adobe Inc", "canonical", 1.0)], "CRM": [("Salesforce", "short", 0.95), ("Salesforce.com", "canonical", 1.0)], "NFLX": [("Netflix", "short", 0.95), ("Netflix Inc", "canonical", 1.0)], "CMCSA": [("Comcast", "short", 0.95), ("Comcast Corporation", "canonical", 1.0)], "TXN": [("Texas Instruments", "short", 0.95), ("Texas Instruments Incorporated", "canonical", 1.0)], "CSCO": [("Cisco", "short", 0.9), ("Cisco Systems", "canonical", 1.0)], "NKE": [("Nike", "short", 0.9), ("Nike Inc", "canonical", 1.0)], "NEE": [("NextEra", "short", 0.9), ("NextEra Energy", "canonical", 1.0)], "AMD": [("AMD", "short", 0.85), ("Advanced Micro Devices", "canonical", 1.0)], "DHR": [("Danaher", "short", 0.95), ("Danaher Corporation", "canonical", 1.0)], "BMY": [("Bristol-Myers Squibb", "canonical", 1.0), ("Bristol Myers Squibb", "alias", 0.95), ("Bristol-Myers", "short", 0.85)], "QCOM": [("Qualcomm", "short", 0.95), ("Qualcomm Incorporated", "canonical", 1.0)], "T": [("AT&T", "short", 0.95), ("AT&T Inc", "canonical", 1.0)], "LOW": [("Lowe's", "short", 0.9), ("Lowe's Companies", "canonical", 1.0)], "PM": [("Philip Morris", "short", 0.95), ("Philip Morris International", "canonical", 1.0)], "HON": [("Honeywell", "short", 0.95), ("Honeywell International", "canonical", 1.0)], "ORCL": [("Oracle", "short", 0.85), ("Oracle Corporation", "canonical", 1.0)], "RTX": [("RTX", "short", 0.85), ("Raytheon", "alias", 0.85), ("Raytheon Technologies", "canonical", 1.0)], "UPS": [("UPS", "short", 0.9), ("United Parcel Service", "canonical", 1.0)], } async def seed(): inserted = 0 skipped = 0 async with AsyncSessionLocal() as db: for symbol, aliases in _SEEDS.items(): for value, alias_type, confidence in aliases: existing = await db.execute( select(CompanyAlias.id).where( CompanyAlias.symbol == symbol, CompanyAlias.alias_value == value, ) ) if existing.first(): skipped += 1 continue db.add( CompanyAlias( symbol=symbol, alias_type=alias_type, alias_value=value, confidence=confidence, active=True, ) ) inserted += 1 await db.commit() logger.info(f"company_aliases seed: inserted={inserted}, skipped={skipped}") return inserted if __name__ == "__main__": n = asyncio.run(seed()) sys.exit(0 if n >= 0 else 1)