eia->fetch(); if ($rows === null) { throw new BrentPriceFetchException('EIA fetch returned no data'); } BrentPrice::upsert($rows, ['date'], ['price_usd']); } /** * Fetch from FRED and persist. Throws on failure. */ public function fetchFromFred(): void { $rows = $this->fred->fetch(); if ($rows === null) { throw new BrentPriceFetchException('FRED fetch returned no data'); } BrentPrice::upsert($rows, ['date'], ['price_usd']); } /** * One-shot Brent backfill via FRED's observation_start/end. Used to * seed `brent_prices` going back to 2018 so Phase 9's volatility * detector and Phase 8's LLM overlay have proper context. * * @return int rows inserted/updated */ public function backfillFromFred(string $from, string $to): int { $rows = $this->fred->fetchRange($from, $to); if ($rows === null) { throw new BrentPriceFetchException("FRED backfill ({$from} → {$to}) returned no data"); } BrentPrice::upsert($rows, ['date'], ['price_usd']); return count($rows); } }