tradeblocks-mcp 3.0.2 → 3.3.1
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 +85 -80
- 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-QTTR7AAW.js → chunk-2I3S2ZLT.js} +325 -84
- package/dist/chunk-2I3S2ZLT.js.map +1 -0
- package/dist/{chunk-4BLCXNQ6.js → chunk-4HZLVUOZ.js} +179 -183
- package/dist/chunk-4HZLVUOZ.js.map +1 -0
- package/dist/{chunk-XXYOUIZY.js → chunk-NWNSKALN.js} +63 -80
- package/dist/chunk-NWNSKALN.js.map +1 -0
- package/dist/{chunk-PRAYH3RT.js → chunk-WNTYA7ER.js} +29 -12
- package/dist/chunk-WNTYA7ER.js.map +1 -0
- package/dist/{chunk-BKQ4PM4Y.js → chunk-YZA4RS76.js} +24 -18
- package/dist/chunk-YZA4RS76.js.map +1 -0
- package/dist/{chunk-W2PP3LEH.js → chunk-ZTJXC3LS.js} +17 -8
- package/dist/chunk-ZTJXC3LS.js.map +1 -0
- package/dist/daily-log-processor-MZW2XBZY.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-6U33TQUT.js +16 -0
- package/dist/{proto-3HZTCWK4.js → proto-V23GIZG2.js} +2 -2
- package/dist/{sync-PO4IPCYV.js → sync-3UBC37VW.js} +7 -7
- package/dist/test-exports.js +876 -483
- package/dist/test-exports.js.map +1 -1
- package/dist/trade-processor-DKDCWGKD.js +9 -0
- package/dist/{trades-store-LOL3FQSF.js → trades-store-R3NL25T2.js} +2 -2
- package/package.json +2 -6
- package/server/{chunk-CSDVJPBB.js → chunk-536NSFED.js} +29 -12
- package/server/chunk-536NSFED.js.map +1 -0
- package/server/{chunk-WA5AAPCH.js → chunk-A3UKD64A.js} +17 -8
- package/server/chunk-A3UKD64A.js.map +1 -0
- package/server/{chunk-PNKG7RY7.js → chunk-OMUDNJBJ.js} +63 -80
- package/server/chunk-OMUDNJBJ.js.map +1 -0
- package/server/{chunk-72GKJE2U.js → chunk-RJDJHZ5Y.js} +934 -335
- package/server/chunk-RJDJHZ5Y.js.map +1 -0
- package/server/{chunk-NZO6PT64.js → chunk-RM4B2VKS.js} +167 -177
- package/server/chunk-RM4B2VKS.js.map +1 -0
- package/server/{chunk-5EBXHT6C.js → chunk-SY6GDNVI.js} +24 -18
- package/server/chunk-SY6GDNVI.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/{config-6IZXEFEX.js → config-DK7KOMNL.js} +1 -1
- package/server/config-DK7KOMNL.js.map +1 -0
- package/server/daily-log-processor-B2VPU2FQ.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 +2497 -2029
- package/server/index.js.map +1 -1
- package/server/iv-solver-worker.js +9 -1
- package/server/market-provider-L56RFHAC.js +17 -0
- package/server/{proto-DWRZJO4E.js → proto-YZ4TLX2N.js} +2 -2
- package/server/{sync-QFI5L7S7.js → sync-CENKDN53.js} +7 -7
- package/server/trade-processor-3PI4LHZI.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 +38 -8
- package/src/db/connection.ts +107 -40
- package/src/db/data-root.ts +22 -0
- 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 +139 -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/index.ts +2 -0
- package/src/tools/blocks/paired-comparison.ts +425 -0
- 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 +11 -14
- 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 +69 -83
- package/src/utils/calibration-probe.ts +3 -4
- 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-QTTR7AAW.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/manifest.json +0 -141
- 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-MZW2XBZY.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-6U33TQUT.js.map} +0 -0
- /package/dist/{proto-3HZTCWK4.js.map → proto-V23GIZG2.js.map} +0 -0
- /package/dist/{sync-PO4IPCYV.js.map → sync-3UBC37VW.js.map} +0 -0
- /package/dist/{trade-processor-NHU4VWRX.js.map → trade-processor-DKDCWGKD.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-B2VPU2FQ.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-L56RFHAC.js.map} +0 -0
- /package/server/{proto-DWRZJO4E.js.map → proto-YZ4TLX2N.js.map} +0 -0
- /package/server/{sync-QFI5L7S7.js.map → sync-CENKDN53.js.map} +0 -0
- /package/server/{trade-processor-JWVS37KM.js.map → trade-processor-3PI4LHZI.js.map} +0 -0
- /package/server/{trades-store-VY26MWER.js.map → trades-store-RTTEYMXH.js.map} +0 -0
|
@@ -57,63 +57,72 @@ export interface MarketLookupKey {
|
|
|
57
57
|
* `e`-prefixed alias {evix, evix9d, evix3m}.
|
|
58
58
|
*/
|
|
59
59
|
interface VixFieldMapping {
|
|
60
|
-
alias: string;
|
|
61
|
-
tableAlias: string;
|
|
62
|
-
sourceCol: string;
|
|
63
|
-
ticker: string;
|
|
64
|
-
timing:
|
|
60
|
+
alias: string; // Column name in query output (e.g., "VIX_Close")
|
|
61
|
+
tableAlias: string; // SQL table alias (e.g., "vix" for OHLCV, "evix" for enriched)
|
|
62
|
+
sourceCol: string; // Source column (e.g., "close" in spot_daily, "ivr" in enriched)
|
|
63
|
+
ticker: string; // Ticker to join on (e.g., "VIX")
|
|
64
|
+
timing: "open" | "close";
|
|
65
65
|
}
|
|
66
66
|
|
|
67
67
|
// OHLCV-sourced VIX columns — come from market.spot_daily, aliased as vix/vix9d/vix3m
|
|
68
68
|
const VIX_OHLCV_MAPPINGS: VixFieldMapping[] = [
|
|
69
69
|
// VIX
|
|
70
|
-
{ alias: "VIX_Open",
|
|
71
|
-
{ alias: "VIX_Close", tableAlias: "vix",
|
|
72
|
-
{ alias: "VIX_High",
|
|
73
|
-
{ alias: "VIX_Low",
|
|
70
|
+
{ alias: "VIX_Open", tableAlias: "vix", sourceCol: "open", ticker: "VIX", timing: "open" },
|
|
71
|
+
{ alias: "VIX_Close", tableAlias: "vix", sourceCol: "close", ticker: "VIX", timing: "close" },
|
|
72
|
+
{ alias: "VIX_High", tableAlias: "vix", sourceCol: "high", ticker: "VIX", timing: "close" },
|
|
73
|
+
{ alias: "VIX_Low", tableAlias: "vix", sourceCol: "low", ticker: "VIX", timing: "close" },
|
|
74
74
|
// VIX9D
|
|
75
|
-
{ alias: "VIX9D_Open",
|
|
76
|
-
{
|
|
75
|
+
{ alias: "VIX9D_Open", tableAlias: "vix9d", sourceCol: "open", ticker: "VIX9D", timing: "open" },
|
|
76
|
+
{
|
|
77
|
+
alias: "VIX9D_Close",
|
|
78
|
+
tableAlias: "vix9d",
|
|
79
|
+
sourceCol: "close",
|
|
80
|
+
ticker: "VIX9D",
|
|
81
|
+
timing: "close",
|
|
82
|
+
},
|
|
77
83
|
// VIX3M
|
|
78
|
-
{ alias: "VIX3M_Open",
|
|
79
|
-
{
|
|
84
|
+
{ alias: "VIX3M_Open", tableAlias: "vix3m", sourceCol: "open", ticker: "VIX3M", timing: "open" },
|
|
85
|
+
{
|
|
86
|
+
alias: "VIX3M_Close",
|
|
87
|
+
tableAlias: "vix3m",
|
|
88
|
+
sourceCol: "close",
|
|
89
|
+
ticker: "VIX3M",
|
|
90
|
+
timing: "close",
|
|
91
|
+
},
|
|
80
92
|
];
|
|
81
93
|
|
|
82
94
|
// Enrichment-sourced VIX columns — come from market.enriched, aliased as evix/evix9d/evix3m
|
|
83
95
|
const VIX_ENRICHED_MAPPINGS: VixFieldMapping[] = [
|
|
84
|
-
{ alias: "VIX_IVR",
|
|
85
|
-
{ alias: "VIX_IVP",
|
|
86
|
-
{ alias: "VIX9D_IVR",
|
|
87
|
-
{ alias: "VIX9D_IVP",
|
|
88
|
-
{ alias: "VIX3M_IVR",
|
|
89
|
-
{ alias: "VIX3M_IVP",
|
|
96
|
+
{ alias: "VIX_IVR", tableAlias: "evix", sourceCol: "ivr", ticker: "VIX", timing: "close" },
|
|
97
|
+
{ alias: "VIX_IVP", tableAlias: "evix", sourceCol: "ivp", ticker: "VIX", timing: "close" },
|
|
98
|
+
{ alias: "VIX9D_IVR", tableAlias: "evix9d", sourceCol: "ivr", ticker: "VIX9D", timing: "close" },
|
|
99
|
+
{ alias: "VIX9D_IVP", tableAlias: "evix9d", sourceCol: "ivp", ticker: "VIX9D", timing: "close" },
|
|
100
|
+
{ alias: "VIX3M_IVR", tableAlias: "evix3m", sourceCol: "ivr", ticker: "VIX3M", timing: "close" },
|
|
101
|
+
{ alias: "VIX3M_IVP", tableAlias: "evix3m", sourceCol: "ivp", ticker: "VIX3M", timing: "close" },
|
|
90
102
|
];
|
|
91
103
|
|
|
92
104
|
// Union of all VIX mappings (order preserved: OHLCV first, then enrichment) — used for
|
|
93
105
|
// SELECT column emission and open/close field-set derivation downstream.
|
|
94
|
-
const VIX_ALL_MAPPINGS: VixFieldMapping[] = [
|
|
95
|
-
...VIX_OHLCV_MAPPINGS,
|
|
96
|
-
...VIX_ENRICHED_MAPPINGS,
|
|
97
|
-
];
|
|
106
|
+
const VIX_ALL_MAPPINGS: VixFieldMapping[] = [...VIX_OHLCV_MAPPINGS, ...VIX_ENRICHED_MAPPINGS];
|
|
98
107
|
|
|
99
108
|
// Unique OHLCV table aliases needed for the JOIN clause (used by buildVixJoinClause)
|
|
100
|
-
const VIX_TICKER_ALIASES = [...new Set(VIX_OHLCV_MAPPINGS.map(m => m.tableAlias))];
|
|
109
|
+
const VIX_TICKER_ALIASES = [...new Set(VIX_OHLCV_MAPPINGS.map((m) => m.tableAlias))];
|
|
101
110
|
const VIX_TICKER_FOR_ALIAS: Record<string, string> = Object.fromEntries([
|
|
102
|
-
...VIX_OHLCV_MAPPINGS.map(m => [m.tableAlias, m.ticker] as const),
|
|
103
|
-
...VIX_ENRICHED_MAPPINGS.map(m => [m.tableAlias, m.ticker] as const),
|
|
111
|
+
...VIX_OHLCV_MAPPINGS.map((m) => [m.tableAlias, m.ticker] as const),
|
|
112
|
+
...VIX_ENRICHED_MAPPINGS.map((m) => [m.tableAlias, m.ticker] as const),
|
|
104
113
|
]);
|
|
105
114
|
|
|
106
115
|
// Derived fields from date_context
|
|
107
116
|
const DERIVED_OPEN_FIELDS: ReadonlySet<string> = new Set(
|
|
108
117
|
Object.entries(derivedColumns)
|
|
109
|
-
.filter(([, desc]) => desc.timing ===
|
|
110
|
-
.map(([name]) => name)
|
|
118
|
+
.filter(([, desc]) => desc.timing === "open")
|
|
119
|
+
.map(([name]) => name),
|
|
111
120
|
);
|
|
112
121
|
|
|
113
122
|
const DERIVED_CLOSE_FIELDS: ReadonlySet<string> = new Set(
|
|
114
123
|
Object.entries(derivedColumns)
|
|
115
|
-
.filter(([, desc]) => desc.timing ===
|
|
116
|
-
.map(([name]) => name)
|
|
124
|
+
.filter(([, desc]) => desc.timing === "close")
|
|
125
|
+
.map(([name]) => name),
|
|
117
126
|
);
|
|
118
127
|
|
|
119
128
|
// ============================================================================
|
|
@@ -128,8 +137,8 @@ const DERIVED_CLOSE_FIELDS: ReadonlySet<string> = new Set(
|
|
|
128
137
|
*/
|
|
129
138
|
export const DAILY_OPEN_FIELDS: ReadonlySet<string> = new Set(
|
|
130
139
|
Object.entries(dailyColumns)
|
|
131
|
-
.filter(([, desc]) => desc.timing ===
|
|
132
|
-
.map(([name]) => name)
|
|
140
|
+
.filter(([, desc]) => desc.timing === "open")
|
|
141
|
+
.map(([name]) => name),
|
|
133
142
|
);
|
|
134
143
|
|
|
135
144
|
/**
|
|
@@ -138,8 +147,8 @@ export const DAILY_OPEN_FIELDS: ReadonlySet<string> = new Set(
|
|
|
138
147
|
*/
|
|
139
148
|
export const DAILY_CLOSE_FIELDS: ReadonlySet<string> = new Set(
|
|
140
149
|
Object.entries(dailyColumns)
|
|
141
|
-
.filter(([, desc]) => desc.timing ===
|
|
142
|
-
.map(([name]) => name)
|
|
150
|
+
.filter(([, desc]) => desc.timing === "close")
|
|
151
|
+
.map(([name]) => name),
|
|
143
152
|
);
|
|
144
153
|
|
|
145
154
|
/**
|
|
@@ -147,15 +156,15 @@ export const DAILY_CLOSE_FIELDS: ReadonlySet<string> = new Set(
|
|
|
147
156
|
*/
|
|
148
157
|
export const DAILY_STATIC_FIELDS: ReadonlySet<string> = new Set(
|
|
149
158
|
Object.entries(dailyColumns)
|
|
150
|
-
.filter(([, desc]) => desc.timing ===
|
|
151
|
-
.map(([name]) => name)
|
|
159
|
+
.filter(([, desc]) => desc.timing === "static")
|
|
160
|
+
.map(([name]) => name),
|
|
152
161
|
);
|
|
153
162
|
|
|
154
163
|
/**
|
|
155
164
|
* Open-known fields from VIX tickers + enriched_context
|
|
156
165
|
*/
|
|
157
166
|
export const CONTEXT_OPEN_FIELDS: ReadonlySet<string> = new Set([
|
|
158
|
-
...VIX_ALL_MAPPINGS.filter(m => m.timing ===
|
|
167
|
+
...VIX_ALL_MAPPINGS.filter((m) => m.timing === "open").map((m) => m.alias),
|
|
159
168
|
...DERIVED_OPEN_FIELDS,
|
|
160
169
|
]);
|
|
161
170
|
|
|
@@ -163,7 +172,7 @@ export const CONTEXT_OPEN_FIELDS: ReadonlySet<string> = new Set([
|
|
|
163
172
|
* Close-derived fields from VIX tickers + enriched_context
|
|
164
173
|
*/
|
|
165
174
|
export const CONTEXT_CLOSE_FIELDS: ReadonlySet<string> = new Set([
|
|
166
|
-
...VIX_ALL_MAPPINGS.filter(m => m.timing ===
|
|
175
|
+
...VIX_ALL_MAPPINGS.filter((m) => m.timing === "close").map((m) => m.alias),
|
|
167
176
|
...DERIVED_CLOSE_FIELDS,
|
|
168
177
|
]);
|
|
169
178
|
|
|
@@ -198,9 +207,7 @@ export const CLOSE_KNOWN_FIELDS: ReadonlySet<string> = new Set([
|
|
|
198
207
|
* Only from market.enriched (context has no static fields).
|
|
199
208
|
* Safe to use as same-day values in trade-entry queries.
|
|
200
209
|
*/
|
|
201
|
-
export const STATIC_FIELDS: ReadonlySet<string> = new Set([
|
|
202
|
-
...DAILY_STATIC_FIELDS,
|
|
203
|
-
]);
|
|
210
|
+
export const STATIC_FIELDS: ReadonlySet<string> = new Set([...DAILY_STATIC_FIELDS]);
|
|
204
211
|
|
|
205
212
|
// ============================================================================
|
|
206
213
|
// Query Builders
|
|
@@ -221,12 +228,9 @@ export const STATIC_FIELDS: ReadonlySet<string> = new Set([
|
|
|
221
228
|
* @param baseAlias alias of the main table the joins attach to (default 'd')
|
|
222
229
|
* @returns SQL fragment string with \n + 6-space indent between JOINs
|
|
223
230
|
*/
|
|
224
|
-
export function buildVixJoinClause(
|
|
225
|
-
tickerAliases: string[],
|
|
226
|
-
baseAlias: string = "d",
|
|
227
|
-
): string {
|
|
231
|
+
export function buildVixJoinClause(tickerAliases: string[], baseAlias: string = "d"): string {
|
|
228
232
|
return tickerAliases
|
|
229
|
-
.flatMap(alias => {
|
|
233
|
+
.flatMap((alias) => {
|
|
230
234
|
const ticker = VIX_TICKER_FOR_ALIAS[alias];
|
|
231
235
|
return [
|
|
232
236
|
`LEFT JOIN market.spot_daily ${alias} ON ${alias}.date = ${baseAlias}.date AND ${alias}.ticker = '${ticker}'`,
|
|
@@ -239,14 +243,12 @@ export function buildVixJoinClause(
|
|
|
239
243
|
// SELECT columns from VIX OHLCV + enrichment mappings, e.g. vix."close" AS "VIX_Close",
|
|
240
244
|
// evix."ivr" AS "VIX_IVR", ...
|
|
241
245
|
function buildVixSelectCols(): string {
|
|
242
|
-
return VIX_ALL_MAPPINGS
|
|
243
|
-
.map(m => `${m.tableAlias}."${m.sourceCol}" AS "${m.alias}"`)
|
|
244
|
-
.join(", ");
|
|
246
|
+
return VIX_ALL_MAPPINGS.map((m) => `${m.tableAlias}."${m.sourceCol}" AS "${m.alias}"`).join(", ");
|
|
245
247
|
}
|
|
246
248
|
|
|
247
249
|
// SELECT columns from enriched_context: cd."Vol_Regime", ...
|
|
248
250
|
function buildDerivedSelectCols(): string {
|
|
249
|
-
return [...DERIVED_OPEN_FIELDS, ...DERIVED_CLOSE_FIELDS].map(f => `cd."${f}"`).join(", ");
|
|
251
|
+
return [...DERIVED_OPEN_FIELDS, ...DERIVED_CLOSE_FIELDS].map((f) => `cd."${f}"`).join(", ");
|
|
250
252
|
}
|
|
251
253
|
|
|
252
254
|
/**
|
|
@@ -280,19 +282,29 @@ function buildDerivedSelectCols(): string {
|
|
|
280
282
|
* @returns Object with `sql` (the query string) and `params` (the parameter values)
|
|
281
283
|
*/
|
|
282
284
|
export function buildLookaheadFreeQuery(tradeDates: string[]): { sql: string; params: string[] };
|
|
283
|
-
export function buildLookaheadFreeQuery(tradeKeys: MarketLookupKey[]): {
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
285
|
+
export function buildLookaheadFreeQuery(tradeKeys: MarketLookupKey[]): {
|
|
286
|
+
sql: string;
|
|
287
|
+
params: string[];
|
|
288
|
+
};
|
|
289
|
+
export function buildLookaheadFreeQuery(tradeDatesOrKeys: string[] | MarketLookupKey[]): {
|
|
290
|
+
sql: string;
|
|
291
|
+
params: string[];
|
|
292
|
+
} {
|
|
287
293
|
if (tradeDatesOrKeys.length === 0) {
|
|
288
294
|
return { sql: `SELECT * FROM market.enriched WHERE 1=0`, params: [] };
|
|
289
295
|
}
|
|
290
296
|
|
|
291
297
|
// Build field lists for the joined CTE. OHLCV columns project from alias `s`
|
|
292
298
|
// (market.spot_daily); enrichment columns project from alias `d` (market.enriched).
|
|
293
|
-
const dailyOpenCols = [...DAILY_OPEN_FIELDS]
|
|
294
|
-
|
|
295
|
-
|
|
299
|
+
const dailyOpenCols = [...DAILY_OPEN_FIELDS]
|
|
300
|
+
.map((f) => `${aliasForDailyCol(f)}."${f}"`)
|
|
301
|
+
.join(", ");
|
|
302
|
+
const dailyStaticCols = [...DAILY_STATIC_FIELDS]
|
|
303
|
+
.map((f) => `${aliasForDailyCol(f)}."${f}"`)
|
|
304
|
+
.join(", ");
|
|
305
|
+
const dailyCloseCols = [...DAILY_CLOSE_FIELDS]
|
|
306
|
+
.map((f) => `${aliasForDailyCol(f)}."${f}"`)
|
|
307
|
+
.join(", ");
|
|
296
308
|
const vixSelectCols = buildVixSelectCols();
|
|
297
309
|
const derivedSelectCols = buildDerivedSelectCols();
|
|
298
310
|
const vixJoins = buildVixJoinClause(VIX_TICKER_ALIASES, "d");
|
|
@@ -301,22 +313,20 @@ export function buildLookaheadFreeQuery(
|
|
|
301
313
|
const dailyLagCols = [...DAILY_CLOSE_FIELDS]
|
|
302
314
|
.map((field) => `LAG("${field}") OVER (PARTITION BY ticker ORDER BY date) AS "prev_${field}"`)
|
|
303
315
|
.join(",\n ");
|
|
304
|
-
const vixLagCols = VIX_ALL_MAPPINGS
|
|
305
|
-
.
|
|
306
|
-
.map(m => `LAG("${m.alias}") OVER (PARTITION BY ticker ORDER BY date) AS "prev_${m.alias}"`)
|
|
316
|
+
const vixLagCols = VIX_ALL_MAPPINGS.filter((m) => m.timing === "close")
|
|
317
|
+
.map((m) => `LAG("${m.alias}") OVER (PARTITION BY ticker ORDER BY date) AS "prev_${m.alias}"`)
|
|
307
318
|
.join(",\n ");
|
|
308
319
|
const derivedLagCols = [...DERIVED_CLOSE_FIELDS]
|
|
309
|
-
.map(f => `LAG("${f}") OVER (PARTITION BY ticker ORDER BY date) AS "prev_${f}"`)
|
|
320
|
+
.map((f) => `LAG("${f}") OVER (PARTITION BY ticker ORDER BY date) AS "prev_${f}"`)
|
|
310
321
|
.join(",\n ");
|
|
311
322
|
|
|
312
323
|
// Pass-through columns for the lagged CTE (unaliased, from joined CTE output)
|
|
313
324
|
const dailyOpenPassthrough = [...DAILY_OPEN_FIELDS].map((f) => `"${f}"`).join(", ");
|
|
314
325
|
const dailyStaticPassthrough = [...DAILY_STATIC_FIELDS].map((f) => `"${f}"`).join(", ");
|
|
315
|
-
const vixOpenPassthrough = VIX_ALL_MAPPINGS
|
|
316
|
-
.
|
|
317
|
-
.map(m => `"${m.alias}"`)
|
|
326
|
+
const vixOpenPassthrough = VIX_ALL_MAPPINGS.filter((m) => m.timing === "open")
|
|
327
|
+
.map((m) => `"${m.alias}"`)
|
|
318
328
|
.join(", ");
|
|
319
|
-
const derivedOpenPassthrough = [...DERIVED_OPEN_FIELDS].map(f => `"${f}"`).join(", ");
|
|
329
|
+
const derivedOpenPassthrough = [...DERIVED_OPEN_FIELDS].map((f) => `"${f}"`).join(", ");
|
|
320
330
|
|
|
321
331
|
// Legacy path for existing date-only callers (single ticker = DEFAULT_MARKET_TICKER)
|
|
322
332
|
if (typeof tradeDatesOrKeys[0] === "string") {
|
|
@@ -423,40 +433,43 @@ export function buildLookaheadFreeQuery(
|
|
|
423
433
|
*/
|
|
424
434
|
export function buildOutcomeQuery(tradeDates: string[]): { sql: string; params: string[] };
|
|
425
435
|
export function buildOutcomeQuery(tradeKeys: MarketLookupKey[]): { sql: string; params: string[] };
|
|
426
|
-
export function buildOutcomeQuery(
|
|
427
|
-
|
|
428
|
-
|
|
436
|
+
export function buildOutcomeQuery(tradeDatesOrKeys: string[] | MarketLookupKey[]): {
|
|
437
|
+
sql: string;
|
|
438
|
+
params: string[];
|
|
439
|
+
} {
|
|
429
440
|
if (tradeDatesOrKeys.length === 0) {
|
|
430
441
|
return { sql: `SELECT * FROM market.enriched WHERE 1=0`, params: [] };
|
|
431
442
|
}
|
|
432
443
|
|
|
433
|
-
const vixCloseCols = VIX_ALL_MAPPINGS
|
|
434
|
-
.
|
|
435
|
-
.map(m => `${m.tableAlias}."${m.sourceCol}" AS "${m.alias}"`)
|
|
444
|
+
const vixCloseCols = VIX_ALL_MAPPINGS.filter((m) => m.timing === "close")
|
|
445
|
+
.map((m) => `${m.tableAlias}."${m.sourceCol}" AS "${m.alias}"`)
|
|
436
446
|
.join(", ");
|
|
437
|
-
const derivedCloseCols = [...DERIVED_CLOSE_FIELDS].map(f => `cd."${f}"`).join(", ");
|
|
447
|
+
const derivedCloseCols = [...DERIVED_CLOSE_FIELDS].map((f) => `cd."${f}"`).join(", ");
|
|
438
448
|
|
|
439
449
|
if (typeof tradeDatesOrKeys[0] === "string") {
|
|
440
450
|
return buildOutcomeQueryForDates(tradeDatesOrKeys as string[], vixCloseCols, derivedCloseCols);
|
|
441
451
|
}
|
|
442
452
|
|
|
443
|
-
return buildOutcomeQueryForKeys(
|
|
453
|
+
return buildOutcomeQueryForKeys(
|
|
454
|
+
tradeDatesOrKeys as MarketLookupKey[],
|
|
455
|
+
vixCloseCols,
|
|
456
|
+
derivedCloseCols,
|
|
457
|
+
);
|
|
444
458
|
}
|
|
445
459
|
|
|
446
460
|
// Emit OHLCV-aware projection for the target-ticker close columns. Columns in
|
|
447
461
|
// OHLCV_COLS come from the spot_daily alias `sAlias`; other enrichment-close
|
|
448
462
|
// columns come from the enriched alias `eAlias`.
|
|
449
|
-
function buildTargetCloseCols(
|
|
450
|
-
eAlias: string,
|
|
451
|
-
sAlias: string,
|
|
452
|
-
): string {
|
|
463
|
+
function buildTargetCloseCols(eAlias: string, sAlias: string): string {
|
|
453
464
|
return [...DAILY_CLOSE_FIELDS]
|
|
454
465
|
.map((f) => `${OHLCV_COLS.has(f) ? sAlias : eAlias}."${f}"`)
|
|
455
466
|
.join(", ");
|
|
456
467
|
}
|
|
457
468
|
|
|
458
469
|
function buildOutcomeQueryForDates(
|
|
459
|
-
tradeDates: string[],
|
|
470
|
+
tradeDates: string[],
|
|
471
|
+
vixCloseCols: string,
|
|
472
|
+
derivedCloseCols: string,
|
|
460
473
|
): { sql: string; params: string[] } {
|
|
461
474
|
const eAlias = "d";
|
|
462
475
|
const sAlias = "s";
|
|
@@ -473,7 +486,9 @@ function buildOutcomeQueryForDates(
|
|
|
473
486
|
}
|
|
474
487
|
|
|
475
488
|
function buildOutcomeQueryForKeys(
|
|
476
|
-
tradeKeys: MarketLookupKey[],
|
|
489
|
+
tradeKeys: MarketLookupKey[],
|
|
490
|
+
vixCloseCols: string,
|
|
491
|
+
derivedCloseCols: string,
|
|
477
492
|
): { sql: string; params: string[] } {
|
|
478
493
|
const eAlias = "m";
|
|
479
494
|
const sAlias = "ms";
|
|
@@ -28,11 +28,18 @@ export interface FilterPredicate {
|
|
|
28
28
|
* Day-of-week name to number mapping (market data uses 1=Mon to 5=Fri).
|
|
29
29
|
*/
|
|
30
30
|
const DAY_NAME_TO_NUM: Record<string, number> = {
|
|
31
|
-
monday: 1,
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
31
|
+
monday: 1,
|
|
32
|
+
mon: 1,
|
|
33
|
+
tuesday: 2,
|
|
34
|
+
tue: 2,
|
|
35
|
+
tues: 2,
|
|
36
|
+
wednesday: 3,
|
|
37
|
+
wed: 3,
|
|
38
|
+
thursday: 4,
|
|
39
|
+
thu: 4,
|
|
40
|
+
thurs: 4,
|
|
41
|
+
friday: 5,
|
|
42
|
+
fri: 5,
|
|
36
43
|
};
|
|
37
44
|
|
|
38
45
|
/**
|
|
@@ -80,10 +87,7 @@ function isCrossFieldRef(value: unknown): value is string {
|
|
|
80
87
|
* if the bare field name (without prev_ prefix) is close-derived, try
|
|
81
88
|
* the prev_ prefixed version.
|
|
82
89
|
*/
|
|
83
|
-
function resolveFieldRef(
|
|
84
|
-
refName: string,
|
|
85
|
-
market: Record<string, unknown>
|
|
86
|
-
): number {
|
|
90
|
+
function resolveFieldRef(refName: string, market: Record<string, unknown>): number {
|
|
87
91
|
// Direct lookup first (handles cases like "prev_VIX_Close" spelled out)
|
|
88
92
|
if (refName in market) {
|
|
89
93
|
return getNum(market, refName);
|