Repository navigation
feat(uw-alpha): budgeted resumable backfill of dark/lit print history - #548
Merged
Merged
Conversation
added 3 commits
October 5, 2026 16:57
Before v0.13.28 the nightly capture kept at most 500 prints per ticker, day and source. dark_lit_backfill re-pages every active-watchlist ticker-day that was cut (>=500 in either source) or is missing, oldest first, from UW's earliest available date through 2026-10-05, through the same capture_dark_lit_for. Budget: per UW budget day (UTC), weekday/Saturday/Sunday caps (15k/60k/ 60k, settings), counted from the job's own external_api_requests rows; stops before a worst-case 120-call ticker-day would exceed the cap, and on research_budget_ok. Progress per ticker-day in dark_lit_backfill_progress (resume); UW historic_data_access_missing marks the date unavailable and skips everything older. One row per run in dark_lit_backfill_runs. Daily 22:30 ET on uw-0, default off.
spent_today counts only this job's UW rows in the run's UTC budget day, and spend already recorded there stops a run on quota before any call.
# Conflicts: # CHANGELOG.md
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
What this adds
Before v0.13.28 (#546) the nightly capture kept at most 500 prints per ticker, day and source. The new
dark_lit_backfilljob re-pages the cut history through the samecapture_dark_lit_for, so there is still one writer.removed_at IS NULL) × trading session, from UW's earliest available date throughLAST_CUT_DATE = 2026-10-05. Oldest first, because UW's 730-trading-day window expires the oldest days first.dark_lit_backfill_progress), and one already complete (both sources under 500 prints, so never cut). Cut (≥500 in either source) or missing ticker-days are fetched.daily_ohlcSPY) only starts 2025-04-14 on prod, so it cannot cover 2023.UW_SCAN_DARK_LIT_BACKFILL_ENABLEDdefault false. No behaviour change on deploy.Budget
Caps per UW budget day (UTC day, the account counter's 00:00 UTC = 20:00 ET reset):
UW_SCAN_DARK_LIT_BACKFILL_WEEKDAY_MAX_CALLSUW_SCAN_DARK_LIT_BACKFILL_SATURDAY_MAX_CALLSUW_SCAN_DARK_LIT_BACKFILL_SUNDAY_MAX_CALLSThe Friday and Saturday 22:30 ET runs fall in UTC Saturday and Sunday; the Sunday-evening run is UTC Monday (weekday cap).
Spend = this job's own rows in
external_api_requestsfor the budget day of the run's start. Every attempt is a row, so retries count. A run that crosses UTC midnight keeps counting instead of resetting, which can only stop it early.Never exceeds the cap: it stops when a worst-case ticker-day (2 sources × 60-page cap = 120 calls) would not fit, leaving at most 120 calls unused.
Governor:
research_budget_ok(research ceiling + total guard) is checked every 25 ticker-days; a "no" stops the run. Live jobs keep priority.Effective weekend spend is capped at ~45k/day by the current research ceiling. Prod has
UW_RESEARCH_DAILY_CEILING=45000, below the 60k weekend cap. Raising it is the user's decision; this PR does not change prod env.Other consumer on the key: the account counter reached 57,004 (UTC Sat 2026-09-26) and 91,629 (UTC Sat 10-03) while argon logged only 1,019 / 1,490 calls.
UW_TOTAL_DAILY_GUARD=105000halts every pool, so weekend headroom can be far below 45k.Resume, window, run log
Resume: progress is stored per ticker-day (
done/unavailable); a restart skips finished rows.Out-of-window: UW answers
403 historic_data_access_missingwith the earliest available date in the message (probed 2026-10-05: earliest 2023-11-02). The job marks that ticker-dayunavailable, skips every ticker on that date and everything before the named earliest date, and future runs skip dates at or before the newestunavailabledate.dark_lit_backfill_runs: one row per run with the budget day, quota, calls, ticker-days done, unavailable, errors, remaining pending ticker-days, andstop_reason.stop_reasonquotaresearch_budgeterror_streakexhaustedcalendar_unavailableMigration 161: creates the two bookkeeping tables only, with no data change. Both are registered as provenance in the data-gap registry, and the policy doc is regenerated.
Horizon (estimate, not a promise)
LAST_CUT_DATETests
tests/unit/worker/test_dark_lit_backfill.py: quota by UTC weekday (Friday-evening ET → Saturday cap); pending list oldest first; complete vs cut rule; finished and out-of-window skips; parsing UW's verbatim 403 message.tests/integration/worker/test_dark_lit_backfill.py(real migrated DB, stub UW):quotaafter the out-of-window probe plus 3 ticker-days. The out-of-window date is probed once and then skipped for the other ticker.exhausted.spent_todaycounts only this job's UW rows in the run's UTC budget day (not another job's, not massive, not the previous day). Spend already recorded there stops a run onquotabefore any call. Mutation:spent_todayreturning 0 fails both.all_enabled/uw-0andall_enabled/all-0only), settings (+4 fields), lock keys (+dark_lit_backfill10806).GROUP BY market_date, tickerover the 16.8M-row table) is an Index Only Scan, 0.83 s.🤖 Generated with Claude Code