SPX ATM Butterfly Calculator
:root {
–color-background-primary: #ffffff;
–color-background-secondary: #f6f4ee;
–color-background-tertiary: #efeee7;
–color-background-info: #e6f1fb;
–color-text-primary: #1a1a1a;
–color-text-secondary: #5f5e5a;
–color-text-tertiary: #888780;
–color-text-info: #0c447c;
–color-border-tertiary: rgba(0, 0, 0, 0.08);
–color-border-secondary: rgba(0, 0, 0, 0.15);
–border-radius-md: 8px;
–border-radius-lg: 12px;
–font-sans: -apple-system, BlinkMacSystemFont, “Inter”, “Segoe UI”, Roboto, sans-serif;
}
@media (prefers-color-scheme: dark) {
:root {
–color-background-primary: #1a1a1a;
–color-background-secondary: #242422;
–color-background-tertiary: #1f1f1d;
–color-background-info: #0c2742;
–color-text-primary: #f0f0ec;
–color-text-secondary: #b4b2a9;
–color-text-tertiary: #888780;
–color-text-info: #85b7eb;
–color-border-tertiary: rgba(255, 255, 255, 0.1);
–color-border-secondary: rgba(255, 255, 255, 0.18);
}
body { background: #161614; }
}
* { box-sizing: border-box; }
body {
margin: 0;
padding: 2rem 1rem 4rem;
font-family: var(–font-sans);
background: var(–color-background-tertiary);
color: var(–color-text-primary);
line-height: 1.5;
font-size: 16px;
}
main {
max-width: 680px;
margin: 0 auto;
}
h1 {
font-size: 22px;
font-weight: 500;
margin: 0 0 0.5rem;
}
.subtitle {
font-size: 14px;
color: var(–color-text-secondary);
margin: 0 0 1.5rem;
}
input[type=”range”] {
-webkit-appearance: none;
appearance: none;
background: transparent;
height: 18px;
margin: 0;
}
input[type=”range”]::-webkit-slider-runnable-track {
height: 4px;
background: var(–color-border-secondary);
border-radius: 2px;
}
input[type=”range”]::-moz-range-track {
height: 4px;
background: var(–color-border-secondary);
border-radius: 2px;
}
input[type=”range”]::-webkit-slider-thumb {
-webkit-appearance: none;
appearance: none;
width: 18px;
height: 18px;
border-radius: 50%;
background: var(–color-text-primary);
margin-top: -7px;
cursor: pointer;
}
input[type=”range”]::-moz-range-thumb {
width: 18px;
height: 18px;
border-radius: 50%;
background: var(–color-text-primary);
border: none;
cursor: pointer;
}
.sr-only {
position: absolute;
width: 1px; height: 1px; padding: 0; margin: -1px;
overflow: hidden; clip: rect(0,0,0,0); white-space: nowrap; border: 0;
}
SPX ATM butterfly calculator
Estimates the price of an at-the-money call butterfly given the ATM straddle premium and wing width.
SPX ATM butterfly pricing model. Estimates butterfly cost from straddle premium and wing width.
$20
15W (30 total)
$1.85
Width = 15W
| Width | $5 | $10 | $15 | $20 | $25 | $30 | $35 | $40 |
|---|
https://cdnjs.cloudflare.com/ajax/libs/Chart.js/4.4.1/chart.umd.js
(function(){
const $ = id => document.getElementById(id);
const SQRT_PI_2 = Math.sqrt(Math.PI / 2);
const REF_S = 6500;
function Phi(x){
const a1=0.254829592,a2=-0.284496736,a3=1.421413741,a4=-1.453152027,a5=1.061405429,p=0.3275911;
const sign = x < 0 ? -1 : 1;
x = Math.abs(x)/Math.sqrt(2);
const t = 1/(1+p*x);
const y = 1 – (((((a5*t+a4)*t)+a3)*t+a2)*t+a1)*t*Math.exp(-x*x);
return 0.5*(1+sign*y);
}
function bsCall(S, K, sst){
if (sst <= 0) return Math.max(S-K, 0);
const d1 = (Math.log(S/K) + 0.5*sst*sst) / sst;
const d2 = d1 – sst;
return S*Phi(d1) – K*Phi(d2);
}
function flyFromStraddle(straddle, W){
const sst = (straddle / REF_S) * SQRT_PI_2;
return bsCall(REF_S, REF_S-W, sst) – 2*bsCall(REF_S, REF_S, sst) + bsCall(REF_S, REF_S+W, sst);
}
function update(){
const straddle = +$('straddle').value;
const W = +$('width').value;
$('straddle-out').textContent = '$' + straddle;
$('width-out').textContent = W + 'W (' + (W*2) + ' total)';
const fly = flyFromStraddle(straddle, W);
$('fly-price').textContent = '$' + fly.toFixed(2);
$('curve-label').textContent = 'Width = ' + W + 'W';
const points = [];
for (let s = 5; s {
const isCurrent = w === W;
const trStyle = isCurrent ? ‘background: var(–color-background-info);’ : ”;
const cellWeight = isCurrent ? ‘font-weight: 500;’ : ”;
let html = ‘
html += ‘
‘;
refStraddles.forEach(s => {
const f = flyFromStraddle(s, w);
const highlight = (isCurrent && s === straddle) ? ‘font-weight: 500; color: var(–color-text-info);’ : (isCurrent ? cellWeight : ‘color: var(–color-text-secondary);’);
html += ‘
‘;
});
html += ‘
‘;
return html;
}).join(”);
$(‘table-body’).innerHTML = rows;
}
const ctx = $(‘curve’).getContext(‘2d’);
const chart = new Chart(ctx, {
type: ‘scatter’,
data: {
datasets: [
{
label: ‘Straddle vs fly’,
data: [],
borderColor: ‘#534AB7’,
backgroundColor: ‘rgba(83, 74, 183, 0.08)’,
borderWidth: 2,
tension: 0.25,
pointRadius: 0,
showLine: true,
fill: false,
},
{
label: ‘Current’,
data: [],
borderColor: ‘#D85A30’,
backgroundColor: ‘#D85A30’,
pointRadius: 7,
pointHoverRadius: 8,
showLine: false,
}
]
},
options: {
responsive: true,
maintainAspectRatio: false,
plugins: {
legend: { display: false },
tooltip: {
callbacks: {
title: () => ”,
label: (item) => ‘Fly: $’ + Number(item.parsed.x).toFixed(2) + ‘ · Straddle: $’ + Number(item.parsed.y).toFixed(0),
}
}
},
scales: {
x: {
title: { display: true, text: ‘Expected fly price ($)’, color: ‘#888780’, font: { size: 12 } },
ticks: { color: ‘#888780’, callback: v => ‘$’ + Number(v).toFixed(2) },
grid: { color: ‘rgba(136,135,128,0.12)’ },
beginAtZero: true,
type: ‘linear’
},
y: {
title: { display: true, text: ‘Straddle price ($)’, color: ‘#888780’, font: { size: 12 } },
ticks: { color: ‘#888780’, callback: v => ‘$’ + v },
grid: { color: ‘rgba(136,135,128,0.12)’ },
min: 0,
max: 50
}
}
}
});
[‘straddle’,’width’].forEach(id => $(id).addEventListener(‘input’, update));
update();
})();
