1. What the strategy is
A calendar spread is an options structure where you sell one expiration and buy a later expiration at the same strike. You collect time decay on the short front leg while the long back leg holds its value, profiting if the underlying stays near the strike and implied volatility holds or rises into the back expiration.
The Forward-Factor variant of this trade adds a discipline: only enter when the front-month implied volatility is meaningfully richer than the forward implied volatility implied by the term structure between the two expirations. The Forward Factor (FF) is the precise number that measures how much richer.
The intuition: if the front month is pricing a lot of volatility but the longer-dated IV thinks the average volatility between today and the back expiration will be lower, you're being paid extra premium on the short front leg relative to the back-leg cost. That premium has to come from somewhere — market expectations of a near-term event (earnings, FOMC, geopolitical), term-structure dislocation, or simply a temporary supply/demand imbalance on near-dated contracts.
2. The math behind it
Implied variance is approximately additive across non-overlapping time intervals. That gives us a way to back out the implied volatility for the period between the front and back expirations:
Solving for the forward variance gives the forward IV:
Where T1 is the front DTE in years and T2 is the back DTE in years.
The Forward Factor itself is just the relative premium of front IV over forward IV:
A default FF threshold of 0.16 means we only enter when the front-month IV is at least 16% above the forward IV. Higher thresholds = fewer signals, more conviction per signal. Lower thresholds = more signals, more noise.
All implied volatilities are solved from option mid prices using the Black-Scholes-Merton formula with a configurable risk-free rate (default 4.5% annualized) and zero dividend yield. The solver uses Newton-Raphson with a Brent bisection fallback for pathological cases. Greeks are computed in closed form from the same BSM model.
3. When it works (and when it fails)
The Forward-Factor calendar is designed for specific market conditions. It is not a universal income trade.
Favorable conditions
- Front-month IV elevated by a known event (earnings, FOMC, product launch) where the back month doesn't fully share the elevation.
- Stable underlying realized vol — the back leg holds value if spot stays near strike.
- Sufficient liquidity — tight bid-ask spreads on both legs so the modeled debit isn't eaten by slippage.
- No upcoming dividend on the strike within the trade window (assignment risk on short calls; pin risk on puts).
Adverse conditions
- Large directional move away from the strike before front expiration — both legs lose value, position approaches max loss.
- Vol crush across the whole curve — if back IV collapses faster than front (which sometimes happens after an event), the structure can lose value even with no spot move.
- Wide spreads — backtest may show edge but real fills give it all back.
- Pinning at strike on front expiration — assignment risk on the short leg requires closing or rolling pre-expiration.
4. Using the live signal page
The live signal page is at /strategies/forward-factor/. It has three regions:
- Strategy config — left panel, all your input parameters.
- Result panel — right panel, the score card, indicator grid, trade ticket, and alerts.
- Open positions — right panel below results, your paper portfolio.
Walkthrough — running your first signal
5. Reading the signal output
The result panel always shows three blocks: the score card, the indicator grid, and either the trade ticket or an explanation of why no ticket fired.
Score card
The big number is the FF value to three decimal places. The status label below it tells you what the system thinks:
| Status | Color | Meaning |
|---|---|---|
| ENTER ✓ | Green | FF cleared the threshold and all liquidity caps passed. Trade ticket shown. |
| HOLD | Yellow | FF positive but below your threshold. Wait or lower the threshold. |
| FILTERED | Red | Liquidity caps failed — OI, volume, or spread too low to trade safely. |
| NO EXPIRATION MATCH | Gray | No expirations exist in both your front and back DTE windows. Widen tolerances or pick a more active underlying. |
| NO STRIKE MATCH | Gray | No common strike present in both expirations within ±5% of spot. Rare; try a higher-priced underlying. |
| IV UNAVAILABLE | Gray | Polygon could not return live IV and our solver failed. Often after-hours or thin chain. |
Indicator grid
The indicator grid below the score shows the inputs to the calculation so you can sanity-check what the engine used:
- Underlying / Spot: the ticker and its live (15-min delayed) reference price.
- Front IV / Forward IV / Back IV: the three implied vols feeding the FF calculation, in decimal form (0.250 = 25%).
- FF threshold: your configured cutoff, so the score card is interpretable at a glance.
Trade ticket
When status is ENTER, the trade ticket fires with:
- SELL 1 at the front expiration and strike (the short leg you collect premium on).
- BUY 1 at the back expiration and same strike (the long leg you pay premium for).
- Net debit: the modeled cost to open one structure.
- Max loss: equal to the net debit. You cannot lose more if you close both legs before front expiration.
- Greeks: Δ (delta), Γ (gamma), Θ (theta), Ν (vega) of the combined position. Calendars are typically near-zero delta, slightly negative gamma, slightly positive theta, and strongly positive vega.
Alerts
The yellow alerts box surfaces conditions that didn't block the signal but you should know about — for example: front leg has earnings within the trade window, back leg has an ex-dividend date inside the holding period, or the spread on one leg is above 5% of mid.
6. Opening a paper trade
If the signal fires with a positive net debit, the trade ticket includes an Open as paper trade button. Clicking it saves the position to your browser's localStorage under the key oit.ff.positions.
What gets saved per position:
- A randomly-generated ID, the ticker, option type, strike, contract count (default 1).
- Front and back expirations, the opening debit, and the FF at the time of entry.
- The IVs (front, forward, back) and spot at entry — useful for forensic review later.
- The opening greeks and any alerts that fired.
- An ISO timestamp of when you opened it, and status = "open".
7. Monitoring open positions
Below the result panel, the Open positions section shows every paper trade you've opened. Each row displays:
- Ticker, strike, option type, status badge (OPEN / closed / expired / rolled / assigned).
- Current P&L in dollars and as a percent of the opening debit — only after you click Monitor.
- Front and back expirations, opening debit, and (post-monitor) current spot and front DTE.
- Triggers that fired on the most recent monitor call (see below).
Clicking Monitor
The Monitor button calls the Worker's /api/ff/monitor endpoint with the position's ticker, strike, expirations, and opening debit. The Worker:
- Fetches live spot.
- Fetches live snapshots for both legs.
- Computes the current bid-ask mids (with a quarter-spread penalty applied to model realistic close fills).
- Computes current MTM (mark-to-market):
(back_mid - front_mid) - opening_debit. - Computes current greeks, current IVs, current front DTE.
- Evaluates exit triggers and returns a recommendation.
Recommendations
| Recommendation | Color | When it fires |
|---|---|---|
| hold | None | Position is within normal bounds. No action needed yet. |
| ROLL NOW | Yellow | Front DTE ≤ 5 days. Time decay on the short leg is accelerating; either close or roll the front leg out. |
| CLOSE NOW | Red | Profit target hit (default 30% of debit), stop loss hit (default 40% of debit), or short leg is ITM by ≥ 1% of strike (assignment risk). |
Triggers
The triggers array in the monitor response can include:
profit_target_hit— MTM ≥ profit target.stop_loss_hit— MTM ≤ stop loss.front_dte_threshold_hit— front DTE ≤ 5 (default).short_itm_force_close— short leg is in-the-money by more than 1% of strike.
8. Closing positions and triggers
Each open position row has two action buttons:
Close
Clicking Close prompts for the realized P&L in dollars. If you've just clicked Monitor, the prompt pre-fills with the current MTM, but you can override it with the actual fill price from your broker (or a paper-fill estimate accounting for spread). It then asks for the outcome: closed (manually closed), expired (let both legs expire), assigned (short leg was assigned and you took stock or paid out), or rolled (you closed both and reopened a new structure).
The position's status changes from "open" to your chosen outcome. The realized P&L is added to the portfolio's lifetime total at the top of the panel. Closed positions stay in the panel for reference until you delete them.
Delete
Closed positions show a Delete button instead of Monitor + Close. Clicking it confirms and removes the position from localStorage permanently. Use this to clean up after a few months; there's no automatic prune.
9. Using the backtest page
The backtest page is at /strategies/forward-factor/backtest/. It runs a rapid 12-week historical study (configurable 4-26 weeks) and shows you how the same FF rules would have performed on weekly Monday entries.
How it works under the hood
For each Monday in the lookback window, the Worker:
- Fetches the underlying's daily close on that Monday.
- Queries Polygon for option contracts that were listed as of that Monday, filtered to the front/back DTE windows and to strikes within ±5% of spot.
- Prefers 3rd-Friday monthly expirations; picks the front and back closest to your DTE targets.
- Finds a common ATM strike present in both expirations.
- Pulls each leg's daily close on that Monday (used as the entry mid).
- Solves IVs, computes forward IV and FF.
- If FF clears the threshold and net debit is positive, records the entry.
- Pulls daily closes at exit (+5 business days, or 1 day before front expiration, whichever sooner).
- Computes realized P&L = (back_close_exit − front_close_exit) − net_debit_at_entry.
Backtest results are cached in KV for 24 hours per unique config, so re-running the same parameters is instant after the first call.
Walkthrough — running your first backtest
10. Interpreting backtest results
The results panel shows three sections in addition to the stats grid:
Stats grid
- Trades / Skipped weeks: how many Mondays produced a signal vs. how many didn't.
- Hit rate: wins divided by total trades. A meaningful number requires ≥ 30 trades; 12 weeks is too few to draw conclusions, treat it as directional evidence only.
- Total / Avg P&L: dollar P&L per 1-contract structure.
- Avg % of debit: realized P&L as a fraction of capital risked. More useful than dollar P&L for comparing across tickers with different strike prices.
- Max win / Max loss: the best and worst single-trade outcomes. Watch for asymmetry — positive avg P&L driven by one outlier is fragile.
- Avg debit: typical capital required per trade.
Equity curve
The SVG line shows cumulative P&L per trade in chronological order. Green dots mark wins, red dots mark losses. A clean upward slope with mostly green dots suggests the rule held in this regime; chop or a single big jump tells you the result is noise.
Trade log
The trade table shows every closed trade with entry/exit dates, the strike picked, both expirations, the FF at entry, the net debit, and the resulting P&L. Look for: clustering of wins/losses around macro events, FF range that produced winners, and whether back-month length correlates with outcome.
Skipped weeks
The expandable details section lists every week that did not fire a trade, grouped by reason: no_trade_ff_low means FF was positive but below threshold, no_contracts means Polygon had no listings in your DTE windows, no_expiration_pair means we couldn't find both a front and back match, etc. High skip rates suggest your DTE windows or threshold are misconfigured for this ticker.
- No spread, slippage, or commissions modeled. Real fills will be worse than closes-as-mids by 5-20% of the structure value.
- Survivorship bias possible. Polygon's contracts list returns contracts that existed; delisted weeks are silently dropped from skipped_weeks.
- One ticker, one window, <30 trades = not statistical evidence. Use this to invalidate bad ideas, not to validate good ones.
- Past performance is not predictive. Rules that worked in calm regimes can fail in vol shocks.
11. Risk disclosures
Strategy-specific risks
- Vega risk: Long calendars are net long vega. A sharp drop in implied vol across the term structure will cost you on both legs, with the back leg losing more in absolute dollar terms because it has higher vega.
- Pin risk: If spot closes very near the strike at front expiration, the short leg can settle with uncertain assignment. Standard practice is to close the front leg the day before expiration.
- Assignment risk on short calls: If a dividend is paid before front expiration and the short call is ITM by less than the dividend amount, early assignment is likely.
- Gap risk: Earnings, FOMC, or news-driven gaps can move spot far from strike before you can react. Both legs lose value; position approaches max loss.
- Liquidity risk: The modeled mid may not be available as a tradeable fill, especially during volatile sessions. Use limit orders only.
Tool-specific risks
- 15-minute delayed data: All live signals reflect Polygon's free-tier 15-minute delay during US market hours. Intraday opportunities visible in the tool may be gone by the time you act.
- Not a recommendation: Signals are educational outputs of a mathematical model, not advice. The model can be wrong; the data can be stale; your risk tolerance may not match the structure's risk profile.
- localStorage only: Paper positions are not backed up. A browser cache clear, device change, or accidental refresh of a different machine will lose them.
- Past calibration: The 16% default threshold was calibrated against a specific historical window. It may not be appropriate for current regime; revisit it periodically.
Regulatory and legal
- OptionIncomeTools does not place trades, hold accounts, or provide brokerage services.
- Nothing on this page constitutes financial, tax, or legal advice.
- Options trading carries significant risk and is not suitable for all investors. Consult a licensed financial advisor and your tax professional before trading.
- Naked options are not permitted in retirement accounts (IRAs); calendar spreads are debit structures and generally allowed but verify with your broker.
12. Frequently asked questions
Why does the signal sometimes return "no_expiration_match" for liquid tickers like SPY?
The Polygon contracts list filter is bounded by your DTE windows AND a ±5% strike band around spot. If your windows are tight (e.g., front 30/3 and back 90/3) the intersection may be empty on a given day. Try widening tolerance to 7 days for front and 14 days for back, which is the default.
Why is the trade ticket showing $0 debit and "Cannot open: non-positive debit"?
One or both legs have missing or stale quotes. This is common outside US market hours when Polygon's snapshot endpoint returns last-traded values from days ago. Re-run during regular market hours (9:30 AM - 4:00 PM ET).
What's the difference between FF and just "vol skew"?
Vol skew is the strike-to-strike IV difference at a single expiration. FF is the expiration-to-expiration IV difference at the same strike (specifically, front IV relative to the forward IV implied by the term structure). They're orthogonal measurements; a stock can have rich skew and zero FF, or vice versa.
Can I customize the profit target and stop loss for the monitor?
Yes, via the API directly — POST /api/ff/monitor accepts profit_target_pct_of_debit (default 0.30 = 30%) and stop_loss_pct_of_debit (default 0.40 = 40%). The UI does not yet expose these; the defaults are appropriate for most users.
How is forward IV different from forward rate?
Forward rate (or forward price) is what the market thinks the underlying will be worth at a future date, derived from interest rates and dividend yield. Forward IV is what the market thinks the average volatility will be between two future dates, derived from option prices at those dates. They're different financial quantities solving different problems.
Why does the backtest sometimes show a "skipped week" reason of "no_entry_prices"?
The Polygon daily-bar endpoint occasionally returns nothing for thinly-traded option contracts on specific dates. We skip those weeks rather than guess prices — the alternative would be inserting fabricated fills into the result, which would be worse than reporting fewer trades.
Can I run the backtest on past dates further back than 26 weeks?
Not in Phase 3a (the current in-Worker rapid backtest). The 26-week cap is set to keep Polygon API calls bounded and to fit within the Worker's CPU/wallclock budget per request. Phase 3b (deferred, multi-year backtest on Cloud Run with R2 storage) will lift this when shipped.
What if I disagree with the system's recommendation to close?
The recommendation is advisory. The triggers are objective rules; the close decision is yours. If you're holding through earnings deliberately, override the front_dte_threshold_hit trigger; if you have conviction the underlying will revert, override profit/loss targets. Just write down your reasoning — ad-hoc overrides without a thesis are how strategies decay.
Is the strategy patentable or proprietary?
No. Forward variance pricing and term-structure trades are well-known in options literature (Carr, Madan, Demeterfi, and others). This tool's contribution is packaging the math into a free, transparent, end-to-end workflow with paper trading and rapid backtest — not the underlying strategy itself.
Does Open as paper trade reserve any capital?
No. There is no balance, no account, no margin check. Paper trades are purely informational records. If you want to simulate an account-level paper portfolio with capital limits, use the dedicated paper trading page.
13. Glossary
- Calendar spread (horizontal spread)
- An options structure that sells one expiration and buys a later expiration at the same strike. Net debit. Long vega, near-zero delta when ATM, positive theta on the short leg net of negative theta on the back leg.
- Implied volatility (IV)
- The volatility input to the Black-Scholes-Merton formula that, when plugged in along with strike, spot, time, and rate, returns the option's market price. Quoted as an annualized decimal (0.25 = 25%).
- Forward implied volatility
- The implied volatility for the period between two future expirations, backed out from the two expirations' IVs using variance additivity. The fair forward IV is the market's expectation of the average vol over that interval.
- Forward Factor (FF)
- Defined as
(front_iv - forward_iv) / forward_iv. Measures how much richer the front-month IV is than the forward IV. Positive FF indicates a sell-the-front, buy-the-back opportunity. - DTE (days to expiration)
- Calendar days from the current date until an option's expiration date.
- 3rd-Friday monthly
- The standard US equity option expiration cycle is the third Friday of each month. These contracts typically have the deepest liquidity. Weekly and quarterly expirations exist but tend to have wider spreads.
- Net debit
- The net cost to enter a multi-leg structure, calculated as premiums paid minus premiums received. For a long calendar, net debit equals back-leg ask minus front-leg bid (or modeled mids if using a calculator).
- Max loss
- The maximum dollar amount that can be lost on a position. For a long calendar held to front expiration and closed cleanly, max loss equals the net debit paid plus any commissions.
- Delta, Gamma, Theta, Vega
- The four primary option greeks. Delta = sensitivity to spot move; Gamma = how delta changes with spot; Theta = time decay per day; Vega = sensitivity to a 1-percentage-point IV change.
- Variance additivity
- The property that implied variance (vol squared times time) is approximately additive across non-overlapping time intervals in the Black-Scholes lognormal model. This is what lets us back out forward IV from front and back IV.
- BSM (Black-Scholes-Merton)
- The closed-form option pricing formula assuming lognormal price evolution, continuous trading, and no arbitrage. Despite well-known limitations (constant vol assumption, no jumps, etc.), it remains the industry-standard pricing baseline.
- Newton-Raphson / Brent bisection
- Two numerical methods used together to solve for implied volatility from a market option price. Newton-Raphson is fast when it converges; Brent bisection is the slower but reliable fallback for pathological cases.
- Polygon
- The third-party market data provider used by OptionIncomeTools for option chains, snapshots, and historical aggregates. We use Polygon's 15-minute-delayed free tier for live signals and the historical aggregates endpoint for the backtest.
- localStorage
- A browser-native key-value store that persists across page reloads and tab closures, but is scoped to a single origin and is wiped if the user clears site data. Used here to store paper positions client-side without any server roundtrip.
- KV (Cloudflare Workers KV)
- The eventually-consistent key-value cache on Cloudflare's edge used by our Worker to memoize Polygon responses and backtest results. Reads from KV are sub-millisecond; writes propagate globally within ~30 seconds.
Ready to try it?
Run a live signal on SPY first — it's the most liquid ticker and the most stable test case. Then try a single-stock name with upcoming earnings for a stronger FF reading.
Run live signal › See 12-week backtest ›