Lucent Composite Fair Value Methodology
Per-market composite fair-value probability served under /api/pm/fair-value. Weighted geometric mean of odds over three provider legs: Kalshi (when a public-API anchor exists), Polymarket (when a Gamma-API anchor exists), and a Lucent internal literature-priors model leg with structured CHMP + FAERS adjustments. Every published probability is reproducible from the response envelope's breakdown field.
Registered markets
V1 admits only registry-listed marketKey values. Requests for any other key return 404 (never available: false — that’s reserved for known markets with insufficient substrate). Registry source of truth: data/pm-market-registry/*.json.
CMPS-slate parity (6)
| marketKey | Ticker | Resolution axis | Kalshi anchor | Polymarket anchor |
|---|---|---|---|---|
| cmps:adcom-yes | CMPS | procedure | — | — |
| cmps:controversy-blinding | CMPS | procedure | — | — |
| cmps:controversy-rems | CMPS | safety | — | — |
| cmps:controversy-voucher | CMPS | procedure | — | — |
| cmps:nda-by-dec-31-2026 | CMPS | timing | KXNEWDRUGAPPLICATIONCMPS-360-26… | — |
| cmps:review-priority | CMPS | procedure | — | — |
Extended Lucent-owned (6)
| marketKey | Ticker | Resolution axis | Kalshi anchor | Polymarket anchor |
|---|---|---|---|---|
| cmps:approval-by-jan-2027 | CMPS | approval | KXFDAAPPROVALDATECMPS-360-27JAN… | — |
| cmps:approval-by-jan-2028 | CMPS | approval | KXFDAAPPROVALDATECMPS-360-28JAN… | — |
| cmps:approval-by-jul-2027 | CMPS | approval | KXFDAAPPROVALDATECMPS-360-27JUL… | — |
| cmps:approval-by-mar-2027 | CMPS | approval | KXFDAAPPROVALDATECMPS-360-27MAR… | — |
| cmps:approval-by-oct-2027 | CMPS | approval | KXFDAAPPROVALDATECMPS-360-27OCT… | — |
| psych:any-by-jan-2027 | — | approval | KXFDAAPPROVALPSYCHEDELIC-27-ANY… | — |
Lucent Composite Fair Value Methodology
This page documents how Lucent computes composite fair-value probabilities for prediction-market contracts served under /api/pm/fair-value. The composite is a weighted geometric mean of odds (logit pool) over three provider legs: two external liquid-market anchors (Kalshi, Polymarket) and one internal literature-priors model leg. Published probabilities are decision-support inputs, not investment advice.
Provider set
Three provider legs compose the fair value:
- **Kalshi** — public trade-api v2 price on markets where the registry entry carries a Kalshi anchor. Mid-price from bid/ask when a valid book exists, falling back to last trade. Non-active status maps to freshness 0.
- **Polymarket** — public Gamma API price on markets where the registry entry carries a Polymarket anchor. Preferred price is
lastTradePrice; falls back to the YES token inoutcomePrices[0]. Closed markets map to freshness 0. - **Lucent internal model** — literature-derived base rate per (eventType, eventSubtype, therapeuticArea) tuple, plus structured adjustments (CHMP precedent, FAERS safety-signal count). Zero use of biopharma-intel's Hit Rate substrate — that measures alert-capture timeliness, not approval probability.
The composite is a pure logit pool at V1 — EXTREMIZATION_FACTOR = 1.0. Satopää et al. (2014) show extremized logit pool outperforms non-extremized on resolved-outcome corpora with d ∈ [1.16, 3.92], but V1 has zero resolved substrate for these markets; any factor choice would be unjustifiable. V2 revisits once N ≥ 30 resolved markets accumulate.
Weight formula
Each provider leg's raw weight is a product of four factors, all in [0, 1]:
w_i = provider_base_i × freshness_score_i × liquidity_score_i × resolution_match_score_i
Provider base weights: Kalshi 0.4, Polymarket 0.4, internal model 0.2. Raw weights normalize to sum to 1.0 (SPEC D4 Step 1); the model leg is then capped at MODEL_LEG_CAP_WITH_EXTERNAL = 0.4 of the FINAL NORMALIZED weight whenever any external leg is present (SPEC D4 Step 2). Cap redistribution is proportional to external legs' RAW weights:
Given raw per-leg weights w_kalshi, w_poly, w_model:
// Step 1 — provisional normalize
total_raw = w_kalshi + w_poly + w_model
n_i = w_i / total_raw for each i // Step 2 — model-leg cap if any external leg is present
if (n_kalshi + n_poly > 0) and n_model > MODEL_LEG_CAP_WITH_EXTERNAL:
excess = n_model - MODEL_LEG_CAP_WITH_EXTERNAL
n_model = MODEL_LEG_CAP_WITH_EXTERNAL
external_raw_sum = w_kalshi + w_poly
n_kalshi += excess × (w_kalshi / external_raw_sum)
n_poly += excess × (w_poly / external_raw_sum)Worked example 1 (both externals full-quality): raw {kalshi: 0.4, poly: 0.4, model: 0.2}. Provisional n = {0.4, 0.4, 0.2}. Model at 0.2 < 0.4 cap. Final {0.4, 0.4, 0.2}.
Worked example 2 (kalshi unreachable, poly stale + thin): raw {kalshi: 0, poly: 0.16, model: 0.2}. Provisional n = {0, 0.444, 0.556}. Cap fires; excess = 0.156 goes fully to poly (kalshi raw = 0). Final {0, 0.6, 0.4}.
Worked example 3 (both externals absent): raw {kalshi: 0, poly: 0, model: 0.2}. Cap does NOT apply (no external leg present). Final {0, 0, 1.0}. Model leg is *the* answer, not a shrinkage.
Model leg composition
The internal-model leg is a literature-derived base rate plus two structured adjustments. The base rate lives in data/fair-value-model-priors/base-rates.json — one row per unique (eventType, eventSubtype, therapeuticArea) tuple, each carrying {rate, citation, capturedAt, notes}. Sources: FDA approval statistics, BIO/MIT/Tufts CSDD industry meta-analyses, PDUFA priority-review base rates, FDA AdCom calendar reviews, FDA PRV disclosure register, FDA REMS document register. Every prior is version-pinned per SPEC D18: the priors JSON is canonicalized into the methodology-hash sha input, so any edit → sha changes → forces FAIR_VALUE_METHODOLOGY_VERSION bump.
Two adjustments apply on the log-odds axis:
1. **CHMP precedent** — applies when regulator ∈ {fda, both} AND a CHMP opinion exists at event_date ≤ asOf. Positive → +CHMP_POSITIVE_LOGODDS_DELTA (+0.05). Negative → CHMP_NEGATIVE_LOGODDS_DELTA (−0.05). Withdrawn / none → 0. EMA-only markets excluded (would double-count).
2. **FAERS safety-signal count** — applies ONLY when resolutionAxis === "safety" AND count > 0 in the 12 months preceding asOf. Delta = FAERS_PER_SIGNAL_LOGODDS_DELTA × min(count, FAERS_COUNT_CAP) = −0.03 × min(count, 3). Ceiling: 3+ signals saturate at −0.09.
All four coefficient constants (CHMP_POSITIVE_LOGODDS_DELTA, CHMP_NEGATIVE_LOGODDS_DELTA, FAERS_PER_SIGNAL_LOGODDS_DELTA, FAERS_COUNT_CAP) plus FAIR_VALUE_METHODOLOGY_VERSION live in src/fair-value/methodology.ts alongside the weight formula. Editing any of them requires version bump per SPEC D12/D18.
Freshness gate
Per-provider freshness maps quote age to a multiplicative factor (SPEC D6):
- Age < 10 minutes → 1.0
- Age < 1 hour → 0.5
- Age < 24 hours → 0.1
- Older than 24 hours OR unreachable → 0 (leg dropped)
Internal-model leg is always freshness 1.0 (computed at request time). Kalshi + Polymarket endpoints don't expose per-quote timestamps cleanly at the V1 wire shape; a live 200 with a valid active/open market maps to 1.0 and any failure maps to 0.
Availability discipline
The response envelope is a discriminated union on available. Silent-omission over caveated inclusion is the load-bearing prior (Phase 26c.3 canonical).
- available: true — composite computed. Carries fairValue, breakdown, computedAt, methodologyHash, methodologyVersion.
- available: false — one of two named reasons:
- no_provider_legs_fresh — every provider leg dropped at the freshness gate.
- internal_model_missing_prior — the registry entry references a tuple absent from the priors JSON, and no external leg is present to carry the composite.
Unknown marketKey values return 404 at the route layer — NOT available: false. That distinction is load-bearing: available: false is for known markets with insufficient substrate.
Cap on internal model
When any external leg contributes, the internal-model leg caps at 40% of the FINAL NORMALIZED weight (MODEL_LEG_CAP_WITH_EXTERNAL = 0.4). Defers to external liquidity by design; on markets where Kalshi/Polymarket carry real anchors, the model leg is a shrinkage prior. When BOTH externals are absent, no cap fires and the model leg becomes the whole composite. V1 accepts the risk of drowning out genuine model-leg edge; V2 revisits if evidence accumulates.
Snapshot cache
Composite results are persisted append-only to pm_fair_value_snapshots keyed on (market_key, computed_at) with methodology-version + methodology-hash pinning. Requests within 10 minutes of the latest snapshot serve the cached envelope; requests past 10 minutes trigger a fresh compute under a per-market advisory lock. The 10-minute TTL is uniform across statuses (D19) — available: true, available: false, and partial all cache for the same window. Snapshot rows are never updated in place.
Version + drift
The methodology hash is sha256(METHODOLOGY_BODY + "::" + FAIR_VALUE_METHODOLOGY_VERSION + "::" + canonicalize(base-rates.json)). Three inputs, one sha:
METHODOLOGY_BODY— this prose, byte-exact.FAIR_VALUE_METHODOLOGY_VERSION— the version string.data/fair-value-model-priors/base-rates.json— read at hash-computation time, canonicalized via the shared sorted-key JSON serializer.
Editing any of the three changes the sha. The methodology-hash regression test pins the current sha. A body edit without a version bump leaves the sha stable — silent-drift risk mitigated only by PR discipline. A priors JSON edit forces the sha to change (D18 closes the priors silent-drift arm). Version-bump discipline mirrors HIT_RATE_COMPUTE_VERSION + BACKTEST_METHODOLOGY_VERSION.
Disclaimer
These composite fair-value probabilities are decision-support inputs, not investment advice. External-provider legs (Kalshi, Polymarket) depend on third-party public APIs whose availability is not part of Lucent's uptime SLA. The internal-model leg is anchored on literature-derived base rates with named citations and structured adjustments — it carries the same known-unknown as any prior-driven estimate on a market with limited resolved-outcome history. Nothing on this page or in the associated API responses constitutes a solicitation, offer, or recommendation to buy or sell any security or take any trading position.
Provider weights
| Provider | Base weight | Notes |
|---|---|---|
| kalshi | 0.40 | Public trade-api v2 mid. |
| polymarket | 0.40 | Public Gamma API price. |
| internal_model | 0.20 | Literature priors + CHMP/FAERS adjustments; capped at 40% of the final normalized weight when any external leg is present (SPEC D4). |
Extremization factor: 1.00 — pure logit pool at V1. Bumping this constant requires FAIR_VALUE_METHODOLOGY_VERSION co-bumped per SPEC D12.
Model-leg adjustment constants
| Constant | Value | Fires when |
|---|---|---|
| CHMP_POSITIVE_LOGODDS_DELTA | +0.05 | Positive CHMP opinion at event_date ≤ asOf; regulator ∈ {fda, both}. |
| CHMP_NEGATIVE_LOGODDS_DELTA | -0.05 | Negative CHMP opinion at event_date ≤ asOf. |
| FAERS_PER_SIGNAL_LOGODDS_DELTA | -0.03 | Per FAERS safety signal in prior 12mo when resolutionAxis === "safety". |
| FAERS_COUNT_CAP | 3 | Signals cap; 10 signals still saturate at -0.09 on log-odds. |
Freshness gate
| Age bucket | Score |
|---|---|
| < 10 min | 1.00 |
| < 1 h | 0.50 |
| < 24 h | 0.10 |
| Older / unreachable | 0 |
Internal-model leg always freshness 1.0 (computed at request time). Providers with freshness 0 are dropped from composition (weight × 0 = 0).
See also the methodology index for Lucent’s other published methodologies (Hit Rate, Strategy Primitive).
Not investment advice. Composite fair-value probabilities are decision-support inputs anchored on third-party public APIs (Kalshi, Polymarket) whose availability is not part of Lucent’s uptime SLA. The internal-model leg is anchored on literature-derived base rates with named citations in data/fair-value-model-priors/base-rates.json (source-viewable in the repo); it carries the same known-unknown as any prior-driven estimate on a market with limited resolved-outcome history. Nothing on this page or in the associated API responses constitutes a solicitation, offer, or recommendation to buy or sell any security or take any trading position.