Without a clean registry there is no shared notion of "the market". Every downstream stage reads from this one source.
Challenge we are solving
Markets resolve, retire, change tick sizes, change fees, or get listed under a new condition_id. If every consumer carries its own snapshot, they drift apart and trades land against stale assumptions.
What this stage does
Maintains the canonical instrument record for every tradable market — id, condition_id, token_ids, status, resolution rule, tick_size, min_size, fee_bps, negRisk flag, and a freshness timestamp.
Why this stage exists
Every signal, score, execution estimate, risk check, and OMS instruction has to dereference the same instrument. The registry is the dictionary they all read from.
Flow
Live APIPolymarket /markets
→
Normaliseschema · ticks · fees
→
Registrymarket_id · token_ids status · tick · fee_bps
→
Freshnesslast_synced_ts
What the backend should expose
market_id, condition_id, token_ids (YES / NO)
status (open · paused · halted · resolving · resolved)
open_time, close_time, resolution_time
resolution_rule (URL or text), resolution_source
tick_size, min_size, fee_bps
negRisk flag, parent_event_id, category
last_synced_ts, freshness_ms
Maths we expect here
Every formula below is implemented in packages/polytraders-bots/ or packages/polytraders-runner/. Treat the worked example as the unit-test sanity check you should be able to reproduce locally.
worked example\[0.645 \cdot 2{,}000 \cdot \tfrac{50}{10{,}000} = \$6.45\]
Stages 6 and 7 both consume this number. The registry is the single source of fee_bps so the two stages never disagree.
4
Freshness window
\[freshness\_ms = now - last\_synced\_ts\]
Symbol
Meaning
Units / range
\(now\)
Current wall-clock time
ms epoch
\(last_synced_ts\)
Timestamp of last registry sync
ms epoch
worked example\[now = 1{,}700{,}000{,}050{,}000,\; last\_synced = 1{,}700{,}000{,}047{,}500 \;\Rightarrow\; 2{,}500\,\text{ms}\]
If freshness_ms exceeds the registry SLO (default 10s) every downstream stage treats the market as stale and refuses to trade.
How a developer codes this stage
Reference TypeScript implementation lives in packages/polytraders-* at the repository root. Stage owners maintain these files — read them before writing new code.
packages/polytraders-contracts/src/MarketSnapshot.tsThe canonical TypeScript shape every stage imports. Treat this as the immutable schema.
packages/polytraders-bots/src/discoveryDiscovery bots that produce the registry feed: marketqualityranker, instrumentnormaliser, resolvability scoring.
packages/polytraders-runner/src/pipeline.jsThe pipeline harness that hydrates the registry once per cycle and passes it into every downstream stage.
See it in the platform mock
The platform mock is the source of truth for what each stage's UI exposes. Open these alongside the code references.