"""FRED API client for macroeconomic data.""" from __future__ import annotations import pandas as pd from fredapi import Fred from src.config import DATA_RAW_FRED, FRED_API_KEY from src.utils import setup_logging logger = setup_logging("fred") def get_fred_client() -> Fred: """Return an authenticated FRED client.""" return Fred(api_key=FRED_API_KEY) def _fetch_series( series_id: str, start: str = "2024-01-01", end: str = "2026-06-01", ) -> pd.DataFrame: """Generic helper: fetch a FRED series and return as DataFrame.""" client = get_fred_client() data = client.get_series(series_id, observation_start=start, observation_end=end) df = data.to_frame(name=series_id) df.index.name = "date" return df def fetch_fed_funds_rate( start: str = "2024-01-01", end: str = "2026-06-01", ) -> pd.DataFrame: """Fetch DFF series (daily federal funds rate).""" df = _fetch_series("DFF", start, end) path = DATA_RAW_FRED / "fed_funds_rate.csv" df.to_csv(path) logger.info("Saved DFF (%d obs) to %s", len(df), path) return df def fetch_cpi( start: str = "2024-01-01", end: str = "2026-06-01", ) -> pd.DataFrame: """Fetch CPIAUCSL series (Consumer Price Index).""" df = _fetch_series("CPIAUCSL", start, end) path = DATA_RAW_FRED / "cpi.csv" df.to_csv(path) logger.info("Saved CPIAUCSL (%d obs) to %s", len(df), path) return df def fetch_unemployment( start: str = "2024-01-01", end: str = "2026-06-01", ) -> pd.DataFrame: """Fetch UNRATE series (unemployment rate).""" df = _fetch_series("UNRATE", start, end) path = DATA_RAW_FRED / "unemployment.csv" df.to_csv(path) logger.info("Saved UNRATE (%d obs) to %s", len(df), path) return df def fetch_all_fred_data() -> None: """Fetch all FRED series and save to data/raw/fred/.""" DATA_RAW_FRED.mkdir(parents=True, exist_ok=True) logger.info("=== Starting FRED data acquisition ===") try: fetch_fed_funds_rate() except Exception as exc: logger.error("Failed to fetch DFF: %s", exc) try: fetch_cpi() except Exception as exc: logger.error("Failed to fetch CPIAUCSL: %s", exc) try: fetch_unemployment() except Exception as exc: logger.error("Failed to fetch UNRATE: %s", exc) logger.info("=== FRED data acquisition complete ===")