expand ci quality gates
All checks were successful
CI / Validate (push) Successful in 1m13s

This commit is contained in:
dirtydishes 2026-05-30 02:34:28 -04:00
parent 65139bf8d0
commit 44431c4e66
71 changed files with 2262 additions and 1173 deletions

View file

@ -14,4 +14,3 @@ export const scoreAlert = (
const severity = score >= 80 ? "high" : score >= 45 ? "medium" : "low";
return { score, severity };
};

View file

@ -573,10 +573,7 @@ const buildVerticalSpreadHit = (
};
};
const buildLadderHit = (
packet: FlowPacket,
config: ClassifierConfig
): ClassifierHit | null => {
const buildLadderHit = (packet: FlowPacket, config: ClassifierConfig): ClassifierHit | null => {
const structureType = getStringFeature(packet, "structure_type");
if (structureType !== "ladder") {
return null;
@ -648,7 +645,8 @@ const buildRollHit = (packet: FlowPacket, config: ClassifierConfig): ClassifierH
}
const activity = getLargeActivity(packet, config);
const qualifies = activity.totalPremium >= config.spikeMinPremium || activity.totalSize >= config.spikeMinSize;
const qualifies =
activity.totalPremium >= config.spikeMinPremium || activity.totalSize >= config.spikeMinSize;
if (!qualifies) {
return null;
}
@ -708,7 +706,9 @@ const buildRollHit = (packet: FlowPacket, config: ClassifierConfig): ClassifierH
const expiryNote = hasExpiryPair
? `Expiries: ${fromExpiry} -> ${toExpiry}${
expiryDaysDelta !== null && expiryDaysDelta !== 0 ? ` (${Math.round(expiryDaysDelta)}d)` : ""
expiryDaysDelta !== null && expiryDaysDelta !== 0
? ` (${Math.round(expiryDaysDelta)}d)`
: ""
}.`
: "Expiry pairing unavailable.";
const strikeNote = hasStrikePair
@ -850,9 +850,10 @@ export const evaluateClassifiers = (
const packetKind = getStringFeature(packet, "packet_kind");
const structureOnly = packetKind === "structure";
const contractId = typeof packet.features.option_contract_id === "string"
? packet.features.option_contract_id
: "";
const contractId =
typeof packet.features.option_contract_id === "string"
? packet.features.option_contract_id
: "";
const contract = structureOnly ? null : parseContractId(contractId);
const hits: ClassifierHit[] = [];

View file

@ -15,10 +15,7 @@ const roundTo = (value: number, digits = 4): number => {
return Number(value.toFixed(digits));
};
export const classifyQuotePlacement = (
price: number,
join: EquityQuoteJoin
): QuotePlacement => {
export const classifyQuotePlacement = (price: number, join: EquityQuoteJoin): QuotePlacement => {
if (!Number.isFinite(price)) {
return "MISSING";
}

View file

@ -46,7 +46,7 @@ import {
enqueueEquityPrintJoinInsert,
enqueueFlowPacketInsert,
enqueueInferredDarkInsert,
enqueueSmartMoneyEventInsert,
enqueueSmartMoneyEventInsert
} from "@islandflow/storage";
import {
AlertEventSchema,
@ -324,7 +324,9 @@ const buildPacketId = (cluster: ClusterState): string => {
const isExpectedShutdownNatsError = (error: unknown): boolean => {
const code = getErrorCode(error);
return runtimeState.shuttingDown && (code === "CONNECTION_DRAINING" || code === "CONNECTION_CLOSED");
return (
runtimeState.shuttingDown && (code === "CONNECTION_DRAINING" || code === "CONNECTION_CLOSED")
);
};
const createPlacementCounts = (): NbboPlacementCounts => ({
@ -337,7 +339,14 @@ const createPlacementCounts = (): NbboPlacementCounts => ({
stale: 0
});
const SPECIAL_PRINT_CONDITIONS = new Set(["AUCTION", "CROSS", "OPENING", "CLOSING", "COMPLEX", "SPREAD"]);
const SPECIAL_PRINT_CONDITIONS = new Set([
"AUCTION",
"CROSS",
"OPENING",
"CLOSING",
"COMPLEX",
"SPREAD"
]);
const SYNTHETIC_EVENT_CONDITION_RE = /^EVENT_(\d+)D$/i;
const normalizeConditions = (conditions: readonly string[] | undefined): string[] =>
@ -460,11 +469,7 @@ const storeRecentRootLeg = (leg: LegEvidence, anchorTs: number): void => {
recentLegsByRoot.set(key, next);
};
const collectActiveLegs = (
key: string,
anchorTs: number,
excludeId: string
): LegEvidence[] => {
const collectActiveLegs = (key: string, anchorTs: number, excludeId: string): LegEvidence[] => {
const legs: LegEvidence[] = [];
for (const [contractId, cluster] of clusters) {
if (contractId === excludeId) {
@ -485,11 +490,7 @@ const collectActiveLegs = (
return legs;
};
const collectActiveRootLegs = (
key: string,
anchorTs: number,
excludeId: string
): LegEvidence[] => {
const collectActiveRootLegs = (key: string, anchorTs: number, excludeId: string): LegEvidence[] => {
const legs: LegEvidence[] = [];
for (const [contractId, cluster] of clusters) {
if (contractId === excludeId) {
@ -601,12 +602,19 @@ const applyDeliverPolicy = (
const buildCluster = (print: OptionPrint): ClusterState => {
const placements = createPlacementCounts();
const normalizedConditions = normalizeConditions(print.conditions);
const executionIv = typeof print.execution_iv === "number" && Number.isFinite(print.execution_iv) ? print.execution_iv : null;
const executionIv =
typeof print.execution_iv === "number" && Number.isFinite(print.execution_iv)
? print.execution_iv
: null;
const executionUnderlyingMid =
typeof print.execution_underlying_mid === "number" && Number.isFinite(print.execution_underlying_mid)
typeof print.execution_underlying_mid === "number" &&
Number.isFinite(print.execution_underlying_mid)
? print.execution_underlying_mid
: null;
recordPlacement(placements, classifyPlacement(print.price, selectNbbo(print.option_contract_id, print.ts)));
recordPlacement(
placements,
classifyPlacement(print.price, selectNbbo(print.option_contract_id, print.ts))
);
return {
contractId: print.option_contract_id,
underlyingId: print.underlying_id ?? null,
@ -661,11 +669,18 @@ const updateCluster = (cluster: ClusterState, print: OptionPrint): ClusterState
if (typeof print.execution_iv === "number" && Number.isFinite(print.execution_iv)) {
cluster.lastExecutionIv = print.execution_iv;
cluster.minExecutionIv =
cluster.minExecutionIv === null ? print.execution_iv : Math.min(cluster.minExecutionIv, print.execution_iv);
cluster.minExecutionIv === null
? print.execution_iv
: Math.min(cluster.minExecutionIv, print.execution_iv);
cluster.maxExecutionIv =
cluster.maxExecutionIv === null ? print.execution_iv : Math.max(cluster.maxExecutionIv, print.execution_iv);
cluster.maxExecutionIv === null
? print.execution_iv
: Math.max(cluster.maxExecutionIv, print.execution_iv);
}
if (typeof print.execution_underlying_mid === "number" && Number.isFinite(print.execution_underlying_mid)) {
if (
typeof print.execution_underlying_mid === "number" &&
Number.isFinite(print.execution_underlying_mid)
) {
if (cluster.firstUnderlyingMid === null) {
cluster.firstUnderlyingMid = print.execution_underlying_mid;
}
@ -686,11 +701,7 @@ type NbboJoin = {
const updateNbboCache = (nbbo: OptionNBBO): void => {
const existing = nbboCache.get(nbbo.option_contract_id);
if (
!existing ||
nbbo.ts > existing.ts ||
(nbbo.ts === existing.ts && nbbo.seq >= existing.seq)
) {
if (!existing || nbbo.ts > existing.ts || (nbbo.ts === existing.ts && nbbo.seq >= existing.seq)) {
nbboCache.set(nbbo.option_contract_id, nbbo);
nbboCacheTouchedAt.set(nbbo.option_contract_id, Date.now());
}
@ -907,14 +918,18 @@ const flushCluster = async (
features.special_print_count = cluster.specialPrintCount;
}
if (cluster.minExecutionIv !== null && cluster.maxExecutionIv !== null) {
features.execution_iv_shock = roundTo(Math.max(0, cluster.maxExecutionIv - cluster.minExecutionIv));
features.execution_iv_shock = roundTo(
Math.max(0, cluster.maxExecutionIv - cluster.minExecutionIv)
);
}
if (
cluster.firstUnderlyingMid !== null &&
cluster.lastUnderlyingMid !== null &&
cluster.firstUnderlyingMid > 0
) {
const moveBps = ((cluster.lastUnderlyingMid - cluster.firstUnderlyingMid) / cluster.firstUnderlyingMid) * 10_000;
const moveBps =
((cluster.lastUnderlyingMid - cluster.firstUnderlyingMid) / cluster.firstUnderlyingMid) *
10_000;
features.underlying_move_bps = roundTo(moveBps);
}
const syntheticEventOffsetDays = parseSyntheticEventOffsetDays(cluster.conditions);
@ -1004,7 +1019,13 @@ const flushCluster = async (
const rollLegs = [currentLeg, ...rootCandidates];
const rollSummary = summarizeStructure(rollLegs);
if (rollSummary?.type === "roll") {
await emitStructurePacketIfNeeded(js, batchWriter, rollLegs, rollSummary, currentLeg.contractId);
await emitStructurePacketIfNeeded(
js,
batchWriter,
rollLegs,
rollSummary,
currentLeg.contractId
);
}
storeRecentLeg(currentLeg, anchorTs);
@ -1072,13 +1093,21 @@ const emitClassifiers = async (
const underlyingId =
typeof packet.features.underlying_id === "string"
? packet.features.underlying_id
: parseContractId(typeof packet.features.option_contract_id === "string" ? packet.features.option_contract_id : "")?.root;
: parseContractId(
typeof packet.features.option_contract_id === "string"
? packet.features.option_contract_id
: ""
)?.root;
const referenceTs =
typeof packet.features.end_ts === "number" && Number.isFinite(packet.features.end_ts)
? packet.features.end_ts
: packet.source_ts;
const eventCalendarMatch = underlyingId ? eventCalendarProvider.findNextEvent(underlyingId, referenceTs) : null;
smartMoneyEvent = SmartMoneyEventSchema.parse(buildSmartMoneyEventFromPacket(packet, { eventCalendarMatch }));
const eventCalendarMatch = underlyingId
? eventCalendarProvider.findNextEvent(underlyingId, referenceTs)
: null;
smartMoneyEvent = SmartMoneyEventSchema.parse(
buildSmartMoneyEventFromPacket(packet, { eventCalendarMatch })
);
enqueueSmartMoneyEventInsert(batchWriter, smartMoneyEvent);
await publishJson(js, SUBJECT_SMART_MONEY_EVENTS, smartMoneyEvent);
emitCounters.smartMoneyEvents += 1;
@ -1282,20 +1311,29 @@ const run = async () => {
if (env.SMART_MONEY_EVENT_CALENDAR_PATH) {
try {
eventCalendarProvider = await loadEventCalendarProviderFromFile(env.SMART_MONEY_EVENT_CALENDAR_PATH);
logger.info("smart money event calendar loaded", { path: env.SMART_MONEY_EVENT_CALENDAR_PATH });
eventCalendarProvider = await loadEventCalendarProviderFromFile(
env.SMART_MONEY_EVENT_CALENDAR_PATH
);
logger.info("smart money event calendar loaded", {
path: env.SMART_MONEY_EVENT_CALENDAR_PATH
});
} catch (error) {
eventCalendarProvider = createEmptyEventCalendarProvider();
logger.warn("smart money event calendar unavailable; scoring will use neutral event features", {
path: env.SMART_MONEY_EVENT_CALENDAR_PATH,
error: error instanceof Error ? error.message : String(error)
});
logger.warn(
"smart money event calendar unavailable; scoring will use neutral event features",
{
path: env.SMART_MONEY_EVENT_CALENDAR_PATH,
error: error instanceof Error ? error.message : String(error)
}
);
}
}
const redis = createRedisClient(env.REDIS_URL);
redis.on("error", (error) => {
logger.warn("redis client error", { error: error instanceof Error ? error.message : String(error) });
logger.warn("redis client error", {
error: error instanceof Error ? error.message : String(error)
});
});
await retry("redis connect", 120, 500, async () => {
@ -1379,7 +1417,10 @@ const run = async () => {
} else {
try {
const info = await jsm.consumers.info(STREAM_OPTION_SIGNAL_PRINTS, durableName);
if (info?.config?.deliver_policy && info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY) {
if (
info?.config?.deliver_policy &&
info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY
) {
logger.warn("resetting consumer due to deliver policy change", {
durable: durableName,
current: info.config.deliver_policy,
@ -1390,7 +1431,10 @@ const run = async () => {
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("not found")) {
logger.warn("failed to inspect jetstream consumer", { durable: durableName, error: message });
logger.warn("failed to inspect jetstream consumer", {
durable: durableName,
error: message
});
}
}
}
@ -1402,13 +1446,19 @@ const run = async () => {
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("not found")) {
logger.warn("failed to reset jetstream consumer", { durable: nbboDurableName, error: message });
logger.warn("failed to reset jetstream consumer", {
durable: nbboDurableName,
error: message
});
}
}
} else {
try {
const info = await jsm.consumers.info(STREAM_OPTION_NBBO, nbboDurableName);
if (info?.config?.deliver_policy && info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY) {
if (
info?.config?.deliver_policy &&
info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY
) {
logger.warn("resetting consumer due to deliver policy change", {
durable: nbboDurableName,
current: info.config.deliver_policy,
@ -1419,7 +1469,10 @@ const run = async () => {
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
if (!message.includes("not found")) {
logger.warn("failed to inspect jetstream consumer", { durable: nbboDurableName, error: message });
logger.warn("failed to inspect jetstream consumer", {
durable: nbboDurableName,
error: message
});
}
}
}
@ -1440,7 +1493,10 @@ const run = async () => {
} else {
try {
const info = await jsm.consumers.info(STREAM_EQUITY_PRINTS, equityPrintDurableName);
if (info?.config?.deliver_policy && info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY) {
if (
info?.config?.deliver_policy &&
info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY
) {
logger.warn("resetting consumer due to deliver policy change", {
durable: equityPrintDurableName,
current: info.config.deliver_policy,
@ -1475,7 +1531,10 @@ const run = async () => {
} else {
try {
const info = await jsm.consumers.info(STREAM_EQUITY_QUOTES, equityQuoteDurableName);
if (info?.config?.deliver_policy && info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY) {
if (
info?.config?.deliver_policy &&
info.config.deliver_policy !== env.COMPUTE_DELIVER_POLICY
) {
logger.warn("resetting consumer due to deliver policy change", {
durable: equityQuoteDurableName,
current: info.config.deliver_policy,
@ -1515,7 +1574,8 @@ const run = async () => {
try {
await jsm.consumers.delete(STREAM_OPTION_SIGNAL_PRINTS, durableName);
} catch (deleteError) {
const deleteMessage = deleteError instanceof Error ? deleteError.message : String(deleteError);
const deleteMessage =
deleteError instanceof Error ? deleteError.message : String(deleteError);
if (!deleteMessage.includes("not found")) {
logger.warn("failed to delete jetstream consumer", {
durable: durableName,
@ -1551,7 +1611,8 @@ const run = async () => {
try {
await jsm.consumers.delete(STREAM_OPTION_NBBO, nbboDurableName);
} catch (deleteError) {
const deleteMessage = deleteError instanceof Error ? deleteError.message : String(deleteError);
const deleteMessage =
deleteError instanceof Error ? deleteError.message : String(deleteError);
if (!deleteMessage.includes("not found")) {
logger.warn("failed to delete jetstream consumer", {
durable: nbboDurableName,
@ -1582,12 +1643,16 @@ const run = async () => {
throw error;
}
logger.warn("resetting jetstream consumer", { durable: equityPrintDurableName, error: message });
logger.warn("resetting jetstream consumer", {
durable: equityPrintDurableName,
error: message
});
try {
await jsm.consumers.delete(STREAM_EQUITY_PRINTS, equityPrintDurableName);
} catch (deleteError) {
const deleteMessage = deleteError instanceof Error ? deleteError.message : String(deleteError);
const deleteMessage =
deleteError instanceof Error ? deleteError.message : String(deleteError);
if (!deleteMessage.includes("not found")) {
logger.warn("failed to delete jetstream consumer", {
durable: equityPrintDurableName,
@ -1626,7 +1691,8 @@ const run = async () => {
try {
await jsm.consumers.delete(STREAM_EQUITY_QUOTES, equityQuoteDurableName);
} catch (deleteError) {
const deleteMessage = deleteError instanceof Error ? deleteError.message : String(deleteError);
const deleteMessage =
deleteError instanceof Error ? deleteError.message : String(deleteError);
if (!deleteMessage.includes("not found")) {
logger.warn("failed to delete jetstream consumer", {
durable: equityQuoteDurableName,

View file

@ -78,7 +78,9 @@ const getDteDays = (packet: FlowPacket): number | null => {
const inferDirection = (packet: FlowPacket): SmartMoneyDirection => {
const structureRights = stringFeature(packet, "structure_rights");
const optionType = stringFeature(packet, "option_type") || parseContractId(stringFeature(packet, "option_contract_id"))?.right;
const optionType =
stringFeature(packet, "option_type") ||
parseContractId(stringFeature(packet, "option_contract_id"))?.right;
const buy = numberFeature(packet, "nbbo_aggressive_buy_ratio");
const sell = numberFeature(packet, "nbbo_aggressive_sell_ratio");
const sellDominant = sell >= buy + 0.12;
@ -102,16 +104,26 @@ export type SmartMoneyParentEventOptions = {
eventCalendarMatch?: EventCalendarMatch | null;
};
const buildFeatures = (packet: FlowPacket, options: SmartMoneyParentEventOptions = {}): SmartMoneyFeatures => {
const buildFeatures = (
packet: FlowPacket,
options: SmartMoneyParentEventOptions = {}
): SmartMoneyFeatures => {
const contractId = stringFeature(packet, "option_contract_id");
const contract = parseContractId(contractId);
const underlyingMid = numberFeature(packet, "underlying_mid");
const quoteAge = numberFeature(packet, "nbbo_age_ms") || numberFeature(packet, "underlying_quote_age_ms");
const printCount = Math.max(0, Math.round(numberFeature(packet, "count") || packet.members.length));
const quoteAge =
numberFeature(packet, "nbbo_age_ms") || numberFeature(packet, "underlying_quote_age_ms");
const printCount = Math.max(
0,
Math.round(numberFeature(packet, "count") || packet.members.length)
);
const staleCount = numberFeature(packet, "nbbo_stale_count");
const missingCount = numberFeature(packet, "nbbo_missing_count");
const structureLegs = Math.max(0, Math.round(numberFeature(packet, "structure_legs")));
const strikeCount = Math.max(1, Math.round(numberFeature(packet, "structure_strikes") || (contract ? 1 : 0)));
const strikeCount = Math.max(
1,
Math.round(numberFeature(packet, "structure_strikes") || (contract ? 1 : 0))
);
const specialCount = numberFeature(packet, "special_print_count");
const calendarEventTs = options.eventCalendarMatch?.event_ts ?? null;
const eventTs = calendarEventTs ?? numberFeature(packet, "corporate_event_ts");
@ -119,7 +131,9 @@ const buildFeatures = (packet: FlowPacket, options: SmartMoneyParentEventOptions
const expiryTs = contract ? Date.parse(`${contract.expiry}T00:00:00Z`) : Number.NaN;
const atmProximity =
contract && underlyingMid > 0 ? Math.abs(contract.strike - underlyingMid) / underlyingMid : null;
contract && underlyingMid > 0
? Math.abs(contract.strike - underlyingMid) / underlyingMid
: null;
return {
contract_count: Math.max(1, structureLegs || 1),
@ -143,14 +157,18 @@ const buildFeatures = (packet: FlowPacket, options: SmartMoneyParentEventOptions
nbbo_stale_ratio: printCount > 0 ? clamp((staleCount + missingCount) / printCount) : 0,
quote_age_ms: quoteAge > 0 ? quoteAge : null,
venue_count: Math.max(1, Math.round(numberFeature(packet, "venue_count") || 1)),
inter_fill_ms_mean: printCount > 1 ? numberFeature(packet, "window_ms") / Math.max(1, printCount - 1) : null,
inter_fill_ms_mean:
printCount > 1 ? numberFeature(packet, "window_ms") / Math.max(1, printCount - 1) : null,
strike_count: strikeCount,
strike_concentration: strikeCount > 0 ? clamp(1 / strikeCount) : 0,
...(stringFeature(packet, "structure_type") ? { structure_type: stringFeature(packet, "structure_type") } : {}),
...(stringFeature(packet, "structure_type")
? { structure_type: stringFeature(packet, "structure_type") }
: {}),
structure_legs: structureLegs,
same_size_leg_symmetry: clamp(numberFeature(packet, "same_size_leg_symmetry")),
net_directional_bias: clamp(
numberFeature(packet, "nbbo_aggressive_buy_ratio") - numberFeature(packet, "nbbo_aggressive_sell_ratio"),
numberFeature(packet, "nbbo_aggressive_buy_ratio") -
numberFeature(packet, "nbbo_aggressive_sell_ratio"),
-1,
1
),
@ -159,7 +177,10 @@ const buildFeatures = (packet: FlowPacket, options: SmartMoneyParentEventOptions
underlying_move_bps: numberFeature(packet, "underlying_move_bps") || null,
days_to_event: eventTs > 0 ? (eventTs - referenceTs) / MS_PER_DAY : null,
expiry_after_event: eventTs > 0 && Number.isFinite(expiryTs) ? expiryTs >= eventTs : null,
pre_event_concentration: eventTs > 0 && eventTs >= referenceTs ? clamp(1 - (eventTs - referenceTs) / (21 * MS_PER_DAY)) : null,
pre_event_concentration:
eventTs > 0 && eventTs >= referenceTs
? clamp(1 - (eventTs - referenceTs) / (21 * MS_PER_DAY))
: null,
special_print_ratio: printCount > 0 ? clamp(specialCount / printCount) : 0
};
};
@ -170,7 +191,10 @@ const detectSuppression = (packet: FlowPacket, features: SmartMoneyFeatures): st
.split(",")
.map((item) => item.trim().toUpperCase())
.filter(Boolean);
if (conditions.some((condition) => SPECIAL_CONDITIONS.has(condition)) || features.special_print_ratio >= 0.34) {
if (
conditions.some((condition) => SPECIAL_CONDITIONS.has(condition)) ||
features.special_print_ratio >= 0.34
) {
reasons.push("special_print_or_complex_context");
}
if (features.nbbo_coverage_ratio < 0.35 || features.nbbo_stale_ratio >= 0.5) {
@ -198,7 +222,10 @@ const evaluateProfiles = (
const burstFactor = clamp(features.print_count / 8);
const quality = clamp(features.nbbo_coverage_ratio - features.nbbo_stale_ratio);
const shortDatedOtm =
dte <= 7 && features.atm_proximity !== null && features.atm_proximity >= 0.05 && features.option_type === "C";
dte <= 7 &&
features.atm_proximity !== null &&
features.atm_proximity >= 0.05 &&
features.option_type === "C";
const nearAtm = features.atm_proximity !== null && features.atm_proximity <= 0.015;
const preEvent =
features.days_to_event !== null &&
@ -211,7 +238,11 @@ const evaluateProfiles = (
"institutional_directional",
suppressed.length > 0 || shortDatedOtm
? 0.18
: 0.2 + premiumFactor * 0.25 + burstFactor * 0.18 + quality * 0.16 + (buy >= 0.58 || sell >= 0.58 ? 0.12 : 0),
: 0.2 +
premiumFactor * 0.25 +
burstFactor * 0.18 +
quality * 0.16 +
(buy >= 0.58 || sell >= 0.58 ? 0.12 : 0),
direction,
[
"large_parent_event",
@ -232,13 +263,19 @@ const evaluateProfiles = (
),
score(
"event_driven",
0.12 + (preEvent ? 0.32 : 0) + premiumFactor * 0.14 + clamp(features.spread_widening ?? 0, 0, 0.16),
0.12 +
(preEvent ? 0.32 : 0) +
premiumFactor * 0.14 +
clamp(features.spread_widening ?? 0, 0, 0.16),
direction === "unknown" ? "neutral" : direction,
["event_calendar_alignment", "expiry_after_event", "pre_event_concentration"]
),
score(
"vol_seller",
0.12 + (sell >= 0.58 ? 0.24 : 0) + (structure === "straddle" || structure === "strangle" ? 0.2 : 0) + premiumFactor * 0.14,
0.12 +
(sell >= 0.58 ? 0.24 : 0) +
(structure === "straddle" || structure === "strangle" ? 0.2 : 0) +
premiumFactor * 0.14,
"neutral",
["sell_side_premium", "short_vol_structure_evidence"]
),
@ -273,11 +310,16 @@ export const buildSmartMoneyEventFromPacket = (
const suppressed = detectSuppression(packet, features);
const profileScores = evaluateProfiles(packet, features, suppressed);
const primary = profileScores[0] ?? null;
const abstained = !primary || primary.probability < 0.42 || suppressed.includes("stale_or_missing_quote_context");
const underlying = stringFeature(packet, "underlying_id") || parseContractId(features.option_contract_id ?? "")?.root || "UNKNOWN";
const eventKind = features.structure_legs >= 2 || stringFeature(packet, "packet_kind") === "structure"
? "multi_leg_event"
: "single_leg_event";
const abstained =
!primary || primary.probability < 0.42 || suppressed.includes("stale_or_missing_quote_context");
const underlying =
stringFeature(packet, "underlying_id") ||
parseContractId(features.option_contract_id ?? "")?.root ||
"UNKNOWN";
const eventKind =
features.structure_legs >= 2 || stringFeature(packet, "packet_kind") === "structure"
? "multi_leg_event"
: "single_leg_event";
return SmartMoneyEventSchema.parse({
source_ts: packet.source_ts,
@ -292,8 +334,8 @@ export const buildSmartMoneyEventFromPacket = (
event_window_ms: features.window_ms,
features,
profile_scores: profileScores,
primary_profile_id: abstained ? null : primary?.profile_id ?? null,
primary_direction: abstained ? "unknown" : primary?.direction ?? "unknown",
primary_profile_id: abstained ? null : (primary?.profile_id ?? null),
primary_direction: abstained ? "unknown" : (primary?.direction ?? "unknown"),
abstained,
suppressed_reasons: suppressed
});
@ -308,7 +350,9 @@ const LEGACY_PROFILE_MAP: Record<SmartMoneyProfileId, string> = {
hedge_reactive: "smart_money_hedge_reactive"
};
export const deriveClassifierHitsFromSmartMoneyEvent = (event: SmartMoneyEvent): ClassifierHit[] => {
export const deriveClassifierHitsFromSmartMoneyEvent = (
event: SmartMoneyEvent
): ClassifierHit[] => {
if (event.abstained || !event.primary_profile_id) {
return [];
}

View file

@ -24,9 +24,7 @@ type RollingWindowEntry = {
};
const toNumbers = (values: string[]): number[] => {
return values
.map((value) => Number(value))
.filter((value) => Number.isFinite(value));
return values.map((value) => Number(value)).filter((value) => Number.isFinite(value));
};
export const computeStats = (values: number[]): { mean: number; stddev: number; count: number } => {

View file

@ -1,4 +1,9 @@
import type { FlowPacket, SmartMoneyDirection, SmartMoneyEvent, SmartMoneyProfileId } from "@islandflow/types";
import type {
FlowPacket,
SmartMoneyDirection,
SmartMoneyEvent,
SmartMoneyProfileId
} from "@islandflow/types";
import { buildSmartMoneyEventFromPacket, type SmartMoneyParentEventOptions } from "./parent-events";
export type SmartMoneyLabel = {
@ -115,8 +120,12 @@ export const compareSmartMoneyReplayOutputs = (
liveEvents: SmartMoneyEvent[],
batchEvents: SmartMoneyEvent[]
): ReplayConsistencyReport => {
const liveById = new Map(liveEvents.map((event) => [event.event_id, smartMoneyEventSignature(event)]));
const batchById = new Map(batchEvents.map((event) => [event.event_id, smartMoneyEventSignature(event)]));
const liveById = new Map(
liveEvents.map((event) => [event.event_id, smartMoneyEventSignature(event)])
);
const batchById = new Map(
batchEvents.map((event) => [event.event_id, smartMoneyEventSignature(event)])
);
const ids = [...new Set([...liveById.keys(), ...batchById.keys()])].sort();
const mismatches: ReplayConsistencyMismatch[] = [];
@ -153,7 +162,9 @@ export const evaluateSmartMoneyEvents = (
const labelsById = new Map(labels.map((label) => [label.event_id, label]));
const labeledEvents = events
.map((event) => ({ event, label: labelsById.get(event.event_id) }))
.filter((entry): entry is { event: SmartMoneyEvent; label: SmartMoneyLabel } => Boolean(entry.label));
.filter((entry): entry is { event: SmartMoneyEvent; label: SmartMoneyLabel } =>
Boolean(entry.label)
);
const emitted = events.filter((event) => !event.abstained && event.primary_profile_id);
const profilePrecision: SmartMoneyEvaluationReport["profile_precision"] = {};
@ -163,7 +174,8 @@ export const evaluateSmartMoneyEvents = (
const predicted = labeledEvents.filter((entry) => entry.event.primary_profile_id === profile);
const actual = labeledEvents.filter((entry) => entry.label.profile_id === profile);
const truePositive = predicted.filter((entry) => entry.label.profile_id === profile).length;
profilePrecision[profile] = predicted.length > 0 ? round(truePositive / predicted.length) : null;
profilePrecision[profile] =
predicted.length > 0 ? round(truePositive / predicted.length) : null;
profileRecall[profile] = actual.length > 0 ? round(truePositive / actual.length) : null;
}
@ -175,7 +187,10 @@ export const evaluateSmartMoneyEvents = (
labeled_count: labeledEvents.length,
emitted_count: emitted.length,
abstained_count: events.filter((event) => event.abstained).length,
abstention_rate: events.length > 0 ? round(events.filter((event) => event.abstained).length / events.length) : 0,
abstention_rate:
events.length > 0
? round(events.filter((event) => event.abstained).length / events.length)
: 0,
profile_precision: profilePrecision,
profile_recall: profileRecall,
calibration,
@ -195,7 +210,9 @@ const buildCalibration = (
}));
for (const { event, label } of entries) {
const probability = event.profile_scores.find((entry) => entry.profile_id === event.primary_profile_id)?.probability ?? 0;
const probability =
event.profile_scores.find((entry) => entry.profile_id === event.primary_profile_id)
?.probability ?? 0;
const index = Math.min(bucketCount - 1, Math.floor(probability * bucketCount));
buckets[index].probabilities.push(probability);
if (!event.abstained && event.primary_profile_id === label.profile_id) {
@ -209,9 +226,13 @@ const buildCalibration = (
count: bucket.probabilities.length,
average_probability:
bucket.probabilities.length > 0
? round(bucket.probabilities.reduce((sum, value) => sum + value, 0) / bucket.probabilities.length)
? round(
bucket.probabilities.reduce((sum, value) => sum + value, 0) /
bucket.probabilities.length
)
: 0,
accuracy: bucket.probabilities.length > 0 ? round(bucket.correct / bucket.probabilities.length) : null
accuracy:
bucket.probabilities.length > 0 ? round(bucket.correct / bucket.probabilities.length) : null
}));
};
@ -223,7 +244,10 @@ const buildEconomicSanity = (
sign: directionalSign(event.primary_direction),
realized: label.realized_return_bps
}))
.filter((entry): entry is { sign: number; realized: number } => entry.sign !== 0 && Number.isFinite(entry.realized));
.filter(
(entry): entry is { sign: number; realized: number } =>
entry.sign !== 0 && Number.isFinite(entry.realized)
);
if (directional.length === 0) {
return {
@ -236,7 +260,12 @@ const buildEconomicSanity = (
const signedReturns = directional.map((entry) => entry.sign * entry.realized);
return {
directional_count: directional.length,
direction_hit_rate: round(signedReturns.filter((value) => value > 0).length / directional.length),
average_signed_return_bps: round(signedReturns.reduce((sum, value) => sum + value, 0) / signedReturns.length, 2)
direction_hit_rate: round(
signedReturns.filter((value) => value > 0).length / directional.length
),
average_signed_return_bps: round(
signedReturns.reduce((sum, value) => sum + value, 0) / signedReturns.length,
2
)
};
};

View file

@ -134,7 +134,9 @@ const dayDiff = (from: string | null, to: string | null): number | null => {
};
const sameSizeLegSymmetry = (legs: LegEvidence[]): number => {
const sizes = legs.map((leg) => leg.totalSize).filter((value) => Number.isFinite(value) && value > 0);
const sizes = legs
.map((leg) => leg.totalSize)
.filter((value) => Number.isFinite(value) && value > 0);
if (sizes.length < 2) {
return 0;
}
@ -146,7 +148,10 @@ const sameSizeLegSymmetry = (legs: LegEvidence[]): number => {
return min / max;
};
export const shouldEmitStructurePacket = (legs: LegEvidence[], currentLegContractId: string): boolean => {
export const shouldEmitStructurePacket = (
legs: LegEvidence[],
currentLegContractId: string
): boolean => {
if (legs.length < 2) {
return false;
}
@ -226,7 +231,8 @@ export const planStructurePacket = (
const totalSize = legs.reduce((sum, leg) => sum + leg.totalSize, 0);
const count = legs.reduce((sum, leg) => sum + leg.members.length, 0);
const placements = mergePlacements(legs);
const placementTotal = placements.aa + placements.a + placements.b + placements.bb + placements.mid;
const placementTotal =
placements.aa + placements.a + placements.b + placements.bb + placements.mid;
const aggressiveTotal = placements.aa + placements.a + placements.b + placements.bb;
const aggressiveBuy = placements.aa + placements.a;
const aggressiveSell = placements.bb + placements.b;
@ -235,7 +241,10 @@ export const planStructurePacket = (
const nbboAggressiveSellRatio = aggressiveTotal > 0 ? aggressiveSell / aggressiveTotal : 0;
const nbboAggressiveRatio = placementTotal > 0 ? aggressiveTotal / placementTotal : 0;
const source_ts = legs.reduce((min, leg) => Math.min(min, leg.source_ts), Number.POSITIVE_INFINITY);
const source_ts = legs.reduce(
(min, leg) => Math.min(min, leg.source_ts),
Number.POSITIVE_INFINITY
);
const ingest_ts = legs.reduce((max, leg) => Math.max(max, leg.ingest_ts), 0);
const seq = legs.reduce((max, leg) => Math.max(max, leg.seq), 0);

View file

@ -47,7 +47,10 @@ export const summarizeStructure = (legs: ContractLeg[]): StructureSummary | null
legs: legs.length,
strikes: strikes.length,
strikeSpan,
rights: rights.size === 2 ? "C/P" : Array.from(rights)[0] ?? "",
contractIds: legs.map((leg) => leg.contractId).slice().sort()
rights: rights.size === 2 ? "C/P" : (Array.from(rights)[0] ?? ""),
contractIds: legs
.map((leg) => leg.contractId)
.slice()
.sort()
};
};

View file

@ -293,4 +293,3 @@ describe("compute classifiers", () => {
expect(hit!.explanations[0]).toMatch(/Consistent with/i);
});
});

View file

@ -17,16 +17,18 @@ export const TEST_CLASSIFIER_CONFIG: ClassifierConfig = {
zeroDteMinSize: 400
};
export const buildFlowPacket = (opts: {
id?: string;
source_ts?: number;
ingest_ts?: number;
seq?: number;
trace_id?: string;
members?: string[];
features?: FlowPacket["features"];
join_quality?: FlowPacket["join_quality"];
} = {}): FlowPacket => {
export const buildFlowPacket = (
opts: {
id?: string;
source_ts?: number;
ingest_ts?: number;
seq?: number;
trace_id?: string;
members?: string[];
features?: FlowPacket["features"];
join_quality?: FlowPacket["join_quality"];
} = {}
): FlowPacket => {
const id = opts.id ?? "flowpacket:test";
const source_ts = opts.source_ts ?? Date.parse("2025-01-01T14:30:00Z");
const ingest_ts = opts.ingest_ts ?? source_ts;
@ -66,4 +68,3 @@ export const buildFlowPacket = (opts: {
export const getHit = (hits: ClassifierHit[], id: string): ClassifierHit | null => {
return hits.find((hit) => hit.classifier_id === id) ?? null;
};

View file

@ -18,7 +18,9 @@ const placements = (overrides?: Partial<LegEvidence["placements"]>): LegEvidence
...overrides
});
const leg = (input: Partial<LegEvidence> & Pick<LegEvidence, "contractId" | "right" | "strike">): LegEvidence => {
const leg = (
input: Partial<LegEvidence> & Pick<LegEvidence, "contractId" | "right" | "strike">
): LegEvidence => {
return {
contractId: input.contractId,
root: "SPY",