Index Methodology
Version: 1.0
Methodology Version: midprice-v1
Last Updated: January 2026
Abstract
This document provides a technical specification of the Net Asset Value (NAV) computation methodology used by Belief Systems. The system aggregates prices from Polymarket prediction markets into composite indices, producing two primary outputs: raw_nav (a probability-weighted aggregate bounded in [0,1]) and index_level (a rebased index starting at 100). The current implementation uses the midprice-v1 methodology, which derives market prices from the midpoint of best bid and best ask quotes in the Polymarket Central Limit Order Book (CLOB).
Table of Contents
- Terminology
- Data Source
- Methodology: midprice-v1
- Worked Examples
- Resolution Handling
- Staleness and Data Quality
- Known Limitations
- Future Methodology Versions
Terminology
| Term | Definition |
|---|---|
| Index (Series) | A named basket of prediction markets with assigned weights |
| Condition ID | Unique identifier for a Polymarket prediction market (66-character hex string) |
| Token ID | Unique identifier for a specific outcome token (YES or NO) within a market |
| Outcome | The tracked side of a binary market: YES or NO |
| Weight | The raw weight assigned to a market in the basket composition |
| Normalized Weight | Weight after normalization such that all weights sum to 1.0 |
| Midprice | Arithmetic mean of best bid and best ask: (bid + ask) / 2 |
| Raw NAV | Weighted average of underlying market prices, bounded [0,1] |
| Index Level | Rebased index value derived from raw_nav relative to inception |
| Inception | The first successful NAV computation for an index |
| Stale | A price or computation that relies on outdated data due to fetch failures |
| Resolved | A market that has been settled with a final outcome (YES=1 or NO=0) |
Data Source
Polymarket CLOB API
All price data is sourced from the Polymarket Central Limit Order Book API (clob.polymarket.com):
- Order Book Endpoint:
/book?token_id={token_id} - Market Metadata:
/markets/{condition_id}
The CLOB API returns bid and ask levels with the following sorting convention:
| Side | Sort Order | Best Price Location |
|---|---|---|
| Bids | Ascending by price | Last element in array |
| Asks | Descending by price | Last element in array |
Precision Specification
All numerical values use the following precision:
| Parameter | Value |
|---|---|
| Decimal Places | 8 |
| Rounding Mode | ROUND_HALF_UP |
Methodology: midprice-v1
Overview
The midprice-v1 methodology computes index NAV using the arithmetic midpoint of best bid and best ask prices from the Polymarket CLOB. This approach provides a simple, transparent, and deterministic price discovery mechanism.
Step 1: Market Price Determination
Active (Unresolved) Markets
For each unresolved market, the price is determined as follows:
- Fetch Order Book: Query CLOB API for the tracked outcome token
- Extract Best Quotes:
best_bid= highest bid price (last element in ascending-sorted bid array)best_ask= lowest ask price (last element in descending-sorted ask array)
- Compute Midprice:
midprice = (best_bid + best_ask) / 2 - Clamp to Valid Range:
price = clamp(midprice, 0, 1)
Example:
best_bid = 0.995
best_ask = 0.996
midprice = (0.995 + 0.996) / 2 = 0.9955
Resolved Markets
When the CLOB API indicates a market is closed (closed == true), the engine uses settlement prices based on the winner field:
If tracked outcome token is winner: settlement_price = 1.0
If tracked outcome token is loser: settlement_price = 0.0
Fallback Behavior
If the CLOB API call fails:
- Retry up to 3 times with exponential backoff
- If all retries fail, use the last successfully fetched price for that market
- Mark the computation as
stale
Step 2: Weight Normalization
Raw weights from the index composition are normalized to ensure the sum equals 1.0:
W = Σ w_i (sum of all raw weights)
w'_i = w_i / W (normalized weight for market i)
Invariant: Σ w'_i = 1
This normalization guarantees that raw_nav remains bounded in [0,1] regardless of the raw weight values specified in the composition.
Example (7 markets with raw weights of 0.1429 each):
W = 7 × 0.1429 = 1.0003
Normalized weight per market = 0.1429 / 1.0003 ≈ 0.14285714
Sum of normalized weights = 1.00000000
Step 3: Raw NAV Calculation
raw_nav = Σ (w'_i × p_i)
Where:
w'_i= normalized weight for market ip_i= price for market i (midprice if active, settlement if resolved)
Proof of Boundedness:
- Since
w'_i ≥ 0andΣ w'_i = 1 - And
p_i ∈ [0, 1]for all markets - Therefore:
raw_nav ∈ [0, 1]
The raw_nav is explicitly clamped to [0, 1] as a defensive measure.
Step 4: Index Level Calculation
The index level provides a rebased representation starting at a base value of 100.
index_level = base_index_level × (raw_nav / inception_raw_nav)
Where:
base_index_level= 100.00000000inception_raw_nav= raw_nav at first successful computationraw_nav= current raw_nav value
Worked Examples
Example 1: Equal-Weighted Index with 7 Markets
Index Composition (7 markets, equal weight):
| # | Best Bid | Best Ask | Midprice | Raw Weight |
|---|---|---|---|---|
| 1 | 0.995 | 0.996 | 0.9955 | 0.1429 |
| 2 | 0.988 | 0.989 | 0.9885 | 0.1429 |
| 3 | 0.006 | 0.007 | 0.0065 | 0.1429 |
| 4 | 0.09 | 0.10 | 0.095 | 0.1429 |
| 5 | 0.017 | 0.018 | 0.0175 | 0.1429 |
| 6 | 0.33 | 0.34 | 0.335 | 0.1429 |
| 7 | 0.04 | 0.043 | 0.0415 | 0.1429 |
Step 1: Normalize Weights
W = 7 × 0.1429 = 1.0003
w'_i = 0.14285714 for each market
Step 2: Compute Raw NAV
raw_nav = (0.14285714 × 0.9955) +
(0.14285714 × 0.9885) +
(0.14285714 × 0.0065) +
(0.14285714 × 0.095) +
(0.14285714 × 0.0175) +
(0.14285714 × 0.335) +
(0.14285714 × 0.0415)
= 0.14221428 + 0.14121428 + 0.00092857 + 0.01357143 +
0.00250000 + 0.04785714 + 0.00592857
= 0.35421428
Step 3: Compute Index Level
inception_raw_nav = 0.35721428
index_level = 100 × (0.35421428 / 0.35721428)
= 100 × 0.9916016795
= 99.16016795
This indicates the index has declined approximately 0.84% from inception.
Example 2: Index with Resolved Market
Index Composition (2 markets):
| # | Status | Tracked Outcome | Price Source | Price | Weight |
|---|---|---|---|---|---|
| 1 | Active | YES | Midprice | 0.45 | 0.50 |
| 2 | Resolved | YES (Lost) | Settlement | 0.00 | 0.50 |
Computation:
W = 0.50 + 0.50 = 1.0
w'_1 = 0.50, w'_2 = 0.50
raw_nav = (0.50 × 0.45) + (0.50 × 0.00)
= 0.225 + 0.000
= 0.225
Resolution Handling
Market Resolution States
| State | Description | Price Source |
|---|---|---|
| Active | Market open for trading | CLOB midprice |
| Resolved | Market settled with outcome | Settlement (1.0 or 0.0) |
Index Resolution States
| State | Condition | Behavior |
|---|---|---|
| Active | All markets unresolved | Continue normal computation |
| Partially Resolved | At least one market resolved | Continue computing; use settlement for resolved markets |
| Fully Resolved | All markets resolved | Return terminal NAV; cease updates |
Terminal NAV
When an index becomes fully resolved:
- Final computation is persisted
- Index status is set to
RESOLVED - Future computations return the terminal NAV
- The terminal value is definitive (not stale)
Staleness and Data Quality
Staleness Conditions
A computation is marked stale: true when:
- Any underlying market price fetch failed, AND
- A fallback (last-known) price was used, AND
- The index is not fully resolved
Single-Sided Order Book
If a market has only bids or only asks:
- Midprice cannot be computed
- Market is marked as stale
- Falls back to last known good price
Known Limitations
Theoretical vs. Executable Pricing
The midprice represents a theoretical value, not an executable price. It does not account for:
- Trading fees (typically 0.5-2% on Polymarket)
- Slippage for market-sized orders
- Market impact of hypothetical replication trades
Implication: The NAV represents a theoretical value, not an executable portfolio price.
Liquidity Variance
Markets within an index may have vastly different liquidity:
| Market Type | Typical Liquidity |
|---|---|
| High-profile events | $1M+ |
| Moderate interest | $10K - $100K |
| Niche markets | < $1K |
Low-liquidity markets may exhibit:
- Wider bid-ask spreads
- Higher relative volatility
- Less reliable price signals
Static Weighting
Current indices use fixed weights assigned at composition time:
- Weights do not adjust for liquidity differences
- No automatic rebalancing based on market conditions
- May over-weight low-confidence or illiquid markets
No Correlation Adjustment
Markets within an index may be correlated. The methodology:
- Treats each market as independent
- Does not discount for information overlap
- May overstate diversification benefits
Future Methodology Versions
All methodology changes are tracked via methodology_version string recorded with each computation.
Proposed Enhancements
| Version | Description | Status |
|---|---|---|
midprice-v1 | Simple bid-ask midpoint | Production |
midprice-v2 | Liquidity-weighted midpoint | Proposed |
vwap-v1 | Volume-weighted average price | Research |
twap-v1 | Time-weighted average price | Research |
Liquidity-Weighted Midprice (v2)
Weight midprice contribution by order book depth:
effective_price_i = midprice_i × min(1, liquidity_i / target_liquidity)
Benefit: Reduces influence of thinly-traded markets.
Time-Weighted Average Price (TWAP)
Compute prices as time-weighted averages over a rolling window:
twap = (1/T) × ∫[t-T, t] midprice(τ) dτ
Benefit: Smooths short-term price volatility.
Volume-Weighted Average Price (VWAP)
Use recent trade data:
vwap = Σ(price_j × volume_j) / Σ(volume_j)
Benefit: Reflects actual executed prices rather than quoted prices.
Formula Reference
Midprice
midprice = (best_bid + best_ask) / 2
Weight Normalization
w'_i = w_i / Σw_j
Raw NAV
raw_nav = Σ(w'_i × p_i) where p_i ∈ [0,1]
Index Level
index_level = base_index_level × (raw_nav / inception_raw_nav)
Questions?
Contact us for more information about our methodology.