chore: decommission FMP, Finnhub and Alpha Vantage (A6)
The A5 cutover has been on and observed in production, so SEC Company Facts + DoltHub earnings are already the live source for `fundamental_data`. This removes everything the legacy path still occupied. Gone: the three providers and their config/env keys; the weekly `fundamental_collector` job; the cutover toggle (SEC + Dolt is now the unconditional path, so `off` can no longer silently freeze scoring inputs); the A5 parity report, whose deltas became structurally zero once the candidate builder started writing the table it compared against; and the FMP tier of universe bootstrap. Two behavioral notes: - Disabling **SEC Fundamentals Import** now stops the SEC network fetch only. The local cache refresh moved outside the job-enable check, because candidates also derive from daily closes and earnings events — freezing those on an ingestion pause would stale scoring with no fallback left to recover from. - `/ingestion/fetch?sources=fundamentals` still accepts the key and reports `skipped`; there is no per-ticker fetch any more. Migration 029 does not blanket-delete the leftover settings rows. Migrations run before the service restart, and pre-A6 code reads an absent `job_*_enabled` row as *enabled* — so the two behavior-bearing keys become tombstones pinned to safe values (hidden in Admin) and only the inert three are deleted. Removing the provider keys from the production `.env` is the matching rollout step. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
@@ -66,26 +66,11 @@ class TestTradingDayCrons:
|
||||
assert "Mon" in weekdays, f"{key} skips Mondays — numeric day-of-week?"
|
||||
assert {"Sat", "Sun"}.isdisjoint(weekdays), f"{key} fires on a weekend"
|
||||
|
||||
def test_fundamentals_runs_on_monday(self):
|
||||
from datetime import datetime
|
||||
|
||||
from apscheduler.triggers.cron import CronTrigger
|
||||
|
||||
trigger = CronTrigger.from_crontab(
|
||||
SCHEDULE_DEFAULTS["schedule_fundamentals_cron"],
|
||||
timezone=SCHEDULE_DEFAULTS["schedule_timezone"],
|
||||
)
|
||||
fire = trigger.get_next_fire_time(
|
||||
None, datetime(2026, 7, 19, tzinfo=trigger.timezone)
|
||||
)
|
||||
assert fire.strftime("%a") == "Mon"
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("key", "hour", "minute"),
|
||||
(
|
||||
("schedule_dolt_earnings_cron", 2, 30),
|
||||
("schedule_sec_fundamentals_cron", 4, 0),
|
||||
("schedule_fundamentals_parity_cron", 5, 30),
|
||||
),
|
||||
)
|
||||
def test_shadow_imports_run_daily_at_expected_et_time(
|
||||
@@ -122,7 +107,7 @@ class TestScheduleConfig:
|
||||
|
||||
async def test_rejects_bad_cron(self, session: AsyncSession):
|
||||
with pytest.raises(ValidationError):
|
||||
await update_schedule_config(session, {"schedule_fundamentals_cron": "every monday"})
|
||||
await update_schedule_config(session, {"schedule_daily_pipeline_cron": "every monday"})
|
||||
|
||||
async def test_rejects_bad_timezone(self, session: AsyncSession):
|
||||
with pytest.raises(ValidationError):
|
||||
|
||||
Reference in New Issue
Block a user