Implement options snapshot tape table
This commit is contained in:
parent
6abfff30d3
commit
e78387130a
15 changed files with 904 additions and 128 deletions
|
|
@ -512,7 +512,23 @@ const normalizeOptionRow = (row: unknown): unknown => {
|
|||
"ts",
|
||||
"price",
|
||||
"size",
|
||||
"notional"
|
||||
"notional",
|
||||
"execution_nbbo_bid",
|
||||
"execution_nbbo_ask",
|
||||
"execution_nbbo_mid",
|
||||
"execution_nbbo_spread",
|
||||
"execution_nbbo_bid_size",
|
||||
"execution_nbbo_ask_size",
|
||||
"execution_nbbo_ts",
|
||||
"execution_nbbo_age_ms",
|
||||
"execution_underlying_spot",
|
||||
"execution_underlying_bid",
|
||||
"execution_underlying_ask",
|
||||
"execution_underlying_mid",
|
||||
"execution_underlying_spread",
|
||||
"execution_underlying_ts",
|
||||
"execution_underlying_age_ms",
|
||||
"execution_iv"
|
||||
]);
|
||||
|
||||
if ("is_etf" in record) {
|
||||
|
|
|
|||
|
|
@ -19,6 +19,25 @@ CREATE TABLE IF NOT EXISTS ${OPTION_PRINTS_TABLE} (
|
|||
option_type Nullable(String),
|
||||
notional Nullable(Float64),
|
||||
nbbo_side Nullable(String),
|
||||
execution_nbbo_bid Nullable(Float64),
|
||||
execution_nbbo_ask Nullable(Float64),
|
||||
execution_nbbo_mid Nullable(Float64),
|
||||
execution_nbbo_spread Nullable(Float64),
|
||||
execution_nbbo_bid_size Nullable(UInt32),
|
||||
execution_nbbo_ask_size Nullable(UInt32),
|
||||
execution_nbbo_ts Nullable(UInt64),
|
||||
execution_nbbo_age_ms Nullable(Float64),
|
||||
execution_nbbo_side Nullable(String),
|
||||
execution_underlying_spot Nullable(Float64),
|
||||
execution_underlying_bid Nullable(Float64),
|
||||
execution_underlying_ask Nullable(Float64),
|
||||
execution_underlying_mid Nullable(Float64),
|
||||
execution_underlying_spread Nullable(Float64),
|
||||
execution_underlying_ts Nullable(UInt64),
|
||||
execution_underlying_age_ms Nullable(Float64),
|
||||
execution_underlying_source Nullable(String),
|
||||
execution_iv Nullable(Float64),
|
||||
execution_iv_source Nullable(String),
|
||||
is_etf Nullable(Bool),
|
||||
signal_pass Nullable(Bool),
|
||||
signal_reasons Array(String) DEFAULT [],
|
||||
|
|
@ -35,6 +54,25 @@ export const optionPrintsTableMigrations = (): string[] => {
|
|||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS option_type Nullable(String)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS notional Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS nbbo_side Nullable(String)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_bid Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_ask Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_mid Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_spread Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_bid_size Nullable(UInt32)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_ask_size Nullable(UInt32)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_ts Nullable(UInt64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_age_ms Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_nbbo_side Nullable(String)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_spot Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_bid Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_ask Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_mid Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_spread Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_ts Nullable(UInt64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_age_ms Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_underlying_source Nullable(String)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_iv Nullable(Float64)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS execution_iv_source Nullable(String)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS is_etf Nullable(Bool)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS signal_pass Nullable(Bool)`,
|
||||
`ALTER TABLE ${OPTION_PRINTS_TABLE} ADD COLUMN IF NOT EXISTS signal_reasons Array(String) DEFAULT []`,
|
||||
|
|
|
|||
|
|
@ -25,10 +25,20 @@ describe("option-prints storage helpers", () => {
|
|||
expect(normalized.conditions).toEqual([]);
|
||||
});
|
||||
|
||||
it("normalizes legacy rows with missing execution context", () => {
|
||||
const normalized = normalizeOptionPrint(basePrint);
|
||||
expect(normalized.execution_nbbo_bid).toBeUndefined();
|
||||
expect(normalized.execution_underlying_spot).toBeUndefined();
|
||||
expect(normalized.execution_iv).toBeUndefined();
|
||||
});
|
||||
|
||||
it("includes the correct table name in the DDL", () => {
|
||||
const ddl = optionPrintsTableDDL();
|
||||
expect(ddl).toContain(OPTION_PRINTS_TABLE);
|
||||
expect(ddl).toContain("CREATE TABLE IF NOT EXISTS");
|
||||
expect(ddl).toContain("execution_nbbo_bid Nullable(Float64)");
|
||||
expect(ddl).toContain("execution_underlying_spot Nullable(Float64)");
|
||||
expect(ddl).toContain("execution_iv Nullable(Float64)");
|
||||
});
|
||||
|
||||
it("builds before/history and trace lookup queries", async () => {
|
||||
|
|
|
|||
|
|
@ -22,6 +22,31 @@ export const OptionPrintSchema = EventMetaSchema.merge(
|
|||
option_type: z.preprocess((value) => (value === null ? undefined : value), OptionTypeSchema.optional()),
|
||||
notional: z.preprocess((value) => (value === null ? undefined : value), z.number().nonnegative().optional()),
|
||||
nbbo_side: z.preprocess((value) => (value === null ? undefined : value), OptionNbboSideSchema.optional()),
|
||||
execution_nbbo_bid: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_nbbo_ask: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_nbbo_mid: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_nbbo_spread: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_nbbo_bid_size: z.preprocess((value) => (value === null ? undefined : value), z.number().int().nonnegative().optional()),
|
||||
execution_nbbo_ask_size: z.preprocess((value) => (value === null ? undefined : value), z.number().int().nonnegative().optional()),
|
||||
execution_nbbo_ts: z.preprocess((value) => (value === null ? undefined : value), z.number().int().nonnegative().optional()),
|
||||
execution_nbbo_age_ms: z.preprocess((value) => (value === null ? undefined : value), z.number().nonnegative().optional()),
|
||||
execution_nbbo_side: z.preprocess((value) => (value === null ? undefined : value), OptionNbboSideSchema.optional()),
|
||||
execution_underlying_spot: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_underlying_bid: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_underlying_ask: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_underlying_mid: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_underlying_spread: z.preprocess((value) => (value === null ? undefined : value), z.number().optional()),
|
||||
execution_underlying_ts: z.preprocess((value) => (value === null ? undefined : value), z.number().int().nonnegative().optional()),
|
||||
execution_underlying_age_ms: z.preprocess((value) => (value === null ? undefined : value), z.number().nonnegative().optional()),
|
||||
execution_underlying_source: z.preprocess(
|
||||
(value) => (value === null ? undefined : value),
|
||||
z.literal("equity_quote_mid").optional()
|
||||
),
|
||||
execution_iv: z.preprocess((value) => (value === null ? undefined : value), z.number().nonnegative().optional()),
|
||||
execution_iv_source: z.preprocess(
|
||||
(value) => (value === null ? undefined : value),
|
||||
z.enum(["provider", "synthetic_pressure_model"]).optional()
|
||||
),
|
||||
is_etf: z.preprocess((value) => (value === null ? undefined : value), z.boolean().optional()),
|
||||
signal_pass: z.preprocess((value) => (value === null ? undefined : value), z.boolean().optional()),
|
||||
signal_reasons: z.array(z.string().min(1)).optional(),
|
||||
|
|
|
|||
41
packages/types/tests/events.test.ts
Normal file
41
packages/types/tests/events.test.ts
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
import { describe, expect, it } from "bun:test";
|
||||
import { OptionPrintSchema } from "../src/events";
|
||||
|
||||
describe("event schemas", () => {
|
||||
it("accepts option print execution context fields", () => {
|
||||
const parsed = OptionPrintSchema.parse({
|
||||
source_ts: 100,
|
||||
ingest_ts: 101,
|
||||
seq: 1,
|
||||
trace_id: "trace-1",
|
||||
ts: 100,
|
||||
option_contract_id: "SPY-2025-01-17-450-C",
|
||||
price: 1.25,
|
||||
size: 10,
|
||||
exchange: "TEST",
|
||||
execution_nbbo_bid: 1.2,
|
||||
execution_nbbo_ask: 1.3,
|
||||
execution_nbbo_mid: 1.25,
|
||||
execution_nbbo_spread: 0.1,
|
||||
execution_nbbo_bid_size: 20,
|
||||
execution_nbbo_ask_size: 30,
|
||||
execution_nbbo_ts: 99,
|
||||
execution_nbbo_age_ms: 1,
|
||||
execution_nbbo_side: "MID",
|
||||
execution_underlying_spot: 450.05,
|
||||
execution_underlying_bid: 450,
|
||||
execution_underlying_ask: 450.1,
|
||||
execution_underlying_mid: 450.05,
|
||||
execution_underlying_spread: 0.1,
|
||||
execution_underlying_ts: 98,
|
||||
execution_underlying_age_ms: 2,
|
||||
execution_underlying_source: "equity_quote_mid",
|
||||
execution_iv: 0.42,
|
||||
execution_iv_source: "synthetic_pressure_model"
|
||||
});
|
||||
|
||||
expect(parsed.execution_nbbo_side).toBe("MID");
|
||||
expect(parsed.execution_underlying_spot).toBe(450.05);
|
||||
expect(parsed.execution_iv_source).toBe("synthetic_pressure_model");
|
||||
});
|
||||
});
|
||||
Loading…
Add table
Add a link
Reference in a new issue