Fix options tape replay formatting

This commit is contained in:
dirtydishes 2026-01-11 10:47:11 -05:00
parent af328f1b32
commit 4a22fcc635

View file

@ -232,7 +232,13 @@ const buildApiUrl = (path: string): string => {
}; };
const formatPrice = (price: number): string => { const formatPrice = (price: number): string => {
return price.toFixed(2); if (!Number.isFinite(price)) {
return "0.00";
}
return price.toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2
});
}; };
const formatSize = (size: number): string => { const formatSize = (size: number): string => {
@ -257,6 +263,19 @@ const formatUsd = (value: number): string => {
}); });
}; };
const normalizeContractId = (value: string): string => value.trim();
const formatContractLabel = (value: string): string => {
const normalized = normalizeContractId(value);
if (!normalized) {
return "Unknown contract";
}
if (/^\d+$/.test(normalized)) {
return `Instrument ${normalized}`;
}
return normalized;
};
const formatDateTime = (ts: number): string => { const formatDateTime = (ts: number): string => {
const date = new Date(ts); const date = new Date(ts);
return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`; return `${date.toLocaleDateString()} ${date.toLocaleTimeString()}`;
@ -2032,13 +2051,14 @@ export default function HomePage() {
const nbboMap = useMemo(() => { const nbboMap = useMemo(() => {
const map = new Map<string, OptionNBBO>(); const map = new Map<string, OptionNBBO>();
for (const quote of nbbo.items) { for (const quote of nbbo.items) {
const existing = map.get(quote.option_contract_id); const contractId = normalizeContractId(quote.option_contract_id);
const existing = map.get(contractId);
if ( if (
!existing || !existing ||
quote.ts > existing.ts || quote.ts > existing.ts ||
(quote.ts === existing.ts && quote.seq >= existing.seq) (quote.ts === existing.ts && quote.seq >= existing.seq)
) { ) {
map.set(quote.option_contract_id, quote); map.set(contractId, quote);
} }
} }
return map; return map;
@ -2196,7 +2216,7 @@ export default function HomePage() {
return options.items; return options.items;
} }
return options.items.filter((print) => return options.items.filter((print) =>
matchesTicker(extractUnderlying(print.option_contract_id)) matchesTicker(extractUnderlying(normalizeContractId(print.option_contract_id)))
); );
}, [options.items, matchesTicker, tickerSet]); }, [options.items, matchesTicker, tickerSet]);
@ -2386,20 +2406,23 @@ export default function HomePage() {
</div> </div>
) : ( ) : (
filteredOptions.map((print) => { filteredOptions.map((print) => {
const quote = nbboMap.get(print.option_contract_id); const contractId = normalizeContractId(print.option_contract_id);
const quote = nbboMap.get(contractId);
const nbboAge = quote ? Math.abs(print.ts - quote.ts) : null; const nbboAge = quote ? Math.abs(print.ts - quote.ts) : null;
const nbboStale = nbboAge !== null && nbboAge > NBBO_MAX_AGE_MS_SAFE; const nbboStale = nbboAge !== null && nbboAge > NBBO_MAX_AGE_MS_SAFE;
const nbboMid = quote ? (quote.bid + quote.ask) / 2 : null; const nbboMid = quote ? (quote.bid + quote.ask) / 2 : null;
const nbboSide = classifyNbboSide(print.price, quote); const nbboSide = classifyNbboSide(print.price, quote);
const notional = print.price * print.size * 100;
return ( return (
<div className="row" key={`${print.trace_id}-${print.seq}`}> <div className="row" key={`${print.trace_id}-${print.seq}`}>
<div> <div>
<div className="contract">{print.option_contract_id}</div> <div className="contract">{formatContractLabel(contractId)}</div>
<div className="meta"> <div className="meta">
<span>${formatPrice(print.price)}</span> <span>${formatPrice(print.price)}</span>
<span>{formatSize(print.size)}x</span> <span>{formatSize(print.size)}x</span>
<span>{print.exchange}</span> <span>{print.exchange}</span>
<span>Notional ${formatUsd(notional)}</span>
{print.conditions?.length ? ( {print.conditions?.length ? (
<span>{print.conditions.join(", ")}</span> <span>{print.conditions.join(", ")}</span>
) : null} ) : null}