/observe response echoes both exhaustion_score and divergence_score so
the two-component HUD is always auditable. We reject H0 only on the §3 evidence; a failure to reject
is the lab's expected and fully successful outcome. No real order is placed this phase; every leg is a
dry_run=True broker echo.
This lab descends from the Hybrid Lab (hybrid_engine.py), documented in the
hybrid_v1 methodology whitepaper. That engine ran a
six-stage pipeline — deterministic exhaustion prior, Kaufman-ER regime gate, a logit-space ensemble of five
regime-gated features, a bounded vision-LLM fold, PAV isotonic calibration, and drawdown-braked ¼-Kelly
sizing — to answer one question: whether merging two individually-weak signals (exhaustion regime, provider
divergence) yields an edge larger than the sum of its parts. Its honesty commitments — an 88% logit clamp, a
per-bucket Wilson lower bound, an openly-displayed identity calibrator below 25 samples — are inherited here
wholesale.
The pivot's headline findings frame why additivity is the right question to re-ask on options. Finding #4 said both source regimes "contain regime information … [and] DO meaningfully shift implied-vol expectations" but produced no executable binary edge. Finding #5 adopted the project conclusion: stop monetising direction as a binary bet, and shape an options payoff around the predicted regime instead. The Hybrid Lab is where those two findings collide most interestingly — because the two component regimes make opposite volatility statements:
The exhaustion regime says "the move is overextended — expect vol contraction as it mean-reverts." The divergence regime says "the readers disagree — expect vol expansion as uncertainty resolves." When both fire at once, they are not redundant confirmations; they are a structured disagreement about the next regime.
That tension is exactly what makes the additivity question non-trivial. In the binary world the two signals
could only ever vote on direction, so their vol disagreement was invisible — washed into a single
bull-probability. On the options rail the disagreement becomes a selectable structure: the relative
magnitude of exhaustion_score vs divergence_score tells the selector whether to lean
short-vol (contraction wins), long-vol (expansion wins), or vol-neutral-directional (they cancel, leaving only
the exhaustion fade direction). Findings #1 and #3 still bind: read real b off geometry, size off
p_lower.
The classifier is hybrid_engine.py, used unmodified as the forecast layer. It emits the §2.2
regime block with both exhaustion and divergence populated. Per the §2.3
contract, this lab's /observe response additionally echoes exhaustion_score and
divergence_score as top-level fields so the page can render the two-component HUD — the user
always sees the two raw inputs that drove the structure choice, never just the verdict. This is the hybrid_v1
"factors[] audit trail" discipline carried onto the options rail.
The selector reads the relative magnitudes of the two scores and selects from the full defined-risk subset of the Periodic Table (WEBULL_PIVOT §3) — this is the only lab whose candidate set spans both the contraction and expansion families, because only the hybrid sees both signals:
| Score relationship | Vol read | Primary candidate | Alternates |
|---|---|---|---|
| Exhaustion ≫ divergence, directional | contraction wins | bear_put_spread / bull_call_spread (debit) | long_iron_butterfly |
| Divergence ≫ exhaustion | expansion wins | long_strangle | long_straddle |
| Both high, comparable (structured disagreement) | direction known, vol ambiguous | bull_call_spread / bear_put_spread (vol-neutral defined-risk) | long_call_calendar_spread |
| Both low | — | floor — regime not armed | — |
The "both high" row is the additivity test's sharp edge: it routes to a defined-risk vertical that monetises
the exhaustion fade direction while staying roughly vol-neutral, on the thesis that the two signals
agree a regime change is imminent even as they disagree on its vol sign. With
defined_risk_only=true the selector never returns a naked short-vol leg even when the contraction
read dominates — the Mertonian fat-tail discipline from the hybrid_v1 CHOP-BUSTER section binds here too.
Closed trades persist on the existing paper_trade_service.py row (no parallel DB) with the §2.4
columns. The additivity question makes per-structure bucketing indispensable:
/api/cv/paper/calibration?strategy_id= lets us compare the hybrid's
bull_call_spread bucket against the Edge and TRAIL labs' same-structure buckets, and
the hybrid's long_strangle bucket against the Divergence lab's — the only way to tell
whether combining the signals beat using either alone. Wilson 95% lower bound per bucket (Wilson 1927);
exhaustion_score / divergence_score are persisted in legs_json context
for post-hoc additivity analysis.
Break-even is p* = 1/(1+b) off each structure's geometry; sizing is fractional Kelly off
p_lower (F7 README — never p_hat), with the hybrid_v1 drawdown brake and
losing-streak damper carried forward. The additive ergodic Monte Carlo (Peters 2019) reports time-average
growth. The hybrid lab is the most exposed to finding #2's trap: combining signals can lift ensemble EV (more
"confirmations" feel like more edge) while the time-average growth path stalls or worse, because the combined
selector trades more often and pays more friction. A positive EV with ≤ 0 growth rate is a fail.
webull_strategy_id bucket, the hybrid's Wilson lower bound
p_lower stays at or below the geometry break-even p*, and never exceeds the
best single-component lab's p_lower for the same structure.
We reject H0 only if, over ≥ 100 closed paper option-trades in at least one
webull_strategy_id bucket, the hybrid Wilson lower bound both exceeds break-even and exceeds
the matching single-lab bucket (the additivity clause):
The second condition is what makes this an additivity test rather than a fourth directional test.
Beating break-even is necessary but not sufficient: if the hybrid clears p* only by routing to a
structure that the Edge or Divergence lab already clears alone, then merging added nothing — the edge
lived in one component, and H0 stands. Additivity is rejected only when the combination
demonstrably outperforms its best part on a ≥ 100-trade bucket.
Per the lab's stance, a null-not-rejected result is a successful run. A sustained failure teaches:
defined_risk_only guard plus drawdown brake contained the most active lab without a ruin path.dry_run=false broker response, any
undefined-risk leg booked while defined_risk_only=true, or — hybrid-specific — an
/observe response that omits exhaustion_score or divergence_score, which
would mean the two-component HUD is rendering a verdict the operator cannot audit. All three are checked by the
smoke-test sign-off.
Must-do:
p_lower table of the
hybrid bucket vs each single-component lab's same-structure bucket — the additivity ledger made visible.theta_paid_usd and vega_at_entry per bucket so a contraction harvest is never
conflated with a directional or expansion edge.+0.8/−1.0 contract so the original binary hybrid additivity result can be benchmarked
directly against the options expression.Must-not:
p_lower > p* that also clears the additivity clause.defined_risk_only=false while p_lower < p* — the busiest, most
structure-diverse lab is the worst place to remove the downside cap before the edge is proven.b, break-even
p* = 1/(1+b); drawdown-braked ¼-Kelly inherited from hybrid_v1.)