Implement smart money event bridge

This commit is contained in:
dirtydishes 2026-05-04 17:36:03 -04:00
parent a8cc2e3875
commit 6822fa1ba4
16 changed files with 1047 additions and 15 deletions

View file

@ -135,6 +135,98 @@ export const FlowPacketSchema = EventMetaSchema.merge(
export type FlowPacket = z.infer<typeof FlowPacketSchema>;
export const SmartMoneyProfileIdSchema = z.enum([
"institutional_directional",
"retail_whale",
"event_driven",
"vol_seller",
"arbitrage",
"hedge_reactive"
]);
export type SmartMoneyProfileId = z.infer<typeof SmartMoneyProfileIdSchema>;
export const SmartMoneyDirectionSchema = z.enum(["bullish", "bearish", "neutral", "mixed", "unknown"]);
export type SmartMoneyDirection = z.infer<typeof SmartMoneyDirectionSchema>;
export const SmartMoneyEventKindSchema = z.enum(["single_leg_event", "multi_leg_event"]);
export type SmartMoneyEventKind = z.infer<typeof SmartMoneyEventKindSchema>;
export const SmartMoneyConfidenceBandSchema = z.enum(["low", "medium", "high"]);
export type SmartMoneyConfidenceBand = z.infer<typeof SmartMoneyConfidenceBandSchema>;
export const SmartMoneyFeaturesSchema = z.object({
contract_count: z.number().int().nonnegative(),
print_count: z.number().int().nonnegative(),
total_size: z.number().nonnegative(),
total_premium: z.number().nonnegative(),
total_notional: z.number().nonnegative(),
start_ts: z.number().int().nonnegative(),
end_ts: z.number().int().nonnegative(),
window_ms: z.number().int().nonnegative(),
option_contract_id: z.string().min(1).optional(),
option_type: z.enum(["C", "P"]).optional(),
dte_days: z.number().nonnegative().nullable(),
moneyness: z.number().nullable(),
atm_proximity: z.number().nullable(),
aggressor_buy_ratio: z.number().min(0).max(1),
aggressor_sell_ratio: z.number().min(0).max(1),
aggressor_ratio: z.number().min(0).max(1),
nbbo_coverage_ratio: z.number().min(0).max(1),
nbbo_inside_ratio: z.number().min(0).max(1),
nbbo_stale_ratio: z.number().min(0).max(1),
quote_age_ms: z.number().nonnegative().nullable(),
venue_count: z.number().int().nonnegative(),
inter_fill_ms_mean: z.number().nonnegative().nullable(),
strike_count: z.number().int().nonnegative(),
strike_concentration: z.number().min(0).max(1),
structure_type: z.string().optional(),
structure_legs: z.number().int().nonnegative(),
same_size_leg_symmetry: z.number().min(0).max(1),
net_directional_bias: z.number().min(-1).max(1),
synthetic_iv_shock: z.number().nullable(),
spread_widening: z.number().nullable(),
underlying_move_bps: z.number().nullable(),
days_to_event: z.number().nullable(),
expiry_after_event: z.boolean().nullable(),
pre_event_concentration: z.number().min(0).max(1).nullable(),
special_print_ratio: z.number().min(0).max(1)
});
export type SmartMoneyFeatures = z.infer<typeof SmartMoneyFeaturesSchema>;
export const SmartMoneyProfileScoreSchema = z.object({
profile_id: SmartMoneyProfileIdSchema,
probability: z.number().min(0).max(1),
confidence_band: SmartMoneyConfidenceBandSchema,
direction: SmartMoneyDirectionSchema,
reasons: z.array(z.string().min(1))
});
export type SmartMoneyProfileScore = z.infer<typeof SmartMoneyProfileScoreSchema>;
export const SmartMoneyEventSchema = EventMetaSchema.merge(
z.object({
event_id: z.string().min(1),
packet_ids: z.array(z.string().min(1)),
member_print_ids: z.array(z.string().min(1)),
underlying_id: z.string().min(1),
event_kind: SmartMoneyEventKindSchema,
event_window_ms: z.number().int().nonnegative(),
features: SmartMoneyFeaturesSchema,
profile_scores: z.array(SmartMoneyProfileScoreSchema),
primary_profile_id: SmartMoneyProfileIdSchema.nullable(),
primary_direction: SmartMoneyDirectionSchema,
abstained: z.boolean(),
suppressed_reasons: z.array(z.string().min(1))
})
);
export type SmartMoneyEvent = z.infer<typeof SmartMoneyEventSchema>;
export const ClassifierHitSchema = z.object({
classifier_id: z.string().min(1),
confidence: z.number().min(0).max(1),
@ -153,7 +245,9 @@ export const AlertEventSchema = EventMetaSchema.merge(
score: z.number(),
severity: z.string().min(1),
hits: z.array(ClassifierHitSchema),
evidence_refs: z.array(z.string().min(1))
evidence_refs: z.array(z.string().min(1)),
primary_profile_id: SmartMoneyProfileIdSchema.optional(),
profile_scores: z.array(SmartMoneyProfileScoreSchema).optional()
})
);

View file

@ -9,7 +9,8 @@ import {
FlowPacketSchema,
InferredDarkEventSchema,
OptionNBBOSchema,
OptionPrintSchema
OptionPrintSchema,
SmartMoneyEventSchema
} from "./events";
import {
OptionFlowFiltersSchema,
@ -30,6 +31,7 @@ export const LiveGenericChannelSchema = z.enum([
"equity-quotes",
"equity-joins",
"flow",
"smart-money",
"classifier-hits",
"alerts",
"inferred-dark"
@ -42,6 +44,7 @@ export const LiveChannelSchema = z.enum([
"equity-quotes",
"equity-joins",
"flow",
"smart-money",
"classifier-hits",
"alerts",
"inferred-dark",
@ -63,6 +66,9 @@ export const LiveSubscriptionSchema = z.discriminatedUnion("channel", [
channel: z.literal("flow"),
filters: OptionFlowFiltersSchema.optional()
}),
z.object({
channel: z.literal("smart-money")
}),
z.object({
channel: z.enum(["nbbo", "equity-quotes", "equity-joins", "classifier-hits", "alerts", "inferred-dark"])
}),
@ -90,6 +96,7 @@ const livePayloadSchemas = {
"equity-quotes": EquityQuoteSchema,
"equity-joins": EquityPrintJoinSchema,
flow: FlowPacketSchema,
"smart-money": SmartMoneyEventSchema,
"classifier-hits": ClassifierHitEventSchema,
alerts: AlertEventSchema,
"inferred-dark": InferredDarkEventSchema,