Skip to content

predict: freeze each market's 900-tick window on the live SVI belly - #1284

Draft
sdelo wants to merge 1 commit into
mainfrom
predict/padded-strike-band
Draft

sdelo wants to merge 1 commit into
mainfrom
predict/padded-strike-band

Conversation

@sdelo

@sdelo sdelo commented Sep 1, 2026

Copy link
Copy Markdown
Collaborator

Summary

  • create_and_share_expiry_market now takes the live Pyth and Block Scholes feeds, inverts the 1%–99% UP belly, pads that interval by cadence belly_pad, and freezes a 900-wide absolute tick window [min_tick, min_tick + 899].
  • Finite mint and reference ticks must sit in that window. Sentinels 0 and pos_inf_tick stay free. The grid does not move after create.
  • belly_pad = 0 means 1.0× (no extra room), not the old from-zero ladder. Cadence tick_size is a floor on derived granularity; admission stays the same multiple of tick_size.
  • MarketCreated carries min_tick. Cadence config and its event carry belly_pad. Keepers get registry::next_deployable_expiry so they can seed the surface for the expiry create will actually open.

Why

Each expiry market’s payout tree has a 1,000-node cap. Unique user-chosen strike ticks become tree nodes, so an unbounded finite-tick domain can exhaust NAV. #1191 capped finite ticks at 1..=900 from zero, which does bound the tree, but those 900 slots are glued to $0. For a live underlier that spends the budget on strikes the market will never trade, or forces a coarse tick_size that skips the region people actually mint.

This change keeps the 900-count budget and aims the window at the live smile. Create is no longer a no-spot snapshot of tick_size alone: it loads a pricer, derives the band, and freezes it. Later mints cannot grow the tree past that window.

Linear / Context

Key decisions

  • One create path, feeds required, invert always. A gated from_surface entrypoint that left belly_pad = 0 on the from-zero grid would leave the tree-cap hole on the default path. The extra create is deleted.
  • belly_pad = 0 is 1.0×, not “skip invert.” Zero maps to FLOAT_SCALING at create. A near-step digital that inverts both 1% and 99% to the same strike is widened by one tick_size before padding.
  • Window checks live on StrikeExposure, not Order. An order id has no market, so a global 1..=900 check cannot express a slid window and still wastes slots below the belly.
  • Cadence tick_size is a floor. Derived granularity can only get coarser, so admission (already a multiple of tick_size) does not change meaning.
  • Propbook test-only overwrite / remove seams. Production ingest is monotonic and create now writes a live surface, so fixtures that must re-seed an older model time or prove absence need force-replace and clear helpers. Staleness tests still use real apply.

Scope / Descoped

  • In scope: create-time band derivation, cadence belly_pad, min_tick snapshot and admission, public docs, harness/SDK/sim create wiring, Predict and Propbook test fixtures.
  • Not in scope: moving the window after create, changing the 900 / 1,000 node constants, or changing mint admission probability bounds.

Test plan

  • /tmp/sui-1.74.1/sui move build --path packages/predict --warnings-are-errors — package builds clean.
  • /tmp/sui-1.74.1/sui move test --path packages/predict --gas-limit 100000000000 — 572/572, including create-window property tests, invert/pad unit tests, and the restored absence / overwide / non-monotone abort paths.

Risk / Rollout

Create now fails closed if the live surface is missing or stale, so keepers must pass fresh feeds and should peek next_deployable_expiry before seeding. Existing harness/SDK create helpers take those feeds; a caller that still treats create as no-spot will not compile.

A too-small belly_pad on a near-step smile can place min_tick at the ATM tick and reject nearby in-the-money ticks (the 1.0× default). Operators who want room below the belly set a pad in [1.0×, 4.0×].

The frozen window is per-expiry. A later spot jump does not slide it; deep-tail pricing still saturates, and the mint probability band still rejects untradeable tails. Pre-deploy: no live objects to migrate.

A from-zero 900-tick ladder still spends the payout-tree budget below the traded region. Create now inverts the live 1–99% belly, pads it, and snapshots [min_tick, min_tick+899] so unique strikes stay inside the tree cap.
@tonylee08
tonylee08 marked this pull request as draft September 1, 2026 18:47
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant