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.
Files changed (47) hide show
  1. package/README.md +40 -1
  2. package/dist/{chunk-YRD62LDE.js → chunk-35RVWZGT.js} +4 -1
  3. package/dist/{chunk-4UU7IT2A.js.map → chunk-35RVWZGT.js.map} +1 -1
  4. package/dist/{chunk-4UU7IT2A.js → chunk-ENXBPJ7Y.js} +148 -6
  5. package/dist/chunk-ENXBPJ7Y.js.map +1 -0
  6. package/dist/{chunk-62GCLMQA.js → chunk-TLX7IBCM.js} +3 -6
  7. package/dist/chunk-TLX7IBCM.js.map +1 -0
  8. package/dist/{daily-logs-store-PXB53WEK.js → daily-logs-store-FZRIGYUX.js} +2 -2
  9. package/dist/{daily-logs-store-65YHFJ5F.js → daily-logs-store-MEZ5S3BR.js} +2 -2
  10. package/dist/market/provenance/index.js +1 -4
  11. package/dist/market/provenance/index.js.map +1 -1
  12. package/dist/{sync-JL7OPLCT.js → sync-EW33QZPD.js} +3 -3
  13. package/dist/test-exports.js +320 -279
  14. package/dist/test-exports.js.map +1 -1
  15. package/dist/{trades-store-UGZ62A7N.js → trades-store-3TOLBL2W.js} +2 -2
  16. package/dist/{trades-store-MOFJHRC2.js → trades-store-PNLPRYRJ.js} +2 -2
  17. package/package.json +1 -1
  18. package/server/{chunk-7N6HBOAY.js → chunk-PDSUY2X2.js} +148 -6
  19. package/server/chunk-PDSUY2X2.js.map +1 -0
  20. package/server/{chunk-J4GWE6JR.js → chunk-YIWLVX7Z.js} +3 -6
  21. package/server/chunk-YIWLVX7Z.js.map +1 -0
  22. package/server/{daily-logs-store-YAXASQN4.js → daily-logs-store-LRVO7COL.js} +2 -2
  23. package/server/index.js +993 -801
  24. package/server/index.js.map +1 -1
  25. package/server/{sync-ZV3QEGMO.js → sync-2POG6KA6.js} +3 -3
  26. package/server/{trades-store-MF7YYLCH.js → trades-store-MXUZLSF5.js} +2 -2
  27. package/src/db/dataset-schemas.ts +97 -23
  28. package/src/tools/market-data.ts +327 -245
  29. package/src/tools/profile-analysis.ts +18 -4
  30. package/src/tools/reports/fields.ts +16 -11
  31. package/src/tools/reports/helpers.ts +6 -2
  32. package/src/tools/reports/predictive.ts +15 -4
  33. package/src/tools/shared/field-analysis.ts +57 -14
  34. package/src/tools/shared/filter-objective.ts +73 -0
  35. package/src/utils/trade-analysis-fields.ts +19 -4
  36. package/dist/chunk-62GCLMQA.js.map +0 -1
  37. package/dist/chunk-YRD62LDE.js.map +0 -1
  38. package/server/chunk-7N6HBOAY.js.map +0 -1
  39. package/server/chunk-J4GWE6JR.js.map +0 -1
  40. /package/dist/{daily-logs-store-65YHFJ5F.js.map → daily-logs-store-FZRIGYUX.js.map} +0 -0
  41. /package/dist/{daily-logs-store-PXB53WEK.js.map → daily-logs-store-MEZ5S3BR.js.map} +0 -0
  42. /package/dist/{sync-JL7OPLCT.js.map → sync-EW33QZPD.js.map} +0 -0
  43. /package/dist/{trades-store-MOFJHRC2.js.map → trades-store-3TOLBL2W.js.map} +0 -0
  44. /package/dist/{trades-store-UGZ62A7N.js.map → trades-store-PNLPRYRJ.js.map} +0 -0
  45. /package/server/{daily-logs-store-YAXASQN4.js.map → daily-logs-store-LRVO7COL.js.map} +0 -0
  46. /package/server/{sync-ZV3QEGMO.js.map → sync-2POG6KA6.js.map} +0 -0
  47. /package/server/{trades-store-MF7YYLCH.js.map → trades-store-MXUZLSF5.js.map} +0 -0
