This commit is contained in:
parent
65139bf8d0
commit
44431c4e66
71 changed files with 2262 additions and 1173 deletions
|
|
@ -16,7 +16,11 @@ import {
|
|||
nanos,
|
||||
millis
|
||||
} from "nats";
|
||||
import { getKnownStreamDefinitions, getStreamDefinition, type StreamRetentionClass } from "./streams";
|
||||
import {
|
||||
getKnownStreamDefinitions,
|
||||
getStreamDefinition,
|
||||
type StreamRetentionClass
|
||||
} from "./streams";
|
||||
|
||||
export type NatsConnectionOptions = {
|
||||
servers: string | string[];
|
||||
|
|
@ -251,9 +255,10 @@ const diffConfigFields = (
|
|||
for (const field of fields) {
|
||||
const currentValue = getFieldValue(current, field);
|
||||
const desiredValue = getFieldValue(desired, field);
|
||||
const matches = Array.isArray(currentValue) && Array.isArray(desiredValue)
|
||||
? arraysEqual(currentValue, desiredValue)
|
||||
: currentValue === desiredValue;
|
||||
const matches =
|
||||
Array.isArray(currentValue) && Array.isArray(desiredValue)
|
||||
? arraysEqual(currentValue, desiredValue)
|
||||
: currentValue === desiredValue;
|
||||
|
||||
if (!matches) {
|
||||
deltas.push({
|
||||
|
|
@ -391,7 +396,10 @@ const formatStructuredValue = (value: unknown): string => {
|
|||
|
||||
const formatStructuralMismatchMessage = (audit: StreamAuditReport): string => {
|
||||
const details = audit.structuralMismatch
|
||||
.map((delta) => `${delta.field} current=${formatStructuredValue(delta.current)} desired=${formatStructuredValue(delta.desired)}`)
|
||||
.map(
|
||||
(delta) =>
|
||||
`${delta.field} current=${formatStructuredValue(delta.current)} desired=${formatStructuredValue(delta.desired)}`
|
||||
)
|
||||
.join("; ");
|
||||
return `Refusing to reconcile stream ${audit.name}: structural mismatch (${details})`;
|
||||
};
|
||||
|
|
@ -447,16 +455,18 @@ const formatReportLine = (
|
|||
case "retention_drift": {
|
||||
const details = report.retentionDrift
|
||||
.map((delta) => {
|
||||
const desiredValue = delta.field === "max_age"
|
||||
? formatDurationMs(millis(Number(delta.desired)))
|
||||
: delta.field === "max_bytes"
|
||||
? formatBytes(Number(delta.desired))
|
||||
: formatStructuredValue(delta.desired);
|
||||
const currentValue = delta.field === "max_age"
|
||||
? formatDurationMs(millis(Number(delta.current)))
|
||||
: delta.field === "max_bytes"
|
||||
? formatBytes(Number(delta.current))
|
||||
: formatStructuredValue(delta.current);
|
||||
const desiredValue =
|
||||
delta.field === "max_age"
|
||||
? formatDurationMs(millis(Number(delta.desired)))
|
||||
: delta.field === "max_bytes"
|
||||
? formatBytes(Number(delta.desired))
|
||||
: formatStructuredValue(delta.desired);
|
||||
const currentValue =
|
||||
delta.field === "max_age"
|
||||
? formatDurationMs(millis(Number(delta.current)))
|
||||
: delta.field === "max_bytes"
|
||||
? formatBytes(Number(delta.current))
|
||||
: formatStructuredValue(delta.current);
|
||||
return `${delta.field}:${currentValue}->${desiredValue}`;
|
||||
})
|
||||
.join(" ");
|
||||
|
|
@ -464,7 +474,10 @@ const formatReportLine = (
|
|||
}
|
||||
case "structural_mismatch": {
|
||||
const details = report.structuralMismatch
|
||||
.map((delta) => `${delta.field}:${formatStructuredValue(delta.current)}->${formatStructuredValue(delta.desired)}`)
|
||||
.map(
|
||||
(delta) =>
|
||||
`${delta.field}:${formatStructuredValue(delta.current)}->${formatStructuredValue(delta.desired)}`
|
||||
)
|
||||
.join(" ");
|
||||
return `● ${report.name} structural-mismatch ${details}`;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -59,7 +59,9 @@ export const STREAM_CATALOG: readonly KnownStreamDefinition[] = [
|
|||
{ name: STREAM_NEWS, subject: SUBJECT_NEWS, retentionClass: "derived" }
|
||||
];
|
||||
|
||||
const STREAM_CATALOG_BY_NAME = new Map(STREAM_CATALOG.map((definition) => [definition.name, definition]));
|
||||
const STREAM_CATALOG_BY_NAME = new Map(
|
||||
STREAM_CATALOG.map((definition) => [definition.name, definition])
|
||||
);
|
||||
|
||||
export const getKnownStreamDefinitions = (): readonly KnownStreamDefinition[] => {
|
||||
return STREAM_CATALOG;
|
||||
|
|
|
|||
|
|
@ -11,44 +11,31 @@ export const SYNTHETIC_CONTROL_GLOBAL_KEY = "global";
|
|||
|
||||
const codec = JSONCodec<SyntheticControlState>();
|
||||
|
||||
const decodeSyntheticControlEntry = (
|
||||
entry: KvEntry | null | undefined
|
||||
): SyntheticControlState => {
|
||||
const decodeSyntheticControlEntry = (entry: KvEntry | null | undefined): SyntheticControlState => {
|
||||
if (!entry || entry.operation !== "PUT") {
|
||||
return DEFAULT_SYNTHETIC_CONTROL_STATE;
|
||||
}
|
||||
return SyntheticControlStateSchema.parse(entry.json());
|
||||
};
|
||||
|
||||
export const openSyntheticControlKv = async (
|
||||
js: JetStreamClient
|
||||
): Promise<KV> => {
|
||||
export const openSyntheticControlKv = async (js: JetStreamClient): Promise<KV> => {
|
||||
return js.views.kv(SYNTHETIC_CONTROL_BUCKET, {
|
||||
description: "Hosted synthetic market internal control state",
|
||||
history: 8
|
||||
});
|
||||
};
|
||||
|
||||
export const readSyntheticControlState = async (
|
||||
kv: KV
|
||||
): Promise<SyntheticControlState> => {
|
||||
return decodeSyntheticControlEntry(
|
||||
await kv.get(SYNTHETIC_CONTROL_GLOBAL_KEY)
|
||||
);
|
||||
export const readSyntheticControlState = async (kv: KV): Promise<SyntheticControlState> => {
|
||||
return decodeSyntheticControlEntry(await kv.get(SYNTHETIC_CONTROL_GLOBAL_KEY));
|
||||
};
|
||||
|
||||
export const ensureSyntheticControlState = async (
|
||||
kv: KV
|
||||
): Promise<SyntheticControlState> => {
|
||||
export const ensureSyntheticControlState = async (kv: KV): Promise<SyntheticControlState> => {
|
||||
const current = await kv.get(SYNTHETIC_CONTROL_GLOBAL_KEY);
|
||||
if (current && current.operation === "PUT") {
|
||||
return SyntheticControlStateSchema.parse(current.json());
|
||||
}
|
||||
|
||||
await kv.put(
|
||||
SYNTHETIC_CONTROL_GLOBAL_KEY,
|
||||
codec.encode(DEFAULT_SYNTHETIC_CONTROL_STATE)
|
||||
);
|
||||
await kv.put(SYNTHETIC_CONTROL_GLOBAL_KEY, codec.encode(DEFAULT_SYNTHETIC_CONTROL_STATE));
|
||||
return DEFAULT_SYNTHETIC_CONTROL_STATE;
|
||||
};
|
||||
|
||||
|
|
@ -57,10 +44,7 @@ export const writeSyntheticControlState = async (
|
|||
control: Partial<SyntheticControlState>
|
||||
): Promise<SyntheticControlState> => {
|
||||
const normalized = normalizeSyntheticControlState(control);
|
||||
await kv.put(
|
||||
SYNTHETIC_CONTROL_GLOBAL_KEY,
|
||||
codec.encode(normalized)
|
||||
);
|
||||
await kv.put(SYNTHETIC_CONTROL_GLOBAL_KEY, codec.encode(normalized));
|
||||
return normalized;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -43,10 +43,9 @@ const buildMockStreamManager = (configs: Record<string, StreamConfig | null>) =>
|
|||
};
|
||||
|
||||
const buildAllKnownConfigs = (env: Record<string, string | undefined> = {}) => {
|
||||
return Object.fromEntries(STREAMS.map((name) => [name, buildKnownStreamConfig(name, env)])) as Record<
|
||||
string,
|
||||
StreamConfig
|
||||
>;
|
||||
return Object.fromEntries(
|
||||
STREAMS.map((name) => [name, buildKnownStreamConfig(name, env)])
|
||||
) as Record<string, StreamConfig>;
|
||||
};
|
||||
|
||||
describe("jetstream retention defaults", () => {
|
||||
|
|
@ -194,7 +193,9 @@ describe("runReconcileStreamsCommand", () => {
|
|||
});
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(outputs.some((line) => line.includes("OPTIONS_PRINTS") && line.includes("drift"))).toBe(true);
|
||||
expect(outputs.some((line) => line.includes("OPTIONS_PRINTS") && line.includes("drift"))).toBe(
|
||||
true
|
||||
);
|
||||
});
|
||||
|
||||
it("updates drift in --apply mode and reports actions", async () => {
|
||||
|
|
@ -240,7 +241,11 @@ describe("runReconcileStreamsCommand", () => {
|
|||
});
|
||||
|
||||
expect(exitCode).toBe(1);
|
||||
expect(outputs.some((line) => line.includes("OPTIONS_PRINTS") && line.includes("structural-mismatch"))).toBe(true);
|
||||
expect(
|
||||
outputs.some(
|
||||
(line) => line.includes("OPTIONS_PRINTS") && line.includes("structural-mismatch")
|
||||
)
|
||||
).toBe(true);
|
||||
expect(errors.some((line) => line.includes("OPTIONS_PRINTS"))).toBe(true);
|
||||
});
|
||||
});
|
||||
|
|
|
|||
|
|
@ -15,14 +15,10 @@ type AlpacaCredentialEnv = {
|
|||
|
||||
const normalize = (value: string | undefined): string => value?.trim() ?? "";
|
||||
|
||||
export const resolveAlpacaCredentials = (
|
||||
env: AlpacaCredentialEnv
|
||||
): AlpacaCredentials => {
|
||||
export const resolveAlpacaCredentials = (env: AlpacaCredentialEnv): AlpacaCredentials => {
|
||||
const legacyToken = normalize(env.ALPACA_API_KEY);
|
||||
const explicitKeyId =
|
||||
normalize(env.ALPACA_API_KEY_ID) || normalize(env.ALPACA_KEY_ID);
|
||||
const secret =
|
||||
normalize(env.ALPACA_API_SECRET_KEY) || normalize(env.ALPACA_SECRET_KEY);
|
||||
const explicitKeyId = normalize(env.ALPACA_API_KEY_ID) || normalize(env.ALPACA_KEY_ID);
|
||||
const secret = normalize(env.ALPACA_API_SECRET_KEY) || normalize(env.ALPACA_SECRET_KEY);
|
||||
const keyId = explicitKeyId || legacyToken;
|
||||
const usesLegacyBearer = !explicitKeyId && !secret && legacyToken.length > 0;
|
||||
|
||||
|
|
@ -42,9 +38,7 @@ export const hasAlpacaCredentials = (credentials: AlpacaCredentials): boolean =>
|
|||
return credentials.keyId.length > 0 && credentials.secret.length > 0;
|
||||
};
|
||||
|
||||
export const buildAlpacaAuthHeaders = (
|
||||
credentials: AlpacaCredentials
|
||||
): Record<string, string> => {
|
||||
export const buildAlpacaAuthHeaders = (credentials: AlpacaCredentials): Record<string, string> => {
|
||||
if (credentials.usesLegacyBearer) {
|
||||
return {
|
||||
Authorization: `Bearer ${credentials.legacyToken}`
|
||||
|
|
|
|||
|
|
@ -99,7 +99,9 @@ const safeProfileScoreArray = (value: string): SmartMoneyProfileScore[] => {
|
|||
return {
|
||||
profile_id: String(record.profile_id ?? "") as SmartMoneyProfileScore["profile_id"],
|
||||
probability: Number(record.probability ?? 0),
|
||||
confidence_band: String(record.confidence_band ?? "low") as SmartMoneyProfileScore["confidence_band"],
|
||||
confidence_band: String(
|
||||
record.confidence_band ?? "low"
|
||||
) as SmartMoneyProfileScore["confidence_band"],
|
||||
direction: String(record.direction ?? "unknown") as SmartMoneyProfileScore["direction"],
|
||||
reasons: Array.isArray(record.reasons) ? record.reasons.map((item) => String(item)) : []
|
||||
};
|
||||
|
|
@ -122,7 +124,9 @@ export const fromAlertRecord = (record: AlertRecord): AlertEvent => {
|
|||
severity: record.severity,
|
||||
hits: safeHitArray(record.hits_json),
|
||||
evidence_refs: safeStringArray(record.evidence_refs_json),
|
||||
...(record.primary_profile_id ? { primary_profile_id: record.primary_profile_id as AlertEvent["primary_profile_id"] } : {}),
|
||||
...(record.primary_profile_id
|
||||
? { primary_profile_id: record.primary_profile_id as AlertEvent["primary_profile_id"] }
|
||||
: {}),
|
||||
profile_scores: safeProfileScoreArray(record.profile_scores_json)
|
||||
};
|
||||
};
|
||||
|
|
|
|||
|
|
@ -35,16 +35,8 @@ import {
|
|||
OPTION_PRINTS_TABLE
|
||||
} from "./option-prints";
|
||||
import { normalizeOptionNBBO, optionNBBOTableDDL, OPTION_NBBO_TABLE } from "./option-nbbo";
|
||||
import {
|
||||
equityPrintsTableDDL,
|
||||
EQUITY_PRINTS_TABLE,
|
||||
normalizeEquityPrint
|
||||
} from "./equity-prints";
|
||||
import {
|
||||
equityQuotesTableDDL,
|
||||
EQUITY_QUOTES_TABLE,
|
||||
normalizeEquityQuote
|
||||
} from "./equity-quotes";
|
||||
import { equityPrintsTableDDL, EQUITY_PRINTS_TABLE, normalizeEquityPrint } from "./equity-prints";
|
||||
import { equityQuotesTableDDL, EQUITY_QUOTES_TABLE, normalizeEquityQuote } from "./equity-quotes";
|
||||
import {
|
||||
equityCandlesTableDDL,
|
||||
EQUITY_CANDLES_TABLE,
|
||||
|
|
@ -93,13 +85,7 @@ import {
|
|||
toSmartMoneyEventRecord,
|
||||
type SmartMoneyEventRecord
|
||||
} from "./smart-money-events";
|
||||
import {
|
||||
NEWS_TABLE,
|
||||
newsTableDDL,
|
||||
fromNewsRecord,
|
||||
toNewsRecord,
|
||||
type NewsRecord
|
||||
} from "./news";
|
||||
import { NEWS_TABLE, newsTableDDL, fromNewsRecord, toNewsRecord, type NewsRecord } from "./news";
|
||||
|
||||
export type ClickHouseOptions = {
|
||||
url: string;
|
||||
|
|
@ -116,7 +102,11 @@ type ClickHouseQueryResult = {
|
|||
|
||||
export type ClickHouseClient = {
|
||||
exec(params: { query: string }): Promise<void>;
|
||||
insert(params: { table: string; values: unknown[]; format: ClickHouseQueryFormat }): Promise<void>;
|
||||
insert(params: {
|
||||
table: string;
|
||||
values: unknown[];
|
||||
format: ClickHouseQueryFormat;
|
||||
}): Promise<void>;
|
||||
query(params: { query: string; format: ClickHouseQueryFormat }): Promise<ClickHouseQueryResult>;
|
||||
ping(): Promise<{ success: boolean; error?: Error }>;
|
||||
close(): Promise<void>;
|
||||
|
|
@ -140,7 +130,9 @@ const buildHeaders = (options: ClickHouseOptions, hasBody: boolean): Headers =>
|
|||
}
|
||||
|
||||
if (options.username || options.password) {
|
||||
const auth = Buffer.from(`${options.username ?? "default"}:${options.password ?? ""}`).toString("base64");
|
||||
const auth = Buffer.from(`${options.username ?? "default"}:${options.password ?? ""}`).toString(
|
||||
"base64"
|
||||
);
|
||||
headers.set("authorization", `Basic ${auth}`);
|
||||
}
|
||||
|
||||
|
|
@ -217,7 +209,8 @@ export const createClickHouseClient = (options: ClickHouseOptions): ClickHouseCl
|
|||
});
|
||||
|
||||
if (!response.ok) {
|
||||
const message = (await response.text()).trim() || `${response.status} ${response.statusText}`;
|
||||
const message =
|
||||
(await response.text()).trim() || `${response.status} ${response.statusText}`;
|
||||
return { success: false, error: new Error(message) };
|
||||
}
|
||||
|
||||
|
|
@ -237,9 +230,7 @@ export const createClickHouseClient = (options: ClickHouseOptions): ClickHouseCl
|
|||
};
|
||||
};
|
||||
|
||||
export const ensureOptionPrintsTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureOptionPrintsTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: optionPrintsTableDDL()
|
||||
});
|
||||
|
|
@ -248,73 +239,55 @@ export const ensureOptionPrintsTable = async (
|
|||
}
|
||||
};
|
||||
|
||||
export const ensureOptionNBBOTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureOptionNBBOTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: optionNBBOTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureEquityPrintsTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureEquityPrintsTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: equityPrintsTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureEquityQuotesTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureEquityQuotesTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: equityQuotesTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureEquityCandlesTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureEquityCandlesTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: equityCandlesTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureEquityPrintJoinsTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureEquityPrintJoinsTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: equityPrintJoinsTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureInferredDarkTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureInferredDarkTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: inferredDarkTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureFlowPacketsTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureFlowPacketsTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: flowPacketsTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureSmartMoneyEventsTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureSmartMoneyEventsTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: smartMoneyEventsTableDDL()
|
||||
});
|
||||
};
|
||||
|
||||
export const ensureClassifierHitsTable = async (
|
||||
client: ClickHouseClient
|
||||
): Promise<void> => {
|
||||
export const ensureClassifierHitsTable = async (client: ClickHouseClient): Promise<void> => {
|
||||
await client.exec({
|
||||
query: classifierHitsTableDDL()
|
||||
});
|
||||
|
|
@ -464,7 +437,10 @@ export const insertAlert = async (client: ClickHouseClient, alert: AlertEvent):
|
|||
});
|
||||
};
|
||||
|
||||
export const insertNewsStory = async (client: ClickHouseClient, story: NewsStory): Promise<void> => {
|
||||
export const insertNewsStory = async (
|
||||
client: ClickHouseClient,
|
||||
story: NewsStory
|
||||
): Promise<void> => {
|
||||
const record = toNewsRecord(story);
|
||||
await client.insert({
|
||||
table: NEWS_TABLE,
|
||||
|
|
@ -617,17 +593,11 @@ export const enqueueClassifierHitInsert = (
|
|||
writer.enqueue(CLASSIFIER_HITS_TABLE, toClassifierHitRecord(hit));
|
||||
};
|
||||
|
||||
export const enqueueAlertInsert = (
|
||||
writer: ClickHouseBatchWriter,
|
||||
alert: AlertEvent
|
||||
): void => {
|
||||
export const enqueueAlertInsert = (writer: ClickHouseBatchWriter, alert: AlertEvent): void => {
|
||||
writer.enqueue(ALERTS_TABLE, toAlertRecord(alert));
|
||||
};
|
||||
|
||||
export const enqueueNewsStoryInsert = (
|
||||
writer: ClickHouseBatchWriter,
|
||||
story: NewsStory
|
||||
): void => {
|
||||
export const enqueueNewsStoryInsert = (writer: ClickHouseBatchWriter, story: NewsStory): void => {
|
||||
writer.enqueue(NEWS_TABLE, toNewsRecord(story));
|
||||
};
|
||||
|
||||
|
|
@ -973,9 +943,7 @@ const normalizeFlowPacketRow = (row: unknown): FlowPacketRecord | null => {
|
|||
seq: coerceNumber(record.seq) as number,
|
||||
trace_id: String(record.trace_id ?? ""),
|
||||
id: String(record.id ?? ""),
|
||||
members: Array.isArray(record.members)
|
||||
? record.members.map((value) => String(value))
|
||||
: [],
|
||||
members: Array.isArray(record.members) ? record.members.map((value) => String(value)) : [],
|
||||
features_json: String(record.features_json ?? "{}"),
|
||||
join_quality_json: String(record.join_quality_json ?? "{}")
|
||||
};
|
||||
|
|
@ -1011,7 +979,9 @@ const normalizeSmartMoneyEventRow = (row: unknown): SmartMoneyEventRecord | null
|
|||
seq: coerceNumber(record.seq) as number,
|
||||
trace_id: String(record.trace_id ?? ""),
|
||||
event_id: String(record.event_id ?? ""),
|
||||
packet_ids: Array.isArray(record.packet_ids) ? record.packet_ids.map((value) => String(value)) : [],
|
||||
packet_ids: Array.isArray(record.packet_ids)
|
||||
? record.packet_ids.map((value) => String(value))
|
||||
: [],
|
||||
member_print_ids: Array.isArray(record.member_print_ids)
|
||||
? record.member_print_ids.map((value) => String(value))
|
||||
: [],
|
||||
|
|
@ -1390,8 +1360,12 @@ export const fetchAlertContextByTraceId = async (
|
|||
const packetIds = new Set(flowPackets.flatMap((packet) => [packet.id, packet.trace_id]));
|
||||
const printIds = new Set(optionPrints.map((print) => print.trace_id));
|
||||
const missingRefs = refs.filter((ref) => {
|
||||
const packetResolved = flowPacketCandidatesFromRef(ref).some((candidate) => packetIds.has(candidate));
|
||||
const printResolved = optionPrintCandidatesFromRef(ref).some((candidate) => printIds.has(candidate));
|
||||
const packetResolved = flowPacketCandidatesFromRef(ref).some((candidate) =>
|
||||
packetIds.has(candidate)
|
||||
);
|
||||
const printResolved = optionPrintCandidatesFromRef(ref).some((candidate) =>
|
||||
printIds.has(candidate)
|
||||
);
|
||||
return !packetResolved && !printResolved;
|
||||
});
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,10 @@ describe("alerts storage helpers", () => {
|
|||
});
|
||||
|
||||
it("returns an empty context when the alert is missing", async () => {
|
||||
const bundle = await fetchAlertContextByTraceId(makeClient(() => []), "alert:missing");
|
||||
const bundle = await fetchAlertContextByTraceId(
|
||||
makeClient(() => []),
|
||||
"alert:missing"
|
||||
);
|
||||
|
||||
expect(bundle).toEqual({
|
||||
alert: null,
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
import { describe, expect, it } from "bun:test";
|
||||
import { createClickHouseClient, fetchFlowPacketById, fetchFlowPacketsBefore } from "../src/clickhouse";
|
||||
import {
|
||||
createClickHouseClient,
|
||||
fetchFlowPacketById,
|
||||
fetchFlowPacketsBefore
|
||||
} from "../src/clickhouse";
|
||||
import {
|
||||
flowPacketsTableDDL,
|
||||
FLOW_PACKETS_TABLE,
|
||||
|
|
|
|||
|
|
@ -1,16 +1,7 @@
|
|||
import { describe, expect, it } from "bun:test";
|
||||
import type { ClickHouseClient } from "../src/clickhouse";
|
||||
import {
|
||||
NEWS_TABLE,
|
||||
fromNewsRecord,
|
||||
newsTableDDL,
|
||||
toNewsRecord
|
||||
} from "../src/news";
|
||||
import {
|
||||
fetchNewsAfter,
|
||||
fetchNewsBefore,
|
||||
fetchRecentNews
|
||||
} from "../src/clickhouse";
|
||||
import { NEWS_TABLE, fromNewsRecord, newsTableDDL, toNewsRecord } from "../src/news";
|
||||
import { fetchNewsAfter, fetchNewsBefore, fetchRecentNews } from "../src/clickhouse";
|
||||
|
||||
const makeClient = (resolver: (query: string) => unknown[]): ClickHouseClient =>
|
||||
({
|
||||
|
|
|
|||
|
|
@ -5,7 +5,11 @@ import {
|
|||
fetchOptionPrintsByTraceIds,
|
||||
fetchRecentOptionPrints
|
||||
} from "../src/clickhouse";
|
||||
import { normalizeOptionPrint, optionPrintsTableDDL, OPTION_PRINTS_TABLE } from "../src/option-prints";
|
||||
import {
|
||||
normalizeOptionPrint,
|
||||
optionPrintsTableDDL,
|
||||
OPTION_PRINTS_TABLE
|
||||
} from "../src/option-prints";
|
||||
|
||||
const basePrint = {
|
||||
source_ts: 100,
|
||||
|
|
|
|||
|
|
@ -18,37 +18,103 @@ export const OptionPrintSchema = EventMetaSchema.merge(
|
|||
size: z.number().int().positive(),
|
||||
exchange: z.string().min(1),
|
||||
conditions: z.array(z.string().min(1)).optional(),
|
||||
underlying_id: z.preprocess((value) => (value === null ? undefined : value), z.string().min(1).optional()),
|
||||
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()),
|
||||
underlying_id: z.preprocess(
|
||||
(value) => (value === null ? undefined : value),
|
||||
z.string().min(1).optional()
|
||||
),
|
||||
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: 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_pass: z.preprocess(
|
||||
(value) => (value === null ? undefined : value),
|
||||
z.boolean().optional()
|
||||
),
|
||||
signal_reasons: z.array(z.string().min(1)).optional(),
|
||||
signal_profile: z.preprocess(
|
||||
(value) => (value === null ? undefined : value),
|
||||
|
|
@ -146,7 +212,13 @@ export const SmartMoneyProfileIdSchema = z.enum([
|
|||
|
||||
export type SmartMoneyProfileId = z.infer<typeof SmartMoneyProfileIdSchema>;
|
||||
|
||||
export const SmartMoneyDirectionSchema = z.enum(["bullish", "bearish", "neutral", "mixed", "unknown"]);
|
||||
export const SmartMoneyDirectionSchema = z.enum([
|
||||
"bullish",
|
||||
"bearish",
|
||||
"neutral",
|
||||
"mixed",
|
||||
"unknown"
|
||||
]);
|
||||
|
||||
export type SmartMoneyDirection = z.infer<typeof SmartMoneyDirectionSchema>;
|
||||
|
||||
|
|
|
|||
|
|
@ -13,10 +13,7 @@ import {
|
|||
OptionPrintSchema,
|
||||
SmartMoneyEventSchema
|
||||
} from "./events";
|
||||
import {
|
||||
OptionFlowFiltersSchema,
|
||||
optionFlowFilterKey
|
||||
} from "./options-flow";
|
||||
import { OptionFlowFiltersSchema, optionFlowFilterKey } from "./options-flow";
|
||||
|
||||
export const CursorSchema = z.object({
|
||||
ts: z.number().int().nonnegative(),
|
||||
|
|
@ -94,7 +91,15 @@ export const LiveSubscriptionSchema = z.discriminatedUnion("channel", [
|
|||
snapshot_limit: z.number().int().positive().optional()
|
||||
}),
|
||||
z.object({
|
||||
channel: z.enum(["nbbo", "equity-quotes", "equity-joins", "classifier-hits", "alerts", "inferred-dark", "news"]),
|
||||
channel: z.enum([
|
||||
"nbbo",
|
||||
"equity-quotes",
|
||||
"equity-joins",
|
||||
"classifier-hits",
|
||||
"alerts",
|
||||
"inferred-dark",
|
||||
"news"
|
||||
]),
|
||||
snapshot_limit: z.number().int().positive().optional()
|
||||
}),
|
||||
z.object({
|
||||
|
|
|
|||
|
|
@ -212,9 +212,10 @@ export const deriveOptionPrintMetadata = (
|
|||
const parsed = parseOptionContractId(print.option_contract_id);
|
||||
const underlying = parsed?.root?.toUpperCase();
|
||||
const optionType = parsed?.right === "C" ? "call" : parsed?.right === "P" ? "put" : undefined;
|
||||
const notional = Number.isFinite(print.price) && Number.isFinite(print.size)
|
||||
? Number((print.price * print.size * 100).toFixed(2))
|
||||
: undefined;
|
||||
const notional =
|
||||
Number.isFinite(print.price) && Number.isFinite(print.size)
|
||||
? Number((print.price * print.size * 100).toFixed(2))
|
||||
: undefined;
|
||||
|
||||
return {
|
||||
underlying_id: underlying,
|
||||
|
|
@ -243,7 +244,14 @@ const balancedThresholds = (config: OptionsSignalConfig): OptionsSignalConfig =>
|
|||
export const evaluateOptionSignal = (
|
||||
print: Pick<
|
||||
OptionPrint,
|
||||
"size" | "conditions" | "signal_profile" | "underlying_id" | "option_type" | "notional" | "nbbo_side" | "is_etf"
|
||||
| "size"
|
||||
| "conditions"
|
||||
| "signal_profile"
|
||||
| "underlying_id"
|
||||
| "option_type"
|
||||
| "notional"
|
||||
| "nbbo_side"
|
||||
| "is_etf"
|
||||
>,
|
||||
baseConfig: OptionsSignalConfig
|
||||
): OptionSignalDecision => {
|
||||
|
|
@ -260,7 +268,8 @@ export const evaluateOptionSignal = (
|
|||
const reasons: string[] = [];
|
||||
const notional = print.notional ?? 0;
|
||||
const side = print.nbbo_side ?? "MISSING";
|
||||
const isSweepOrIso = hasCondition(print.conditions, "SWEEP") || hasCondition(print.conditions, "ISO");
|
||||
const isSweepOrIso =
|
||||
hasCondition(print.conditions, "SWEEP") || hasCondition(print.conditions, "ISO");
|
||||
|
||||
if (notional < config.minNotional) {
|
||||
return {
|
||||
|
|
@ -413,8 +422,14 @@ export const matchesFlowPacketFilters = (
|
|||
}
|
||||
|
||||
const features = packet.features ?? {};
|
||||
const totalNotional = typeof features.total_notional === "number" ? features.total_notional : Number(features.total_notional ?? 0);
|
||||
if (typeof filters.minNotional === "number" && (!Number.isFinite(totalNotional) || totalNotional < filters.minNotional)) {
|
||||
const totalNotional =
|
||||
typeof features.total_notional === "number"
|
||||
? features.total_notional
|
||||
: Number(features.total_notional ?? 0);
|
||||
if (
|
||||
typeof filters.minNotional === "number" &&
|
||||
(!Number.isFinite(totalNotional) || totalNotional < filters.minNotional)
|
||||
) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -433,10 +448,7 @@ export const matchesFlowPacketFilters = (
|
|||
: typeof features.structure_rights === "string"
|
||||
? features.structure_rights.toLowerCase()
|
||||
: null;
|
||||
if (
|
||||
!optionType ||
|
||||
!filters.optionTypes.some((selected) => optionType.includes(selected))
|
||||
) {
|
||||
if (!optionType || !filters.optionTypes.some((selected) => optionType.includes(selected))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -501,7 +501,7 @@ export const SP500_SYMBOLS = [
|
|||
"YUM",
|
||||
"ZBRA",
|
||||
"ZBH",
|
||||
"ZTS",
|
||||
"ZTS"
|
||||
] as const;
|
||||
|
||||
export type Sp500Symbol = typeof SP500_SYMBOLS[number];
|
||||
export type Sp500Symbol = (typeof SP500_SYMBOLS)[number];
|
||||
|
|
|
|||
|
|
@ -26,10 +26,7 @@ const SMART_MONEY_PROFILE_IDS = [
|
|||
"arbitrage",
|
||||
"hedge_reactive"
|
||||
] as const satisfies readonly SmartMoneyProfileId[];
|
||||
const SYNTHETIC_SCENARIO_FAMILY_IDS = [
|
||||
...SMART_MONEY_PROFILE_IDS,
|
||||
"neutral_noise"
|
||||
] as const;
|
||||
const SYNTHETIC_SCENARIO_FAMILY_IDS = [...SMART_MONEY_PROFILE_IDS, "neutral_noise"] as const;
|
||||
const REGIME_IDS = [
|
||||
"trend_up",
|
||||
"trend_down",
|
||||
|
|
@ -54,18 +51,14 @@ export const SyntheticCoverageWindowMinutesSchema = z.union([
|
|||
z.literal(20),
|
||||
z.literal(30)
|
||||
]);
|
||||
export type SyntheticCoverageWindowMinutes = z.infer<
|
||||
typeof SyntheticCoverageWindowMinutesSchema
|
||||
>;
|
||||
export type SyntheticCoverageWindowMinutes = z.infer<typeof SyntheticCoverageWindowMinutesSchema>;
|
||||
|
||||
export const SyntheticProfileWeightValueSchema = z.union([
|
||||
z.literal(0.6),
|
||||
z.literal(1.0),
|
||||
z.literal(1.6)
|
||||
]);
|
||||
export type SyntheticProfileWeightValue = z.infer<
|
||||
typeof SyntheticProfileWeightValueSchema
|
||||
>;
|
||||
export type SyntheticProfileWeightValue = z.infer<typeof SyntheticProfileWeightValueSchema>;
|
||||
|
||||
export const SyntheticProfileWeightMapSchema = z
|
||||
.object({
|
||||
|
|
@ -77,9 +70,7 @@ export const SyntheticProfileWeightMapSchema = z
|
|||
hedge_reactive: SyntheticProfileWeightValueSchema
|
||||
})
|
||||
.strict();
|
||||
export type SyntheticProfileWeightMap = z.infer<
|
||||
typeof SyntheticProfileWeightMapSchema
|
||||
>;
|
||||
export type SyntheticProfileWeightMap = z.infer<typeof SyntheticProfileWeightMapSchema>;
|
||||
|
||||
export const SyntheticControlStateSchema = z
|
||||
.object({
|
||||
|
|
@ -94,23 +85,14 @@ export const SyntheticControlStateSchema = z
|
|||
.strict();
|
||||
export type SyntheticControlState = z.infer<typeof SyntheticControlStateSchema>;
|
||||
|
||||
export const SyntheticSessionPhaseSchema = z.enum([
|
||||
"open",
|
||||
"midday",
|
||||
"power_hour",
|
||||
"after_event"
|
||||
]);
|
||||
export const SyntheticSessionPhaseSchema = z.enum(["open", "midday", "power_hour", "after_event"]);
|
||||
export type SyntheticSessionPhase = z.infer<typeof SyntheticSessionPhaseSchema>;
|
||||
|
||||
export const SyntheticRegimeSchema = z.enum(REGIME_IDS);
|
||||
export type SyntheticRegime = z.infer<typeof SyntheticRegimeSchema>;
|
||||
|
||||
export const SyntheticScenarioFamilyIdSchema = z.enum(
|
||||
SYNTHETIC_SCENARIO_FAMILY_IDS
|
||||
);
|
||||
export type SyntheticScenarioFamilyId = z.infer<
|
||||
typeof SyntheticScenarioFamilyIdSchema
|
||||
>;
|
||||
export const SyntheticScenarioFamilyIdSchema = z.enum(SYNTHETIC_SCENARIO_FAMILY_IDS);
|
||||
export type SyntheticScenarioFamilyId = z.infer<typeof SyntheticScenarioFamilyIdSchema>;
|
||||
|
||||
export const SyntheticCoverageConfigSchema = z
|
||||
.object({
|
||||
|
|
@ -118,9 +100,7 @@ export const SyntheticCoverageConfigSchema = z
|
|||
coverage_window_minutes: SyntheticCoverageWindowMinutesSchema
|
||||
})
|
||||
.strict();
|
||||
export type SyntheticCoverageConfig = z.infer<
|
||||
typeof SyntheticCoverageConfigSchema
|
||||
>;
|
||||
export type SyntheticCoverageConfig = z.infer<typeof SyntheticCoverageConfigSchema>;
|
||||
|
||||
export const SyntheticDerivedStatusSchema = z
|
||||
.object({
|
||||
|
|
@ -131,9 +111,7 @@ export const SyntheticDerivedStatusSchema = z
|
|||
coverage_window_minutes: SyntheticCoverageWindowMinutesSchema
|
||||
})
|
||||
.strict();
|
||||
export type SyntheticDerivedStatus = z.infer<
|
||||
typeof SyntheticDerivedStatusSchema
|
||||
>;
|
||||
export type SyntheticDerivedStatus = z.infer<typeof SyntheticDerivedStatusSchema>;
|
||||
|
||||
export type SyntheticSessionState = {
|
||||
session_phase: SyntheticSessionPhase;
|
||||
|
|
@ -160,10 +138,7 @@ export type SyntheticUnderlyingState = {
|
|||
offExchangeBias: number;
|
||||
};
|
||||
|
||||
export type SyntheticScenarioWeightMap = Record<
|
||||
SyntheticScenarioFamilyId,
|
||||
number
|
||||
>;
|
||||
export type SyntheticScenarioWeightMap = Record<SyntheticScenarioFamilyId, number>;
|
||||
|
||||
export type SyntheticCoverageState = {
|
||||
profile_hit_counts: Record<SmartMoneyProfileId, number>;
|
||||
|
|
@ -195,10 +170,7 @@ export const DEFAULT_SYNTHETIC_CONTROL_STATE: SyntheticControlState = {
|
|||
updated_by: "system"
|
||||
};
|
||||
|
||||
const PRESET_REGIME_BIAS: Record<
|
||||
SyntheticControlPresetId,
|
||||
Record<SyntheticRegime, number>
|
||||
> = {
|
||||
const PRESET_REGIME_BIAS: Record<SyntheticControlPresetId, Record<SyntheticRegime, number>> = {
|
||||
balanced_demo: {
|
||||
trend_up: 1.0,
|
||||
trend_down: 0.95,
|
||||
|
|
@ -257,10 +229,7 @@ const PRESET_ACTIVITY_BIAS: Record<
|
|||
quiet_range: { focusCount: 2, eventCount: 1, amplitude: 0.72 }
|
||||
};
|
||||
|
||||
const REGIME_PROFILE_BIAS: Record<
|
||||
SyntheticRegime,
|
||||
SyntheticScenarioWeightMap
|
||||
> = {
|
||||
const REGIME_PROFILE_BIAS: Record<SyntheticRegime, SyntheticScenarioWeightMap> = {
|
||||
trend_up: {
|
||||
institutional_directional: 1.35,
|
||||
retail_whale: 1.05,
|
||||
|
|
@ -411,16 +380,12 @@ const mixSeed = (...parts: number[]): number => {
|
|||
return seed >>> 0;
|
||||
};
|
||||
|
||||
const pick = <T,>(items: readonly T[], seed: number): T => {
|
||||
const pick = <T>(items: readonly T[], seed: number): T => {
|
||||
const index = Math.abs(seed) % items.length;
|
||||
return items[index]!;
|
||||
};
|
||||
|
||||
const pickManyUnique = <T,>(
|
||||
items: readonly T[],
|
||||
count: number,
|
||||
seed: number
|
||||
): T[] => {
|
||||
const pickManyUnique = <T>(items: readonly T[], count: number, seed: number): T[] => {
|
||||
const pool = [...items];
|
||||
const output: T[] = [];
|
||||
let cursor = seed;
|
||||
|
|
@ -432,10 +397,7 @@ const pickManyUnique = <T,>(
|
|||
return output;
|
||||
};
|
||||
|
||||
const weightedPick = <T extends string>(
|
||||
weights: Record<T, number>,
|
||||
seed: number
|
||||
): T => {
|
||||
const weightedPick = <T extends string>(weights: Record<T, number>, seed: number): T => {
|
||||
const entries = Object.entries(weights) as Array<[T, number]>;
|
||||
const total = entries.reduce((sum, [, weight]) => sum + Math.max(0.0001, weight), 0);
|
||||
let target = positiveNoise(seed) * total;
|
||||
|
|
@ -461,10 +423,7 @@ export const hashSyntheticSymbol = (value: string): number => {
|
|||
return hash;
|
||||
};
|
||||
|
||||
export const buildEmptySyntheticProfileHitCounts = (): Record<
|
||||
SmartMoneyProfileId,
|
||||
number
|
||||
> => ({
|
||||
export const buildEmptySyntheticProfileHitCounts = (): Record<SmartMoneyProfileId, number> => ({
|
||||
institutional_directional: 0,
|
||||
retail_whale: 0,
|
||||
event_driven: 0,
|
||||
|
|
@ -487,10 +446,7 @@ export const normalizeSyntheticControlState = (
|
|||
return SyntheticControlStateSchema.parse(merged);
|
||||
};
|
||||
|
||||
const resolvePhaseBias = (
|
||||
phase: SyntheticSessionPhase,
|
||||
regime: SyntheticRegime
|
||||
): number => {
|
||||
const resolvePhaseBias = (phase: SyntheticSessionPhase, regime: SyntheticRegime): number => {
|
||||
if (phase === "open") {
|
||||
return regime === "event_ramp" ? 1.08 : 1.02;
|
||||
}
|
||||
|
|
@ -566,10 +522,7 @@ export const getSyntheticSessionState = (
|
|||
mixSeed(activitySeed, 211)
|
||||
);
|
||||
const focus_symbols: string[] = pickManyUnique(
|
||||
[
|
||||
...event_symbols,
|
||||
...SYNTHETIC_SYMBOLS.filter((symbol) => !event_symbols.includes(symbol))
|
||||
],
|
||||
[...event_symbols, ...SYNTHETIC_SYMBOLS.filter((symbol) => !event_symbols.includes(symbol))],
|
||||
focusCount,
|
||||
mixSeed(activitySeed, 389)
|
||||
);
|
||||
|
|
@ -579,11 +532,7 @@ export const getSyntheticSessionState = (
|
|||
session_phase: phase,
|
||||
regime,
|
||||
volatility_level: roundTo(
|
||||
clamp(
|
||||
stateBase.volatility * amplitude + signedNoise(activitySeed + 3) * 0.08,
|
||||
0.18,
|
||||
1.2
|
||||
)
|
||||
clamp(stateBase.volatility * amplitude + signedNoise(activitySeed + 3) * 0.08, 0.18, 1.2)
|
||||
),
|
||||
liquidity_level: roundTo(
|
||||
clamp(
|
||||
|
|
@ -656,9 +605,7 @@ export const getSyntheticUnderlyingState = (
|
|||
? -meanRevertWave * (12 + session.liquidity_level * 10)
|
||||
: meanRevertWave * 6;
|
||||
const gammaChop =
|
||||
session.regime === "dealer_gamma"
|
||||
? Math.sin((minuteOfSession + (hash % 11)) / 2.8) * 16
|
||||
: 0;
|
||||
session.regime === "dealer_gamma" ? Math.sin((minuteOfSession + (hash % 11)) / 2.8) * 16 : 0;
|
||||
const noiseBps =
|
||||
signedNoise(mixSeed(hash, session.seed_bucket, control.shared_seed)) *
|
||||
(6 + session.volatility_level * 18);
|
||||
|
|
@ -731,10 +678,7 @@ export const getSyntheticScenarioWeights = (
|
|||
};
|
||||
|
||||
for (const profileId of SMART_MONEY_PROFILE_IDS) {
|
||||
weights[profileId] = roundTo(
|
||||
weights[profileId] * normalized.profile_weights[profileId],
|
||||
4
|
||||
);
|
||||
weights[profileId] = roundTo(weights[profileId] * normalized.profile_weights[profileId], 4);
|
||||
}
|
||||
|
||||
if (isFocus) {
|
||||
|
|
@ -745,10 +689,7 @@ export const getSyntheticScenarioWeights = (
|
|||
}
|
||||
if (isEvent) {
|
||||
weights.event_driven = roundTo(weights.event_driven * 1.36, 4);
|
||||
weights.institutional_directional = roundTo(
|
||||
weights.institutional_directional * 1.04,
|
||||
4
|
||||
);
|
||||
weights.institutional_directional = roundTo(weights.institutional_directional * 1.04, 4);
|
||||
weights.neutral_noise = roundTo(weights.neutral_noise * 0.8, 4);
|
||||
}
|
||||
if (isPower) {
|
||||
|
|
@ -765,10 +706,7 @@ export const getSyntheticScenarioWeights = (
|
|||
export const getSyntheticCoverageBoost = (
|
||||
profileId: SmartMoneyProfileId,
|
||||
coverageState: SyntheticCoverageState,
|
||||
control: Pick<
|
||||
SyntheticControlState,
|
||||
"coverage_assist" | "coverage_window_minutes"
|
||||
>
|
||||
control: Pick<SyntheticControlState, "coverage_assist" | "coverage_window_minutes">
|
||||
): number => {
|
||||
if (!control.coverage_assist) {
|
||||
return 1;
|
||||
|
|
|
|||
|
|
@ -31,9 +31,7 @@ describe("live protocol types", () => {
|
|||
underlying_ids: ["NVDA", "AAPL"],
|
||||
option_contract_id: "AAPL-2025-01-17-200-C"
|
||||
})
|
||||
).toBe(
|
||||
'options|{"view":"signal"}|underlyings:AAPL,NVDA|contract:AAPL-2025-01-17-200-C'
|
||||
);
|
||||
).toBe('options|{"view":"signal"}|underlyings:AAPL,NVDA|contract:AAPL-2025-01-17-200-C');
|
||||
expect(getSubscriptionKey({ channel: "equities", underlying_ids: ["NVDA", "AAPL"] })).toBe(
|
||||
"equities|underlyings:AAPL,NVDA"
|
||||
);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue