Spread Scoring Algorithm

How FrenzyCap ranks bull put, bear call, iron condor, and calendar spreads. Last updated: 2026-02-22. Back to Quote

This document describes an algorithmic scoring methodology for educational purposes. Scores do not constitute trading recommendations. See Terms §17.

Overview

Every spread candidate passes through a three-stage scoring pipeline. Each stage applies a multiplicative adjustment so the stages interact rather than simply adding points.

Stage 1
Base Score
GPU scanner
×
Stage 2
Skew
±25% cap
×
Stage 3
Technical
±50% cap
=
Final
Score
score = base_score × skew_multiplier × tech_multiplier

The base score is the primary signal — probability of profit times capital efficiency. Skew and technical layers are tiebreakers and regime-alignment filters, each capped so they cannot dominate the ranking.

Stage 1 — Base Score GPU Scanner

The GPU-accelerated scanner evaluates every valid spread combination across all expiries in the live options chain.

prob_profit = 1.0 − |short_leg_delta| prob_factor = prob_profit × (1.0 − 0.5 × max(prob_profit − 0.85, 0) / 0.15) credit_pct = credit / spread_width base_score = prob_factor × credit_pct
  • prob_profit — delta-based probability of the short leg expiring OTM. A 0.30-delta short put → 70% P(profit).
  • prob_factor — penalises very-high-probability spreads (> 85%) where credit is too thin. Sweet spot is 60–80%.
  • credit_pct — credit as % of spread width. Rewards capital efficiency: $0.50 on a $2-wide spread (25%) scores higher than $0.50 on a $10-wide spread (5%).

Iron condors

prob_profit = (1 − |put_delta|) × (1 − |call_delta|) credit_pct = total_credit / max(put_width, call_width)

Credit calculation

All strategies use mid-price credit (short_mid − long_mid) rather than bid[short] − ask[long]. For illiquid chains with wide bid/ask spreads, the bid-based calculation frequently returns zero or negative credit even when a fair-value trade exists at the mid.

Stage 2 — Skew Adjustment ±25% cap

Uses the nearest-expiry skew metrics derived from the live options chain (same data shown in the Skew Metrics table on the quote page).

Risk Reversal (RR25)
IV(25-delta call) − IV(25-delta put)

Measures which side the market is paying up for. Negative = put skew (fear / portfolio hedging). Most large-caps have mild negative RR as a structural baseline.

Butterfly (BF25)
½ × (IV(25d call) + IV(25d put)) − IV(ATM)

Measures wing curvature — how much the market pays for tail hedges above ATM vol. High BF = fat tails priced in (earnings, catalysts).

rr_factor = clamp(RR25 / 20.0, −1.0, +1.0) bf_factor = clamp(BF25 / 5.0, 0.0, +1.0) bull_put skew_mult = 1.0 + clamp(−rr_factor × 0.30, −0.25, +0.25) bear_call skew_mult = 1.0 + clamp( rr_factor × 0.20, −0.25, +0.25) iron_condor skew_mult = 1.0 + clamp( bf_factor × 0.20, −0.25, +0.25) calendar skew_mult = 1.0 (skew-neutral; trades term structure)
Why this matters: When the market pays a heavy premium for puts (negative RR), selling puts is more lucrative — the credit is richer and the edge is larger. Bull put spreads get a boost; bear calls get a penalty because calls are cheap. A high butterfly means both wings are bid up, making iron condors more attractive on both sides.
Stage 3 — Technical Overlay ±50% cap

Five signal groups computed from three data sources:

  • Technical indicators — 252 days of daily OHLCV → RSI, MACD, SMAs, Stochastic, Williams %R, ATR, Bollinger Bands
  • Options context — iv_rank, straddle_price (same source as IV Rank card on quote page)
  • Spread-level data — min open interest across all legs, carried from the scanner
tech_adj = G1 + G2 + G3(a+b+c) + G4 + G5 tech_multiplier = 1.0 + clamp(tech_adj, −0.50, +0.50)
Group 1
Directional Bias max ±0.25

Five signals contribute ±1 each, normalised by signals available:

SignalBullish (+1)Bearish (−1)
RSI (14)< 40 oversold> 60 overbought
MACD vs signalMACD above signalMACD below signal
MACD histogramPositive & growingNegative & falling
Price vs SMA 50Price > SMA 50Price < SMA 50
Price vs SMA 200Price > SMA 200Price < SMA 200
bias_factor = raw_bias / signals_available → [−1.0, +1.0] bull_put adj += bias_factor × 0.25 (bullish → boost, bearish → penalty) bear_call adj -= bias_factor × 0.25 (bearish → boost, bullish → penalty) iron_condor adj -= |bias_factor| × 0.15 (strong trend hurts IC; neutral helps) calendar adj = 0 (direction-agnostic)
The MACD histogram adds a fifth signal beyond the simple crossover — it measures whether momentum is accelerating or decelerating. A rising histogram means buying pressure is building; a falling one means it's fading. This fires continuously, while the crossover fires only once per regime change, so together they give both direction and strength.
Group 2
Momentum Confirmation max ±0.10

Shorter-period oscillators confirm or temper the Group 1 bias:

SignalBullish (+1)Bearish (−1)
Stochastic %K< 20 oversold> 80 overbought
Williams %R< −80 oversold> −20 overbought
momentum_factor = raw_momentum / 2.0 → [−1.0, +1.0] bull_put adj += momentum_factor × 0.10 bear_call adj -= momentum_factor × 0.10 iron_condor adj -= |momentum_factor| × 0.05 calendar adj = 0
When Groups 1 and 2 agree, the adjustments stack and amplify. When they disagree, they partially cancel — naturally moderating the total adjustment without any special override logic.
Group 3
Volatility Context max −0.25 to +0.15

3a — Blended Expected-Move Penalty

atr_move = ATR(14) × √(DTE / 252) straddle_move = straddle_price × √(DTE / 30) [if available from DB] expected_move = 0.60 × atr_move + 0.40 × straddle_move move_ratio = expected_move / breakeven_distance if move_ratio > 1.0: adj -= min(0.25, (move_ratio − 1.0) × 0.15)
ATR is backward-looking (what the stock has done). The straddle is forward-looking (what the options market expects). Blending both is more robust: ATR misses upcoming events; the straddle can be inflated by short-term catalysts. When the straddle is unavailable, ATR alone is used. The straddle is scaled to the spread's DTE via √(DTE/30) before blending.

3b — Bollinger Band Signal

if overbought (price > upper band): bear_call adj += 0.10 (mean-reversion alignment) bull_put adj -= 0.05 (counter-trend penalty) if oversold (price < lower band): bull_put adj += 0.10 (mean-reversion alignment) bear_call adj -= 0.05 (counter-trend penalty)
The counter-trend penalty prevents ranking a bull put highly when the stock is already breaking below the lower band — that's picking up pennies in front of a steamroller.

3c — Bollinger Band Width (Iron Condor regime)

bb_width_pct = (bb_upper − bb_lower) / bb_middle iron_condor adj += clamp((0.10 − bb_width_pct) × 1.0, −0.10, +0.10)
Narrow bands (< 10% of price) signal volatility contraction — favorable for ICs (price likely range-bound). Wide bands signal expansion — bad for ICs. This is distinct from 3b: 3b checks whether price is at the band; 3c checks how wide the band is.
Group 4
IV Regime max ±0.15

Source: iv_rank — same field shown on the IV Rank card on the quote page.

For bull_put and bear_call: iv_rank ≥ 75 → adj += 0.15 (rich premium — strong boost) iv_rank 50–74 → adj += 0.08 (elevated — moderate boost) iv_rank 25–49 → no adjustment iv_rank < 25 → adj -= 0.10 (cheap vol — penalty) For iron_condor: iv_rank ≥ 75 → adj += 0.10 iv_rank 50–74 → adj += 0.05 iv_rank 25–49 → no adjustment iv_rank < 25 → adj -= 0.07 Calendar: no adjustment
Skew vs IV rank: Skew (Stage 2) captures the shape of IV — which side is expensive relative to the other. IV rank captures the level — whether options overall are cheap or expensive versus the past year. Selling premium at the 80th percentile IV rank generates richer credits and has stronger mean-reversion odds. At low IV rank the premium barely covers the risk of being wrong. Calendars are excluded because they are long-vega and benefit from IV expansion.
Group 5
Liquidity Quality max penalty −0.10

Source: min_oi — minimum open interest across all legs, carried from the spread scanner.

if strategy ≠ calendar: min_oi < 100 → adj -= 0.10 (very thin — exit/assignment risk) min_oi < 500 → adj -= 0.05 (moderate liquidity concern) min_oi ≥ 500 → no penalty Iron condor: min_oi = min(put_short_OI, put_long_OI, call_short_OI, call_long_OI)
A spread that looks great on probability and credit can still be a poor trade if contracts have near-zero open interest: the bid/ask on exit will be punishing, and early assignment on the short leg becomes more likely. OI was previously used only as a filter (zero-OI contracts excluded); the actual values are now carried through to the final spread dict and used here.
Beta — informational only. Beta is surfaced in the API response but does not adjust scores. ATR (Group 3a) already captures the stock's realized volatility relative to its own history. Adding a beta multiplier would double-count the same risk signal. High beta is useful for position sizing: a beta of 2.0 means you should use wider strike widths or shorter DTE to maintain a target P(profit).
Final Score Assembly
score = base_score × skew_multiplier × tech_multiplier skew_multiplier = 1.0 + clamp(skew_adj, −0.25, +0.25) tech_multiplier = 1.0 + clamp(tech_adj, −0.50, +0.50) tech_adj = G1_bias + G2_momentum + G3a_expected_move + G3b_bb_signal + G3c_bb_width + G4_iv_regime + G5_liquidity

Both multipliers are stored on each spread in the API response for transparency and displayed as badges on the quote page.

API Response Fields (per spread)
FieldDescription
scoreFinal composite score after all adjustments
raw_scoreBase score before skew adjustment
skew_multiplierStage 2 multiplier (e.g. 1.20 = skew boosted by 20%)
tech_multiplierStage 3 multiplier (e.g. 0.85 = penalised by 15%)
prob_profitDelta-based probability of profit (not ATR-adjusted)
creditMid-price credit received
max_lossMaximum loss = spread width − credit
risk_rewardcredit / max_loss
min_oiMinimum open interest across all legs of the spread
technical_signals (top-level, per symbol): rsi, macd_crossover, macd_histogram, sma_50, sma_200 (Group 1) · stoch_k, williams_r (Group 2) · atr, bb_signal, bb_width_pct, straddle_price (Group 3) · iv_rank (Group 4)
Tuning Notes
  • All caps are intentionally conservative. The base score (delta × capital efficiency) should remain the primary signal; Stages 2 and 3 are tiebreakers.
  • ±50% tech cap: a spread with base score 0.30 can at most reach 0.45 or drop to 0.15 from technicals alone.
  • If IV rank boost proves too aggressive, reduce Group 4 coefficients (0.15 → 0.10, 0.08 → 0.05).
  • OI thresholds (100 / 500) suit liquid large-caps. For low-volume ETFs or small-caps, consider lowering or disabling Group 5.
  • IC directional bias penalty (|bias_factor| × 0.15) can be tuned independently — if the market is trending and ICs still perform, lower this.
  • BB width threshold (0.10 = 10%) is calibrated for large-cap stocks. High-beta names naturally have wider bands; consider raising to 0.15 for those.