import { Fragment } from 'react' import type { ChainRow } from './math.ts' function fmt(n: number | null | undefined, digits = 2): string { if (n == null || !Number.isFinite(n)) return '-' return n.toFixed(digits) } function fmtInt(n: number | null | undefined): string { if (n == null || !Number.isFinite(n)) return '-' return Math.round(n).toLocaleString() } function fmtQuote(px: number | null | undefined, sz: number | null | undefined): string { if (px == null || !Number.isFinite(px)) return '-' if (sz != null && Number.isFinite(sz) && sz > 0) return `${px.toFixed(2)} x${Math.round(sz)}` return px.toFixed(2) } export function StraddleTable({ rows, spot, atmStrike, onPickContract, }: { rows: ChainRow[] spot: number | null atmStrike: number | null onPickContract?: (occ: string) => void }) { let maxOi = 1 for (const r of rows) { if ((r.callOi ?? 0) > maxOi) maxOi = r.callOi! if ((r.putOi ?? 0) > maxOi) maxOi = r.putOi! } let atmInserted = false const pick = (occ: string) => { if (onPickContract) onPickContract(occ) } return (
{rows.map((r, i) => { const next = rows[i + 1] const showDividerAfter = !atmInserted && spot != null && r.strike <= spot && (next == null || next.strike > spot) if (showDividerAfter) atmInserted = true const callOiPct = r.callOi ? Math.min(100, Math.round((r.callOi / maxOi) * 100)) : 0 const putOiPct = r.putOi ? Math.min(100, Math.round((r.putOi / maxOi) * 100)) : 0 const isAtm = atmStrike != null && r.strike === atmStrike const cClass = `oc-clickable ${r.callItm ? 'oc-itm' : ''}` const pClass = `oc-clickable ${r.putItm ? 'oc-itm' : ''}` return ( {showDividerAfter && ( )} ) })}
Calls Strike Puts
OI Vol IV% Delta Bid Ask Last K Last Bid Ask Delta IV% Vol OI
pick(r.callContract)} title={r.callContract}> {callOiPct > 0 && } {fmtInt(r.callOi)} pick(r.callContract)}>{fmtInt(r.callVol)} pick(r.callContract)}>{r.callIv != null ? `${fmt(r.callIv, 1)}%` : '-'} pick(r.callContract)}>{fmt(r.callDelta, 2)} pick(r.callContract)}>{fmtQuote(r.callBid, r.callBidSize)} pick(r.callContract)}>{fmtQuote(r.callAsk, r.callAskSize)} pick(r.callContract)}>{fmt(r.callLast)} {fmt(r.strike)} {isAtm ? ' *' : ''} pick(r.putContract)} title={r.putContract}>{fmt(r.putLast)} pick(r.putContract)}>{fmtQuote(r.putBid, r.putBidSize)} pick(r.putContract)}>{fmtQuote(r.putAsk, r.putAskSize)} pick(r.putContract)}>{fmt(r.putDelta, 2)} pick(r.putContract)}>{r.putIv != null ? `${fmt(r.putIv, 1)}%` : '-'} pick(r.putContract)}>{fmtInt(r.putVol)} pick(r.putContract)} title={r.putContract}> {putOiPct > 0 && } {fmtInt(r.putOi)}
CALLS ITM - UNDERLYING SPOT ${fmt(spot)} - PUTS ITM
) }