stock-prediction-api / scripts /backfill_sectors.py
Hermes Agent
Baseline commit: full project state before audit fixes
9fc69ab
Raw
History Blame Contribute Delete
2.28 kB
"""
Backfill missing sector on stocks via yfinance (batch, rate-limited).
Run: python scripts/backfill_sectors.py [--limit 500]
"""
import argparse
import asyncio
import os
import sys
import time
from pathlib import Path
sys.path.insert(0, str(Path(__file__).parent.parent))
from dotenv import load_dotenv
load_dotenv()
from app.services.database_service import DatabaseService
try:
import yfinance as yf
except ImportError:
print("pip install yfinance")
sys.exit(1)
def yf_ticker(symbol: str, suffix: str) -> str:
s = symbol.upper()
if not suffix:
return s
suf = suffix if suffix.startswith(".") else f".{suffix}"
return s if s.endswith(suf) else f"{s}{suf}"
async def main(limit: int) -> None:
turso_url = os.getenv("TURSO_URL")
turso_token = os.getenv("TURSO_TOKEN")
if not turso_url or not turso_token:
print("Set TURSO_URL and TURSO_TOKEN in backend/.env")
sys.exit(1)
db = DatabaseService(url=turso_url, token=turso_token)
await db.initialize()
rows = await db._execute(
"""
SELECT symbol, country, yfinance_suffix, name
FROM stocks
WHERE sector IS NULL OR sector = ''
ORDER BY market_cap DESC NULLS LAST
LIMIT ?
""",
[limit],
)
print(f"Backfilling sector for {len(rows)} stocks...")
updated = 0
for i, row in enumerate(rows, 1):
sym = yf_ticker(row["symbol"], row.get("yfinance_suffix") or "")
try:
info = yf.Ticker(sym).info or {}
sector = info.get("sector") or info.get("industry")
if sector:
await db._execute(
"UPDATE stocks SET sector = ? WHERE symbol = ? AND country = ?",
[str(sector)[:120], row["symbol"], row["country"]],
)
updated += 1
print(f" [{i}/{len(rows)}] {sym} -> {sector}")
except Exception as e:
print(f" [{i}/{len(rows)}] {sym} skip: {e}")
time.sleep(0.25)
print(f"Done. Updated {updated} rows.")
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument("--limit", type=int, default=500)
args = parser.parse_args()
asyncio.run(main(args.limit))