feat: add Kalshi as a market source - #253
Conversation
|
A few AI-generated comments. First set is ones I've verified myself that should be considered: I1 — Update downloads the complete resolution backlogPriority: P2
Every resolved file is therefore downloaded and parsed nightly but never read. The cost grows Recommended fix: after loading ids = dfq.loc[~dfq["resolved"], "id"]
existing_resolution_files = _source_io.load_existing_resolution_files(SOURCE, ids=ids)This bounds content downloads to the live pool while retaining the cheap all-ID existence listing T1 — The cap test uses the production limit and dominates the unit suitePriority: P2
The test is checking boundary behavior, not production-scale performance. Recommended fix: monkeypatch Second set of AI comments I have not verified and looked into as they concern API specifics: K1 — Stored questions omit or contradict the actual binary contractPriority: P1
dfq.at[index, "question"] = market["title"]Kalshi frequently defines an event-like title shared by many child contracts and puts the actual Examples:
There are also qualifying contracts whose title is factually inconsistent with their own rules.
The rules are later appended to an LLM forecaster's background, which partly mitigates omitted
Recommended fix: build a self-contained binary question from market-specific data, including K2 — Latest close time is not a safe earliest-resolution filterPriority: P1
The code describes Two market-specific live records demonstrate the contamination path:
July 23, 2026 was an actual ForecastBench curation day, with forecasts due around August 2. Both Blindly replacing Recommended fix: model both bounds deliberately:
Tests should cover a sports market with expected resolution before the minimum but a later K3 — ET daily candles violate the UTC forecasting cutoffPriority: P1
Kalshi's 1,440-minute candles end at midnight US Eastern time: 04:00 UTC during daylight time and ForecastBench's nightly job and forecast dates use UTC. This creates two failures from the same
A live comparison for
This directly affects Recommended fix: use hourly or finer candles and select the last observation at or before each This replaces the old report's L7. The old appendix claim that subtracting 24 hours was “safe” K4 — Finalization can permanently preserve a nonterminal probabilityPriority: P1 The early return checks only whether the existing file reaches the resolution date: if last_date >= cutoff:
return existing_dfThat is insufficient when a market has just transitioned from active/determined to finalized. An This was reproduced with a finalized Yes market settling on January 13 and an existing January 13
Recommended fix: the resolved early return must verify the terminal row represents the current K5 — Historical routing and 404 lifecycle are conflatedPriority: P2
Kalshi moves older settled market data behind historical endpoints. On 2026-07-24, the returned
Historical candles also use a different price shape ( This breaks the source's explicit missing-resolution-file regeneration path for older resolved The same
Recommended fix: distinguish transient propagation, historical partitioning, and genuine K6 — Open events can include non-active child marketsPriority: P2 The events request uses
No non-active child in the reviewed live snapshot happened to pass every other filter, so this is a Recommended fix: require |
4f8cc27 to
49d43b2
Compare
97d24d3 to
49d43b2
Compare
|
Thanks for the detailed review. I have reproduced the core issues and I'm working through them. I'll keep the PR as a single amended commit and follow up with the final verification results. |
49d43b2 to
a4357a5
Compare
|
I have now pushed the latest rebased implementation and updated the PR description. I reviewed all of the feedback again and applied the relevant changes, including unresolved-only resolution downloads, the improved cap test, conditional child-market labels, structured timing normalization, UTC-safe price histories, exact terminal settlement values, archived-market fallback, and active-only discovery/curation. I deliberately kept two recommendations bounded: the code does not attempt a universal semantic comparison between Kalshi titles and rules, and it does not parse arbitrary free-text early-close conditions. Kalshi's full primary and secondary rules remain available as the authoritative contract, while the implemented structured checks cover the reliable provider fields without adding a fragile parsing subsystem. Validation completed successfully: 110 focused tests and all changed-file style checks passed, with no Kalshi failures in the full local suite. The latest personal-sandbox Cloud Run jobs also succeeded, and all 3,219 generated questions and resolution histories passed the data-quality checks. This should now be ready for re-review. |
Summary
Adds Kalshi as a ForecastBench market source, following the structure and conventions used by the existing market sources.
The implementation:
Review feedback addressed
The latest implementation incorporates the relevant review feedback:
0or1settlement value.The implementation deliberately does not attempt to infer contract semantics from tickers or parse arbitrary free-text early-close conditions. Kalshi's primary and secondary rules remain the authoritative resolution criteria.
Validation
git diff --check: passedFirst-deployment note
Before the first update run, an empty
kalshi_questions.jsonlmust be manually seeded in the target question-bank bucket.Deploy and run
kalshi-fetchbeforekalshi-update-questions, because the update pipeline consumes theevent_tickerandseries_tickerfields emitted by the fetch job.