Skip to content

feat(squid): Brier score for predict-polymarket - #123

Merged
Tanya-atatakai merged 4 commits into
mainfrom
feat/squid-brier-score
Sep 2, 2026
Merged

feat(squid): Brier score for predict-polymarket#123
Tanya-atatakai merged 4 commits into
mainfrom
feat/squid-brier-score

Conversation

@Tanya-atatakai

@Tanya-atatakai Tanya-atatakai commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Resolves BDMARK-2258

What

Adds Brier-score tracking to squids/predict-polymarket, mirroring the predict-omen implementation (see BRIER_SCORE.md), so the predict-economy Performance card can compute windowed Brier from the same query shape on both indexers.

  • Bet.impliedProbability: BigInt! — per-token fill price, 1e18-scaled (|amount| * 1e18 / |shares|), set in handleOrderFill for v1 and v2 fills. Buys: the market-implied probability of the bet's outcome. Sells: closing price, excluded from aggregation. Zero = degenerate zero-share fill, skipped.
  • DailyProfitStatistic.brierSum: BigInt! / brierCount: Int! — per buy, (p − actual)² / 1e18 with actual ∈ {1e18 won, 0 lost, 5e17 invalid}, credited on the resolution day inside processMarketResolution's existing per-participant bet loop. Windowed mean = Σ brierSum / Σ brierCount.
  • New src/brier.ts with the pure primitives (computeImpliedProbability, brierContribution, actualForOutcome); invalid markets are keyed off winningIndex === -1.
  • Migration 1787931352501-Data.js: three additive columns.
  • Version bump to 0.3.0 (also syncs the stale 0.1.0 in package-lock.json).
  • Docs: BRIER_SCORE.md polymarket section rewritten from "planning" to "shipped"; one line in root CLAUDE.md.

Omen's brierSumApplied/brierCountApplied reversal fields are deliberately absent: Polymarket resolutions are write-once (processMarketResolution returns early if a QuestionResolution exists), so there is no re-answer path.

Tests

  • tests/brier.test.ts — fixed-point primitives (scale, sign handling, zero sentinel, no clamp, invalid = 0.5).
  • tests/lifecycle.test.ts — new brier score block: win/loss sums on the resolution day, sells and zero-share fills excluded, invalid resolution, repeat-resolution idempotency; plus Brier assertions on the NegRisk path and impliedProbability on the existing buy test.
  • 38/38 vitest tests pass; tsc clean.
  • Migration verified against a fresh Postgres: migration:apply succeeds, subsequent migration:generate reports no schema diff.

Deployment

Requires a blue-green re-index from zero (historical bets need impliedProbability; running totals forbid partial replay). The current production stack stays untouched until cutover — procedure per the squid README.

🤖 Generated with Claude Code

https://claude.ai/code/session_01AykA7kdEeusgyDs8dndpRx

Tanya-atatakai and others added 3 commits August 31, 2026 11:50
Mirror predict-omen's Brier scoring in the squid: Bet.impliedProbability
(1e18-scaled fill price) set in handleOrderFill, brierSum/brierCount
accumulated on the resolution-day DailyProfitStatistic inside
processMarketResolution's existing bet loop. No reversal fields —
resolutions are write-once. Requires a blue-green re-index.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AykA7kdEeusgyDs8dndpRx
…4964)

GHSA-xvcm-6775-5m9r, published after the last green main run; hits every
yarn tree via graph-cli > immutable. Same handling as the July/August
immutable waves: build-time CLI tooling only, patched in >=5.1.8 but
pinned by the graph-cli line; review 2026-11-29.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AykA7kdEeusgyDs8dndpRx
…ries

Follow-up to 335e3af: the graph-cli 0.64.0 trees (autonolas,
autonolas-base) hit the same immutable GHSA under a second id for the
<4.3.9 range (1144965) plus the new node-tar stack-overflow advisory
(1145647, graph-cli > binary-install-raw > tar). Build-time tooling
only, pinned by the legacy graph-cli line; review 2026-11-29.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01AykA7kdEeusgyDs8dndpRx
jmoreira-valory
jmoreira-valory previously approved these changes Sep 1, 2026

@jmoreira-valory jmoreira-valory left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review round 1 — ✅ Approve

What this does. Adds Brier-score tracking to the predict-polymarket squid so the predict-economy Performance card can compute windowed Brier from the same query on both indexers. Every order fill now stores its 1e18-scaled implied probability on the Bet, and at market resolution each buy's (p - actual)^2 contribution is credited to the agent's resolution-day DailyProfitStatistic (brierSum/brierCount), with invalid markets scored against 0.5. Requires a blue-green re-index from zero since historical bets lack the new column.

