Options Payoff Curve Skill
Generates a fully interactive HTML widget (via visualize:show_widget) showing:
- Expiry payoff curve (dashed gray line) β intrinsic value at expiration
- Theoretical value curve (solid colored line) β Black-Scholes price at current DTE/IV
- Dynamic sliders for all key parameters
- Real-time stats: max profit, max loss, breakevens, current P&L at spot
Step 1: Extract Strategy From User Input
When the user provides a screenshot or text, extract:
| Field |
Where to find it |
Default if missing |
| Strategy type |
Title bar / leg description |
"custom" |
| Underlying |
Ticker symbol |
SPX |
| Strike(s) |
K1, K2, K3... in title or leg table |
nearest round number |
| Premium paid/received |
Filled price or avg price |
5.00 |
| Quantity |
Position size |
1 |
| Multiplier |
100 for equity options, 100 for SPX |
100 |
| Expiry |
Date in title |
30 DTE |
| Spot price |
Current underlying price (NOT strike) |
middle strike |
| IV |
Shown in greeks panel, or estimate from vega |
20% |
| Risk-free rate |
β |
4.3% |
Critical for screenshots: The spot price is the CURRENT price of the underlying index/stock, NOT the strikes. Never default spot to a strike price value.
Current SPX reference price:
!`python3 -c "import yfinance as yf; print(f'SPX β {yf.Ticker(\"^GSPC\").fast_info[\"lastPrice\"]:.0f}')" 2>/dev/null || echo "SPX price unavailable β check market data"`
Step 2: Identify Strategy Type
Match to one of the supported strategies below, then read the corresponding section in references/strategies.md.
| Strategy |
Legs |
Key Identifiers |
| butterfly |
Buy K1, Sell 2ΓK2, Buy K3 |
3 strikes, "Butterfly" in title |
| vertical_spread |
Buy K1, Sell K2 (same expiry) |
2 strikes, debit or credit |
| calendar_spread |
Buy far-expiry K, Sell near-expiry K |
Same strike, 2 expiries |
| iron_condor |
Sell K2/K3, Buy K1/K4 wings |
4 strikes, 2 spreads |
| straddle |
Buy Call K + Buy Put K |
Same strike, both types |
| strangle |
Buy OTM Call + Buy OTM Put |
2 strikes, both OTM |
| covered_call |
Long 100 shares + Sell Call K |
Stock + short call |
| naked_put |
Sell Put K |
Single leg |
| ratio_spread |
Buy 1ΓK1, Sell NΓK2 |
Unequal quantities |
For strategies not listed, use custom mode: decompose into individual legs and sum their P&Ls.
Step 3: Compute Payoffs
Black-Scholes Put Price
d1 = (ln(S/K) + (r + ΟΒ²/2)Β·T) / (ΟΒ·βT)
d2 = d1 - ΟΒ·βT
put = KΒ·e^(-rT)Β·N(-d2) - SΒ·N(-d1)
Black-Scholes Call Price (via put-call parity)
call = put + S - KΒ·e^(-rT)
Butterfly Put Payoff (expiry)
if S >= K3: 0
if S >= K2: K3 - S
if S >= K1: S - K1
else: 0
Net P&L per share = payoff β premium_paid
Vertical Spread (call debit) Payoff (expiry)
long_call = max(S - K1, 0)
short_call = max(S - K2, 0)
payoff = long_call - short_call - net_debit
Calendar Spread Theoretical Value
Calendar cannot be expressed as a simple expiry function β always use BS pricing for both legs:
value = BS(S, K, T_far, r, IV_far) - BS(S, K, T_near, r, IV_near)
For expiry curve of calendar: near leg expires worthless, far leg = BS with remaining T.
Iron Condor Payoff (expiry)
put_spread = max(K2-S, 0) - max(K1-S, 0) // short put spread
call_spread = max(S-K3, 0) - max(S-K4, 0) // short call spread
payoff = credit_received - put_spread - call_spread
Step 4: Render the Widget
Use visualize:read_me with modules ["chart", "interactive"] before building.
Required Controls (sliders)
Structure section:
- All strike prices (K1, K2, K3... as needed by strategy)
- Premium paid/received
- Quantity
- Multiplier (100 default, show for clarity)
Pricing variables section:
- IV % (5β80%, step 0.5)
- DTE β days to expiry (0β90)
- Risk-free rate % (0β8%)
Spot price:
- Full-width slider, range = [min_strike - 20%, max_strike + 20%], defaulting to ACTUAL current spot
Required Stats Cards (live-updating)
- Max profit (expiry)
- Max loss (expiry)
- Breakeven(s) β show both for two-sided strategies
- Current theoretical P&L at spot
Chart Specs
- X-axis: SPX/underlying price
- Y-axis: Total USD P&L (not per-share)
- Blue solid line = theoretical value at current DTE/IV
- Gray dashed line = expiry payoff
- Green dashed vertical = strike prices (K2 center strike brighter)
- Amber dashed vertical = current spot price
- Fill above zero = green 10% opacity; below zero = red 10% opacity
- Tooltip: show both curves on hover
Code template
Use this JS structure inside the widget, adapting pnlExpiry() and bfTheory() per strategy:
function normCDF(x) { }
function bsCall(S,K,T,r,sig) { }
function bsPut(S,K,T,r,sig) { }
function expiryValue(S, ...strikes) { ... }
function theoreticalValue(S, ...strikes, T, r, iv) { ... }
function update() { ... }
['k1','k2',...,'iv','dte','rate','spot'].forEach(id => {
document.getElementById(id).addEventListener('input', update);
});
update();
Step 5: Respond to User
After rendering the widget, briefly explain:
- What strategy was detected and how legs were mapped
- Max profit / max loss at current settings
- One key insight (e.g., "spot is currently 950 pts below the profit zone, expiring tomorrow")
Keep it concise β the chart speaks for itself.
Reference Files
references/strategies.md β Detailed payoff formulas and edge cases for each strategy type
references/bs_code.md β Copy-paste ready Black-Scholes JS implementation with normCDF
Read the relevant reference file if you're unsure about payoff formula edge cases for a given strategy.