Webull F7 Options Gate — Does a Calibrated Paper Edge Survive the Live Flip?NULL-HYPOTHESIS · METHODOLOGY

Webull F7 (options) · Phase 2 · 2026-06-17 · ~10 min read · Largest bucket n = 29 closed · gate at n = 100 · this is the authorization document for a live flip


Abstract. F7 was the binary Monte-Carlo lab that rendered the project's verdict on candle-direction betting: bucket closed paper trades by stated confidence, compute the Wilson lower bound p_lower, and size by Kelly off that lower bound — never off the optimistic point estimate. F7-options carries that exact machinery onto multi-leg defined-risk Webull structures: each webull_strategy_id is its own bucket, its break-even p* is read from the structure's payoff geometry, and the gate clears only when that one bucket's p_lower exceeds its own p*. The gate is deliberately bucket-level, not pool-level — averaging an edge in one structure against a drag in another is precisely how a non-existent edge is manufactured, so no aggregate claim ever authorizes a live flip. We are on the n = 25 → n ≥ 100 trajectory (largest bucket long_call at 29 closed); this document sets the gate, it does not promise the gate will clear.
Contents
  1. §1 Null hypothesis
  2. §2 Stop criterion (binding)
  3. §3 break_even per Periodic-Table element
  4. §4 Why Wilson's lower bound
  5. §5 Why Kelly-budget sizing on defined-risk max-loss
  6. §6 How OPRA enrichment changes b
  7. §7 Live-flip authorization (operator-only)
  8. §8 Citations
  9. §9 Current Phase-1 closed-trade tally

§1 · Null hypothesis

"Calibrated lower-bound p_lower over ≥100 closed paper trades of a multi-leg options structure does NOT predict p_lower > break_even survival when the same structure is flipped live, because (a) the chain Greeks used by options_strategy_mapper.select_strategy are synthesized at selection time and only OPRA-enriched at submit (per Phase-2 §2.2), and (b) live execution friction — assignment risk, gap risk, IV crush around earnings, dealer skew flips — is not simulated in the paper-mode harness."

The null is the working assumption until data overturns it: a paper edge is an artifact of the harness, not a property of the market. What would falsify it is narrow and specific — a single webull_strategy_id bucket where, after ≥ 100 closed paper trades, p_lower > break_even and the realized p_hat on the first 30 live trades stays within ±5 points of the paper p_hat. Both halves are required. A paper bucket that clears the gate but whose p_hat collapses on contact with real spreads, real fills, and real assignment is not a falsification — it is a confirmation of the null, and the correct response is to stop flipping buckets, not to flip more. The gate is a hypothesis test whose default outcome is "the edge did not survive"; clearing it is the surprising result that has to earn its way past the lower bound.

This is the same posture the TRAIL Phase 1.5 study took toward a 36% vision hit rate and the F7 binary lab took toward the candle bet: a friction-honest instrument that returns "your edge did not survive" is doing its job. The F7-options gate is that instrument, pointed at the 52-element options Periodic Table one bucket at a time.

§2 · Stop criterion (binding)

The gate clears for a bucket if and only if, over ≥ 100 closed paper trades of that specific webull_strategy_id, the Wilson lower bound exceeds that bucket's geometry break-even:

p_lower(strategy_id) > break_even(strategy_id), over n_closed ≥ 100 for that one strategy_id

This is the §0.6 binding rule of the original workboard, applied at bucket granularity. The discipline is stated as a prohibition: no aggregate-level edge claim authorizes a live flip; only per-bucket clearance does. A pool-level "the Webull labs are net-positive on paper" number is meaningless here — it can hide a real edge in long_call behind a drag in short_box_spread, or, far more dangerously, manufacture an apparent edge by averaging across structures whose risks do not net. The gate refuses to look at the pool.

The gate's machinery emits a per-bucket verdict (from webull_service.f7_gate()):

verdict ∈ {
  "INSUFFICIENT_SAMPLE",   # n_closed < 100  → keep accumulating paper trades; nothing else changes
  "EDGE_REJECTED",         # n_closed ≥ 100 AND p_lower ≤ break_even → bucket retired from live consideration
  "EDGE_CONFIRMED",        # n_closed ≥ 100 AND p_lower > break_even → operator review may begin (NOT auto-flip)
}

Exactly one verdict authorizes operator action: EDGE_CONFIRMED. INSUFFICIENT_SAMPLE means we are not done measuring. EDGE_REJECTED means we measured, and the edge was not there — that bucket is retired from live consideration until the methodology itself is revised. Neither of those two is a failure of the lab; they are the lab succeeding at telling the truth.

§3 · Methodology — break_even per Periodic-Table element

Every element of the options Periodic Table (options_strategy_mapper.supported_strategies() → 52 entries) has a price-level break-even read directly from its leg geometry, and a probability-sense break-even in Kelly form. The 6–8 most common structures:

