Polyterm is a multi-version bot platform. A single app runs one kernel
(src/engine.js) that owns all the shared machinery, and drives whichever
strategy plugin is currently selected in the Version Manager. Strategies
decide what to bet; the kernel decides how to execute and book it.
┌──────────────────────────────────────────────┐
│ KERNEL (engine.js) │
Spot feeds ─────► │ feeds · market discovery · order execution │
(Binance WS) │ risk gates · per-version ledgers · wallet │ ◄── Version
Target watcher ──► │ settlement · dashboard stream │ Manager
(/activity API) │ ▲ │ │ (selects
On-chain watcher ► │ ctx │ │ events │ the bot)
(CTF transfers) └──────────────────────┼─────┼──────────────────┘
│ ▼
┌────────────┴───────────────┐
│ Strategy plugin (active) │
│ v1 Copy · v2 Strategy · … │
└─────────────────────────────┘
The dashboard lands on the Version Manager — a control panel, independent of any bot. It lists every registered version with its own P&L (separate per version) and an Enter button. Entering a bot:
- switches the kernel's active strategy (live, no restart), and
- opens that bot's dedicated UI.
A ← MANAGER button returns to the launcher; the bot keeps running in the background. Implemented bots are enterable; planned ones show "coming soon".
Decisions baked in: dashboard launcher (not a startup screen) · separate P&L per version · live-switchable any time.
Owns everything shared, so every bot inherits it for free:
- Spot feeds — one Binance WS price feed per asset (
spotFeed.js); provides live price, the window-open price, and a momentum reading. - Market discovery (
markets.js) — finds the currently-active window per asset. Two schemes:- epoch (5m/15m): the slug is
‹ticker›-updown-‹N›m-‹openTs›, withopenTs = floor(now / windowSeconds) * windowSeconds. - series (1h/1d): the slugs are date-based (e.g.
bitcoin-up-or-down-june-23-2026-9pm-et) so they can't be constructed; the live event is resolved from the Gamma series (‹ticker›-up-or-down-‹hourly|daily›) — the open, accepting event whose end is soonest in the future.
- epoch (5m/15m): the slug is
- Unified window model — per-asset timing is driven by each market's own
endTs, so it's correct for both epoch-aligned (5m/15m, 1h) and non-aligned (1d = ET midnight) windows. Rollover fires when the active window changes. - Order execution & risk gates — a single serialized-per-window path with all the gates (paused, asset-off, not-accepting, no-trade tail, max clips, throttle, max entry price, risk halt) and the dust-bump (size up to the 5-share minimum instead of skipping). Every skip is categorized for the copy-health breakdown.
- Per-(version + mode) ledgers —
vdata, keyed‹version›:‹paper|live›. Each holds its own broker, P&L series, blotter, settlements, reject counts, and slippage accumulators. Switching versions never mixes results. - Brokers —
paperBroker.js(simulated fills vs the live book) andliveBroker.js(real CLOB FAK orders); identical interface so the kernel is broker-agnostic. Both supportbuyClip,sellSide(copy-exit one side),sellMarket(recycle), andsettleWindow(resolution). - Wallet — live pUSD balance + funding/allowance preflight (
clobClient.js), or the paper bankroll. - Dashboard stream (
server.js) — WebSocket + HTTP; broadcasts full state each tick plus discrete fill/settle/window/target events.
Used by target-following bots (Copy Bot). Two paths, deduped by
txHash | conditionId | side:
| Path | Source | Latency | Role |
|---|---|---|---|
| On-chain | CTF ERC-1155 transfers (WebSocket eth_subscribe) |
~2–4 s | primary |
| API | Polymarket /activity (cache-busted) |
~16–22 s | fallback / enrichment |
On-chain detects both directions: a transfer to the target = a BUY, a transfer from the target = a SELL (two subscriptions / log filters). RPC endpoints fail over (Alchemy → Infura → public).
The
/tradesAPI is not used — it lags 10–15 minutes, fatal for a copy bot./activityis the real-time profile feed.
base.js— theStrategyinterface. Static metadata (version,title,description,implemented,needs) and optional lifecycle hooks:onStart,onStop,onTick,onWindow(assetKey),onTargetTrade(trade),onOnchainFill(fill), andstatus(assetKey).registry.js— the catalog of versions (listVersions,createStrategy,defaultVersion, …). Adding a bot = aStrategysubclass + one row.copy.js(v1),momentum.js(v2), and stubs for v3–v5.
The kernel hands each strategy a ctx object — its only window into the
platform. Highlights:
ctx.assets / windowFor() / market(k) / marketByConditionId / marketByTokenId
ctx.price(k) / priceFresh(k) / momentum(k) / openPrice(k) / feed(k)
ctx.watcher() / settings() / cash()
ctx.sizeUsd(targetTrade) → $ per the active betting mode
ctx.placeClip(assetKey, side, {usd, reason, refPrice}) → a gated, booked BUY
ctx.sellSide(assetKey, side, {reason}) → mirror an exit
ctx.getBook / bestAsk / bestBid / getMidpoint / log
A strategy never touches feeds, brokers, or the network directly — it reads
state and places bets through ctx. That's what makes versions independent and
the platform safe to extend.
- Kernel refreshes each asset's active market (cached; forced at window expiry).
- Detection events (on-chain / API) route to the active strategy's
onOnchainFill/onTargetTrade. - The strategy decides and calls
ctx.placeClip/ctx.sellSide. - The kernel runs gates, places the order via the active broker, books it to the
active ledger, records slippage/rejects, and emits a
fill. - Near close, positions are exited (sell-to-recycle) or held to resolution.
- The kernel broadcasts the full state to the dashboard.
| Module | Responsibility |
|---|---|
src/engine.js |
The kernel (everything above). |
src/strategies/ |
Version plugins + registry (base, copy, momentum, registry). |
src/markets.js |
Active-market discovery (epoch + series), order books, resolution. |
src/spotFeed.js |
Binance price feed + window-open price + momentum, per asset. |
src/targetWatcher.js |
Target fills via /activity; stance tracking. |
src/onchainWatcher.js |
On-chain CTF transfer detection (BUY in / SELL out). |
src/paperBroker.js / liveBroker.js |
Simulated / real order execution + settlement. |
src/clobClient.js |
CLOB auth + funding/allowance preflight + market orders. |
src/scout.js |
Target Scout + Market Scout (copyability scoring). |
src/settings.js |
Runtime settings store (runtime-config.json). |
src/server.js |
Dashboard WebSocket + HTTP API. |
web/ |
React/Vite dashboard (Version Manager + per-bot views). |