Skip to content

predict: add the entropic inventory statistic (DBU-732) - #1259

Closed
tonylee08 wants to merge 1 commit into
mainfrom
at/dbu-732-weighted-entropic
Closed

tonylee08 wants to merge 1 commit into
mainfrom
at/dbu-732-weighted-entropic

Conversation

@tonylee08

Copy link
Copy Markdown
Collaborator

Summary

  • Adds inventory_entropic, the arithmetic for an inventory charge on the certainty-equivalent cost of the pool's payout book, weighted by where settlement is actually likely.
  • Nothing calls it. The module owns the statistic and its incremental fold; the accumulators and the range reads they need are a separate change.
  • Draft: this is the first of two, and it is opened now so the shape can be argued about before the index work is done.
D(W) = b * ln( sum q(S) * exp(W(S)/b) )  -  sum q(S) * W(S)

W(S) is what the pool owes if the market settles at tick S; q is the risk-neutral probability of settling there, frozen at market creation; b is the risk tolerance. D is zero when the pool owes the same at every price and grows with how unevenly the book sits, weighted by likelihood.

Why this shape

Two properties the mean-plus-standard-deviation form cannot have.

Buying every outcome is free, exactly. Adding a payout at every settlement price raises the certainty equivalent and the fair value by the same amount, so the difference is unchanged. Asserted as an equality, not within a tolerance.

No rate can misprice a strictly worse book. A trade's total is (1 - rate) * fair value + rate * certainty equivalent, a convex combination of two monotone functions, so it is monotone for any rate in [0, 1] with no dependence on the ladder. The deviation form admits no such rate once the ladder is fine: its monotonicity bound is rate <= sqrt(q_min / (1 - q_min)), set by the smallest bucket, which collapses toward zero as the ladder refines. Standard deviation is also positively homogeneous, so worst-case loss is unbounded; here it is bounded by b * ln(1/q_min).

The large-b limit of this statistic is the probability-weighted variance over 2b, so the deviation form is its leading term. The square root is what buys positive homogeneity, and positive homogeneity is what forfeits the bound.

Key decisions

  • The fold is multiplicative, not additive. Adding a payout across a range multiplies that range's share of the exponential total by exp(payout/b) and leaves the rest alone, so the read a trade needs is the range's own share rather than anything about the whole book.
  • The exponent is bounded well inside exp's input ceiling. exp cannot return a value outside u64 and aborts rather than wrapping. Deriving b from the market's allocation keeps W/b inside the bound by construction; that wiring is owed by the next change and the module asserts the bound in the meantime.
  • The statistic clamps at zero rather than aborting. Jensen puts the true difference at or above zero, but both terms are floored independently, and on a book that owes the same everywhere they are the same number — the flooring can leave the logarithm a unit short. The clamp can only bind within the rounding error of a book carrying no unevenness at all.
  • Probability weights are frozen at creation. A moving weight would score the two legs of a round trip against different measures and the refund would stop being exact.

Scope / Descoped

  • In scope: the statistic, the fold, and unit coverage.
  • Descoped, and owed by the follow-up: the accumulators on StrikeExposure, the range read from the payout index (a multiplicative monoid over boundaries, not the additive one that exists), the frozen surface snapshot at market creation, the config knob deriving b from the allocation, and the charge wiring into mint and close.
  • Not decided here: whether a trade that flattens the book is paid, and what rate this would run at. It ships unreachable either way.

Test plan

  • sui move test --path packages/predict --gas-limit 100000000000492 pass, no Move.lock drift.
  • sui move build --path packages/predict --warnings-are-errors — clean.
  • adding_the_same_payout_everywhere_leaves_the_statistic_at_zero — the property the design rests on, asserted exactly.
  • a_range_opened_and_closed_returns_the_totals — a round trip returns both accumulators, so it collects nothing.
  • an_empty_book_owes_the_same_everywhere_and_scores_zero.
  • a_half_covered_book_carries_the_gap_between_cost_and_value — expected value derived independently from math.log/math.exp. Asserted within a granularity-derived bound rather than exactly, because this repository does not document the precision of its fixed-point exp and ln; every mathematically exact property is pinned by the tests above.
  • Both abort codes covered.

Risk / Rollout

Unreachable — no caller. The module is inert until the follow-up wires it, and any charge it eventually feeds would ship at a zero rate like the two mechanisms already open.

An empirical comparison of this statistic against the two open designs, on real BTC price paths, is in progress and will be posted here. If it does not beat them this branch should be closed rather than continued.

