- PR1: Project scaffold, DB models, price loader - PR2: Congressional trade ingestion (House Stock Watcher) - PR3: Security enrichment + deployment infrastructure - 37 passing tests, 87%+ coverage - Docker + Proxmox deployment ready - Complete documentation - Works 100% offline with fixtures
64 lines
2.2 KiB
Python
Executable File
64 lines
2.2 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
"""
|
|
Enrich securities with data from yfinance (names, sectors, industries).
|
|
Usage: python scripts/enrich_securities.py [--ticker TICKER] [--limit N] [--force]
|
|
"""
|
|
|
|
import argparse
|
|
import logging
|
|
|
|
from pote.db import SessionLocal
|
|
from pote.ingestion.security_enricher import SecurityEnricher
|
|
|
|
logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(name)s: %(message)s")
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
def main():
|
|
"""Enrich securities with yfinance data."""
|
|
parser = argparse.ArgumentParser(description="Enrich securities with yfinance data")
|
|
parser.add_argument("--ticker", type=str, help="Enrich a specific ticker")
|
|
parser.add_argument("--limit", type=int, help="Maximum number of securities to enrich")
|
|
parser.add_argument(
|
|
"--force", action="store_true", help="Re-enrich already enriched securities"
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
|
|
logger.info("=== Security Enrichment (yfinance) ===")
|
|
|
|
try:
|
|
with SessionLocal() as session:
|
|
enricher = SecurityEnricher(session)
|
|
|
|
if args.ticker:
|
|
logger.info(f"Enriching single ticker: {args.ticker}")
|
|
success = enricher.enrich_by_ticker(args.ticker)
|
|
if success:
|
|
logger.info(f"✓ Successfully enriched {args.ticker}")
|
|
else:
|
|
logger.error(f"✗ Failed to enrich {args.ticker}")
|
|
return 1
|
|
else:
|
|
logger.info(f"Enriching {'all' if not args.limit else args.limit} securities")
|
|
if args.force:
|
|
logger.info("Force mode: re-enriching already enriched securities")
|
|
|
|
counts = enricher.enrich_all_securities(limit=args.limit, force=args.force)
|
|
|
|
logger.info("\n=== Summary ===")
|
|
logger.info(f"Total processed: {counts['total']}")
|
|
logger.info(f"✓ Successfully enriched: {counts['enriched']}")
|
|
logger.info(f"✗ Failed: {counts['failed']}")
|
|
|
|
logger.info("\n✅ Done!")
|
|
return 0
|
|
|
|
except Exception as e:
|
|
logger.error(f"Enrichment failed: {e}", exc_info=True)
|
|
return 1
|
|
|
|
|
|
if __name__ == "__main__":
|
|
exit(main())
|