Markets

Prices

Two numbers, and the whole product is organised around not confusing them. The reference probability is where the market is. The execution price is what a trade costs.

referenceProbability and executionPrice

The reference probability is the midpoint between bid and ask. A buy executes at the ask.bid 71¢a seller hits thisreference 71.5¢nobody trades hereask 72¢a buyer crosses thisexecutionPrice is a side of the book. referenceProbability is the midpoint between them.
referenceProbabilityexecutionPrice
What it isPredicta’s normalised view of where the market sits. Usually the midpoint of the book.A side of a real book. What the trade actually crosses.
Who has offered itNobody. A midpoint is a statistic, not an offer.Somebody. A resting order sits there.
Where it appearsprobability, yesCents, noCents on the catalogueexecution.buyYes / execution.buyNo on the catalogue, executionPrice on a quote
Use it forShowing a player “63% chance”.Charging a player, and computing a payout.

They differ enough to matter

Measured across 22,586 open contracts in this catalogue, the ask sits a median 1.5¢ above the reference, 31¢ at the 90th percentile and 59¢ at the 99th. Roughly one contract in four differs by more than 10¢. The worst observed case displays 0.5¢ and executes at 99¢.

A ticket that renders the reference shows a number the player will not be charged, and a payout computed from it is wrong in the player's favour every time.

priceBasis

Every quote and every catalogue row says which of the two you are holding. Read it: a reference-priced quote is an estimate wearing a price's clothes, and you are entitled to know which one you have.

ValueWhereMeaning
bookQuoteA real side of a real order book. A buy crossed the ask.
referenceQuoteNo usable two-way price upstream, so this is the normalised probability. An estimate.
midpointCatalogueReference derived from bid and ask.
lastCatalogueReference derived from the last trade.
sourceCatalogueReference taken from a probability the source published directly.
noneCatalogueNo price could be derived at all.

How a side is priced

  • Buying YES crosses the YES ask. Selling YES hits the YES bid.
  • Where a source publishes a NO book directly, that book is used. Where it does not, NO is mirrored from YES: a NO ask is 1 − (YES bid), which is arithmetically exact for a binary contract.
  • A crossed book, bid at or above ask, is discarded on both sides and the quote falls back to the reference. Bad data that looks like a gift is exactly what a router would otherwise pick every time.
  • A spread wider than the configured maximum (0.2 by default) is treated as no usable two-way price: an illiquid book's midpoint is noise, not a probability.
  • 0 and 1 are settled, not tradeable. Neither is ever published as a price.

When there is no executable price

On a catalogue row, execution.buyYes and execution.buyNo are null whenever the book publishes no usable side. That null is a value, not a gap in the response.

json
"price":     { "yesCents": 63.4, "noCents": 37.2, ... },   // reference — a midpoint
"execution": { "buyYes": 0.651, "buyNo": null, "basis": "book" }

Never fall back to the reference

A null means show no price and disable the control. It does not mean “use yesCents instead”. The reference is a midpoint nobody has offered; substituting it renders a number the player cannot trade at, and the substitution is invisible to them.

One side may be executable while the other is not. Price and enable each side independently: a tradeable YES does not make NO tradeable.

  • execution.basis is book when at least one side came off a real two-way price, and reference when neither did. Read the per-side value for what to display, and the basis for how much to trust the row.
  • A quote is the authority, not the catalogue. The catalogue tells you whether to offer a control; the quote tells you what the trade costs. Never charge from a catalogue price.
  • An outcome with no executable side can still be shown as a market with a probability. What it cannot be shown with is a price or a buy button.

Precision, and why sub-cent prices are real

Catalogue prices are decimals between 0 and 1. The cent figures, yesCents and noCents, are rounded to the tenth of a cent, which is the finest tick any upstream actually uses. 63.4 is a legitimate value and so is 0.3.

Do not round to whole cents

Thousands of open contracts in this catalogue trade below one cent. Rounding a price of 0.4¢ to zero turns a long-shot contract into a free one, and a payout computed from a zero price is a division by zero or an infinite position, depending on which line runs first.

  • Carry prices at the precision you receive them, all the way to display. Round for the player's eye only, at the last step, and never before a calculation.
  • Contract counts are returned rounded to four decimal places for transport. The stored quote keeps full precision and is what the fill is checked against: so do not recompute contracts from a rounded figure and expect a match.
  • Money amounts are cents-exact: the fee rounds up to the cent and the payout rounds down. Prices are not money, and rounding them the same way is the error this section exists to prevent.
  • Never store a price as an integer number of cents. It is the same bug as rounding, held for longer.

Freshness

Prices carry an age, and the age decides what may be traded. Thresholds are per feed, because a streamed price 60 seconds old means the socket broke while a polled price 60 seconds old is simply normal.

LevelStreamedPolledEffect
fresh≤ 30s≤ 90sTrades at any size.
aging≤ 90s≤ 300sTrades at any size.
stale≤ 300s≤ 900sStake capped ($25 by default). Over the cap is 422 stake_exceeds_stale_limit.
suspended> 300s> 900sNo quote at any size: 409 price_stale.
  • A missing timestamp is treated as suspended, not fresh. An unknown age is precisely the case where the price could be hours old.
  • The gate runs on the server, at quote time and again at order time. A quote that was fresh when issued can go stale inside its own 30-second window.
  • Every quote returns its own verdict in freshness. Render that rather than recomputing your own: the two disagreeing is the bug the field exists to prevent.
json
"freshness": { "level": "fresh", "ageSeconds": 5, "feed": "websocket" }

Note

Most of the catalogue is polled rather than streamed: the live socket budget is finite and goes to the contracts with demand behind them. A cold contract is legitimately minutes behind for most of every cycle, which is why the polled bands are wider rather than the streamed bands being loose.

Fees and edge

Two independent levers, deliberately not folded together. An edge is hidden in the price; a fee is an explicit charge a player can see.

LeverDefaultHow it works
Platform fee120 bps (1.2%)Deducted from the stake before contracts are bought. A $50 stake wagers $49.40.
House edge0 bpsApplied on top of the reference probability, widening YES and NO. Zero by default: Predicta’s model is the transaction layer, not taking the other side.
text
stake         50.00
− fee          0.60   (120 bps, rounded up to the cent)
= wagered     49.40
÷ price        0.72   (executionPrice)
= contracts   68.6111
× $1.00 each
= payout      68.61   (rounded down to the cent)
− stake       50.00
= profit      18.61   (measured against the FULL stake)
  • The fee rounds up to the cent; the payout rounds down. Neither direction accrues a fractional cent to the player.
  • Profit is measured against the full stake, because that is what left the player's balance.
  • venueFee is null, not 0. No upstream publishes a readable taker fee and writing zero would assert a fact Predicta does not have.