Price the window.
Trade the gap.

A DreamDEX event contract asks one question: does this window close at or above the price it opened at? That makes the fair value of its YES token a real probability - so Vaticr derives it from the price process, tilts it with live news, and lets you trade the difference.

+0.3791
backtested skill
900 forecasts
114
tests
python · ts · solidity
12/12
settlements
independently recomputed
vaticr · connecting
reading the book…

live from somnia testnet · refreshed every 12s

the honest part

This is not a market factory, and it could not be.

Vaticr began as a headline-to-contract factory: scan the news, deploy a matching event contract, resolve it from a signed news payload. Building against the live protocol, all three premises turned out to be impossible. That is a property of DreamDEX, not a gap in it.

Markets cannot be created

Event contracts are rolling Up/Down windows on BTC and ETH, minted per window by BinaryMarketsModule. There is no permissionless creation entry point and the question text is fixed.

Contracts cannot be resolved

Settlement is automatic. The question is scheduled on the OracleHub at creation with its resolution gas reserved, and Somnia reactivity fires the callback at expiry.

It is a CLOB, not an AMM

One on-chain order book per market, quoted in YES terms, where a NO price is always 1 − yes. There is no curve to provide liquidity to.

So Vaticr does what is actually unowned. It decides what these windows are worth, trades that view through the official Bot Kit, and makes the resulting track record auditable by someone who does not trust it. The pivot cost nothing in ambition - it swapped a subsystem the protocol forbids for one it rewards.

how it works

A prior from physics, a posterior from the news.

Two stages. The price process gives an honest base rate; the news moves it. Bayes' rule is additive in log-odds, so the two combine exactly rather than by fudge factor.
01

Prior - the price process

Over seconds to an hour a driftless geometric Brownian motion is a defensible model of BTC/ETH. With S the current level, S₀ the window’s opening price and τ the seconds remaining:

P(S_TS₀) = Φln(S/S₀) − σ²τ/2στ

This is already an edge: the honest read of where a window sits against its own open, which a book of people watching a candle chart tends to misprice near the extremes.

02

Posterior - the headlines

Five public feeds are scored for direction, salience and source credibility. Each headline contributes a log-likelihood ratio:

logit(posterior) = logit(prior) + Σᵢ LLRᵢ

Every contribution is discounted three ways - by credibility, by exponential time decay, and by how much of the window is left, since a headline cannot move a contract expiring in four seconds. The total is hard-capped so a burst of correlated stories cannot run the posterior into a corner.

03

Trade it, then prove it

When the posterior clears the touch - never the mid, because paying the spread is how a signal with real edge still loses money - it crosses with an IOC. Otherwise it rests a two-sided quote.

Every forecast is committed before its window closes, then Brier-scored against what happened. A model that cannot beat 0.25 is a coin flip with extra steps, and this is the only way to know.

evidence

Does the model actually work?

The claim is testable, so it is tested. Every input is public and historical, so the backtest replays settled windows the model never saw. The figures below are frozen in docs/evidence/ - re-running drifts, because it replays a rolling window.
sample900 forecasts / 300 windows
Brier0.15522
coin flip0.25
skill+0.3791
accuracy0.7622
log loss0.46816

skill by time elapsed

+0.1816
25%brier 0.2046
+0.3469
50%brier 0.16327
+0.6088
75%brier 0.09779

Skill rises as the window closes. That is the signature of a model reading the price process rather than fitting noise: information accumulates and the posterior sharpens.

No lookahead

Volatility and level at each decision point use only ticks at or before that instant. All 900 cases assert it, and 120 are re-run against a physically truncated history so the assertion is not vacuous.

Prior only

The headline layer is excluded, because a historical scout window cannot be reconstructed without leaking the future. This measures the price-process prior alone.

Edge is concentrated

The 300s windows - where the bot actually trades - score +0.3865 over n=597. The long windows are thin and closer to a coin flip on small samples.

the mechanic

Mint-a-pair: making markets with zero inventory.

Of the four ways orders cross on a binary book, one needs no seller at all. It is the best thing about building on this venue and deserves more than a row in a table.

How orders cross

  • Buy YES × Sell YESdirecttokens ↔ collateral
  • Buy NO × Sell NOdirecttokens ↔ collateral
  • Buy YES × Buy NOmint-a-pairthe pool mints a fresh pair - no seller needed
  • Sell YES × Sell NOburn-a-pairboth positions burn

Two resting buys are a complete quote

BUY_YES @ p − δ
BUY_NO  @ (1 − p) − δ

Because two opposite-side buyers cross against each other, that pair quotes both sides with no inventory and no counterparty maker. A conventional maker must hold what it sells. Vaticr never sells.

So the only risk is the imbalance

Since it only buys, its position is complete sets plus a remainder. A complete set redeems for exactly 1 collateral whatever the outcome - riskless. The only exposure is the net YES-minus-NO imbalance, which the inventory cap bounds directly.

what we measured

Two findings that changed the implementation.

Both were silent failures - the code runs, the orders fill, and the money quietly goes the wrong way. Both are written up in the SDK feedback report.

Settlement resolves against the EMA, not spot

The docs describe the reference only as “a multi-source price reference”, which reads like spot. The feed publishes both. It settles on mark.

close-vs-open over the eight most recent settlements

mark
8/8
spot
6/8

The two disagreements are exactly the windows where the series drifted apart in direction - the near-the-money ones, where the probability is most sensitive and most worth trading.

Naive volatility reads four times too low

Because mark is an EMA sampled every second, consecutive increments are heavily autocorrelated. The textbook estimator measures the smoothing, not the process.

step1s5s15s30s60s
mark0.0790.1550.2340.2780.264
spot0.2480.2720.2980.3030.274

Ground truth from realised 300-second moves is ≈0.33. Fed into a Gaussian model, 0.079 drives P(Up) to 0.0000 on windows that are genuinely a coin flip - maximum confidence exactly where there is least information.

under the hood

Four subsystems, one command.

Python reads and models; TypeScript owns every write, because that is where the Bot Kit and markets-sdk own signing, nonces and escrow - and two senders on one key race each other.

Modules

  • agents/scout.pyheadlines → directional evidence
  • agents/pricing.pyGBM prior + log-odds evidence
  • agents/resolver.pyaudit · Brier · backstops
  • agents/server.pyFastAPI surface the bot polls
  • bot/src/runner.tsthe trading loop
  • bot/src/strategy.tstake-vs-quote, mint-a-pair levels
  • VaticrForecastRegistryappend-only commitments

Get it running

git clone github.com/mrnetwork0001/Vaticr
cd Vaticr

npm install
python -m venv .venv && ./.venv/bin/pip install -r requirements.txt
cp .env.example .env

npm run bot:start   # brain + bot, one command

Starts in DRY_RUN, logging every order it would place and sending nothing.

Live on Somnia testnet

The forecast registry is deployed, with a forecast committed on-chain 318 seconds before its window closed and a real order placed.

0x3D04ff026A4Dc553a2ae9071dbc238a40D24b27A
Somnia testnet 50312DreamDEX Event ContractsdreamDEX Bot Kit@somnia-chain/markets-sdkSolidity 0.8.24Next.js 14Python 3.11 · FastAPIwagmi + viem

See it pricing live windows right now.

Every live BTC and ETH window with its prior, its posterior and the book side by side - plus the headlines moving them, every settlement recomputed from the oracle, and a wallet that can trade the gap.