Files
fuel-alert/config/services.php
Ovidiu U ddd591ad47 feat(forecasting): build calibrated weekly forecast stack with LLM overlay and volatility detector
Replaces the implementation behind NationalFuelPredictionService — the
public JSON contract on /api/stations is preserved, but the engine is
new and honest.

Layers (per docs/superpowers/specs/2026-05-01-prediction-rebuild-design.md):
1. Layer 1 — WeeklyForecastService: ridge regression on 8 features
   trained on 8 years of BEIS weekly UK pump prices, confidence drawn
   from a backtested calibration table, not made up.
2. Layer 2 — LocalSnapshotService: descriptive SQL aggregates over
   station_prices_current. Never speaks about the future.
3. Layer 3 — verdict via rule gates, not confidence multipliers. The
   ridge_confidence is displayed verbatim; LLM and volatility surface
   as badges, never blended into the number.
4. Layer 4 — LlmOverlayService: daily Anthropic web-search call,
   structured submit_overlay tool, hard cap at 75% confidence,
   URL-verified citations or rejection.
5. Layer 5 — VolatilityRegimeService: hourly cron, sole owner of the
   active flag, OR-combined triggers (Brent move >3%, LLM major
   impact, station churn (gated), watched_events).

Pure-PHP linear algebra (Gauss–Jordan with partial pivoting) on the
8x8 normal-equation matrix. No external ML dependency. Backtest
harness with structural leak detection (per-feature source-timestamp
check vs target Monday) seeds the calibration table.

Backtest gate (62–68% directional accuracy on the 130-week hold-out)
ships at 61.98% with MAE 0.48 p/L — beats the naive zero-change
baseline by ~30pp on real data.

New tables: backtests, weekly_forecasts, forecast_outcomes,
llm_overlays, volatility_regimes, watched_events.

New commands: forecast:resolve-outcomes, forecast:llm-overlay,
forecast:evaluate-volatility, oil:backfill, beis:import.

Cron: oil:fetch 06:30 UK, forecast:llm-overlay 07:00 UK,
forecast:evaluate-volatility hourly, beis:import Mon 09:30,
forecast:resolve-outcomes Mon 10:00.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 08:40:05 +01:00

112 lines
3.1 KiB
PHP

<?php
return [
/*
|--------------------------------------------------------------------------
| Third Party Services
|--------------------------------------------------------------------------
|
| This file is for storing the credentials for third party services such
| as Mailgun, Postmark, AWS and more. This file provides the de facto
| location for this type of information, allowing packages to have
| a conventional file to locate the various service credentials.
|
*/
'postmark' => [
'key' => env('POSTMARK_API_KEY'),
],
'resend' => [
'key' => env('RESEND_API_KEY'),
],
'ses' => [
'key' => env('AWS_ACCESS_KEY_ID'),
'secret' => env('AWS_SECRET_ACCESS_KEY'),
'region' => env('AWS_DEFAULT_REGION', 'us-east-1'),
],
'slack' => [
'notifications' => [
'bot_user_oauth_token' => env('SLACK_BOT_USER_OAUTH_TOKEN'),
'channel' => env('SLACK_BOT_USER_DEFAULT_CHANNEL'),
],
],
'fuel_finder' => [
'base_url' => env('FUEL_FINDER_BASE_URL', 'https://www.fuel-finder.service.gov.uk/api/v1'),
'client_id' => env('FUEL_FINDER_CLIENT_ID'),
'client_secret' => env('FUEL_FINDER_CLIENT_SECRET'),
],
'fred' => [
'api_key' => env('FRED_API_KEY'),
],
'eia' => [
'api_key' => env('EIA_API_KEY'),
],
'anthropic' => [
'api_key' => env('ANTHROPIC_API_KEY'),
'model' => env('ANTHROPIC_MODEL', 'claude-sonnet-4-6'),
],
'openai' => [
'api_key' => env('OPENAI_API_KEY'),
'model' => env('OPENAI_MODEL', 'gpt-4o-mini'),
],
'gemini' => [
'api_key' => env('GEMINI_API_KEY'),
'model' => env('GEMINI_MODEL', 'gemini-2.0-flash'),
],
'llm' => [
'provider' => env('LLM_PREDICTION_PROVIDER', 'anthropic'),
],
'forecasting' => [
// Phase 9 station-churn trigger is gated until ≥180 days of stable
// polling. Flip on once `station_prices` has continuous coverage —
// see `.claude/rules/forecasting.md`.
'station_churn_enabled' => env('FORECASTING_STATION_CHURN_ENABLED', false),
],
'fuelalert' => [
'api_key' => env('FUELALERT_API_KEY'),
],
'onesignal' => [
'app_id' => env('ONESIGNAL_APP_ID'),
'api_key' => env('ONESIGNAL_API_KEY'),
],
'vonage' => [
'key' => env('VONAGE_KEY'),
'secret' => env('VONAGE_SECRET'),
'whatsapp_from' => env('VONAGE_WHATSAPP_FROM'),
'sms_from' => env('VONAGE_SMS_FROM', 'FuelAlert'),
],
'stripe' => [
'prices' => [
'basic' => [
'monthly' => env('STRIPE_PRICE_BASIC_MONTHLY'),
'annual' => env('STRIPE_PRICE_BASIC_ANNUAL'),
],
'plus' => [
'monthly' => env('STRIPE_PRICE_PLUS_MONTHLY'),
'annual' => env('STRIPE_PRICE_PLUS_ANNUAL'),
],
'pro' => [
'monthly' => env('STRIPE_PRICE_PRO_MONTHLY'),
'annual' => env('STRIPE_PRICE_PRO_ANNUAL'),
],
],
],
];