tradeblocks-mcp 3.0.2 → 3.0.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +82 -68
- package/dist/{chunk-LDKTV7GW.js → chunk-27S67XW3.js} +24 -52
- package/dist/chunk-27S67XW3.js.map +1 -0
- package/dist/{chunk-FGZH632F.js → chunk-2E63THNI.js} +13 -11
- package/dist/chunk-2E63THNI.js.map +1 -0
- package/dist/{chunk-BKQ4PM4Y.js → chunk-6S37CXUA.js} +11 -13
- package/dist/chunk-6S37CXUA.js.map +1 -0
- package/dist/{chunk-PRAYH3RT.js → chunk-AP7IHUUR.js} +29 -12
- package/dist/chunk-AP7IHUUR.js.map +1 -0
- package/dist/{chunk-QTTR7AAW.js → chunk-C6LL746C.js} +67 -84
- package/dist/{chunk-QTTR7AAW.js.map → chunk-C6LL746C.js.map} +1 -1
- package/dist/{chunk-W2PP3LEH.js → chunk-SEUZYQGQ.js} +17 -8
- package/dist/chunk-SEUZYQGQ.js.map +1 -0
- package/dist/{chunk-4BLCXNQ6.js → chunk-UBUC5A66.js} +105 -114
- package/dist/chunk-UBUC5A66.js.map +1 -0
- package/dist/{chunk-XXYOUIZY.js → chunk-VDU25Z6X.js} +63 -80
- package/dist/chunk-VDU25Z6X.js.map +1 -0
- package/dist/daily-log-processor-BY3ISY6K.js +9 -0
- package/dist/{daily-logs-store-D3QC2XPV.js → daily-logs-store-3C3OTGPK.js} +2 -2
- package/dist/iv-solver-worker.js +9 -1
- package/dist/market-provider-H3ARIVZ4.js +16 -0
- package/dist/{proto-3HZTCWK4.js → proto-V23GIZG2.js} +2 -2
- package/dist/{sync-PO4IPCYV.js → sync-EVLKB3ZJ.js} +7 -7
- package/dist/test-exports.js +358 -254
- package/dist/test-exports.js.map +1 -1
- package/dist/trade-processor-EYA3I3XB.js +9 -0
- package/dist/{trades-store-LOL3FQSF.js → trades-store-R3NL25T2.js} +2 -2
- package/manifest.json +3 -11
- package/package.json +1 -1
- package/server/{chunk-NZO6PT64.js → chunk-4P7D7YZP.js} +102 -113
- package/server/chunk-4P7D7YZP.js.map +1 -0
- package/server/{chunk-72GKJE2U.js → chunk-BOPHW5M6.js} +521 -235
- package/server/chunk-BOPHW5M6.js.map +1 -0
- package/server/{chunk-WA5AAPCH.js → chunk-GH2552SE.js} +17 -8
- package/server/chunk-GH2552SE.js.map +1 -0
- package/server/{chunk-5EBXHT6C.js → chunk-OBYKFW2B.js} +11 -13
- package/server/chunk-OBYKFW2B.js.map +1 -0
- package/server/{chunk-FBNDMCT5.js → chunk-T66KH2XH.js} +13 -11
- package/server/chunk-T66KH2XH.js.map +1 -0
- package/server/{chunk-NRFXAJF7.js → chunk-W5E7FHC4.js} +24 -52
- package/server/chunk-W5E7FHC4.js.map +1 -0
- package/server/{chunk-CSDVJPBB.js → chunk-YUCOAJ4Z.js} +29 -12
- package/server/chunk-YUCOAJ4Z.js.map +1 -0
- package/server/{chunk-PNKG7RY7.js → chunk-ZBJCF4ZG.js} +63 -80
- package/server/chunk-ZBJCF4ZG.js.map +1 -0
- package/server/{config-6IZXEFEX.js → config-DK7KOMNL.js} +1 -1
- package/server/config-DK7KOMNL.js.map +1 -0
- package/server/daily-log-processor-ENEUT22A.js +10 -0
- package/server/{daily-logs-store-NU7M4L5C.js → daily-logs-store-YFNXTB7J.js} +2 -2
- package/server/http-server.js +2 -5
- package/server/index.js +1771 -1538
- package/server/index.js.map +1 -1
- package/server/iv-solver-worker.js +9 -1
- package/server/market-provider-B437HKLW.js +17 -0
- package/server/{proto-DWRZJO4E.js → proto-YZ4TLX2N.js} +2 -2
- package/server/{sync-QFI5L7S7.js → sync-V25UQJA3.js} +7 -7
- package/server/trade-processor-L3PIQ5TG.js +10 -0
- package/server/{trades-store-VY26MWER.js → trades-store-RTTEYMXH.js} +2 -2
- package/src/auth/clients-store.ts +4 -4
- package/src/auth/code-store.ts +1 -1
- package/src/auth/config.ts +11 -12
- package/src/auth/login-page.ts +8 -10
- package/src/auth/provider.ts +35 -30
- package/src/auth/token.ts +17 -15
- package/src/db/backtest-schemas.ts +12 -4
- package/src/db/connection.ts +107 -40
- package/src/db/index.ts +37 -5
- package/src/db/json-adapters.ts +22 -31
- package/src/db/json-migration.ts +11 -15
- package/src/db/json-store.ts +5 -3
- package/src/db/market-datasets.ts +48 -15
- package/src/db/market-schemas.ts +11 -5
- package/src/db/market-views.ts +119 -32
- package/src/db/parquet-writer.ts +7 -7
- package/src/db/profile-schemas.ts +39 -22
- package/src/db/schemas.ts +2 -2
- package/src/http-server.ts +7 -12
- package/src/index.ts +8 -9
- package/src/market/ingestor/index.ts +1 -4
- package/src/market/ingestor/market-ingestor.ts +140 -67
- package/src/market/ingestor/types.ts +1 -3
- package/src/market/stores/chain-sql.ts +2 -8
- package/src/market/stores/chain-store.ts +1 -4
- package/src/market/stores/duckdb-chain-store.ts +3 -14
- package/src/market/stores/duckdb-enriched-store.ts +3 -13
- package/src/market/stores/duckdb-quote-store.ts +10 -27
- package/src/market/stores/duckdb-spot-store.ts +4 -20
- package/src/market/stores/enriched-sql.ts +3 -9
- package/src/market/stores/enriched-store.ts +2 -2
- package/src/market/stores/parquet-chain-store.ts +5 -22
- package/src/market/stores/parquet-enriched-store.ts +4 -16
- package/src/market/stores/parquet-oi-daily-store.ts +3 -14
- package/src/market/stores/parquet-quote-store.ts +9 -29
- package/src/market/stores/parquet-spot-store.ts +14 -33
- package/src/market/stores/quote-store.ts +2 -10
- package/src/market/stores/spot-sql.ts +3 -15
- package/src/market/stores/spot-store.ts +1 -1
- package/src/market/tickers/defaults.json +6 -6
- package/src/market/tickers/loader.ts +2 -7
- package/src/market/tickers/registry.ts +5 -15
- package/src/market/tickers/schemas.ts +2 -6
- package/src/models/strategy-profile.ts +39 -39
- package/src/sync/block-sync.ts +44 -65
- package/src/sync/index.ts +1 -4
- package/src/sync/metadata.ts +14 -20
- package/src/test-exports.ts +127 -123
- package/src/tools/analysis.ts +180 -159
- package/src/tools/batch-exit-analysis.ts +100 -59
- package/src/tools/blocks/analysis.ts +116 -101
- package/src/tools/blocks/comparison.ts +281 -364
- package/src/tools/blocks/core.ts +208 -253
- package/src/tools/blocks/health.ts +571 -563
- package/src/tools/blocks/similarity.ts +316 -283
- package/src/tools/edge-decay.ts +124 -197
- package/src/tools/exit-analysis.ts +130 -77
- package/src/tools/greeks-attribution.ts +84 -35
- package/src/tools/guides.ts +4 -6
- package/src/tools/imports.ts +9 -12
- package/src/tools/market-data.ts +1067 -757
- package/src/tools/market-enrichment.ts +3 -3
- package/src/tools/market-fetch.ts +148 -67
- package/src/tools/market-imports.ts +12 -12
- package/src/tools/middleware/sync-middleware.ts +5 -6
- package/src/tools/performance.ts +185 -302
- package/src/tools/profile-analysis.ts +52 -66
- package/src/tools/profiles.ts +106 -69
- package/src/tools/regime-advisor.ts +20 -45
- package/src/tools/replay.ts +81 -77
- package/src/tools/reports/discrepancies.ts +298 -328
- package/src/tools/reports/fields.ts +7 -25
- package/src/tools/reports/helpers.ts +18 -49
- package/src/tools/reports/predictive.ts +27 -70
- package/src/tools/reports/slippage-trends.ts +315 -345
- package/src/tools/reports/slippage.ts +1 -4
- package/src/tools/reports/strategy-matches.ts +399 -441
- package/src/tools/schema.ts +43 -40
- package/src/tools/shared/filters.ts +3 -9
- package/src/tools/snapshot.ts +9 -30
- package/src/tools/sql.ts +15 -14
- package/src/tools/tickers.ts +1 -4
- package/src/utils/batch-exit-analysis.ts +31 -42
- package/src/utils/black-scholes.ts +39 -29
- package/src/utils/block-loader.ts +68 -82
- package/src/utils/calibration-probe.ts +1 -2
- package/src/utils/chain-loader.ts +3 -3
- package/src/utils/csv-discovery.ts +16 -22
- package/src/utils/data-quality.ts +24 -36
- package/src/utils/exit-triggers.ts +91 -96
- package/src/utils/field-timing.ts +94 -79
- package/src/utils/filter-predicates.ts +13 -9
- package/src/utils/flatfile-importer.ts +94 -64
- package/src/utils/greeks-decomposition.ts +152 -100
- package/src/utils/iv-solver-pool.ts +55 -25
- package/src/utils/iv-solver-worker.ts +5 -5
- package/src/utils/market-enricher.ts +528 -497
- package/src/utils/market-importer.ts +31 -12
- package/src/utils/market-provider.ts +21 -23
- package/src/utils/massive-tier.ts +5 -7
- package/src/utils/migrate-option-data-helpers.ts +2 -8
- package/src/utils/option-quote-greeks.ts +25 -31
- package/src/utils/option-time.ts +4 -8
- package/src/utils/output-formatter.ts +1 -4
- package/src/utils/provider-capabilities.ts +1 -4
- package/src/utils/providers/massive.ts +59 -93
- package/src/utils/providers/thetadata/backfill.ts +14 -23
- package/src/utils/providers/thetadata/client.ts +12 -8
- package/src/utils/providers/thetadata/decode.ts +2 -20
- package/src/utils/providers/thetadata/endpoints.ts +32 -40
- package/src/utils/providers/thetadata/join.ts +11 -10
- package/src/utils/providers/thetadata/proto.ts +12 -10
- package/src/utils/providers/thetadata/quote-mid-greeks.ts +5 -5
- package/src/utils/providers/thetadata.ts +11 -10
- package/src/utils/quote-enricher.ts +4 -4
- package/src/utils/quote-parquet-projection.ts +3 -11
- package/src/utils/sample-date-selector.ts +3 -5
- package/src/utils/schema-metadata.ts +102 -70
- package/src/utils/ticker.ts +5 -9
- package/src/utils/trade-replay.ts +77 -68
- package/dist/chunk-4BLCXNQ6.js.map +0 -1
- package/dist/chunk-BKQ4PM4Y.js.map +0 -1
- package/dist/chunk-FGZH632F.js.map +0 -1
- package/dist/chunk-LDKTV7GW.js.map +0 -1
- package/dist/chunk-PRAYH3RT.js.map +0 -1
- package/dist/chunk-W2PP3LEH.js.map +0 -1
- package/dist/chunk-XXYOUIZY.js.map +0 -1
- package/dist/daily-log-processor-6MWJ23JK.js +0 -9
- package/dist/market-provider-VDRJUEF2.js +0 -16
- package/dist/trade-processor-NHU4VWRX.js +0 -9
- package/server/chunk-5EBXHT6C.js.map +0 -1
- package/server/chunk-72GKJE2U.js.map +0 -1
- package/server/chunk-CSDVJPBB.js.map +0 -1
- package/server/chunk-FBNDMCT5.js.map +0 -1
- package/server/chunk-NRFXAJF7.js.map +0 -1
- package/server/chunk-NZO6PT64.js.map +0 -1
- package/server/chunk-PNKG7RY7.js.map +0 -1
- package/server/chunk-WA5AAPCH.js.map +0 -1
- package/server/config-6IZXEFEX.js.map +0 -1
- package/server/daily-log-processor-Y3PVSVBM.js +0 -10
- package/server/market-provider-VOYYVYWT.js +0 -17
- package/server/trade-processor-JWVS37KM.js +0 -10
- /package/dist/{daily-log-processor-6MWJ23JK.js.map → daily-log-processor-BY3ISY6K.js.map} +0 -0
- /package/dist/{daily-logs-store-D3QC2XPV.js.map → daily-logs-store-3C3OTGPK.js.map} +0 -0
- /package/dist/{market-provider-VDRJUEF2.js.map → market-provider-H3ARIVZ4.js.map} +0 -0
- /package/dist/{proto-3HZTCWK4.js.map → proto-V23GIZG2.js.map} +0 -0
- /package/dist/{sync-PO4IPCYV.js.map → sync-EVLKB3ZJ.js.map} +0 -0
- /package/dist/{trade-processor-NHU4VWRX.js.map → trade-processor-EYA3I3XB.js.map} +0 -0
- /package/dist/{trades-store-LOL3FQSF.js.map → trades-store-R3NL25T2.js.map} +0 -0
- /package/server/{daily-log-processor-Y3PVSVBM.js.map → daily-log-processor-ENEUT22A.js.map} +0 -0
- /package/server/{daily-logs-store-NU7M4L5C.js.map → daily-logs-store-YFNXTB7J.js.map} +0 -0
- /package/server/{market-provider-VOYYVYWT.js.map → market-provider-B437HKLW.js.map} +0 -0
- /package/server/{proto-DWRZJO4E.js.map → proto-YZ4TLX2N.js.map} +0 -0
- /package/server/{sync-QFI5L7S7.js.map → sync-V25UQJA3.js.map} +0 -0
- /package/server/{trade-processor-JWVS37KM.js.map → trade-processor-L3PIQ5TG.js.map} +0 -0
- /package/server/{trades-store-VY26MWER.js.map → trades-store-RTTEYMXH.js.map} +0 -0
|
@@ -8,11 +8,7 @@ import {
|
|
|
8
8
|
OPTION_QUOTE_GREEKS_RATE_TYPE,
|
|
9
9
|
OPTION_QUOTE_GREEKS_REVISION,
|
|
10
10
|
} from "../../option-quote-greeks.ts";
|
|
11
|
-
import type {
|
|
12
|
-
ThetaFirstOrderGreekRow,
|
|
13
|
-
ThetaQuoteRow,
|
|
14
|
-
ThetaRight,
|
|
15
|
-
} from "./types.ts";
|
|
11
|
+
import type { ThetaFirstOrderGreekRow, ThetaQuoteRow, ThetaRight } from "./types.ts";
|
|
16
12
|
|
|
17
13
|
export interface ThetaJoinedQuoteRow extends BulkQuoteRow {
|
|
18
14
|
greeks_revision?: number | null;
|
|
@@ -76,10 +72,12 @@ type CompleteThetaFirstOrderGreekRow = ThetaFirstOrderGreekRow & {
|
|
|
76
72
|
function hasProviderFirstOrderGreeks(
|
|
77
73
|
row: ThetaFirstOrderGreekRow,
|
|
78
74
|
): row is CompleteThetaFirstOrderGreekRow {
|
|
79
|
-
return
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
75
|
+
return (
|
|
76
|
+
isFiniteNumber(row.delta) &&
|
|
77
|
+
isFiniteNumber(row.theta) &&
|
|
78
|
+
isFiniteNumber(row.vega) &&
|
|
79
|
+
isFiniteNumber(row.iv)
|
|
80
|
+
);
|
|
83
81
|
}
|
|
84
82
|
|
|
85
83
|
function splitTimestamp(timestamp: string): { date: string; time: string } {
|
|
@@ -87,7 +85,10 @@ function splitTimestamp(timestamp: string): { date: string; time: string } {
|
|
|
87
85
|
return { date, time: time.slice(0, 5) };
|
|
88
86
|
}
|
|
89
87
|
|
|
90
|
-
function computeGamma(
|
|
88
|
+
function computeGamma(
|
|
89
|
+
row: ThetaQuoteRow,
|
|
90
|
+
greek: ThetaFirstOrderGreekRow,
|
|
91
|
+
): {
|
|
91
92
|
gamma: number | null;
|
|
92
93
|
rateValue: number | null;
|
|
93
94
|
} {
|
|
@@ -9,16 +9,18 @@ import type { Root } from "protobufjs";
|
|
|
9
9
|
const moduleDir = dirname(fileURLToPath(import.meta.url));
|
|
10
10
|
|
|
11
11
|
function protoCandidates(): string[] {
|
|
12
|
-
return Array.from(
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
12
|
+
return Array.from(
|
|
13
|
+
new Set([
|
|
14
|
+
resolve(moduleDir, "mdds.proto"),
|
|
15
|
+
resolve(moduleDir, "../../../mdds.proto"),
|
|
16
|
+
resolve(moduleDir, "../../../../server/mdds.proto"),
|
|
17
|
+
resolve(moduleDir, "../../../../dist/mdds.proto"),
|
|
18
|
+
resolve(process.cwd(), "packages/mcp-server/src/utils/providers/thetadata/mdds.proto"),
|
|
19
|
+
resolve(process.cwd(), "src/utils/providers/thetadata/mdds.proto"),
|
|
20
|
+
resolve(process.cwd(), "server/mdds.proto"),
|
|
21
|
+
resolve(process.cwd(), "dist/mdds.proto"),
|
|
22
|
+
]),
|
|
23
|
+
);
|
|
22
24
|
}
|
|
23
25
|
|
|
24
26
|
export function resolveMddsProtoPath(): string {
|
|
@@ -53,11 +53,11 @@ export function computeThetaQuoteMidGreekRow(params: {
|
|
|
53
53
|
OPTION_QUOTE_MID_GREEKS_DIVIDEND_YIELD,
|
|
54
54
|
);
|
|
55
55
|
if (
|
|
56
|
-
!isFiniteNumber(greeks.delta)
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
56
|
+
!isFiniteNumber(greeks.delta) ||
|
|
57
|
+
!isFiniteNumber(greeks.gamma) ||
|
|
58
|
+
!isFiniteNumber(greeks.theta) ||
|
|
59
|
+
!isFiniteNumber(greeks.vega) ||
|
|
60
|
+
!isFiniteNumber(greeks.iv)
|
|
61
61
|
) {
|
|
62
62
|
return null;
|
|
63
63
|
}
|
|
@@ -185,10 +185,12 @@ function isGreekForBulkContract(
|
|
|
185
185
|
right: ThetaRight,
|
|
186
186
|
contract: ThetaContractListRow,
|
|
187
187
|
): boolean {
|
|
188
|
-
return
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
188
|
+
return (
|
|
189
|
+
row.symbol.toUpperCase() === root.toUpperCase() &&
|
|
190
|
+
row.expiration === contract.expiration &&
|
|
191
|
+
formatStrike(row.strike) === formatStrike(contract.strike) &&
|
|
192
|
+
row.right === right
|
|
193
|
+
);
|
|
192
194
|
}
|
|
193
195
|
|
|
194
196
|
function toMinuteQuote(row: BulkQuoteRow & { greeks_revision?: number | null }): MinuteQuote {
|
|
@@ -524,13 +526,12 @@ export class ThetaDataProvider implements MarketDataProvider {
|
|
|
524
526
|
date,
|
|
525
527
|
interval: "1m",
|
|
526
528
|
} as const;
|
|
527
|
-
const [quotes, bandGreeks]: [ThetaQuoteRow[], ThetaFirstOrderGreekRow[]] =
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
|
|
531
|
-
]);
|
|
529
|
+
const [quotes, bandGreeks]: [ThetaQuoteRow[], ThetaFirstOrderGreekRow[]] = await Promise.all([
|
|
530
|
+
this.quoteEndpoint(this.client, request),
|
|
531
|
+
this.fetchBulkGreekBand(root, contract.expiration, date, greekBandCache),
|
|
532
|
+
]);
|
|
532
533
|
const contractBandGreeks = bandGreeks.filter((row) =>
|
|
533
|
-
isGreekForBulkContract(row, root, right, contract)
|
|
534
|
+
isGreekForBulkContract(row, root, right, contract),
|
|
534
535
|
);
|
|
535
536
|
const bandJoined = joinThetaQuotesAndFirstOrderGreeks({
|
|
536
537
|
quotes,
|
|
@@ -39,7 +39,7 @@ export interface EnrichmentPlanItem {
|
|
|
39
39
|
*/
|
|
40
40
|
export interface QuoteEnrichmentResult {
|
|
41
41
|
tickersProcessed: number;
|
|
42
|
-
tickersSkipped: number;
|
|
42
|
+
tickersSkipped: number; // already dense
|
|
43
43
|
rowsWritten: number;
|
|
44
44
|
errors: Array<{ ticker: string; date: string; error: string }>;
|
|
45
45
|
unsupportedReason?: string;
|
|
@@ -47,7 +47,7 @@ export interface QuoteEnrichmentResult {
|
|
|
47
47
|
|
|
48
48
|
export interface EnrichmentPlanInput {
|
|
49
49
|
tickers: Array<{ ticker: string; fromDate: string; toDate: string }>;
|
|
50
|
-
existingCoverage: Map<string, number>;
|
|
50
|
+
existingCoverage: Map<string, number>; // "ticker:date" → barCount
|
|
51
51
|
providerSupportsQuotes: boolean;
|
|
52
52
|
}
|
|
53
53
|
|
|
@@ -108,8 +108,8 @@ export function buildEnrichmentPlan(input: EnrichmentPlanInput): EnrichmentPlanI
|
|
|
108
108
|
*/
|
|
109
109
|
function expandDateRange(fromDate: string, toDate: string): string[] {
|
|
110
110
|
const dates: string[] = [];
|
|
111
|
-
const from = new Date(fromDate +
|
|
112
|
-
const to = new Date(toDate +
|
|
111
|
+
const from = new Date(fromDate + "T00:00:00Z");
|
|
112
|
+
const to = new Date(toDate + "T00:00:00Z");
|
|
113
113
|
const current = new Date(from);
|
|
114
114
|
while (current <= to) {
|
|
115
115
|
dates.push(current.toISOString().slice(0, 10));
|
|
@@ -105,14 +105,9 @@ export function quoteParquetGreekProjection(
|
|
|
105
105
|
* Read path (`quoteParquetGreekProjection` above) stays untouched so
|
|
106
106
|
* existing DOUBLE partitions continue to read without widening cost.
|
|
107
107
|
*/
|
|
108
|
-
export function quoteParquetGreekWriteProjection(
|
|
109
|
-
columns: ParquetColumnSet,
|
|
110
|
-
alias = "q",
|
|
111
|
-
): string {
|
|
108
|
+
export function quoteParquetGreekWriteProjection(columns: ParquetColumnSet, alias = "q"): string {
|
|
112
109
|
const castReal = (name: string) =>
|
|
113
|
-
hasColumn(columns, name)
|
|
114
|
-
? `CAST(${alias}.${name} AS REAL)`
|
|
115
|
-
: `NULL::REAL`;
|
|
110
|
+
hasColumn(columns, name) ? `CAST(${alias}.${name} AS REAL)` : `NULL::REAL`;
|
|
116
111
|
return [
|
|
117
112
|
`${castReal("delta")} AS delta`,
|
|
118
113
|
`${castReal("gamma")} AS gamma`,
|
|
@@ -127,10 +122,7 @@ export function quoteParquetGreekWriteProjection(
|
|
|
127
122
|
].join(",\n ");
|
|
128
123
|
}
|
|
129
124
|
|
|
130
|
-
export function quoteParquetCanonicalProjection(
|
|
131
|
-
columns: ParquetColumnSet,
|
|
132
|
-
alias = "q",
|
|
133
|
-
): string {
|
|
125
|
+
export function quoteParquetCanonicalProjection(columns: ParquetColumnSet, alias = "q"): string {
|
|
134
126
|
return [
|
|
135
127
|
`${quoteParquetColumnExpr(columns, alias, "underlying", "VARCHAR")} AS underlying`,
|
|
136
128
|
`${quoteParquetColumnExpr(columns, alias, "date", "VARCHAR")} AS date`,
|
|
@@ -118,9 +118,7 @@ export function selectVerificationSampleDates(
|
|
|
118
118
|
...PHASE_5_KNOWN_EVENTS.map((s) => s.date),
|
|
119
119
|
...PHASE_5_STRUCTURAL_DATES.map((s) => s.date),
|
|
120
120
|
]);
|
|
121
|
-
const candidates = enumerateWeekdays(fromDate, toDate).filter(
|
|
122
|
-
(d) => !selectedSet.has(d),
|
|
123
|
-
);
|
|
121
|
+
const candidates = enumerateWeekdays(fromDate, toDate).filter((d) => !selectedSet.has(d));
|
|
124
122
|
|
|
125
123
|
const random: SampleDate[] = [];
|
|
126
124
|
const pool = [...candidates];
|
|
@@ -129,7 +127,7 @@ export function selectVerificationSampleDates(
|
|
|
129
127
|
random.push({ date: pool.splice(idx, 1)[0], category: "random" });
|
|
130
128
|
}
|
|
131
129
|
|
|
132
|
-
return [...PHASE_5_KNOWN_EVENTS, ...PHASE_5_STRUCTURAL_DATES, ...random].sort(
|
|
133
|
-
|
|
130
|
+
return [...PHASE_5_KNOWN_EVENTS, ...PHASE_5_STRUCTURAL_DATES, ...random].sort((a, b) =>
|
|
131
|
+
a.date.localeCompare(b.date),
|
|
134
132
|
);
|
|
135
133
|
}
|
|
@@ -30,7 +30,7 @@ export interface ColumnDescription {
|
|
|
30
30
|
* - 'static': Calendar/metadata facts known before the day (Day_of_Week, Month, Is_Opex)
|
|
31
31
|
* Only applicable to market.enriched and market.enriched_context columns. Omit for non-market tables.
|
|
32
32
|
*/
|
|
33
|
-
timing?:
|
|
33
|
+
timing?: "open" | "close" | "static";
|
|
34
34
|
}
|
|
35
35
|
|
|
36
36
|
export interface TableDescription {
|
|
@@ -164,7 +164,8 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
164
164
|
hypothesis: true,
|
|
165
165
|
},
|
|
166
166
|
legs: {
|
|
167
|
-
description:
|
|
167
|
+
description:
|
|
168
|
+
"Option legs description with strikes (e.g., 'SPY 450P/445P') - compare with trade_data.legs to identify strike differences",
|
|
168
169
|
hypothesis: true,
|
|
169
170
|
},
|
|
170
171
|
initial_premium: {
|
|
@@ -221,174 +222,182 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
221
222
|
hypothesis: true,
|
|
222
223
|
},
|
|
223
224
|
date: {
|
|
224
|
-
description:
|
|
225
|
+
description:
|
|
226
|
+
"Trading date (VARCHAR, format YYYY-MM-DD). Composite primary key with ticker.",
|
|
225
227
|
hypothesis: true,
|
|
226
228
|
},
|
|
227
229
|
// Raw OHLCV
|
|
228
230
|
open: {
|
|
229
231
|
description: "Underlying open price",
|
|
230
232
|
hypothesis: false,
|
|
231
|
-
timing:
|
|
233
|
+
timing: "open",
|
|
232
234
|
},
|
|
233
235
|
high: {
|
|
234
236
|
description: "Underlying high price",
|
|
235
237
|
hypothesis: false,
|
|
236
|
-
timing:
|
|
238
|
+
timing: "close",
|
|
237
239
|
},
|
|
238
240
|
low: {
|
|
239
241
|
description: "Underlying low price",
|
|
240
242
|
hypothesis: false,
|
|
241
|
-
timing:
|
|
243
|
+
timing: "close",
|
|
242
244
|
},
|
|
243
245
|
close: {
|
|
244
246
|
description: "Underlying close price",
|
|
245
247
|
hypothesis: false,
|
|
246
|
-
timing:
|
|
248
|
+
timing: "close",
|
|
247
249
|
},
|
|
248
250
|
Prior_Close: {
|
|
249
251
|
description: "Previous day's close price",
|
|
250
252
|
hypothesis: false,
|
|
251
|
-
timing:
|
|
253
|
+
timing: "open",
|
|
252
254
|
},
|
|
253
255
|
// Tier 1 enrichment — open-known
|
|
254
256
|
Gap_Pct: {
|
|
255
257
|
description: "Overnight gap percentage ((Open - Prior_Close) / Prior_Close * 100)",
|
|
256
258
|
hypothesis: true,
|
|
257
|
-
timing:
|
|
259
|
+
timing: "open",
|
|
258
260
|
},
|
|
259
261
|
Prev_Return_Pct: {
|
|
260
262
|
description: "Previous day's total return percentage (prior close to prior close)",
|
|
261
263
|
hypothesis: true,
|
|
262
|
-
timing:
|
|
264
|
+
timing: "open",
|
|
263
265
|
},
|
|
264
266
|
Prior_Range_vs_ATR: {
|
|
265
|
-
description:
|
|
267
|
+
description:
|
|
268
|
+
"Prior trading day's (high - low) / ATR ratio, measures prior day's range relative to average true range",
|
|
266
269
|
hypothesis: true,
|
|
267
|
-
timing:
|
|
270
|
+
timing: "open",
|
|
268
271
|
},
|
|
269
272
|
// Tier 1 enrichment — close-derived
|
|
270
273
|
ATR_Pct: {
|
|
271
274
|
description: "Average True Range as percentage of price (14-day Wilder smoothing)",
|
|
272
275
|
hypothesis: true,
|
|
273
|
-
timing:
|
|
276
|
+
timing: "close",
|
|
274
277
|
},
|
|
275
278
|
RSI_14: {
|
|
276
279
|
description: "14-day RSI (0-100, >70 overbought, <30 oversold)",
|
|
277
280
|
hypothesis: true,
|
|
278
|
-
timing:
|
|
281
|
+
timing: "close",
|
|
279
282
|
},
|
|
280
283
|
Price_vs_EMA21_Pct: {
|
|
281
284
|
description: "Price vs 21-day EMA as percentage ((close - EMA21) / EMA21 * 100)",
|
|
282
285
|
hypothesis: true,
|
|
283
|
-
timing:
|
|
286
|
+
timing: "close",
|
|
284
287
|
},
|
|
285
288
|
Price_vs_SMA50_Pct: {
|
|
286
289
|
description: "Price vs 50-day SMA as percentage ((close - SMA50) / SMA50 * 100)",
|
|
287
290
|
hypothesis: true,
|
|
288
|
-
timing:
|
|
291
|
+
timing: "close",
|
|
289
292
|
},
|
|
290
293
|
Realized_Vol_5D: {
|
|
291
294
|
description: "5-day realized volatility (annualized standard deviation of log returns)",
|
|
292
295
|
hypothesis: true,
|
|
293
|
-
timing:
|
|
296
|
+
timing: "close",
|
|
294
297
|
},
|
|
295
298
|
Realized_Vol_20D: {
|
|
296
|
-
description:
|
|
299
|
+
description:
|
|
300
|
+
"20-day realized volatility (annualized standard deviation of log returns)",
|
|
297
301
|
hypothesis: true,
|
|
298
|
-
timing:
|
|
302
|
+
timing: "close",
|
|
299
303
|
},
|
|
300
304
|
Return_5D: {
|
|
301
305
|
description: "5-day cumulative return percentage",
|
|
302
306
|
hypothesis: true,
|
|
303
|
-
timing:
|
|
307
|
+
timing: "close",
|
|
304
308
|
},
|
|
305
309
|
Return_20D: {
|
|
306
310
|
description: "20-day cumulative return percentage",
|
|
307
311
|
hypothesis: true,
|
|
308
|
-
timing:
|
|
312
|
+
timing: "close",
|
|
309
313
|
},
|
|
310
314
|
Intraday_Range_Pct: {
|
|
311
315
|
description: "Intraday range as percentage ((High - Low) / Open * 100)",
|
|
312
316
|
hypothesis: true,
|
|
313
|
-
timing:
|
|
317
|
+
timing: "close",
|
|
314
318
|
},
|
|
315
319
|
Intraday_Return_Pct: {
|
|
316
320
|
description: "Open to close return percentage ((Close - Open) / Open * 100)",
|
|
317
321
|
hypothesis: true,
|
|
318
|
-
timing:
|
|
322
|
+
timing: "close",
|
|
319
323
|
},
|
|
320
324
|
Close_Position_In_Range: {
|
|
321
325
|
description: "Where close is in day's range (0 = low, 1 = high)",
|
|
322
326
|
hypothesis: true,
|
|
323
|
-
timing:
|
|
327
|
+
timing: "close",
|
|
324
328
|
},
|
|
325
329
|
Gap_Filled: {
|
|
326
330
|
description: "Whether overnight gap was filled (1 = yes, 0 = no)",
|
|
327
331
|
hypothesis: true,
|
|
328
|
-
timing:
|
|
332
|
+
timing: "close",
|
|
329
333
|
},
|
|
330
334
|
Consecutive_Days: {
|
|
331
335
|
description: "Consecutive up/down days (positive=up, negative=down)",
|
|
332
336
|
hypothesis: true,
|
|
333
|
-
timing:
|
|
337
|
+
timing: "close",
|
|
334
338
|
},
|
|
335
339
|
// Tier 3 intraday timing (columns exist in schema, enrichment deferred)
|
|
336
340
|
High_Time: {
|
|
337
341
|
description: "Time of day high as decimal hours (e.g., 10.5 = 10:30 AM ET)",
|
|
338
342
|
hypothesis: true,
|
|
339
|
-
timing:
|
|
343
|
+
timing: "close",
|
|
340
344
|
},
|
|
341
345
|
Low_Time: {
|
|
342
346
|
description: "Time of day low as decimal hours (e.g., 14.25 = 2:15 PM ET)",
|
|
343
347
|
hypothesis: true,
|
|
344
|
-
timing:
|
|
348
|
+
timing: "close",
|
|
345
349
|
},
|
|
346
350
|
High_Before_Low: {
|
|
347
351
|
description: "Did high occur before low? (1=yes, 0=no)",
|
|
348
352
|
hypothesis: true,
|
|
349
|
-
timing:
|
|
353
|
+
timing: "close",
|
|
350
354
|
},
|
|
351
355
|
Reversal_Type: {
|
|
352
|
-
description:
|
|
356
|
+
description:
|
|
357
|
+
"Reversal pattern type (1=morning reversal up, -1=morning reversal down, 0=trend day)",
|
|
353
358
|
hypothesis: true,
|
|
354
|
-
timing:
|
|
359
|
+
timing: "close",
|
|
355
360
|
},
|
|
356
361
|
Opening_Drive_Strength: {
|
|
357
|
-
description:
|
|
362
|
+
description:
|
|
363
|
+
"First-30-min range / full-day range ratio (0-1); higher = strong opening drive",
|
|
358
364
|
hypothesis: true,
|
|
359
|
-
timing:
|
|
365
|
+
timing: "close",
|
|
360
366
|
},
|
|
361
367
|
Intraday_Realized_Vol: {
|
|
362
|
-
description:
|
|
368
|
+
description:
|
|
369
|
+
"Annualized realized volatility from intraday bar returns (decimal, e.g., 0.15 = 15%)",
|
|
363
370
|
hypothesis: true,
|
|
364
|
-
timing:
|
|
371
|
+
timing: "close",
|
|
365
372
|
},
|
|
366
373
|
// Calendar fields — static
|
|
367
374
|
Day_of_Week: {
|
|
368
375
|
description: "Day of week (2=Monday through 6=Friday)",
|
|
369
376
|
hypothesis: true,
|
|
370
|
-
timing:
|
|
377
|
+
timing: "static",
|
|
371
378
|
},
|
|
372
379
|
Month: {
|
|
373
380
|
description: "Month number (1-12)",
|
|
374
381
|
hypothesis: true,
|
|
375
|
-
timing:
|
|
382
|
+
timing: "static",
|
|
376
383
|
},
|
|
377
384
|
Is_Opex: {
|
|
378
385
|
description: "Options expiration day flag (1=opex, 0=not)",
|
|
379
386
|
hypothesis: true,
|
|
380
|
-
timing:
|
|
387
|
+
timing: "static",
|
|
381
388
|
},
|
|
382
389
|
// VIX-family ticker IVR/IVP (populated for VIX, VIX9D, VIX3M, etc.)
|
|
383
390
|
ivr: {
|
|
384
|
-
description:
|
|
391
|
+
description:
|
|
392
|
+
"Implied Volatility Rank (252-day): where current close sits in range (0=min, 100=max). Populated for VIX-family tickers only.",
|
|
385
393
|
hypothesis: true,
|
|
386
|
-
timing:
|
|
394
|
+
timing: "close",
|
|
387
395
|
},
|
|
388
396
|
ivp: {
|
|
389
|
-
description:
|
|
397
|
+
description:
|
|
398
|
+
"Implied Volatility Percentile (252-day): percentage of prior 251 trading days where close was at or below current level (0-100). Populated for VIX-family tickers only.",
|
|
390
399
|
hypothesis: true,
|
|
391
|
-
timing:
|
|
400
|
+
timing: "close",
|
|
392
401
|
},
|
|
393
402
|
},
|
|
394
403
|
},
|
|
@@ -402,29 +411,33 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
402
411
|
hypothesis: true,
|
|
403
412
|
},
|
|
404
413
|
Vol_Regime: {
|
|
405
|
-
description:
|
|
414
|
+
description:
|
|
415
|
+
"Volatility regime classification based on VIX close (1=very low <10, 2=low 10-15, 3=normal 15-20, 4=elevated 20-25, 5=high 25-30, 6=extreme >30)",
|
|
406
416
|
hypothesis: true,
|
|
407
|
-
timing:
|
|
417
|
+
timing: "close",
|
|
408
418
|
},
|
|
409
419
|
Term_Structure_State: {
|
|
410
|
-
description:
|
|
420
|
+
description:
|
|
421
|
+
"VIX term structure state based on VIX9D/VIX ratio (-1=backwardation/inverted, 0=flat, 1=contango/normal). NULL when VIX9D data is absent.",
|
|
411
422
|
hypothesis: true,
|
|
412
|
-
timing:
|
|
423
|
+
timing: "close",
|
|
413
424
|
},
|
|
414
425
|
Trend_Direction: {
|
|
415
|
-
description:
|
|
426
|
+
description:
|
|
427
|
+
"Trend direction classification based on 20-day return: up (>1%), down (<-1%), flat (-1% to 1%). NULL if Return_20D unavailable.",
|
|
416
428
|
hypothesis: true,
|
|
417
|
-
timing:
|
|
429
|
+
timing: "close",
|
|
418
430
|
},
|
|
419
431
|
VIX_Spike_Pct: {
|
|
420
432
|
description: "VIX spike from open to high as percentage",
|
|
421
433
|
hypothesis: true,
|
|
422
|
-
timing:
|
|
434
|
+
timing: "close",
|
|
423
435
|
},
|
|
424
436
|
VIX_Gap_Pct: {
|
|
425
|
-
description:
|
|
437
|
+
description:
|
|
438
|
+
"VIX overnight gap percentage ((VIX_Open - prior VIX_Close) / prior VIX_Close * 100)",
|
|
426
439
|
hypothesis: true,
|
|
427
|
-
timing:
|
|
440
|
+
timing: "open",
|
|
428
441
|
},
|
|
429
442
|
},
|
|
430
443
|
},
|
|
@@ -434,15 +447,18 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
434
447
|
keyColumns: ["ticker", "date", "time"],
|
|
435
448
|
columns: {
|
|
436
449
|
ticker: {
|
|
437
|
-
description:
|
|
450
|
+
description:
|
|
451
|
+
"Underlying ticker symbol (part of composite primary key with date and time).",
|
|
438
452
|
hypothesis: true,
|
|
439
453
|
},
|
|
440
454
|
date: {
|
|
441
|
-
description:
|
|
455
|
+
description:
|
|
456
|
+
"Trading date (VARCHAR, format YYYY-MM-DD). Part of composite primary key.",
|
|
442
457
|
hypothesis: true,
|
|
443
458
|
},
|
|
444
459
|
time: {
|
|
445
|
-
description:
|
|
460
|
+
description:
|
|
461
|
+
"Bar time in HH:MM Eastern Time format (e.g., '09:30', '10:00'). Part of composite primary key.",
|
|
446
462
|
hypothesis: false,
|
|
447
463
|
},
|
|
448
464
|
open: {
|
|
@@ -587,19 +603,23 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
587
603
|
hypothesis: false,
|
|
588
604
|
},
|
|
589
605
|
delta: {
|
|
590
|
-
description:
|
|
606
|
+
description:
|
|
607
|
+
"Option delta for the minute when available from provider data or computed fallback.",
|
|
591
608
|
hypothesis: true,
|
|
592
609
|
},
|
|
593
610
|
gamma: {
|
|
594
|
-
description:
|
|
611
|
+
description:
|
|
612
|
+
"Option gamma for the minute when available from provider data or computed fallback.",
|
|
595
613
|
hypothesis: false,
|
|
596
614
|
},
|
|
597
615
|
theta: {
|
|
598
|
-
description:
|
|
616
|
+
description:
|
|
617
|
+
"Option theta for the minute when available from provider data or computed fallback.",
|
|
599
618
|
hypothesis: false,
|
|
600
619
|
},
|
|
601
620
|
vega: {
|
|
602
|
-
description:
|
|
621
|
+
description:
|
|
622
|
+
"Option vega (per 1% IV move) for the minute when available from provider data or computed fallback.",
|
|
603
623
|
hypothesis: false,
|
|
604
624
|
},
|
|
605
625
|
iv: {
|
|
@@ -607,15 +627,18 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
607
627
|
hypothesis: true,
|
|
608
628
|
},
|
|
609
629
|
greeks_source: {
|
|
610
|
-
description:
|
|
630
|
+
description:
|
|
631
|
+
"Origin of the stored minute greeks: provider-native or computed fallback.",
|
|
611
632
|
hypothesis: false,
|
|
612
633
|
},
|
|
613
634
|
greeks_revision: {
|
|
614
|
-
description:
|
|
635
|
+
description:
|
|
636
|
+
"Computation revision for stored computed greeks; null for provider-native values.",
|
|
615
637
|
hypothesis: false,
|
|
616
638
|
},
|
|
617
639
|
rate_type: {
|
|
618
|
-
description:
|
|
640
|
+
description:
|
|
641
|
+
"Interest-rate curve or rate label used by the provider or computed-greeks path.",
|
|
619
642
|
hypothesis: false,
|
|
620
643
|
},
|
|
621
644
|
rate_value: {
|
|
@@ -623,7 +646,8 @@ export const SCHEMA_DESCRIPTIONS: SchemaMetadata = {
|
|
|
623
646
|
hypothesis: false,
|
|
624
647
|
},
|
|
625
648
|
gamma_source: {
|
|
626
|
-
description:
|
|
649
|
+
description:
|
|
650
|
+
"Provenance label for the stored gamma value when it differs from the broader greeks source.",
|
|
627
651
|
hypothesis: false,
|
|
628
652
|
},
|
|
629
653
|
},
|
|
@@ -716,7 +740,8 @@ ORDER BY t.date_opened`,
|
|
|
716
740
|
],
|
|
717
741
|
joins: [
|
|
718
742
|
{
|
|
719
|
-
description:
|
|
743
|
+
description:
|
|
744
|
+
"Trade P&L with market context (lag-aware: multi-table JOIN before LAG for correctness)",
|
|
720
745
|
sql: `WITH joined AS (
|
|
721
746
|
SELECT d.ticker, d.date,
|
|
722
747
|
d.Gap_Pct, d.Prior_Close, d.Prev_Return_Pct,
|
|
@@ -748,7 +773,8 @@ WHERE t.block_id = 'my-block'
|
|
|
748
773
|
ORDER BY t.date_opened DESC`,
|
|
749
774
|
},
|
|
750
775
|
{
|
|
751
|
-
description:
|
|
776
|
+
description:
|
|
777
|
+
"Trades with ORB context (opening range breakout from minute bars in market.spot)",
|
|
752
778
|
sql: `WITH orb_range AS (
|
|
753
779
|
SELECT ticker, date,
|
|
754
780
|
MAX(high) AS ORB_High,
|
|
@@ -775,7 +801,8 @@ WHERE t.block_id = 'my-block'
|
|
|
775
801
|
ORDER BY t.date_opened`,
|
|
776
802
|
},
|
|
777
803
|
{
|
|
778
|
-
description:
|
|
804
|
+
description:
|
|
805
|
+
"VIX intraday data for a specific date (VIX bars are in market.spot with ticker='VIX')",
|
|
779
806
|
sql: `SELECT time, open, high, low, close
|
|
780
807
|
FROM market.spot
|
|
781
808
|
WHERE ticker = 'VIX'
|
|
@@ -783,7 +810,8 @@ WHERE ticker = 'VIX'
|
|
|
783
810
|
ORDER BY time`,
|
|
784
811
|
},
|
|
785
812
|
{
|
|
786
|
-
description:
|
|
813
|
+
description:
|
|
814
|
+
"Trades on reversal days (lag-aware: Reversal_Type uses prior trading day via LAG)",
|
|
787
815
|
sql: `WITH joined AS (
|
|
788
816
|
SELECT d.ticker, d.date,
|
|
789
817
|
d.High_Before_Low, d.Reversal_Type
|
|
@@ -805,7 +833,8 @@ WHERE m.prev_Reversal_Type != 0
|
|
|
805
833
|
AND t.block_id = 'my-block'`,
|
|
806
834
|
},
|
|
807
835
|
{
|
|
808
|
-
description:
|
|
836
|
+
description:
|
|
837
|
+
"Enrich trades with market data (lag-aware: use enrich_trades tool for full enrichment)",
|
|
809
838
|
sql: `WITH joined AS (
|
|
810
839
|
SELECT d.ticker, d.date,
|
|
811
840
|
d.Gap_Pct, d.Prior_Close,
|
|
@@ -833,7 +862,8 @@ WHERE t.block_id = 'my-block'`,
|
|
|
833
862
|
],
|
|
834
863
|
hypothesis: [
|
|
835
864
|
{
|
|
836
|
-
description:
|
|
865
|
+
description:
|
|
866
|
+
"Win rate by VIX regime (lag-aware: uses prior day's Vol_Regime from market.enriched_context)",
|
|
837
867
|
sql: `WITH joined AS (
|
|
838
868
|
SELECT d.ticker, d.date, cd.Vol_Regime
|
|
839
869
|
FROM market.enriched d
|
|
@@ -872,7 +902,8 @@ GROUP BY d.Day_of_Week
|
|
|
872
902
|
ORDER BY d.Day_of_Week`,
|
|
873
903
|
},
|
|
874
904
|
{
|
|
875
|
-
description:
|
|
905
|
+
description:
|
|
906
|
+
"Performance by VIX term structure (lag-aware: uses prior day's Term_Structure_State from market.enriched_context)",
|
|
876
907
|
sql: `WITH joined AS (
|
|
877
908
|
SELECT d.ticker, d.date, cd.Term_Structure_State
|
|
878
909
|
FROM market.enriched d
|
|
@@ -899,7 +930,8 @@ WHERE t.block_id = 'my-block'
|
|
|
899
930
|
GROUP BY term_structure`,
|
|
900
931
|
},
|
|
901
932
|
{
|
|
902
|
-
description:
|
|
933
|
+
description:
|
|
934
|
+
"Aggregate by VIX buckets (lag-aware: uses prior day's VIX close from market.spot_daily ticker='VIX')",
|
|
903
935
|
sql: `WITH joined AS (
|
|
904
936
|
SELECT d.ticker, d.date, vix_s.close AS VIX_Close
|
|
905
937
|
FROM market.enriched d
|