Skip to content

feat(research): point-in-time clamp + SEC EDGAR, Polymarket, StockTwits/Reddit Sources (#142) - #152

Merged
sudoTomas merged 1 commit into
mainfrom
feat/pit-clamp-sources
Nov 4, 2026
Merged

sudoTomas merged 1 commit into
mainfrom
feat/pit-clamp-sources

Conversation

@sudoTomas

Copy link
Copy Markdown
Owner

What changed

  • Point-in-time clamp (src/trader/loop/pit.py). This is one shared rule. Every SourceSlice now carries an available_at: the moment the newest thing it holds became public. The ContextBuilder wraps every Source, old and new, in PointInTime. In replay this does two things:

    • a read is clamped to as_of (a request past it is clamped, not answered);
    • a slice dated after as_of, or with no date, is refused.

    Each existing Source now sets its availability time: macro view created_at, brief ts, sentiment ts, the held position at the clock. FRED now counts a daily print only once its day has ended (New York). Before this, a replayed 11:00 step could read that same day's VIX close. This changes only the FRED line in two replay golden prompts. Live prompts are unchanged.

  • Vendor Sources (src/trader/loop/vendor_sources.py) read rows from the new append-only vendor_reads table (migration 0017). The row id is the Source version.

    • sec_filings: recent 8-K/10-Q/10-K filings and as-filed fundamentals. Each item is dated by when SEC accepted it. EDGAR's timestamp says "Z" but is New York time, so it is read as New York time, which is never earlier than the truth. A restatement shows the figure that was on file at the replayed step.
    • polymarket: odds on Fed decision, CPI and recession, the same for every symbol.
    • retail_sentiment: StockTwits message and label counts plus Reddit post counts. It is its own lane beside X sentiment, not merged into it. Counts are always shown, and small ones are flagged "thin".
  • Producers live in research/edgar.py, polymarket.py and retail.py, run by research/vendors.py (VendorDesk).

    • A producer runs only for Sources that some Bot subscribes to. It runs in a background task on the tick, so it never delays the stop or the decide.
    • Cadence: EDGAR every 6 h, the others every 1 h. Stamps are shared across Bots and reloaded from the store after a restart.
    • All three vendors are free. EDGAR needs TRADER_SEC_EDGAR_USER_AGENT (a name and a contact address; there is no default email in the code). Without it, EDGAR is simply not built.
  • Macro View compiler: behind TRADER_POLYMARKET_IN_MACRO_VIEW (a gate, off by default), the latest odds become an input the compiler can cite as [poly:<id>]. With the gate off, the compiler prompt and audit are byte-identical to before (asserted).

  • Doors: vendor_reads (query) and collect_vendor (command) on the API (/research/vendors, /research/vendors/collect), MCP, and CLI (trader vendors history|collect).

  • Docs: CONTEXT.md (new term Availability time), docs/architecture.md, the regenerated docs/configuration.md and .env.example, and a section in docs/runbooks/second-bot.md on switching these Sources on.

Acceptance criteria

  • Look-ahead tests per Source: in tests/test_point_in_time.py, a parametrized case for each of the 8 Sources a Bot can subscribe to. A test asserts that the case list equals SOURCE_NAMES, so a Source added later cannot skip it. Each case plants data dated after the step and asserts:

    • none of it reaches the replayed prompt;
    • the lane is still present, so the check is not passing on an empty lane;
    • every slice's available_at is at or before as_of.

    There are also tests for a misbehaving Source that ignores as_of and an undated one, plus an end-to-end ReplayHarness run against the DB.

  • Fixture-based producer tests: tests/test_vendors.py and tests/vendor_fixtures.py, all over httpx.MockTransport; no test touches the network. They cover the SEC User-Agent header, the New York reading of acceptance times, the first-tag-wins rule, restatement vintages, Polymarket's open-market filter, StockTwits/Reddit window counts, one feed down vs both down, cadence and default-off, the runner scheduling, the compiler gate, and the same answer on all four doors.

  • Docs updated: as listed above.

How to switch it on

Subscribe a Bot by name:

trader bot version <bot> --source ... --source sec_filings --source polymarket --source retail_sentiment

--source replaces the list, so name the existing Sources too. For EDGAR, also set TRADER_SEC_EDGAR_USER_AGENT in .env. Polymarket into the Macro View is a separate gate, through the decide-change gate.

Bot #1 and every existing Bot are unaffected until subscribed. Blind replay drops all three lanes.

Tests

963 total: the full suite passed 961, then 62 passed in the affected files after the last two changes.

Closes #142

https://claude.ai/code/session_01UDNLNu854ULHbHSL59UJKu

…ts/Reddit Sources (#142)

- loop/pit.py: one as-of rule. Every SourceSlice carries an availability time and the
  ContextBuilder reads every Source through PointInTime. In replay a read is clamped to
  as_of, and a slice dated after it, or undated, is refused. FRED prints count from the
  end of their day, so a replayed 11:00 step no longer reads that day's VIX close.
- vendor Sources (loop/vendor_sources.py): sec_filings, polymarket, retail_sentiment,
  each reading versioned vendor_reads rows (migration 0017) and each off per Bot.
- producers (research/edgar.py, polymarket.py, retail.py) run by research/vendors.py,
  only for Sources some Bot subscribes to, in the background of the tick.
- EDGAR needs TRADER_SEC_EDGAR_USER_AGENT and is absent without it. Polymarket odds can
  feed the Macro View compiler behind TRADER_POLYMARKET_IN_MACRO_VIEW (gate, off).
- doors: vendor_reads / collect_vendor on API, MCP and CLI (trader vendors ...).

Claude-Session: https://claude.ai/code/session_01UDNLNu854ULHbHSL59UJKu
@sudoTomas
sudoTomas merged commit 39c8d56 into main Nov 4, 2026
1 check passed
@sudoTomas
sudoTomas deleted the feat/pit-clamp-sources branch November 4, 2026 18:08
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Point-in-time clamp + SEC EDGAR, Polymarket, StockTwits/Reddit Sources

1 participant