Strategybreak_even (price-level)break_even (probability sense)
long_callS_T > K + premium_paid1/(1+b), b = (max_gain_at_T − premium)/premium
long_putS_T < K − premium_paidsame form, b from the put payoff geometry
long_call_spreadS_T > K_long + net_debit1/(1+b), b = (K_short − K_long − debit)/debit
long_put_spreadS_T < K_long − net_debitsymmetric to the call spread
short_iron_condorK_put_short < S_T < K_call_short (both wings stay OTM)credit/(max_loss − credit) inverted into 1/(1+b)
bull_put_spreadS_T > K_short − net_creditcredit/(spread_width − credit) → 1/(1+b)
long_straddle|S_T − K| > total_premium1/(1+b), b keyed to expected move
long_strangleas straddle, with two strikessymmetric
The unifying observation: every element of the Periodic Table reduces to a Kelly-form break-even p* = 1/(1+b), where b is the realized payoff ratio averaged over the closed trades in that bucket. This is exactly the F7 binary break-even — the formula does not change at all when we move from a one-touch candle bet to a four-leg defined-risk structure. The only thing that changes is the source of b: in the binary lab it was a fixed per-trade ratio |target−entry|/|entry−stop|; here it is a per-bucket empirical average of the realized payoff ratio across that structure's closed trades. The options pivot did not invent new math; it changed what fills the one variable the math already had.

The three buckets carrying live data (long_call, bull_put_ladder, short_box_spread — §9) each resolve to the same p* = 1/(1+b) form; their b values differ because the geometries differ, which is exactly why the gate is computed per bucket and never pooled. The break-even semantics above are read-only descriptions of options_strategy_mapper.py; this document does not modify the selector.

§4 · Why Wilson's lower bound

The win/loss outcome of a closed options bucket is a binomial proportion, and at the sample sizes we are at — long_call at n = 29 is the largest bucket — the naive Wald normal approximation p̂ ± z·√(p̂(1−p̂)/n) is badly miscalibrated: it produces intervals that are too narrow, can run below 0 or above 1, and degenerate entirely when is near 0 or 1. The Wilson (1927) score interval is the standard remedy:

p_lower = (p̂ + z²/2n − z·√[ p̂(1−p̂)/n + z²/4n² ]) / (1 + z²/n), z = 1.96 (95% CI)

Wilson's interval is centred at a shrinkage of toward ½, is bounded in [0,1] by construction, and — the property we depend on — its lower bound is materially tighter (more conservative) than Wald's at small n, which is exactly the regime where over-claiming an edge blows up an account. Brown, Cai & DasGupta (2001) surveyed the binomial-proportion interval zoo and found Wilson (and Agresti-Coull, which approximates it) decisively preferable to Wald across small and moderate n. We size off p_lower, not , precisely so that a lucky-looking thin bucket cannot fund a fat bet — the F7 README's binding instruction, carried forward verbatim.

The 100-trade gate is not a magic number. It is the minimum n at which the Wilson lower bound begins to converge meaningfully on the truth for proportions in the 0.4–0.7 range we care about — the gap between p_lower and at n = 30 is wide enough that almost no bucket could honestly clear, and by n = 100 that gap has narrowed to where a real edge, if present, can show itself above break-even. The number is a convergence threshold, not a ritual.

§5 · Why Kelly-budget sizing on defined-risk max-loss

Once a bucket has a defensible p_lower and a geometry-derived b, the growth-optimal fraction is Kelly (1956), evaluated at the lower bound rather than the point estimate:

f* = (b·p − q)/b = ((1+b)·p_lower − 1) / b, then f_max ≤ 0.25 · f* (quarter-Kelly)

The quarter-Kelly cap is the Peters (2019) ergodicity discipline: full Kelly maximises the time-average growth rate only if p and b are known exactly, which they never are; fractional Kelly is the Bayesian-correct response to parameter uncertainty and trades a sliver of growth for a large reduction in the dispersion of the single trajectory we actually live. The binding rule that makes this safe on the live flip:

The risk budget is f × defined_max_loss, NOT f × notional. A defined-risk structure has a max loss we know to the dollar before submit — the debit paid, or the spread width minus the credit. Sizing to that floor (not to the implied-notional ceiling the underlying could theoretically reach) is what keeps a live flip survivable even for an EDGE_CONFIRMED bucket. The synthesized chain at selection time gives us a modeled max-loss; the OPRA enrichment at submit (§6) gives us the priced max-loss — Phase 2 is what makes the dollar figure in the budget honest rather than mocked.

§6 · How OPRA enrichment changes b

Phase 1 selected and submitted on a synthesized chain: smooth mocked volatility, zero mocked spreads. Phase 2 leaves the selector's synthesized chain in place (we still have no real chain endpoint) but enriches the submitted legs with a live OPRA snapshot via webull_service.enrich_legs() — real bid/ask, real IV, real per-leg Greeks. The two sources produce different b:

Input to bSynthesized chain (_ensure_chain)OPRA-enriched (enrich_legs)
Bid–ask spreadzero → no entry dragreal → debit paid is higher, b lower
Implied volsmooth/flat surfacetrue IV smile → realized payoff geometry shifts as vol moves
Resulting btypically over-estimatedrealistic — reflects the price you can actually be filled at
Calibration honesty flagenriched: falseenriched: true (written into legs_json)

This is Phase 2's central honesty improvement. The synthesized chain flatters b because zero spreads and smooth vol are free money that does not exist; an over-stated b lowers p* = 1/(1+b) and makes a bucket look closer to clearing than it is. The 75 additional closed paper trades that bring each bucket from ~25 to 100 will be better trades, not merely more of them: their b reflects the real OPRA payoff geometry, so the p_lower > break_even test they feed is measuring the structure we could actually trade live — not a frictionless cartoon of it. Every leg carries the enriched flag so calibration can, if needed, segregate the honest trades from the synthesized ones.

§7 · Live-flip authorization (operator-only)

Code may surface the gate state. Code may not flip dry_run=False. The flip is a deliberate, signed, bucket-scoped operator action:

GET /api/webull/f7/gate
  ↓
for bucket in response.buckets:
  if bucket.verdict == "EDGE_CONFIRMED":
      Operator review required. NOT auto-flipped.
      Operator may then set  ALLOW_LIVE_BUCKET=<strategy_id>  in webull.env
      and restart the service. webull_service.submit() reads this env on
      every call and permits dry_run=False for that ONE strategy_id only.
      All other strategies remain paper-mode.
  elif bucket.verdict == "EDGE_REJECTED":
      Bucket permanently retired from live consideration until methodology revision.
  elif bucket.verdict == "INSUFFICIENT_SAMPLE":
      Continue accumulating paper trades. Nothing else changes.
The flip is operator-only, bucket-scoped, env-var-gated, and signed by service restart. The env-var edit plus the restart is the operator's signature — it cannot happen by accident, by aggregate claim, or by code path. One strategy_id at a time, never the pool. No verdict other than EDGE_CONFIRMED on that specific bucket authorizes it, and even then the authorization is permission for a human to review, not an instruction for the system to act.

§8 · Citations

  1. Cox, J. C., Ross, S. A., & Rubinstein, M. (1979). Option pricing: A simplified approach. Journal of Financial Economics, 7(3), 229–263.
  2. Black, F., & Scholes, M. (1973). The Pricing of Options and Corporate Liabilities. Journal of Political Economy, 81(3), 637–654.
  3. Kelly, J. L. (1956). A new interpretation of information rate. Bell System Technical Journal, 35(4), 917–926.
  4. Wilson, E. B. (1927). Probable inference, the law of succession, and statistical inference. Journal of the American Statistical Association, 22(158), 209–212.
  5. Brown, L. D., Cai, T. T., & DasGupta, A. (2001). Interval estimation for a binomial proportion. Statistical Science, 16(2), 101–117. (Why Wilson > Wald > Agresti-Coull at small n.)
  6. Peters, O. (2019). The ergodicity problem in economics. Nature Physics, 15(12), 1216–1221.
  7. Taleb, N. N. (2007). The Black Swan: The Impact of the Highly Improbable. Random House.
  8. Internal: MONTECARLOLAB/F7_MONTECARLO_LAB_README.md (F7 lineage — Wilson lower-bound, derived b, ergodic Monte Carlo); docs/WEBULL_PIVOT_STUB_PROMPT.md §1 findings 1–4; TRAIL Lab Phase 1.5 study. Companion Phase-1 whitepapers: Edge, Exhaustion, Divergence, TRAIL, Hybrid.

§9 · Current Phase-1 closed-trade tally

This is the gauge of where we are — a live snapshot of closed paper trades per bucket against the n = 100 gate:

long_call         n=29 closed  →  71 more to gate
bull_put_ladder   n=15 closed  →  85 more to gate
short_box_spread  n=15 closed  →  85 more to gate
long_call
29 / 100
71 closed trades to gate
bull_put_ladder
15 / 100
85 closed trades to gate
short_box_spread
15 / 100
85 closed trades to gate

The F7 page in the Labs² nav surfaces this live (cursor's per-lab Gate cards plus the labs2-gate-pill make it visible at a glance). Operator review is triggered when any bucket hits EDGE_CONFIRMED — not when all of them do, and not on any pooled summary. As of this writing every bucket is INSUFFICIENT_SAMPLE; the honest reading is that we have not yet measured enough to say anything, and the gate is doing exactly what it should by withholding judgment.

If, after n reaches 100 across every bucket, no bucket clears, the F7-options gate has still done its job: it will have told us — with the math to back it — that no element of the 52-strategy Periodic Table carries a calibrated edge on this harness, and that the correct move is to revise the harness, not to flip live anyway. The null is the truth-telling friend; this document sets the gate, it does not promise it will clear.