Adds the arithmetic for an inventory charge built on the certainty-equivalent
cost of the pool's payout book under exponential utility, weighted by the
risk-neutral probability of each settlement price:

    D(W) = b * ln( sum q(S) * exp(W(S)/b) )  -  sum q(S) * W(S)

Nothing calls it. The module owns the statistic and its incremental fold; the
accumulators and the range reads they need are a separate change.

The shape is chosen for two properties the mean-plus-standard-deviation form
cannot have. Adding a payout at every settlement price raises the certainty
equivalent and the fair value by the same amount, so buying every outcome is
free — asserted exactly, not within a tolerance. And because a trade's total is a
convex combination of the fair value and the certainty equivalent, both monotone,
no rate in [0, 1] can price a strictly worse book lower; the deviation form
admits no such rate once the settlement ladder is fine, because its monotonicity
bound is set by the smallest bucket on it.

The statistic is a difference of two independently floored terms and Jensen puts
the true difference at or above zero, so a book that owes the same everywhere can
leave the logarithm a unit short. That case clamps rather than aborts, and the
clamp can only bind within the rounding error of a book carrying no unevenness.

`exp` cannot return a value outside `u64`, so the exponent is bounded well inside
its input ceiling. Deriving the risk tolerance from the market's allocation keeps
the ratio inside that bound by construction rather than by hoping, which is the
wiring the next change owes.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
@tonylee08

Copy link
Copy Markdown
Collaborator Author

Closing this. Two independent checks came back and both go against it.

The measure does not earn its place

Scored on the same 17,082 books settled on real BTC paths as the other candidates:

Q5 tail share ρ dispersion size-controlled ρ
windowed spread (#1248+#1250) 0.3918 0.897 0.747
bucketed shortfall (#1252) 0.4488 0.879 0.649
probability-weighted spread 0.4330 0.983 0.951
this 0.4479 0.845 0.604
book size alone 0.3829 0.813

It never beats the probability-weighted spread at any risk tolerance — the sweep is a strict tradeoff with no interior win. Its one real gain is exactly the bucketed design's gain, at the same magnitude, and their rank correlation is 0.972. At small tolerance this is a smoothed version of #1252.

The theory held up completely: zero monotonicity violations across 9.6M charge evaluations, and the deviation form's ceiling λ* = sqrt(q/(1-q)) reproduced analytically to ratio 1.0000, collapsing to 2e-8 on a full tick ladder. That part was right. It just is not worth ranking markets worse for.

And the implementation is not sound

The formula, the sign convention and the fold algebra are correct — verified against the entropic risk measure definition and brute-forced over ~960 random books with no structural error. The integer implementation is another matter.

Both fold directions floor, so the charge decays to zero under churn. A round trip permanently removes 1–2 raw units of expo, with no re-anchoring path. Repeatedly opening and closing a throwaway range drives the charge on an unrelated real position monotonically to zero — measured at 6,249 cycles for W/b = 0.01, 1,124 for W/b = 0.003. The same mechanism makes the charge path-dependent: splitting one mint into 10,000 slices takes it to zero for an identical final book.

The exponent guard bounds the trade, not the book. Nothing bounds cumulative W/b, and deviation narrows to u64. Five individually-admissible trades reach W/b = 25 and the statistic aborts permanently, with fold still succeeding into a region where the value can never be read again.

The headline property is not what it appears. adding_the_same_payout_everywhere_leaves_the_statistic_at_zero passes because saturating_sub clamps a pre-clamp value of −4. The module doc and the test both claim this is exact. It is not — it is clamped, and without the clamp that test would abort.

There is also a dead zone below W/b ≈ 3e-4 where the statistic returns exactly zero however uneven the book is, and the clamp can silently waive up to ~12 payout units at a large tolerance.

What is worth keeping

The rounding fix is real and general: floor the add, ceiling the remove, which biases dust to the protocol per this repo's own rounding policy rather than to the trader. That applies to any multiplicative fold, not only this one.

And the reason this branch existed is unchanged — the deviation form used by both open designs is not monotone, and its ceiling vanishes as the ladder refines. That finding stands and belongs in the design record regardless of which measure ships.

Closing rather than iterating: the measure would have to beat the probability-weighted spread to be worth the multiplicative index this needs, and it does not.

@tonylee08

Copy link
Copy Markdown
Collaborator Author

Superseded by the measurement — see above.

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