Sharpen P/L extrema & curve at strike kinks

Evaluate the expiration P/L at the exact strike prices (and sample bounds),
not just on the coarse grid — so max profit / max loss are exact for
piecewise payoffs (butterfly peak now $800 not ~$679) and the chart renders
sharp vertices for butterflies, condors, etc.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
ojy
2026-05-13 04:12:16 +00:00
parent 2ebc0eeb20
commit 57473ec271

View File

@@ -352,9 +352,14 @@
}
}
const uniqBE = bes.filter((v,i)=> i===0 || Math.abs(v - bes[i-1]) > 1e-6);
// extremes within sample
// extremes — include the grid samples AND the exact kink points (strikes)
// plus the sample bounds, since piecewise payoffs peak/trough at strikes
let maxY = -Infinity, minY = Infinity;
for (const y of ys) { if (y > maxY) maxY = y; if (y < minY) minY = y; }
for (const k of new Set([...legs.map(l=>l.strike), lo0, hi0])) {
const y = plAt(legs, net, k, this.minDTE);
if (y > maxY) maxY = y; if (y < minY) minY = y;
}
// unbounded detection from the far-right slope of the expiration curve
// (downside is always bounded since the underlying can't go below 0)
const slopeR = (ys[Nd] - ys[Nd-1]) / (xs[Nd] - xs[Nd-1]);
@@ -447,10 +452,15 @@
const lo = Math.max(0.01, spot - half), hi = spot + half;
const expAt = this.minDTE;
const N = 161;
// x-grid = evenly spaced points + the exact strike kinks (so payoff
// vertices — butterfly peak, condor body, etc. — render sharply)
const xGrid = [];
for (let i = 0; i <= N; i++) xGrid.push(lo + (hi-lo)*i/N);
for (const k of strikes) if (k > lo && k < hi) xGrid.push(k);
xGrid.sort((a,b)=>a-b);
const expData = [], tnData = [];
let yMin = Infinity, yMax = -Infinity;
for (let i = 0; i <= N; i++) {
const x = lo + (hi-lo)*i/N;
for (const x of xGrid) {
const ye = plAt(legs, net, x, expAt);
const yt = plAt(legs, net, x, this.dteOffset);
expData.push([x, +ye.toFixed(2)]);
@@ -467,7 +477,7 @@
// breakevens for light vertical lines
const bes = [];
for (let i = 1; i <= N; i++) {
for (let i = 1; i < expData.length; i++) {
const y0 = expData[i-1][1], y1 = expData[i][1];
if ((y0 < 0 && y1 > 0) || (y0 > 0 && y1 < 0)) {
const x = expData[i-1][0] + (0 - y0) * (expData[i][0]-expData[i-1][0]) / (y1 - y0);