My previous blocker is resolved: the branch moved by one commit (b0d8626) that adds exactly the two missing allowlist entries — 1144965 (immutable 4.x, the range-sibling of the already-added 1144964) and 1145647 (node-tar DoS) — following the file's established same-GHSA-different-range twin pattern, and the previously-red Dependency audit (subgraphs/autonolas) job is now green. CI is fully green at HEAD (79/79 check runs, all 25 audit jobs passing) and the PR is mergeable.

The Brier implementation itself is unchanged since my last pass, and I had verified the load-bearing claims against source at HEAD rather than trusting the PR body:

  • Omen parity is exact: PROBABILITY_SCALE = 1e18, (p - actual)^2 / 1e18, the zero-denominator sentinel, invalid → 5e17, and the brierSum/brierCount field names all match subgraphs/predict-omen/src/utils.ts, so the cross-indexer query-shape claim holds.
  • Write-once resolution is real: processMarketResolution returns early when a QuestionResolution exists, and the per-participant settled guard gives second-layer idempotency — dropping Omen's brierSumApplied reversal fields is justified. Both the UMA and NegRisk paths funnel into it, and equal/short payouts correctly derive winningOutcome = -1 (invalid).
  • The moved cache.set(DailyProfitStatistic, ...) (now after the bets loop) is safe: betsByParticipant's mid-loop flush only writes dirty entities, the in-memory mutations survive, and the deferred set lands in a later/end-of-batch flush. Participants are one-per-agent per market, so no cross-iteration aliasing.
  • Sells store negative amounts and computeImpliedProbability absolutes them; sells and zero-share fills are excluded from aggregation by the isBuy && impliedProbability > 0n gate — all covered by tests.
  • Tests are CI-enforced (the squid-tests job runs the vitest suite, green at HEAD), and the migration's NOT NULL-without-default columns are safe given the documented blue-green re-index from zero — they'd fail loudly if ever misapplied to a populated database, which is the right direction.

One out-of-scope aside carried over: the audit logs show ~40 allowlist entries past their review date — the backlog deserves its own sweep PR before the warnings drown real signal.

Findings — 1 · ⚪ 1 Nit

# Sev Location Issue
F1 ⚪ NIT squids/predict-polymarket/schema.graphql:90 Zero sentinel also swallows zero-amount buys, not just zero-share fills

Comment thread squids/predict-polymarket/schema.graphql Outdated
Adamantios
Adamantios previously approved these changes Sep 1, 2026
Co-authored-by: jmoreira-valory <96571377+jmoreira-valory@users.noreply.github.com>

@jmoreira-valory jmoreira-valory left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review round 1 — ✅ Approve

What this does. Adds Brier-score tracking to the predict-polymarket squid. Every order fill now records its 1e18-scaled implied probability on the Bet, and when a market resolves each buy's (p - actual)^2 contribution is credited to the agent's resolution-day DailyProfitStatistic, with invalid markets scored against 0.5. This gives the predict-economy Performance card the same windowed-Brier query shape on Polymarket as on Omen, at the cost of a blue-green re-index from zero.

Re-review — re-affirming my approval at HEAD. The branch moved by exactly one commit since my previous approve (b0d8626d8ffc6e), verified via the compare API: the applied F1 suggestion on the Bet.impliedProbability schema comment. One line, comment-only, no code, tests, migration, or allowlist changes. That push dismissed my earlier approval, so this review restores it.

  • CI is fully green at d8ffc6e (30/30 check runs, including the dependency-audit and lockfile-validation jobs that were the subject of my earlier blocker), and @Adamantios has approved at the same commit.
  • Nothing to re-verify in the implementationsrc/brier.ts, src/logic.ts, src/handlers.ts, the additive migration, and both test files are byte-identical to the commit I already verified (Omen fixed-point parity, write-once resolution guard, deferred cache.set after the bets loop, sell / zero-fill exclusion via the isBuy && impliedProbability > 0n gate).
  • Footgun sweep: the fleet-wide checklist (tx receipts, Safe execTransaction, TypedDict, CONTRACTS[chain], EIP-150/191, FSM sync, composed-app final states) does not apply to a TypeScript squid indexer. The subgraph-specific ones are moot here too: the migration is purely additive (no schema-drop / graft concern) and this is an SQD squid, not a graph-node file-data-source, so causality regions do not come into play.

The single NIT below is the leftover half of my F1: the suggestion block only covered schema.graphql, so the matching JSDoc in src/brier.ts still names only the zero-share case. Cosmetic; not worth another round on its own.

Findings — 1 · ⚪ 1 Nit

# Sev Location Issue
F1 ⚪ NIT squids/predict-polymarket/src/brier.ts:9 computeImpliedProbability docstring still names only the zero-share case

Comment thread squids/predict-polymarket/src/brier.ts
@Tanya-atatakai
Tanya-atatakai merged commit 8b8fff8 into main Sep 2, 2026
79 checks passed
@Tanya-atatakai
Tanya-atatakai deleted the feat/squid-brier-score branch September 2, 2026 10:25
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.

3 participants