tradeblocks-mcp 4.2.0 → 4.3.0
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 +40 -1
- package/dist/{chunk-YRD62LDE.js → chunk-35RVWZGT.js} +4 -1
- package/dist/{chunk-4UU7IT2A.js.map → chunk-35RVWZGT.js.map} +1 -1
- package/dist/{chunk-4UU7IT2A.js → chunk-ENXBPJ7Y.js} +148 -6
- package/dist/chunk-ENXBPJ7Y.js.map +1 -0
- package/dist/{chunk-62GCLMQA.js → chunk-TLX7IBCM.js} +3 -6
- package/dist/chunk-TLX7IBCM.js.map +1 -0
- package/dist/{daily-logs-store-PXB53WEK.js → daily-logs-store-FZRIGYUX.js} +2 -2
- package/dist/{daily-logs-store-65YHFJ5F.js → daily-logs-store-MEZ5S3BR.js} +2 -2
- package/dist/market/provenance/index.js +1 -4
- package/dist/market/provenance/index.js.map +1 -1
- package/dist/{sync-JL7OPLCT.js → sync-EW33QZPD.js} +3 -3
- package/dist/test-exports.js +320 -279
- package/dist/test-exports.js.map +1 -1
- package/dist/{trades-store-UGZ62A7N.js → trades-store-3TOLBL2W.js} +2 -2
- package/dist/{trades-store-MOFJHRC2.js → trades-store-PNLPRYRJ.js} +2 -2
- package/package.json +1 -1
- package/server/{chunk-7N6HBOAY.js → chunk-PDSUY2X2.js} +148 -6
- package/server/chunk-PDSUY2X2.js.map +1 -0
- package/server/{chunk-J4GWE6JR.js → chunk-YIWLVX7Z.js} +3 -6
- package/server/chunk-YIWLVX7Z.js.map +1 -0
- package/server/{daily-logs-store-YAXASQN4.js → daily-logs-store-LRVO7COL.js} +2 -2
- package/server/index.js +993 -801
- package/server/index.js.map +1 -1
- package/server/{sync-ZV3QEGMO.js → sync-2POG6KA6.js} +3 -3
- package/server/{trades-store-MF7YYLCH.js → trades-store-MXUZLSF5.js} +2 -2
- package/src/db/dataset-schemas.ts +97 -23
- package/src/tools/market-data.ts +327 -245
- package/src/tools/profile-analysis.ts +18 -4
- package/src/tools/reports/fields.ts +16 -11
- package/src/tools/reports/helpers.ts +6 -2
- package/src/tools/reports/predictive.ts +15 -4
- package/src/tools/shared/field-analysis.ts +57 -14
- package/src/tools/shared/filter-objective.ts +73 -0
- package/src/utils/trade-analysis-fields.ts +19 -4
- package/dist/chunk-62GCLMQA.js.map +0 -1
- package/dist/chunk-YRD62LDE.js.map +0 -1
- package/server/chunk-7N6HBOAY.js.map +0 -1
- package/server/chunk-J4GWE6JR.js.map +0 -1
- /package/dist/{daily-logs-store-65YHFJ5F.js.map → daily-logs-store-FZRIGYUX.js.map} +0 -0
- /package/dist/{daily-logs-store-PXB53WEK.js.map → daily-logs-store-MEZ5S3BR.js.map} +0 -0
- /package/dist/{sync-JL7OPLCT.js.map → sync-EW33QZPD.js.map} +0 -0
- /package/dist/{trades-store-MOFJHRC2.js.map → trades-store-3TOLBL2W.js.map} +0 -0
- /package/dist/{trades-store-UGZ62A7N.js.map → trades-store-PNLPRYRJ.js.map} +0 -0
- /package/server/{daily-logs-store-YAXASQN4.js.map → daily-logs-store-LRVO7COL.js.map} +0 -0
- /package/server/{sync-ZV3QEGMO.js.map → sync-2POG6KA6.js.map} +0 -0
- /package/server/{trades-store-MF7YYLCH.js.map → trades-store-MXUZLSF5.js.map} +0 -0
package/dist/test-exports.js
CHANGED
|
@@ -131,7 +131,7 @@ import {
|
|
|
131
131
|
writeParquetPartition,
|
|
132
132
|
writeQuoteMinutesPartition,
|
|
133
133
|
writeSpotPartition
|
|
134
|
-
} from "./chunk-
|
|
134
|
+
} from "./chunk-TLX7IBCM.js";
|
|
135
135
|
import "./chunk-D4AWELQU.js";
|
|
136
136
|
import "./chunk-IW75IC6I.js";
|
|
137
137
|
import "./chunk-ZSVYX5PP.js";
|
|
@@ -149,7 +149,7 @@ import {
|
|
|
149
149
|
resolveTreasuryRateByKey,
|
|
150
150
|
setPublishedRates,
|
|
151
151
|
validatePublishedRates
|
|
152
|
-
} from "./chunk-
|
|
152
|
+
} from "./chunk-ENXBPJ7Y.js";
|
|
153
153
|
import "./chunk-BH6SQOWF.js";
|
|
154
154
|
import {
|
|
155
155
|
loadMddsProtoRoot
|
|
@@ -3589,9 +3589,13 @@ async function handleDeleteProfile(input, baseDir) {
|
|
|
3589
3589
|
}
|
|
3590
3590
|
|
|
3591
3591
|
// src/tools/profile-analysis.ts
|
|
3592
|
-
import { z as
|
|
3592
|
+
import { z as z6 } from "zod";
|
|
3593
3593
|
|
|
3594
3594
|
// src/db/dataset-schemas.ts
|
|
3595
|
+
import { z as z5 } from "zod";
|
|
3596
|
+
var maxMissedSessionsSchema = z5.number().int().nonnegative().optional().describe(
|
|
3597
|
+
"Opt-in maximum missed XNYS sessions for dataset values. No limit when omitted. Unsupported calendar ages (outside 2022\u20132030) are refused when a limit is set."
|
|
3598
|
+
);
|
|
3595
3599
|
async function listDatasets(conn) {
|
|
3596
3600
|
const exists = await conn.runAndReadAll(
|
|
3597
3601
|
"SELECT count(*) FROM information_schema.tables WHERE table_schema = 'datasets' AND table_name = 'dataset'"
|
|
@@ -3641,7 +3645,7 @@ function datasetFields(entries) {
|
|
|
3641
3645
|
(value) => typeof value === "number" || typeof value === "string" && value.trim() !== ""
|
|
3642
3646
|
).every((value) => typeof value === "number") ? "numeric" : "categorical",
|
|
3643
3647
|
timing: dataset.columnTiming[column],
|
|
3644
|
-
knownBy: dataset.knownBy ?? null,
|
|
3648
|
+
knownBy: dataset.columnTiming[column] === "open" ? dataset.knownBy ?? null : null,
|
|
3645
3649
|
source
|
|
3646
3650
|
}))
|
|
3647
3651
|
);
|
|
@@ -3661,24 +3665,26 @@ async function runtimeFieldCatalog(conn) {
|
|
|
3661
3665
|
...datasetFields(entries)
|
|
3662
3666
|
];
|
|
3663
3667
|
}
|
|
3664
|
-
function resolveTradeDatasets(entries, trade) {
|
|
3668
|
+
function resolveTradeDatasets(entries, trade, maxMissedSessions) {
|
|
3665
3669
|
const values = {};
|
|
3666
3670
|
const provenance = {};
|
|
3671
|
+
const rejected = {};
|
|
3667
3672
|
const entryTime = combineDateAndTime(trade.dateOpened, trade.timeOpened);
|
|
3668
3673
|
for (const { dataset, rows, ticker } of entries) {
|
|
3669
3674
|
if (ticker && ticker !== resolveTradeTicker(trade)) continue;
|
|
3670
3675
|
for (const column of dataset.columns) {
|
|
3671
|
-
const match = resolveDatasetColumnAtTime(dataset, rows, column, entryTime);
|
|
3676
|
+
const match = resolveDatasetColumnAtTime(dataset, rows, column, entryTime, maxMissedSessions);
|
|
3672
3677
|
if (!match) continue;
|
|
3673
3678
|
const field = `${dataset.name}.${column}`;
|
|
3674
|
-
values[field] = match.value;
|
|
3675
|
-
provenance[field] = {
|
|
3679
|
+
if (match.accepted) values[field] = match.value;
|
|
3680
|
+
(match.accepted ? provenance : rejected)[field] = {
|
|
3676
3681
|
sourceTimestamp: match.row.timestamp.toISOString(),
|
|
3677
|
-
availableAt: match.availableAt.toISOString()
|
|
3682
|
+
availableAt: match.availableAt.toISOString(),
|
|
3683
|
+
sessionAge: match.sessionAge
|
|
3678
3684
|
};
|
|
3679
3685
|
}
|
|
3680
3686
|
}
|
|
3681
|
-
return { values, provenance };
|
|
3687
|
+
return { values, provenance, rejected };
|
|
3682
3688
|
}
|
|
3683
3689
|
var easternCalendar = new Intl.DateTimeFormat("en-US", {
|
|
3684
3690
|
timeZone: "America/New_York",
|
|
@@ -3700,23 +3706,37 @@ function summarizeDatasetAge(trades, matches) {
|
|
|
3700
3706
|
const entryDay = easternDayNumber(
|
|
3701
3707
|
combineDateAndTime(trades[i].dateOpened, trades[i].timeOpened)
|
|
3702
3708
|
);
|
|
3703
|
-
for (const [field, provenance] of Object.entries(
|
|
3704
|
-
|
|
3705
|
-
|
|
3709
|
+
for (const [field, provenance] of Object.entries({
|
|
3710
|
+
...matches[i].provenance,
|
|
3711
|
+
...matches[i].rejected
|
|
3712
|
+
})) {
|
|
3713
|
+
const samples = ages.get(field) ?? { days: [], sessions: [], unsupported: 0, rejected: 0 };
|
|
3714
|
+
if (matches[i].rejected?.[field]) samples.rejected++;
|
|
3715
|
+
else samples.days.push(entryDay - easternDayNumber(new Date(provenance.sourceTimestamp)));
|
|
3716
|
+
if (typeof provenance.sessionAge === "number") samples.sessions.push(provenance.sessionAge);
|
|
3717
|
+
else samples.unsupported++;
|
|
3706
3718
|
ages.set(field, samples);
|
|
3707
3719
|
}
|
|
3708
3720
|
}
|
|
3709
3721
|
return Object.fromEntries(
|
|
3710
3722
|
[...ages].map(([field, samples]) => {
|
|
3711
|
-
samples.sort((a, b) => a - b);
|
|
3712
|
-
const
|
|
3723
|
+
const days = samples.days.sort((a, b) => a - b);
|
|
3724
|
+
const sessions = samples.sessions.sort((a, b) => a - b);
|
|
3725
|
+
const middle = Math.floor(days.length / 2);
|
|
3726
|
+
const sessionMiddle = Math.floor(sessions.length / 2);
|
|
3713
3727
|
return [
|
|
3714
3728
|
field,
|
|
3715
3729
|
{
|
|
3716
|
-
attachments:
|
|
3717
|
-
medianAgeDays:
|
|
3718
|
-
maxAgeDays:
|
|
3719
|
-
olderThan3Days:
|
|
3730
|
+
attachments: days.length,
|
|
3731
|
+
medianAgeDays: !days.length ? null : days.length % 2 ? days[middle] : (days[middle - 1] + days[middle]) / 2,
|
|
3732
|
+
maxAgeDays: days.length ? days[days.length - 1] : null,
|
|
3733
|
+
olderThan3Days: days.filter((age) => age > 3).length,
|
|
3734
|
+
sessionAgeStatus: samples.unsupported ? "unsupported" : "supported",
|
|
3735
|
+
medianAgeSessions: !sessions.length ? null : sessions.length % 2 ? sessions[sessionMiddle] : (sessions[sessionMiddle - 1] + sessions[sessionMiddle]) / 2,
|
|
3736
|
+
maxAgeSessions: sessions.length ? sessions[sessions.length - 1] : null,
|
|
3737
|
+
staleAttachments: sessions.filter((age) => age >= 1).length,
|
|
3738
|
+
unsupportedSessionAge: samples.unsupported,
|
|
3739
|
+
rejectedAttachments: samples.rejected
|
|
3720
3740
|
}
|
|
3721
3741
|
];
|
|
3722
3742
|
})
|
|
@@ -3726,7 +3746,18 @@ function datasetAgeOutput(summary, fields) {
|
|
|
3726
3746
|
const selected = Object.fromEntries(
|
|
3727
3747
|
fields.filter((field) => summary[field]).map((field) => [field, summary[field]])
|
|
3728
3748
|
);
|
|
3729
|
-
|
|
3749
|
+
const datasetWarnings = Object.entries(selected).flatMap(([field, age]) => [
|
|
3750
|
+
...age.staleAttachments ? [
|
|
3751
|
+
`${field}: ${age.staleAttachments} candidate attachments missed at least one expected XNYS session.`
|
|
3752
|
+
] : [],
|
|
3753
|
+
...age.unsupportedSessionAge ? [
|
|
3754
|
+
`${field}: session age unsupported for ${age.unsupportedSessionAge} candidate attachments outside XNYS calendar 2022\u20132030.`
|
|
3755
|
+
] : [],
|
|
3756
|
+
...age.rejectedAttachments ? [
|
|
3757
|
+
`${field}: ${age.rejectedAttachments} attachments refused by maxMissedSessions; counted as uncovered.`
|
|
3758
|
+
] : []
|
|
3759
|
+
]);
|
|
3760
|
+
return Object.keys(selected).length ? { datasetAge: selected, ...datasetWarnings.length ? { datasetWarnings } : {} } : {};
|
|
3730
3761
|
}
|
|
3731
3762
|
|
|
3732
3763
|
// src/tools/profile-analysis.ts
|
|
@@ -3838,7 +3869,7 @@ function partitionMarketFilters(entryFilters, catalog) {
|
|
|
3838
3869
|
);
|
|
3839
3870
|
return { filters, unresolvable, warnings };
|
|
3840
3871
|
}
|
|
3841
|
-
async function loadTradesAndMarket(baseDir, blockId, strategyName) {
|
|
3872
|
+
async function loadTradesAndMarket(baseDir, blockId, strategyName, maxMissedSessions) {
|
|
3842
3873
|
const block = await loadBlock(baseDir, blockId);
|
|
3843
3874
|
let trades = filterByStrategy(block.trades, strategyName);
|
|
3844
3875
|
if (trades.length === 0 && block.trades.length > 0) {
|
|
@@ -3857,7 +3888,9 @@ async function loadTradesAndMarket(baseDir, blockId, strategyName) {
|
|
|
3857
3888
|
const marketRecords = resultToRecords(result);
|
|
3858
3889
|
const marketMap = recordsByTickerDate(marketRecords);
|
|
3859
3890
|
const datasets = await listDatasets(conn);
|
|
3860
|
-
const datasetMatches = trades.map(
|
|
3891
|
+
const datasetMatches = trades.map(
|
|
3892
|
+
(trade) => resolveTradeDatasets(datasets, trade, maxMissedSessions)
|
|
3893
|
+
);
|
|
3861
3894
|
const rows = [];
|
|
3862
3895
|
let unmatchedCount = 0;
|
|
3863
3896
|
for (const [index, trade] of trades.entries()) {
|
|
@@ -3869,7 +3902,8 @@ async function loadTradesAndMarket(baseDir, blockId, strategyName) {
|
|
|
3869
3902
|
trade,
|
|
3870
3903
|
builtIn,
|
|
3871
3904
|
market: { ...builtIn, ...datasetValues },
|
|
3872
|
-
provenance: datasetMatches[index].provenance
|
|
3905
|
+
provenance: datasetMatches[index].provenance,
|
|
3906
|
+
rejected: datasetMatches[index].rejected
|
|
3873
3907
|
});
|
|
3874
3908
|
if (!builtIn) unmatchedCount++;
|
|
3875
3909
|
}
|
|
@@ -3913,10 +3947,11 @@ function findBucket(value, buckets) {
|
|
|
3913
3947
|
}
|
|
3914
3948
|
return null;
|
|
3915
3949
|
}
|
|
3916
|
-
var analyzeStructureFitSchema =
|
|
3917
|
-
blockId:
|
|
3918
|
-
strategyName:
|
|
3919
|
-
|
|
3950
|
+
var analyzeStructureFitSchema = z6.object({
|
|
3951
|
+
blockId: z6.string().describe("Block ID to analyze"),
|
|
3952
|
+
strategyName: z6.string().describe("Strategy name matching a stored profile"),
|
|
3953
|
+
maxMissedSessions: maxMissedSessionsSchema,
|
|
3954
|
+
minTrades: z6.number().optional().default(10).describe("Minimum trades per bucket for reliable stats (thin-data warning threshold)")
|
|
3920
3955
|
});
|
|
3921
3956
|
async function handleAnalyzeStructureFit(input, baseDir) {
|
|
3922
3957
|
const { blockId, strategyName } = input;
|
|
@@ -3932,7 +3967,8 @@ async function handleAnalyzeStructureFit(input, baseDir) {
|
|
|
3932
3967
|
const { rows, unmatchedCount, allTrades } = await loadTradesAndMarket(
|
|
3933
3968
|
baseDir,
|
|
3934
3969
|
blockId,
|
|
3935
|
-
strategyName
|
|
3970
|
+
strategyName,
|
|
3971
|
+
input.maxMissedSessions
|
|
3936
3972
|
);
|
|
3937
3973
|
const catalog = await runtimeFieldCatalog(conn);
|
|
3938
3974
|
const marketFilters = partitionMarketFilters(profile.entryFilters, catalog);
|
|
@@ -3949,6 +3985,7 @@ async function handleAnalyzeStructureFit(input, baseDir) {
|
|
|
3949
3985
|
return createToolOutput(`Uncovered dataset fields: ${uncovered.join(", ")}`, {
|
|
3950
3986
|
error: "uncovered_fields",
|
|
3951
3987
|
fields: uncovered,
|
|
3988
|
+
...datasetAgeOutput(datasetAge, uncovered),
|
|
3952
3989
|
warnings
|
|
3953
3990
|
});
|
|
3954
3991
|
if (allTrades.length === 0) {
|
|
@@ -4135,11 +4172,12 @@ async function handleAnalyzeStructureFit(input, baseDir) {
|
|
|
4135
4172
|
}
|
|
4136
4173
|
});
|
|
4137
4174
|
}
|
|
4138
|
-
var validateEntryFiltersSchema =
|
|
4139
|
-
blockId:
|
|
4140
|
-
strategyName:
|
|
4141
|
-
|
|
4142
|
-
|
|
4175
|
+
var validateEntryFiltersSchema = z6.object({
|
|
4176
|
+
blockId: z6.string().describe("Block ID to analyze"),
|
|
4177
|
+
strategyName: z6.string().describe("Strategy name matching a stored profile"),
|
|
4178
|
+
maxMissedSessions: maxMissedSessionsSchema,
|
|
4179
|
+
minTrades: z6.number().optional().default(10).describe("Minimum trades per group for reliable stats"),
|
|
4180
|
+
maxAblationFilters: z6.number().optional().default(8).describe("Maximum number of filters for pairwise ablation (cap for combinatorial explosion)")
|
|
4143
4181
|
});
|
|
4144
4182
|
async function handleValidateEntryFilters(input, baseDir) {
|
|
4145
4183
|
const { blockId, strategyName } = input;
|
|
@@ -4179,7 +4217,8 @@ async function handleValidateEntryFilters(input, baseDir) {
|
|
|
4179
4217
|
const { rows, unmatchedCount, allTrades } = await loadTradesAndMarket(
|
|
4180
4218
|
baseDir,
|
|
4181
4219
|
blockId,
|
|
4182
|
-
strategyName
|
|
4220
|
+
strategyName,
|
|
4221
|
+
input.maxMissedSessions
|
|
4183
4222
|
);
|
|
4184
4223
|
const predicates = filters.map(
|
|
4185
4224
|
(filter) => buildFilterPredicate(filter, catalog)
|
|
@@ -4187,9 +4226,10 @@ async function handleValidateEntryFilters(input, baseDir) {
|
|
|
4187
4226
|
const matched = rows.filter(
|
|
4188
4227
|
({ market }) => predicates.every((predicate) => predicate.hasData(market))
|
|
4189
4228
|
);
|
|
4229
|
+
const ageRows = input.maxMissedSessions === void 0 ? matched : rows;
|
|
4190
4230
|
const datasetAge = summarizeDatasetAge(
|
|
4191
|
-
|
|
4192
|
-
|
|
4231
|
+
ageRows.map(({ trade }) => trade),
|
|
4232
|
+
ageRows
|
|
4193
4233
|
);
|
|
4194
4234
|
const uncovered = filters.filter(
|
|
4195
4235
|
(filter) => filter.field.includes(".") && !rows.some(({ market }) => market[filter.field] !== void 0)
|
|
@@ -4198,6 +4238,7 @@ async function handleValidateEntryFilters(input, baseDir) {
|
|
|
4198
4238
|
return createToolOutput(`Uncovered dataset fields: ${uncovered.join(", ")}`, {
|
|
4199
4239
|
error: "uncovered_fields",
|
|
4200
4240
|
fields: uncovered,
|
|
4241
|
+
...datasetAgeOutput(datasetAge, uncovered),
|
|
4201
4242
|
warnings
|
|
4202
4243
|
});
|
|
4203
4244
|
if (executionFilters.length > 0) {
|
|
@@ -4372,9 +4413,9 @@ async function handleValidateEntryFilters(input, baseDir) {
|
|
|
4372
4413
|
warnings
|
|
4373
4414
|
});
|
|
4374
4415
|
}
|
|
4375
|
-
var portfolioStructureMapSchema =
|
|
4376
|
-
blockId:
|
|
4377
|
-
minTrades:
|
|
4416
|
+
var portfolioStructureMapSchema = z6.object({
|
|
4417
|
+
blockId: z6.string().optional().describe("Block ID to analyze. When omitted, aggregate across all blocks."),
|
|
4418
|
+
minTrades: z6.number().optional().default(10).describe("Thin-data warning threshold (default: 10)")
|
|
4378
4419
|
});
|
|
4379
4420
|
async function handlePortfolioStructureMap(input, baseDir) {
|
|
4380
4421
|
try {
|
|
@@ -4566,7 +4607,7 @@ async function handlePortfolioStructureMap(input, baseDir) {
|
|
|
4566
4607
|
}
|
|
4567
4608
|
|
|
4568
4609
|
// src/tools/regime-advisor.ts
|
|
4569
|
-
import { z as
|
|
4610
|
+
import { z as z7 } from "zod";
|
|
4570
4611
|
function formatTradeDate2(date) {
|
|
4571
4612
|
if (typeof date === "string") {
|
|
4572
4613
|
const match = date.match(/^(\d{4})-(\d{2})-(\d{2})/);
|
|
@@ -4632,9 +4673,9 @@ var VOL_REGIME_LABELS2 = {
|
|
|
4632
4673
|
5: "high",
|
|
4633
4674
|
6: "extreme"
|
|
4634
4675
|
};
|
|
4635
|
-
var regimeAllocationAdvisorSchema =
|
|
4636
|
-
blockId:
|
|
4637
|
-
minTrades:
|
|
4676
|
+
var regimeAllocationAdvisorSchema = z7.object({
|
|
4677
|
+
blockId: z7.string().optional().describe("Block ID to analyze. When omitted, aggregate across all profiled strategies."),
|
|
4678
|
+
minTrades: z7.number().optional().default(5).describe("Minimum trades per regime cell for reliable stats (default: 5)")
|
|
4638
4679
|
});
|
|
4639
4680
|
async function handleRegimeAllocationAdvisor(input, baseDir) {
|
|
4640
4681
|
const minTrades = input.minTrades ?? 5;
|
|
@@ -4812,7 +4853,7 @@ async function handleRegimeAllocationAdvisor(input, baseDir) {
|
|
|
4812
4853
|
}
|
|
4813
4854
|
|
|
4814
4855
|
// src/utils/providers/massive.ts
|
|
4815
|
-
import { z as
|
|
4856
|
+
import { z as z8 } from "zod";
|
|
4816
4857
|
|
|
4817
4858
|
// src/utils/black-scholes.ts
|
|
4818
4859
|
var BACHELIER_DTE_THRESHOLD = 0.1;
|
|
@@ -5072,94 +5113,94 @@ function resolveMassiveDataTier(env = process.env) {
|
|
|
5072
5113
|
}
|
|
5073
5114
|
|
|
5074
5115
|
// src/utils/providers/massive.ts
|
|
5075
|
-
var MassiveBarSchema =
|
|
5076
|
-
v:
|
|
5077
|
-
vw:
|
|
5078
|
-
o:
|
|
5079
|
-
c:
|
|
5080
|
-
h:
|
|
5081
|
-
l:
|
|
5082
|
-
t:
|
|
5083
|
-
n:
|
|
5116
|
+
var MassiveBarSchema = z8.object({
|
|
5117
|
+
v: z8.number().optional(),
|
|
5118
|
+
vw: z8.number().optional(),
|
|
5119
|
+
o: z8.number(),
|
|
5120
|
+
c: z8.number(),
|
|
5121
|
+
h: z8.number(),
|
|
5122
|
+
l: z8.number(),
|
|
5123
|
+
t: z8.number(),
|
|
5124
|
+
n: z8.number().optional()
|
|
5084
5125
|
});
|
|
5085
|
-
var MassiveAggregateResponseSchema =
|
|
5086
|
-
ticker:
|
|
5087
|
-
queryCount:
|
|
5088
|
-
resultsCount:
|
|
5089
|
-
adjusted:
|
|
5090
|
-
results:
|
|
5091
|
-
status:
|
|
5092
|
-
request_id:
|
|
5093
|
-
next_url:
|
|
5126
|
+
var MassiveAggregateResponseSchema = z8.object({
|
|
5127
|
+
ticker: z8.string(),
|
|
5128
|
+
queryCount: z8.number(),
|
|
5129
|
+
resultsCount: z8.number().optional(),
|
|
5130
|
+
adjusted: z8.boolean().optional(),
|
|
5131
|
+
results: z8.array(MassiveBarSchema).default([]),
|
|
5132
|
+
status: z8.string(),
|
|
5133
|
+
request_id: z8.string(),
|
|
5134
|
+
next_url: z8.string().optional()
|
|
5094
5135
|
});
|
|
5095
|
-
var MassiveQuoteSchema =
|
|
5096
|
-
bid_price:
|
|
5097
|
-
ask_price:
|
|
5098
|
-
sip_timestamp:
|
|
5136
|
+
var MassiveQuoteSchema = z8.object({
|
|
5137
|
+
bid_price: z8.number(),
|
|
5138
|
+
ask_price: z8.number(),
|
|
5139
|
+
sip_timestamp: z8.number(),
|
|
5099
5140
|
// nanoseconds
|
|
5100
|
-
bid_size:
|
|
5101
|
-
ask_size:
|
|
5102
|
-
sequence_number:
|
|
5141
|
+
bid_size: z8.number(),
|
|
5142
|
+
ask_size: z8.number(),
|
|
5143
|
+
sequence_number: z8.number()
|
|
5103
5144
|
});
|
|
5104
|
-
var MassiveQuotesResponseSchema =
|
|
5105
|
-
status:
|
|
5106
|
-
request_id:
|
|
5107
|
-
results:
|
|
5108
|
-
next_url:
|
|
5145
|
+
var MassiveQuotesResponseSchema = z8.object({
|
|
5146
|
+
status: z8.string(),
|
|
5147
|
+
request_id: z8.string(),
|
|
5148
|
+
results: z8.array(MassiveQuoteSchema).default([]),
|
|
5149
|
+
next_url: z8.string().optional()
|
|
5109
5150
|
});
|
|
5110
|
-
var MassiveSnapshotGreeksSchema =
|
|
5111
|
-
delta:
|
|
5112
|
-
gamma:
|
|
5113
|
-
theta:
|
|
5114
|
-
vega:
|
|
5151
|
+
var MassiveSnapshotGreeksSchema = z8.object({
|
|
5152
|
+
delta: z8.number(),
|
|
5153
|
+
gamma: z8.number(),
|
|
5154
|
+
theta: z8.number(),
|
|
5155
|
+
vega: z8.number()
|
|
5115
5156
|
});
|
|
5116
|
-
var MassiveSnapshotDaySchema =
|
|
5117
|
-
open:
|
|
5118
|
-
high:
|
|
5119
|
-
low:
|
|
5120
|
-
close:
|
|
5121
|
-
change:
|
|
5122
|
-
change_percent:
|
|
5123
|
-
volume:
|
|
5124
|
-
vwap:
|
|
5125
|
-
previous_close:
|
|
5126
|
-
last_updated:
|
|
5157
|
+
var MassiveSnapshotDaySchema = z8.object({
|
|
5158
|
+
open: z8.number(),
|
|
5159
|
+
high: z8.number(),
|
|
5160
|
+
low: z8.number(),
|
|
5161
|
+
close: z8.number(),
|
|
5162
|
+
change: z8.number(),
|
|
5163
|
+
change_percent: z8.number(),
|
|
5164
|
+
volume: z8.number().optional(),
|
|
5165
|
+
vwap: z8.number().optional(),
|
|
5166
|
+
previous_close: z8.number(),
|
|
5167
|
+
last_updated: z8.number()
|
|
5127
5168
|
});
|
|
5128
|
-
var MassiveSnapshotQuoteSchema =
|
|
5129
|
-
bid:
|
|
5130
|
-
ask:
|
|
5131
|
-
midpoint:
|
|
5132
|
-
bid_size:
|
|
5133
|
-
ask_size:
|
|
5134
|
-
last_updated:
|
|
5135
|
-
timeframe:
|
|
5169
|
+
var MassiveSnapshotQuoteSchema = z8.object({
|
|
5170
|
+
bid: z8.number(),
|
|
5171
|
+
ask: z8.number(),
|
|
5172
|
+
midpoint: z8.number(),
|
|
5173
|
+
bid_size: z8.number(),
|
|
5174
|
+
ask_size: z8.number(),
|
|
5175
|
+
last_updated: z8.number(),
|
|
5176
|
+
timeframe: z8.string()
|
|
5136
5177
|
});
|
|
5137
|
-
var MassiveSnapshotTradeSchema =
|
|
5138
|
-
price:
|
|
5139
|
-
size:
|
|
5140
|
-
sip_timestamp:
|
|
5141
|
-
conditions:
|
|
5142
|
-
timeframe:
|
|
5178
|
+
var MassiveSnapshotTradeSchema = z8.object({
|
|
5179
|
+
price: z8.number(),
|
|
5180
|
+
size: z8.number(),
|
|
5181
|
+
sip_timestamp: z8.number(),
|
|
5182
|
+
conditions: z8.array(z8.number()).optional(),
|
|
5183
|
+
timeframe: z8.string()
|
|
5143
5184
|
});
|
|
5144
|
-
var MassiveSnapshotDetailsSchema =
|
|
5145
|
-
ticker:
|
|
5146
|
-
contract_type:
|
|
5147
|
-
strike_price:
|
|
5148
|
-
expiration_date:
|
|
5149
|
-
exercise_style:
|
|
5150
|
-
shares_per_contract:
|
|
5185
|
+
var MassiveSnapshotDetailsSchema = z8.object({
|
|
5186
|
+
ticker: z8.string(),
|
|
5187
|
+
contract_type: z8.string(),
|
|
5188
|
+
strike_price: z8.number(),
|
|
5189
|
+
expiration_date: z8.string(),
|
|
5190
|
+
exercise_style: z8.string(),
|
|
5191
|
+
shares_per_contract: z8.number()
|
|
5151
5192
|
});
|
|
5152
|
-
var MassiveSnapshotUnderlyingSchema =
|
|
5153
|
-
ticker:
|
|
5154
|
-
price:
|
|
5155
|
-
change_to_break_even:
|
|
5156
|
-
last_updated:
|
|
5157
|
-
timeframe:
|
|
5193
|
+
var MassiveSnapshotUnderlyingSchema = z8.object({
|
|
5194
|
+
ticker: z8.string(),
|
|
5195
|
+
price: z8.number(),
|
|
5196
|
+
change_to_break_even: z8.number(),
|
|
5197
|
+
last_updated: z8.number(),
|
|
5198
|
+
timeframe: z8.string()
|
|
5158
5199
|
});
|
|
5159
|
-
var MassiveSnapshotContractSchema =
|
|
5160
|
-
break_even_price:
|
|
5161
|
-
implied_volatility:
|
|
5162
|
-
open_interest:
|
|
5200
|
+
var MassiveSnapshotContractSchema = z8.object({
|
|
5201
|
+
break_even_price: z8.number(),
|
|
5202
|
+
implied_volatility: z8.number(),
|
|
5203
|
+
open_interest: z8.number(),
|
|
5163
5204
|
greeks: MassiveSnapshotGreeksSchema.optional(),
|
|
5164
5205
|
day: MassiveSnapshotDaySchema,
|
|
5165
5206
|
last_quote: MassiveSnapshotQuoteSchema,
|
|
@@ -5167,23 +5208,23 @@ var MassiveSnapshotContractSchema = z7.object({
|
|
|
5167
5208
|
details: MassiveSnapshotDetailsSchema,
|
|
5168
5209
|
underlying_asset: MassiveSnapshotUnderlyingSchema
|
|
5169
5210
|
});
|
|
5170
|
-
var MassiveSnapshotResponseSchema =
|
|
5171
|
-
request_id:
|
|
5172
|
-
status:
|
|
5173
|
-
results:
|
|
5174
|
-
next_url:
|
|
5211
|
+
var MassiveSnapshotResponseSchema = z8.object({
|
|
5212
|
+
request_id: z8.string(),
|
|
5213
|
+
status: z8.string(),
|
|
5214
|
+
results: z8.array(MassiveSnapshotContractSchema),
|
|
5215
|
+
next_url: z8.string().optional()
|
|
5175
5216
|
});
|
|
5176
|
-
var MassiveContractReferenceSchema =
|
|
5177
|
-
ticker:
|
|
5178
|
-
strike_price:
|
|
5179
|
-
expiration_date:
|
|
5180
|
-
contract_type:
|
|
5181
|
-
exercise_style:
|
|
5217
|
+
var MassiveContractReferenceSchema = z8.object({
|
|
5218
|
+
ticker: z8.string(),
|
|
5219
|
+
strike_price: z8.number(),
|
|
5220
|
+
expiration_date: z8.string(),
|
|
5221
|
+
contract_type: z8.string(),
|
|
5222
|
+
exercise_style: z8.string().optional().default("american")
|
|
5182
5223
|
});
|
|
5183
|
-
var MassiveContractListResponseSchema =
|
|
5184
|
-
results:
|
|
5185
|
-
next_url:
|
|
5186
|
-
count:
|
|
5224
|
+
var MassiveContractListResponseSchema = z8.object({
|
|
5225
|
+
results: z8.array(MassiveContractReferenceSchema),
|
|
5226
|
+
next_url: z8.string().nullable().optional(),
|
|
5227
|
+
count: z8.number().optional()
|
|
5187
5228
|
});
|
|
5188
5229
|
var MASSIVE_BASE_URL = "https://api.massive.com";
|
|
5189
5230
|
var MASSIVE_MAX_LIMIT = 5e4;
|
|
@@ -8224,7 +8265,7 @@ function getResolvedProviderCapabilities(env = process.env) {
|
|
|
8224
8265
|
}
|
|
8225
8266
|
|
|
8226
8267
|
// src/tools/replay.ts
|
|
8227
|
-
import { z as
|
|
8268
|
+
import { z as z9 } from "zod";
|
|
8228
8269
|
|
|
8229
8270
|
// src/market/tickers/resolver.ts
|
|
8230
8271
|
var OCC_RE = /^([A-Z]+)\d{6}[CP]\d{6,11}$/;
|
|
@@ -8243,39 +8284,39 @@ function rootToUnderlying(input, registry) {
|
|
|
8243
8284
|
}
|
|
8244
8285
|
|
|
8245
8286
|
// src/tools/replay.ts
|
|
8246
|
-
var replayTradeSchema =
|
|
8287
|
+
var replayTradeSchema = z9.object({
|
|
8247
8288
|
// Mode A: Hypothetical / explicit legs
|
|
8248
|
-
legs:
|
|
8249
|
-
|
|
8250
|
-
ticker:
|
|
8251
|
-
strike:
|
|
8252
|
-
type:
|
|
8253
|
-
expiry:
|
|
8254
|
-
quantity:
|
|
8255
|
-
entry_price:
|
|
8289
|
+
legs: z9.array(
|
|
8290
|
+
z9.object({
|
|
8291
|
+
ticker: z9.string().describe("Underlying ticker, e.g., 'SPY', 'SPX'"),
|
|
8292
|
+
strike: z9.number().describe("Strike price"),
|
|
8293
|
+
type: z9.enum(["C", "P"]).describe("Call or Put"),
|
|
8294
|
+
expiry: z9.string().describe("Expiration date YYYY-MM-DD"),
|
|
8295
|
+
quantity: z9.number().describe("Positive = long, negative = short"),
|
|
8296
|
+
entry_price: z9.number().describe("Per-contract entry price (premium paid/received)")
|
|
8256
8297
|
})
|
|
8257
8298
|
).optional().describe("Explicit leg definitions for hypothetical replay"),
|
|
8258
8299
|
// Mode B: Tradelog replay
|
|
8259
|
-
block_id:
|
|
8260
|
-
trade_index:
|
|
8300
|
+
block_id: z9.string().optional().describe("Block ID to load trade from"),
|
|
8301
|
+
trade_index: z9.number().optional().describe("0-based index of trade in block's tradelog (ordered by date_opened)"),
|
|
8261
8302
|
// Common fields
|
|
8262
|
-
open_date:
|
|
8303
|
+
open_date: z9.string().optional().describe(
|
|
8263
8304
|
"Trade open date YYYY-MM-DD (required for hypothetical mode, auto-resolved for tradelog mode)"
|
|
8264
8305
|
),
|
|
8265
|
-
close_date:
|
|
8306
|
+
close_date: z9.string().optional().describe(
|
|
8266
8307
|
"Trade close date YYYY-MM-DD (required for hypothetical, auto-resolved for tradelog)"
|
|
8267
8308
|
),
|
|
8268
|
-
open_time:
|
|
8309
|
+
open_time: z9.string().optional().describe(
|
|
8269
8310
|
"Trade entry time HH:MM ET. The P&L path starts at the first bar at or after this time on open_date. Optional for hypothetical mode (defaults to the first available bar); auto-resolved from the tradelog's time_opened in tradelog mode."
|
|
8270
8311
|
),
|
|
8271
|
-
multiplier:
|
|
8272
|
-
format:
|
|
8312
|
+
multiplier: z9.number().default(100).describe("Contract multiplier (default 100 for standard options)"),
|
|
8313
|
+
format: z9.enum(["full", "summary", "sampled"]).default("sampled").describe(
|
|
8273
8314
|
"Output format: 'sampled' returns path sampled at ~15min intervals (default), 'full' returns complete minute-by-minute P&L path, 'summary' returns MFE/MAE/P&L without minute-level path"
|
|
8274
8315
|
),
|
|
8275
|
-
close_at:
|
|
8316
|
+
close_at: z9.enum(["trade", "expiry"]).default("trade").describe(
|
|
8276
8317
|
"When to end the P&L path: 'trade' (default) truncates at the trade's actual close time, 'expiry' shows full path through option expiry. Only applies to tradelog mode."
|
|
8277
8318
|
),
|
|
8278
|
-
skip_quotes:
|
|
8319
|
+
skip_quotes: z9.boolean().default(false).describe(
|
|
8279
8320
|
"Skip NBBO quote enrichment for option bars. Faster, but uses cached trade bars / HL2 marks."
|
|
8280
8321
|
)
|
|
8281
8322
|
});
|
|
@@ -8574,27 +8615,27 @@ import { existsSync as existsSync3, readdirSync as readdirSync2 } from "fs";
|
|
|
8574
8615
|
import * as path3 from "path";
|
|
8575
8616
|
|
|
8576
8617
|
// src/market/tickers/schemas.ts
|
|
8577
|
-
import { z as
|
|
8618
|
+
import { z as z10 } from "zod";
|
|
8578
8619
|
var TICKER_RE = /^[A-Z][A-Z0-9^_-]*$/;
|
|
8579
|
-
var UnderlyingsFileSchema =
|
|
8580
|
-
version:
|
|
8581
|
-
underlyings:
|
|
8582
|
-
|
|
8583
|
-
underlying:
|
|
8584
|
-
roots:
|
|
8620
|
+
var UnderlyingsFileSchema = z10.object({
|
|
8621
|
+
version: z10.literal(1),
|
|
8622
|
+
underlyings: z10.array(
|
|
8623
|
+
z10.object({
|
|
8624
|
+
underlying: z10.string().min(1).max(16).regex(TICKER_RE),
|
|
8625
|
+
roots: z10.array(z10.string().min(1).max(16).regex(TICKER_RE)).min(1).max(32)
|
|
8585
8626
|
})
|
|
8586
8627
|
)
|
|
8587
8628
|
});
|
|
8588
|
-
var registerUnderlyingSchema =
|
|
8589
|
-
underlying:
|
|
8590
|
-
roots:
|
|
8629
|
+
var registerUnderlyingSchema = z10.object({
|
|
8630
|
+
underlying: z10.string().min(1).max(16).regex(TICKER_RE).describe("Canonical underlying symbol, e.g. SPX"),
|
|
8631
|
+
roots: z10.array(z10.string().min(1).max(16).regex(TICKER_RE)).min(1).max(32).describe("OCC roots that resolve to this underlying, e.g. ['SPX','SPXW','SPXQ']")
|
|
8591
8632
|
});
|
|
8592
|
-
var unregisterUnderlyingSchema =
|
|
8593
|
-
underlying:
|
|
8633
|
+
var unregisterUnderlyingSchema = z10.object({
|
|
8634
|
+
underlying: z10.string().min(1).max(16).regex(TICKER_RE).describe("Underlying to remove. Bundled defaults cannot be removed.")
|
|
8594
8635
|
});
|
|
8595
|
-
var listUnderlyingsSchema =
|
|
8596
|
-
var resolveRootSchema =
|
|
8597
|
-
input:
|
|
8636
|
+
var listUnderlyingsSchema = z10.object({});
|
|
8637
|
+
var resolveRootSchema = z10.object({
|
|
8638
|
+
input: z10.string().min(1).max(32).describe("Bare root ('SPXW') or full OCC ticker ('SPXW251219C05000000')")
|
|
8598
8639
|
});
|
|
8599
8640
|
|
|
8600
8641
|
// src/market/stores/enriched-legacy-migration.ts
|
|
@@ -11558,15 +11599,15 @@ async function proveCanonicalMarketDataPrefix(partitions, ancestor, descendant)
|
|
|
11558
11599
|
}
|
|
11559
11600
|
|
|
11560
11601
|
// src/tools/snapshot.ts
|
|
11561
|
-
import { z as
|
|
11562
|
-
var getOptionSnapshotSchema =
|
|
11563
|
-
underlying:
|
|
11564
|
-
strike_price_gte:
|
|
11565
|
-
strike_price_lte:
|
|
11566
|
-
expiration_date_gte:
|
|
11567
|
-
expiration_date_lte:
|
|
11568
|
-
contract_type:
|
|
11569
|
-
limit:
|
|
11602
|
+
import { z as z11 } from "zod";
|
|
11603
|
+
var getOptionSnapshotSchema = z11.object({
|
|
11604
|
+
underlying: z11.string().describe("Underlying ticker symbol (e.g., 'SPX', 'SPY', 'AAPL')"),
|
|
11605
|
+
strike_price_gte: z11.number().optional().describe("Minimum strike price filter"),
|
|
11606
|
+
strike_price_lte: z11.number().optional().describe("Maximum strike price filter"),
|
|
11607
|
+
expiration_date_gte: z11.string().optional().describe("Earliest expiration date (YYYY-MM-DD)"),
|
|
11608
|
+
expiration_date_lte: z11.string().optional().describe("Latest expiration date (YYYY-MM-DD)"),
|
|
11609
|
+
contract_type: z11.enum(["call", "put"]).optional().describe("Filter by call or put"),
|
|
11610
|
+
limit: z11.number().optional().default(50).describe("Max contracts to return (default 50, use higher for full chain)")
|
|
11570
11611
|
});
|
|
11571
11612
|
async function handleGetOptionSnapshot(params) {
|
|
11572
11613
|
try {
|
|
@@ -12437,8 +12478,8 @@ function analyzeExitTriggers(config) {
|
|
|
12437
12478
|
}
|
|
12438
12479
|
|
|
12439
12480
|
// src/tools/exit-analysis.ts
|
|
12440
|
-
import { z as
|
|
12441
|
-
var triggerTypeEnum =
|
|
12481
|
+
import { z as z12 } from "zod";
|
|
12482
|
+
var triggerTypeEnum = z12.enum([
|
|
12442
12483
|
"profitTarget",
|
|
12443
12484
|
"stopLoss",
|
|
12444
12485
|
"trailingStop",
|
|
@@ -12455,70 +12496,70 @@ var triggerTypeEnum = z11.enum([
|
|
|
12455
12496
|
"slRatioThreshold",
|
|
12456
12497
|
"slRatioMove"
|
|
12457
12498
|
]);
|
|
12458
|
-
var triggerConfigSchema =
|
|
12499
|
+
var triggerConfigSchema = z12.object({
|
|
12459
12500
|
type: triggerTypeEnum,
|
|
12460
|
-
threshold:
|
|
12461
|
-
unit:
|
|
12462
|
-
expiry:
|
|
12463
|
-
openDate:
|
|
12464
|
-
clockTime:
|
|
12465
|
-
trailAmount:
|
|
12466
|
-
steps:
|
|
12467
|
-
|
|
12468
|
-
armAt:
|
|
12469
|
-
stopAt:
|
|
12470
|
-
closeAllocationPct:
|
|
12501
|
+
threshold: z12.number(),
|
|
12502
|
+
unit: z12.enum(["percent", "dollar"]).default("dollar").optional(),
|
|
12503
|
+
expiry: z12.string().optional(),
|
|
12504
|
+
openDate: z12.string().optional(),
|
|
12505
|
+
clockTime: z12.string().optional(),
|
|
12506
|
+
trailAmount: z12.number().optional(),
|
|
12507
|
+
steps: z12.array(
|
|
12508
|
+
z12.object({
|
|
12509
|
+
armAt: z12.number(),
|
|
12510
|
+
stopAt: z12.number(),
|
|
12511
|
+
closeAllocationPct: z12.number().min(0).max(1).optional().describe("Fraction of REMAINING position to close at this milestone (0-1)")
|
|
12471
12512
|
})
|
|
12472
12513
|
).optional(),
|
|
12473
|
-
spreadWidth:
|
|
12474
|
-
contracts:
|
|
12475
|
-
legIndex:
|
|
12476
|
-
exitAbove:
|
|
12477
|
-
exitBelow:
|
|
12514
|
+
spreadWidth: z12.number().optional(),
|
|
12515
|
+
contracts: z12.number().optional(),
|
|
12516
|
+
legIndex: z12.number().optional().describe("0-based leg index for perLegDelta \u2014 targets specific leg"),
|
|
12517
|
+
exitAbove: z12.number().optional().describe("Fire when value exceeds this (directional, no abs)"),
|
|
12518
|
+
exitBelow: z12.number().optional().describe("Fire when value drops below this (directional, no abs)")
|
|
12478
12519
|
});
|
|
12479
|
-
var legSchema =
|
|
12480
|
-
ticker:
|
|
12481
|
-
strike:
|
|
12482
|
-
type:
|
|
12483
|
-
expiry:
|
|
12484
|
-
quantity:
|
|
12485
|
-
entry_price:
|
|
12520
|
+
var legSchema = z12.object({
|
|
12521
|
+
ticker: z12.string(),
|
|
12522
|
+
strike: z12.number(),
|
|
12523
|
+
type: z12.enum(["C", "P"]),
|
|
12524
|
+
expiry: z12.string(),
|
|
12525
|
+
quantity: z12.number(),
|
|
12526
|
+
entry_price: z12.number()
|
|
12486
12527
|
});
|
|
12487
|
-
var analyzeExitTriggersSchema =
|
|
12528
|
+
var analyzeExitTriggersSchema = z12.object({
|
|
12488
12529
|
// Replay inputs (same shape as replay_trade)
|
|
12489
|
-
legs:
|
|
12490
|
-
block_id:
|
|
12491
|
-
trade_index:
|
|
12492
|
-
open_date:
|
|
12493
|
-
close_date:
|
|
12494
|
-
multiplier:
|
|
12495
|
-
triggers:
|
|
12496
|
-
actual_exit_timestamp:
|
|
12497
|
-
leg_groups:
|
|
12498
|
-
|
|
12499
|
-
label:
|
|
12500
|
-
leg_indices:
|
|
12501
|
-
triggers:
|
|
12530
|
+
legs: z12.array(legSchema).optional(),
|
|
12531
|
+
block_id: z12.string().optional(),
|
|
12532
|
+
trade_index: z12.number().optional(),
|
|
12533
|
+
open_date: z12.string().optional(),
|
|
12534
|
+
close_date: z12.string().optional(),
|
|
12535
|
+
multiplier: z12.number().default(100),
|
|
12536
|
+
triggers: z12.array(triggerConfigSchema).describe("Exit triggers to evaluate against the P&L path"),
|
|
12537
|
+
actual_exit_timestamp: z12.string().optional().describe("Actual exit time for comparison (format: YYYY-MM-DD HH:MM)"),
|
|
12538
|
+
leg_groups: z12.array(
|
|
12539
|
+
z12.object({
|
|
12540
|
+
label: z12.string(),
|
|
12541
|
+
leg_indices: z12.array(z12.number()),
|
|
12542
|
+
triggers: z12.array(triggerConfigSchema)
|
|
12502
12543
|
})
|
|
12503
12544
|
).optional().describe("Per-leg-group exit triggers for multi-structure strategies"),
|
|
12504
|
-
format:
|
|
12545
|
+
format: z12.enum(["summary", "full"]).default("summary").describe("'summary' omits per-step trigger states, 'full' includes all fire events")
|
|
12505
12546
|
});
|
|
12506
|
-
var decomposeGreeksSchema =
|
|
12547
|
+
var decomposeGreeksSchema = z12.object({
|
|
12507
12548
|
// Same replay inputs
|
|
12508
|
-
legs:
|
|
12509
|
-
block_id:
|
|
12510
|
-
trade_index:
|
|
12511
|
-
open_date:
|
|
12512
|
-
close_date:
|
|
12513
|
-
multiplier:
|
|
12514
|
-
leg_groups:
|
|
12515
|
-
|
|
12516
|
-
label:
|
|
12517
|
-
leg_indices:
|
|
12549
|
+
legs: z12.array(legSchema).optional(),
|
|
12550
|
+
block_id: z12.string().optional(),
|
|
12551
|
+
trade_index: z12.number().optional(),
|
|
12552
|
+
open_date: z12.string().optional(),
|
|
12553
|
+
close_date: z12.string().optional(),
|
|
12554
|
+
multiplier: z12.number().default(100),
|
|
12555
|
+
leg_groups: z12.array(
|
|
12556
|
+
z12.object({
|
|
12557
|
+
label: z12.string(),
|
|
12558
|
+
leg_indices: z12.array(z12.number())
|
|
12518
12559
|
})
|
|
12519
12560
|
).optional().describe("Leg grouping for per-group vega attribution (e.g., front_month vs back_month)"),
|
|
12520
|
-
format:
|
|
12521
|
-
skip_quotes:
|
|
12561
|
+
format: z12.enum(["summary", "full"]).default("summary").describe("'summary' shows ranked factors, 'full' includes per-step contributions"),
|
|
12562
|
+
skip_quotes: z12.boolean().default(false).describe("Skip NBBO quote enrichment for option bars. Faster, but lower precision.")
|
|
12522
12563
|
});
|
|
12523
12564
|
var REVERSE_ROOT_MAP = {
|
|
12524
12565
|
SPXW: "SPX",
|
|
@@ -12952,7 +12993,7 @@ function analyzeBatch(trades, config) {
|
|
|
12952
12993
|
}
|
|
12953
12994
|
|
|
12954
12995
|
// src/tools/batch-exit-analysis.ts
|
|
12955
|
-
import { z as
|
|
12996
|
+
import { z as z13 } from "zod";
|
|
12956
12997
|
async function mapWithLimit(items, limit, fn) {
|
|
12957
12998
|
const results = new Array(items.length);
|
|
12958
12999
|
let idx = 0;
|
|
@@ -12966,7 +13007,7 @@ async function mapWithLimit(items, limit, fn) {
|
|
|
12966
13007
|
await Promise.all(workers);
|
|
12967
13008
|
return results;
|
|
12968
13009
|
}
|
|
12969
|
-
var triggerTypeEnum2 =
|
|
13010
|
+
var triggerTypeEnum2 = z13.enum([
|
|
12970
13011
|
"profitTarget",
|
|
12971
13012
|
"stopLoss",
|
|
12972
13013
|
"trailingStop",
|
|
@@ -12983,50 +13024,50 @@ var triggerTypeEnum2 = z12.enum([
|
|
|
12983
13024
|
"slRatioThreshold",
|
|
12984
13025
|
"slRatioMove"
|
|
12985
13026
|
]);
|
|
12986
|
-
var triggerConfigSchema2 =
|
|
13027
|
+
var triggerConfigSchema2 = z13.object({
|
|
12987
13028
|
type: triggerTypeEnum2,
|
|
12988
|
-
threshold:
|
|
12989
|
-
unit:
|
|
12990
|
-
expiry:
|
|
12991
|
-
openDate:
|
|
12992
|
-
clockTime:
|
|
12993
|
-
trailAmount:
|
|
12994
|
-
steps:
|
|
12995
|
-
|
|
12996
|
-
armAt:
|
|
12997
|
-
stopAt:
|
|
12998
|
-
closeAllocationPct:
|
|
13029
|
+
threshold: z13.number(),
|
|
13030
|
+
unit: z13.enum(["percent", "dollar"]).default("dollar").optional(),
|
|
13031
|
+
expiry: z13.string().optional(),
|
|
13032
|
+
openDate: z13.string().optional(),
|
|
13033
|
+
clockTime: z13.string().optional(),
|
|
13034
|
+
trailAmount: z13.number().optional(),
|
|
13035
|
+
steps: z13.array(
|
|
13036
|
+
z13.object({
|
|
13037
|
+
armAt: z13.number(),
|
|
13038
|
+
stopAt: z13.number(),
|
|
13039
|
+
closeAllocationPct: z13.number().min(0).max(1).optional().describe("Fraction of REMAINING position to close at this milestone (0-1)")
|
|
12999
13040
|
})
|
|
13000
13041
|
).optional(),
|
|
13001
|
-
spreadWidth:
|
|
13002
|
-
contracts:
|
|
13003
|
-
legIndex:
|
|
13004
|
-
exitAbove:
|
|
13005
|
-
exitBelow:
|
|
13042
|
+
spreadWidth: z13.number().optional(),
|
|
13043
|
+
contracts: z13.number().optional(),
|
|
13044
|
+
legIndex: z13.number().optional().describe("0-based leg index for perLegDelta \u2014 targets specific leg"),
|
|
13045
|
+
exitAbove: z13.number().optional().describe("Fire when value exceeds this (directional, no abs)"),
|
|
13046
|
+
exitBelow: z13.number().optional().describe("Fire when value drops below this (directional, no abs)")
|
|
13006
13047
|
});
|
|
13007
|
-
var batchExitAnalysisSchema =
|
|
13008
|
-
block_id:
|
|
13009
|
-
strategy:
|
|
13010
|
-
date_range:
|
|
13011
|
-
from:
|
|
13012
|
-
to:
|
|
13048
|
+
var batchExitAnalysisSchema = z13.object({
|
|
13049
|
+
block_id: z13.string().describe("Block ID to analyze trades from"),
|
|
13050
|
+
strategy: z13.string().optional().describe("Filter trades by strategy name (case-insensitive ILIKE)"),
|
|
13051
|
+
date_range: z13.object({
|
|
13052
|
+
from: z13.string().optional().describe("Start date YYYY-MM-DD"),
|
|
13053
|
+
to: z13.string().optional().describe("End date YYYY-MM-DD")
|
|
13013
13054
|
}).optional().describe("Filter trades by date range"),
|
|
13014
|
-
candidate_policy:
|
|
13015
|
-
leg_groups:
|
|
13016
|
-
|
|
13017
|
-
label:
|
|
13018
|
-
leg_indices:
|
|
13019
|
-
triggers:
|
|
13055
|
+
candidate_policy: z13.array(triggerConfigSchema2).describe("Candidate exit policy triggers to evaluate -- same schema as analyze_exit_triggers"),
|
|
13056
|
+
leg_groups: z13.array(
|
|
13057
|
+
z13.object({
|
|
13058
|
+
label: z13.string(),
|
|
13059
|
+
leg_indices: z13.array(z13.number()),
|
|
13060
|
+
triggers: z13.array(triggerConfigSchema2)
|
|
13020
13061
|
})
|
|
13021
13062
|
).optional().describe("Per-leg-group exit triggers for multi-structure strategies"),
|
|
13022
|
-
baseline_mode:
|
|
13063
|
+
baseline_mode: z13.enum(["actual", "holdToEnd"]).default("actual").describe(
|
|
13023
13064
|
"'actual' compares candidate vs trade's actual P&L; 'holdToEnd' compares vs last replay timestamp"
|
|
13024
13065
|
),
|
|
13025
|
-
limit:
|
|
13026
|
-
min_pl:
|
|
13027
|
-
max_pl:
|
|
13028
|
-
multiplier:
|
|
13029
|
-
format:
|
|
13066
|
+
limit: z13.number().min(1).max(200).default(50).describe("Max trades to analyze. Most recent trades selected"),
|
|
13067
|
+
min_pl: z13.number().optional().describe("Only include trades with actual P&L >= this value"),
|
|
13068
|
+
max_pl: z13.number().optional().describe("Only include trades with actual P&L <= this value"),
|
|
13069
|
+
multiplier: z13.number().default(100).describe("Contract multiplier (default 100)"),
|
|
13070
|
+
format: z13.enum(["summary", "full"]).default("summary").describe(
|
|
13030
13071
|
"'summary' returns aggregate stats + trigger attribution; 'full' adds per-trade breakdown"
|
|
13031
13072
|
)
|
|
13032
13073
|
});
|
|
@@ -13244,7 +13285,7 @@ function expandDateRange(fromDate, toDate) {
|
|
|
13244
13285
|
|
|
13245
13286
|
// src/tools/sql.ts
|
|
13246
13287
|
import * as path6 from "path";
|
|
13247
|
-
import { z as
|
|
13288
|
+
import { z as z14 } from "zod";
|
|
13248
13289
|
import { DuckDBDateValue } from "@duckdb/node-api";
|
|
13249
13290
|
var BLOCKED_PATTERNS = [
|
|
13250
13291
|
// External access
|
|
@@ -13640,18 +13681,18 @@ function formatIsoDate2(date) {
|
|
|
13640
13681
|
}
|
|
13641
13682
|
|
|
13642
13683
|
// src/tools/greeks-attribution.ts
|
|
13643
|
-
import { z as
|
|
13644
|
-
var getGreeksAttributionSchema =
|
|
13645
|
-
block_id:
|
|
13646
|
-
mode:
|
|
13647
|
-
trade_index:
|
|
13684
|
+
import { z as z15 } from "zod";
|
|
13685
|
+
var getGreeksAttributionSchema = z15.object({
|
|
13686
|
+
block_id: z15.string().describe("Block ID to analyze"),
|
|
13687
|
+
mode: z15.enum(["summary", "instance"]).default("summary").describe("summary: block-level attribution. instance: single trade time-series."),
|
|
13688
|
+
trade_index: z15.number().int().min(0).optional().describe(
|
|
13648
13689
|
"Trade index (required for instance mode). Use get_block_info to find trade indices."
|
|
13649
13690
|
),
|
|
13650
|
-
skip_quotes:
|
|
13691
|
+
skip_quotes: z15.boolean().default(true).describe(
|
|
13651
13692
|
"Use cached bar data only (fast). Set false to fetch NBBO quotes for higher precision."
|
|
13652
13693
|
),
|
|
13653
|
-
detailed:
|
|
13654
|
-
strategy:
|
|
13694
|
+
detailed: z15.boolean().default(false).describe("false: 5 factors (delta, gamma, theta, vega, residual). true: adds charm, vanna."),
|
|
13695
|
+
strategy: z15.string().optional().describe("Filter to trades matching this strategy name (case-insensitive).")
|
|
13655
13696
|
});
|
|
13656
13697
|
var COLLAPSE_MAP = {
|
|
13657
13698
|
charm: "delta",
|