@@ -131,7 +131,7 @@ import {
131
131
  writeParquetPartition,
132
132
  writeQuoteMinutesPartition,
133
133
  writeSpotPartition
134
- } from "./chunk-62GCLMQA.js";
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-4UU7IT2A.js";
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 z5 } from "zod";
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(matches[i].provenance)) {
3704
- const samples = ages.get(field) ?? [];
3705
- samples.push(entryDay - easternDayNumber(new Date(provenance.sourceTimestamp)));
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 middle = Math.floor(samples.length / 2);
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: samples.length,
3717
- medianAgeDays: samples.length % 2 ? samples[middle] : (samples[middle - 1] + samples[middle]) / 2,
3718
- maxAgeDays: samples[samples.length - 1],
3719
- olderThan3Days: samples.filter((age) => age > 3).length
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
- return Object.keys(selected).length ? { datasetAge: selected } : {};
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((trade) => resolveTradeDatasets(datasets, trade));
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 = z5.object({
3917
- blockId: z5.string().describe("Block ID to analyze"),
3918
- strategyName: z5.string().describe("Strategy name matching a stored profile"),
3919
- minTrades: z5.number().optional().default(10).describe("Minimum trades per bucket for reliable stats (thin-data warning threshold)")
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 = z5.object({
4139
- blockId: z5.string().describe("Block ID to analyze"),
4140
- strategyName: z5.string().describe("Strategy name matching a stored profile"),
4141
- minTrades: z5.number().optional().default(10).describe("Minimum trades per group for reliable stats"),
4142
- maxAblationFilters: z5.number().optional().default(8).describe("Maximum number of filters for pairwise ablation (cap for combinatorial explosion)")
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
- matched.map(({ trade }) => trade),
4192
- matched
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 = z5.object({
4376
- blockId: z5.string().optional().describe("Block ID to analyze. When omitted, aggregate across all blocks."),
4377
- minTrades: z5.number().optional().default(10).describe("Thin-data warning threshold (default: 10)")
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 z6 } from "zod";
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 = z6.object({
4636
- blockId: z6.string().optional().describe("Block ID to analyze. When omitted, aggregate across all profiled strategies."),
4637
- minTrades: z6.number().optional().default(5).describe("Minimum trades per regime cell for reliable stats (default: 5)")
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 z7 } from "zod";
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 = z7.object({
5076
- v: z7.number().optional(),
5077
- vw: z7.number().optional(),
5078
- o: z7.number(),
5079
- c: z7.number(),
5080
- h: z7.number(),
5081
- l: z7.number(),
5082
- t: z7.number(),
5083
- n: z7.number().optional()
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 = z7.object({
5086
- ticker: z7.string(),
5087
- queryCount: z7.number(),
5088
- resultsCount: z7.number().optional(),
5089
- adjusted: z7.boolean().optional(),
5090
- results: z7.array(MassiveBarSchema).default([]),
5091
- status: z7.string(),
5092
- request_id: z7.string(),
5093
- next_url: z7.string().optional()
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 = z7.object({
5096
- bid_price: z7.number(),
5097
- ask_price: z7.number(),
5098
- sip_timestamp: z7.number(),
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: z7.number(),
5101
- ask_size: z7.number(),
5102
- sequence_number: z7.number()
5141
+ bid_size: z8.number(),
5142
+ ask_size: z8.number(),
5143
+ sequence_number: z8.number()
5103
5144
  });
5104
- var MassiveQuotesResponseSchema = z7.object({
5105
- status: z7.string(),
5106
- request_id: z7.string(),
5107
- results: z7.array(MassiveQuoteSchema).default([]),
5108
- next_url: z7.string().optional()
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 = z7.object({
5111
- delta: z7.number(),
5112
- gamma: z7.number(),
5113
- theta: z7.number(),
5114
- vega: z7.number()
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 = z7.object({
5117
- open: z7.number(),
5118
- high: z7.number(),
5119
- low: z7.number(),
5120
- close: z7.number(),
5121
- change: z7.number(),
5122
- change_percent: z7.number(),
5123
- volume: z7.number().optional(),
5124
- vwap: z7.number().optional(),
5125
- previous_close: z7.number(),
5126
- last_updated: z7.number()
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 = z7.object({
5129
- bid: z7.number(),
5130
- ask: z7.number(),
5131
- midpoint: z7.number(),
5132
- bid_size: z7.number(),
5133
- ask_size: z7.number(),
5134
- last_updated: z7.number(),
5135
- timeframe: z7.string()
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 = z7.object({
5138
- price: z7.number(),
5139
- size: z7.number(),
5140
- sip_timestamp: z7.number(),
5141
- conditions: z7.array(z7.number()).optional(),
5142
- timeframe: z7.string()
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 = z7.object({
5145
- ticker: z7.string(),
5146
- contract_type: z7.string(),
5147
- strike_price: z7.number(),
5148
- expiration_date: z7.string(),
5149
- exercise_style: z7.string(),
5150
- shares_per_contract: z7.number()
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 = z7.object({
5153
- ticker: z7.string(),
5154
- price: z7.number(),
5155
- change_to_break_even: z7.number(),
5156
- last_updated: z7.number(),
5157
- timeframe: z7.string()
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 = z7.object({
5160
- break_even_price: z7.number(),
5161
- implied_volatility: z7.number(),
5162
- open_interest: z7.number(),
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 = z7.object({
5171
- request_id: z7.string(),
5172
- status: z7.string(),
5173
- results: z7.array(MassiveSnapshotContractSchema),
5174
- next_url: z7.string().optional()
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 = z7.object({
5177
- ticker: z7.string(),
5178
- strike_price: z7.number(),
5179
- expiration_date: z7.string(),
5180
- contract_type: z7.string(),
5181
- exercise_style: z7.string().optional().default("american")
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 = z7.object({
5184
- results: z7.array(MassiveContractReferenceSchema),
5185
- next_url: z7.string().nullable().optional(),
5186
- count: z7.number().optional()
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 z8 } from "zod";
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 = z8.object({
8287
+ var replayTradeSchema = z9.object({
8247
8288
  // Mode A: Hypothetical / explicit legs
8248
- legs: z8.array(
8249
- z8.object({
8250
- ticker: z8.string().describe("Underlying ticker, e.g., 'SPY', 'SPX'"),
8251
- strike: z8.number().describe("Strike price"),
8252
- type: z8.enum(["C", "P"]).describe("Call or Put"),
8253
- expiry: z8.string().describe("Expiration date YYYY-MM-DD"),
8254
- quantity: z8.number().describe("Positive = long, negative = short"),
8255
- entry_price: z8.number().describe("Per-contract entry price (premium paid/received)")
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: z8.string().optional().describe("Block ID to load trade from"),
8260
- trade_index: z8.number().optional().describe("0-based index of trade in block's tradelog (ordered by date_opened)"),
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: z8.string().optional().describe(
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: z8.string().optional().describe(
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: z8.string().optional().describe(
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: z8.number().default(100).describe("Contract multiplier (default 100 for standard options)"),
8272
- format: z8.enum(["full", "summary", "sampled"]).default("sampled").describe(
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: z8.enum(["trade", "expiry"]).default("trade").describe(
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: z8.boolean().default(false).describe(
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 z9 } from "zod";
8618
+ import { z as z10 } from "zod";
8578
8619
  var TICKER_RE = /^[A-Z][A-Z0-9^_-]*$/;
8579
- var UnderlyingsFileSchema = z9.object({
8580
- version: z9.literal(1),
8581
- underlyings: z9.array(
8582
- z9.object({
8583
- underlying: z9.string().min(1).max(16).regex(TICKER_RE),
8584
- roots: z9.array(z9.string().min(1).max(16).regex(TICKER_RE)).min(1).max(32)
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 = z9.object({
8589
- underlying: z9.string().min(1).max(16).regex(TICKER_RE).describe("Canonical underlying symbol, e.g. SPX"),
8590
- roots: z9.array(z9.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']")
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 = z9.object({
8593
- underlying: z9.string().min(1).max(16).regex(TICKER_RE).describe("Underlying to remove. Bundled defaults cannot be removed.")
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 = z9.object({});
8596
- var resolveRootSchema = z9.object({
8597
- input: z9.string().min(1).max(32).describe("Bare root ('SPXW') or full OCC ticker ('SPXW251219C05000000')")
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 z10 } from "zod";
11562
- var getOptionSnapshotSchema = z10.object({
11563
- underlying: z10.string().describe("Underlying ticker symbol (e.g., 'SPX', 'SPY', 'AAPL')"),
11564
- strike_price_gte: z10.number().optional().describe("Minimum strike price filter"),
11565
- strike_price_lte: z10.number().optional().describe("Maximum strike price filter"),
11566
- expiration_date_gte: z10.string().optional().describe("Earliest expiration date (YYYY-MM-DD)"),
11567
- expiration_date_lte: z10.string().optional().describe("Latest expiration date (YYYY-MM-DD)"),
11568
- contract_type: z10.enum(["call", "put"]).optional().describe("Filter by call or put"),
11569
- limit: z10.number().optional().default(50).describe("Max contracts to return (default 50, use higher for full chain)")
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 z11 } from "zod";
12441
- var triggerTypeEnum = z11.enum([
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 = z11.object({
12499
+ var triggerConfigSchema = z12.object({
12459
12500
  type: triggerTypeEnum,
12460
- threshold: z11.number(),
12461
- unit: z11.enum(["percent", "dollar"]).default("dollar").optional(),
12462
- expiry: z11.string().optional(),
12463
- openDate: z11.string().optional(),
12464
- clockTime: z11.string().optional(),
12465
- trailAmount: z11.number().optional(),
12466
- steps: z11.array(
12467
- z11.object({
12468
- armAt: z11.number(),
12469
- stopAt: z11.number(),
12470
- closeAllocationPct: z11.number().min(0).max(1).optional().describe("Fraction of REMAINING position to close at this milestone (0-1)")
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: z11.number().optional(),
12474
- contracts: z11.number().optional(),
12475
- legIndex: z11.number().optional().describe("0-based leg index for perLegDelta \u2014 targets specific leg"),
12476
- exitAbove: z11.number().optional().describe("Fire when value exceeds this (directional, no abs)"),
12477
- exitBelow: z11.number().optional().describe("Fire when value drops below this (directional, no abs)")
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 = z11.object({
12480
- ticker: z11.string(),
12481
- strike: z11.number(),
12482
- type: z11.enum(["C", "P"]),
12483
- expiry: z11.string(),
12484
- quantity: z11.number(),
12485
- entry_price: z11.number()
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 = z11.object({
12528
+ var analyzeExitTriggersSchema = z12.object({
12488
12529
  // Replay inputs (same shape as replay_trade)
12489
- legs: z11.array(legSchema).optional(),
12490
- block_id: z11.string().optional(),
12491
- trade_index: z11.number().optional(),
12492
- open_date: z11.string().optional(),
12493
- close_date: z11.string().optional(),
12494
- multiplier: z11.number().default(100),
12495
- triggers: z11.array(triggerConfigSchema).describe("Exit triggers to evaluate against the P&L path"),
12496
- actual_exit_timestamp: z11.string().optional().describe("Actual exit time for comparison (format: YYYY-MM-DD HH:MM)"),
12497
- leg_groups: z11.array(
12498
- z11.object({
12499
- label: z11.string(),
12500
- leg_indices: z11.array(z11.number()),
12501
- triggers: z11.array(triggerConfigSchema)
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: z11.enum(["summary", "full"]).default("summary").describe("'summary' omits per-step trigger states, 'full' includes all fire events")
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 = z11.object({
12547
+ var decomposeGreeksSchema = z12.object({
12507
12548
  // Same replay inputs
12508
- legs: z11.array(legSchema).optional(),
12509
- block_id: z11.string().optional(),
12510
- trade_index: z11.number().optional(),
12511
- open_date: z11.string().optional(),
12512
- close_date: z11.string().optional(),
12513
- multiplier: z11.number().default(100),
12514
- leg_groups: z11.array(
12515
- z11.object({
12516
- label: z11.string(),
12517
- leg_indices: z11.array(z11.number())
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: z11.enum(["summary", "full"]).default("summary").describe("'summary' shows ranked factors, 'full' includes per-step contributions"),
12521
- skip_quotes: z11.boolean().default(false).describe("Skip NBBO quote enrichment for option bars. Faster, but lower precision.")
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 z12 } from "zod";
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 = z12.enum([
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 = z12.object({
13027
+ var triggerConfigSchema2 = z13.object({
12987
13028
  type: triggerTypeEnum2,
12988
- threshold: z12.number(),
12989
- unit: z12.enum(["percent", "dollar"]).default("dollar").optional(),
12990
- expiry: z12.string().optional(),
12991
- openDate: z12.string().optional(),
12992
- clockTime: z12.string().optional(),
12993
- trailAmount: z12.number().optional(),
12994
- steps: z12.array(
12995
- z12.object({
12996
- armAt: z12.number(),
12997
- stopAt: z12.number(),
12998
- closeAllocationPct: z12.number().min(0).max(1).optional().describe("Fraction of REMAINING position to close at this milestone (0-1)")
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: z12.number().optional(),
13002
- contracts: z12.number().optional(),
13003
- legIndex: z12.number().optional().describe("0-based leg index for perLegDelta \u2014 targets specific leg"),
13004
- exitAbove: z12.number().optional().describe("Fire when value exceeds this (directional, no abs)"),
13005
- exitBelow: z12.number().optional().describe("Fire when value drops below this (directional, no abs)")
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 = z12.object({
13008
- block_id: z12.string().describe("Block ID to analyze trades from"),
13009
- strategy: z12.string().optional().describe("Filter trades by strategy name (case-insensitive ILIKE)"),
13010
- date_range: z12.object({
13011
- from: z12.string().optional().describe("Start date YYYY-MM-DD"),
13012
- to: z12.string().optional().describe("End date YYYY-MM-DD")
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: z12.array(triggerConfigSchema2).describe("Candidate exit policy triggers to evaluate -- same schema as analyze_exit_triggers"),
13015
- leg_groups: z12.array(
13016
- z12.object({
13017
- label: z12.string(),
13018
- leg_indices: z12.array(z12.number()),
13019
- triggers: z12.array(triggerConfigSchema2)
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: z12.enum(["actual", "holdToEnd"]).default("actual").describe(
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: z12.number().min(1).max(200).default(50).describe("Max trades to analyze. Most recent trades selected"),
13026
- min_pl: z12.number().optional().describe("Only include trades with actual P&L >= this value"),
13027
- max_pl: z12.number().optional().describe("Only include trades with actual P&L <= this value"),
13028
- multiplier: z12.number().default(100).describe("Contract multiplier (default 100)"),
13029
- format: z12.enum(["summary", "full"]).default("summary").describe(
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 z13 } from "zod";
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 z14 } from "zod";
13644
- var getGreeksAttributionSchema = z14.object({
13645
- block_id: z14.string().describe("Block ID to analyze"),
13646
- mode: z14.enum(["summary", "instance"]).default("summary").describe("summary: block-level attribution. instance: single trade time-series."),
13647
- trade_index: z14.number().int().min(0).optional().describe(
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: z14.boolean().default(true).describe(
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: z14.boolean().default(false).describe("false: 5 factors (delta, gamma, theta, vega, residual). true: adds charm, vanna."),
13654
- strategy: z14.string().optional().describe("Filter to trades matching this strategy name (case-insensitive).")
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",