Hydrate options feed across live routes
This commit is contained in:
parent
cfc3836815
commit
b4f87b50d2
2 changed files with 70 additions and 8 deletions
|
|
@ -10,6 +10,7 @@ import {
|
||||||
getAlertWindowAnchorTs,
|
getAlertWindowAnchorTs,
|
||||||
getOptionTableSnapshot,
|
getOptionTableSnapshot,
|
||||||
getLiveFeedStatus,
|
getLiveFeedStatus,
|
||||||
|
getLiveManifest,
|
||||||
normalizeAlertSeverity,
|
normalizeAlertSeverity,
|
||||||
nextFlowFilterPopoverState,
|
nextFlowFilterPopoverState,
|
||||||
projectPausableTapeState,
|
projectPausableTapeState,
|
||||||
|
|
@ -38,6 +39,42 @@ const makeAlert = (overrides: Record<string, unknown> = {}) =>
|
||||||
...overrides
|
...overrides
|
||||||
}) as any;
|
}) as any;
|
||||||
|
|
||||||
|
describe("live manifest", () => {
|
||||||
|
it("includes options on every live route", () => {
|
||||||
|
const filters = buildDefaultFlowFilters();
|
||||||
|
for (const pathname of ["/", "/tape", "/signals", "/charts", "/replay"]) {
|
||||||
|
expect(
|
||||||
|
getLiveManifest(pathname, "SPY", 60000, filters).some(
|
||||||
|
(subscription) => subscription.channel === "options"
|
||||||
|
)
|
||||||
|
).toBe(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
it("dedupes tape options subscription", () => {
|
||||||
|
const tapeOptionsSubscriptions = getLiveManifest(
|
||||||
|
"/tape",
|
||||||
|
"SPY",
|
||||||
|
60000,
|
||||||
|
buildDefaultFlowFilters()
|
||||||
|
).filter((subscription) => subscription.channel === "options");
|
||||||
|
expect(tapeOptionsSubscriptions).toHaveLength(1);
|
||||||
|
});
|
||||||
|
|
||||||
|
it("keeps option filters on baseline subscription", () => {
|
||||||
|
const filters = {
|
||||||
|
...buildDefaultFlowFilters(),
|
||||||
|
minNotional: 125_000
|
||||||
|
};
|
||||||
|
|
||||||
|
const optionsSubscription = getLiveManifest("/signals", "SPY", 60000, filters).find(
|
||||||
|
(subscription) => subscription.channel === "options"
|
||||||
|
);
|
||||||
|
|
||||||
|
expect(optionsSubscription?.filters).toBe(filters);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
describe("live tape pausable helpers", () => {
|
describe("live tape pausable helpers", () => {
|
||||||
it("queues new items while paused and flushes them on resume", () => {
|
it("queues new items while paused and flushes them on resume", () => {
|
||||||
let state = reducePausableTapeData(
|
let state = reducePausableTapeData(
|
||||||
|
|
|
||||||
|
|
@ -2185,47 +2185,72 @@ type LiveSessionState = {
|
||||||
chartOverlay: EquityPrint[];
|
chartOverlay: EquityPrint[];
|
||||||
};
|
};
|
||||||
|
|
||||||
const getLiveManifest = (
|
const dedupeLiveSubscriptions = (subscriptions: LiveSubscription[]): LiveSubscription[] => {
|
||||||
|
const seen = new Set<string>();
|
||||||
|
return subscriptions.filter((subscription) => {
|
||||||
|
const key = getLiveSubscriptionKey(subscription);
|
||||||
|
if (seen.has(key)) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
seen.add(key);
|
||||||
|
return true;
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
export const getLiveManifest = (
|
||||||
pathname: string,
|
pathname: string,
|
||||||
chartTicker: string,
|
chartTicker: string,
|
||||||
chartIntervalMs: number,
|
chartIntervalMs: number,
|
||||||
flowFilters: OptionFlowFilters
|
flowFilters: OptionFlowFilters
|
||||||
): LiveSubscription[] => {
|
): LiveSubscription[] => {
|
||||||
|
const baselineSubs: LiveSubscription[] = [{ channel: "options", filters: flowFilters }];
|
||||||
const chartSubs: LiveSubscription[] = [
|
const chartSubs: LiveSubscription[] = [
|
||||||
{ channel: "equity-candles", underlying_id: chartTicker, interval_ms: chartIntervalMs },
|
{ channel: "equity-candles", underlying_id: chartTicker, interval_ms: chartIntervalMs },
|
||||||
{ channel: "equity-overlay", underlying_id: chartTicker }
|
{ channel: "equity-overlay", underlying_id: chartTicker }
|
||||||
];
|
];
|
||||||
|
|
||||||
if (pathname === "/tape") {
|
if (pathname === "/tape") {
|
||||||
return [
|
return dedupeLiveSubscriptions([
|
||||||
|
...baselineSubs,
|
||||||
{ channel: "options", filters: flowFilters },
|
{ channel: "options", filters: flowFilters },
|
||||||
{ channel: "nbbo" },
|
{ channel: "nbbo" },
|
||||||
{ channel: "equities" },
|
{ channel: "equities" },
|
||||||
{ channel: "flow", filters: flowFilters },
|
{ channel: "flow", filters: flowFilters },
|
||||||
{ channel: "classifier-hits" }
|
{ channel: "classifier-hits" }
|
||||||
];
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathname === "/signals") {
|
if (pathname === "/signals") {
|
||||||
return [{ channel: "alerts" }, { channel: "classifier-hits" }, { channel: "inferred-dark" }];
|
return dedupeLiveSubscriptions([
|
||||||
|
...baselineSubs,
|
||||||
|
{ channel: "alerts" },
|
||||||
|
{ channel: "classifier-hits" },
|
||||||
|
{ channel: "inferred-dark" }
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathname === "/charts") {
|
if (pathname === "/charts") {
|
||||||
return [...chartSubs, { channel: "classifier-hits" }, { channel: "inferred-dark" }];
|
return dedupeLiveSubscriptions([
|
||||||
|
...baselineSubs,
|
||||||
|
...chartSubs,
|
||||||
|
{ channel: "classifier-hits" },
|
||||||
|
{ channel: "inferred-dark" }
|
||||||
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (pathname === "/replay") {
|
if (pathname === "/replay") {
|
||||||
return [];
|
return baselineSubs;
|
||||||
}
|
}
|
||||||
|
|
||||||
return [
|
return dedupeLiveSubscriptions([
|
||||||
|
...baselineSubs,
|
||||||
{ channel: "equities" },
|
{ channel: "equities" },
|
||||||
{ channel: "flow" },
|
{ channel: "flow" },
|
||||||
{ channel: "alerts" },
|
{ channel: "alerts" },
|
||||||
{ channel: "classifier-hits" },
|
{ channel: "classifier-hits" },
|
||||||
{ channel: "inferred-dark" },
|
{ channel: "inferred-dark" },
|
||||||
...chartSubs
|
...chartSubs
|
||||||
];
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
const useLiveSession = (
|
const useLiveSession = (
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue