You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

112 lines
6.1 KiB
Python

"""
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)