/consensus <category> [N] [K] computes a consensus signal over a freshly-fetched, category-specific PNL cohort: it pulls the top-N category leaderboard traders, fans out their positions, filters to their in-category bets, and surfaces bets where ≥K distinct cohort wallets agree. Async (the bot replies instantly and spawns a background job). Shipped 2026-06-05; replaced the short-lived tag-based tag_consensus.
For Agents
- Command:
/consensus <category> [N] [K]— defaults N=50, K=3.<category>must be one of the 9 leaderboard categories (see category-leaderboard-api); otherwise rejected.- Module:
crates/polymarket-fetch/src/pmv2/category_consensus.rs.- Tables (migration
20260605010000_pm_category_consensus.sql):pm_category_consensus_runs+pm_category_consensus_rows.- 10-min cache: a recent done run is served immediately; else the bot replies
running consensus algo for {category}…andtokio::spawns the job.- No edge/band — the fetched traders are NOT in
pmv2_traders; the signal is agreement-count + stake + their leaderboard PNL.
Flow
- Validate —
<category>must be one of the 9 leaderboard categories. - Cache check — if a
donerun < 10 min old exists, serve its snapshot immediately. - Else reply instantly
running consensus algo for {category}…andtokio::spawna background job that:- Fetch the top-N category leaderboard traders by monthly PNL (category-leaderboard-api).
- Fan out their positions — bounded
buffer_unordered(16)+ a 30s per-wallettokio::timeout. - Filter to their in-category bets via gamma
event_tags. - Compute consensus — group by
(condition_id, outcome_index), keep groups where ≥K distinct cohort wallets agree, rank by agreement-count then stake, take top 25. - Persist to the run/rows tables.
- Push the snapshot to Telegram.
What the signal is (and isn’t)
No edge/band — distinct from the pmv2 cohort
These traders are pulled fresh off the category leaderboard and are NOT in
pmv2_traders, so there is notrader_score/ skill band / conviction. The signal is purely agreement-count + total stake + the traders’ leaderboard PNL. It is a “the month’s top category PNL earners agree on this bet” read, not a skill-weighted edge score.
Don't confuse with the other two consensus-shaped things
- v1 wallet-consensus — retired/dormant (see bot-pmv2-native-v1-consensus-deleted).
- pmv2 cohort-overlap — annotates the operator’s own book against the edge-scored cohort (see first-mover-overlap-watcher / bot-pmv2-native-v1-consensus-deleted).
- category consensus (this) — a freshly-fetched, category-specific PNL cohort, no edge/band.
They look alike but the cohort source differs entirely.
category → gamma-tag mapping
The position filter (step 3.3) maps a leaderboard category to the gamma event_tags used to keep only in-category bets. It is identity for most, with three exceptions:
| leaderboard category | gamma tag(s) |
|---|---|
| (most) | identity (same slug) |
culture | pop-culture |
economics | economy, economics |
mentions | NO clean tag → skip-filter fallback (no tag filter applied) |
This mismatch is exactly why the 9 leaderboard categories are a separate namespace from gamma tags (see category-leaderboard-api and pmv2-gamma-tags-categorization).
Replaced the tag-based consensus
This REPLACED a short-lived
tag_consensusAn earlier, briefly-shipped tag-based
tag_consensusran the consensus over the existing pmv2 cohort filtered by tag (a SQL query). It was removed in favor of this fetch-based version, which builds a fresh category-specific PNL cohort instead of reusing the pmv2 cohort.
Fan-out tuning
Initial 8/90s was too slow — a weather run looked stuck
The position fan-out started at 8 concurrent / 90s per-wallet timeout; a weather run took ~9.4 min and looked stuck. Tuned to 16 concurrent / 30s per-wallet timeout. (Same
connect_timeout/per-item-timeout discipline as the silent-hang fix.)
Scope
Does NOT touch the /topbets or the pmv2 scoring algo — it is a self-contained command with its own tables.
Related
- category-leaderboard-api — the per-category leaderboard endpoint this fetches from
- pmv2-gamma-tags-categorization — the gamma
event_tagsused for the position filter (and the namespace mismatch) - bot-pmv2-native-v1-consensus-deleted — the other consensus-shaped surfaces, to keep distinct
- first-mover-overlap-watcher
- polymarket-fetch