tradeblocks-mcp 3.0.2 → 3.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (214) hide show
  1. package/README.md +82 -68
  2. package/dist/{chunk-LDKTV7GW.js → chunk-27S67XW3.js} +24 -52
  3. package/dist/chunk-27S67XW3.js.map +1 -0
  4. package/dist/{chunk-FGZH632F.js → chunk-2E63THNI.js} +13 -11
  5. package/dist/chunk-2E63THNI.js.map +1 -0
  6. package/dist/{chunk-BKQ4PM4Y.js → chunk-6S37CXUA.js} +11 -13
  7. package/dist/chunk-6S37CXUA.js.map +1 -0
  8. package/dist/{chunk-PRAYH3RT.js → chunk-AP7IHUUR.js} +29 -12
  9. package/dist/chunk-AP7IHUUR.js.map +1 -0
  10. package/dist/{chunk-QTTR7AAW.js → chunk-C6LL746C.js} +67 -84
  11. package/dist/{chunk-QTTR7AAW.js.map → chunk-C6LL746C.js.map} +1 -1
  12. package/dist/{chunk-W2PP3LEH.js → chunk-SEUZYQGQ.js} +17 -8
  13. package/dist/chunk-SEUZYQGQ.js.map +1 -0
  14. package/dist/{chunk-4BLCXNQ6.js → chunk-UBUC5A66.js} +105 -114
  15. package/dist/chunk-UBUC5A66.js.map +1 -0
  16. package/dist/{chunk-XXYOUIZY.js → chunk-VDU25Z6X.js} +63 -80
  17. package/dist/chunk-VDU25Z6X.js.map +1 -0
  18. package/dist/daily-log-processor-BY3ISY6K.js +9 -0
  19. package/dist/{daily-logs-store-D3QC2XPV.js → daily-logs-store-3C3OTGPK.js} +2 -2
  20. package/dist/iv-solver-worker.js +9 -1
  21. package/dist/market-provider-H3ARIVZ4.js +16 -0
  22. package/dist/{proto-3HZTCWK4.js → proto-V23GIZG2.js} +2 -2
  23. package/dist/{sync-PO4IPCYV.js → sync-EVLKB3ZJ.js} +7 -7
  24. package/dist/test-exports.js +358 -254
  25. package/dist/test-exports.js.map +1 -1
  26. package/dist/trade-processor-EYA3I3XB.js +9 -0
  27. package/dist/{trades-store-LOL3FQSF.js → trades-store-R3NL25T2.js} +2 -2
  28. package/manifest.json +3 -11
  29. package/package.json +1 -1
  30. package/server/{chunk-NZO6PT64.js → chunk-4P7D7YZP.js} +102 -113
  31. package/server/chunk-4P7D7YZP.js.map +1 -0
  32. package/server/{chunk-72GKJE2U.js → chunk-BOPHW5M6.js} +521 -235
  33. package/server/chunk-BOPHW5M6.js.map +1 -0
  34. package/server/{chunk-WA5AAPCH.js → chunk-GH2552SE.js} +17 -8
  35. package/server/chunk-GH2552SE.js.map +1 -0
  36. package/server/{chunk-5EBXHT6C.js → chunk-OBYKFW2B.js} +11 -13
  37. package/server/chunk-OBYKFW2B.js.map +1 -0
  38. package/server/{chunk-FBNDMCT5.js → chunk-T66KH2XH.js} +13 -11
  39. package/server/chunk-T66KH2XH.js.map +1 -0
  40. package/server/{chunk-NRFXAJF7.js → chunk-W5E7FHC4.js} +24 -52
  41. package/server/chunk-W5E7FHC4.js.map +1 -0
  42. package/server/{chunk-CSDVJPBB.js → chunk-YUCOAJ4Z.js} +29 -12
  43. package/server/chunk-YUCOAJ4Z.js.map +1 -0
  44. package/server/{chunk-PNKG7RY7.js → chunk-ZBJCF4ZG.js} +63 -80
  45. package/server/chunk-ZBJCF4ZG.js.map +1 -0
  46. package/server/{config-6IZXEFEX.js → config-DK7KOMNL.js} +1 -1
  47. package/server/config-DK7KOMNL.js.map +1 -0
  48. package/server/daily-log-processor-ENEUT22A.js +10 -0
  49. package/server/{daily-logs-store-NU7M4L5C.js → daily-logs-store-YFNXTB7J.js} +2 -2
  50. package/server/http-server.js +2 -5
  51. package/server/index.js +1771 -1538
  52. package/server/index.js.map +1 -1
  53. package/server/iv-solver-worker.js +9 -1
  54. package/server/market-provider-B437HKLW.js +17 -0
  55. package/server/{proto-DWRZJO4E.js → proto-YZ4TLX2N.js} +2 -2
  56. package/server/{sync-QFI5L7S7.js → sync-V25UQJA3.js} +7 -7
  57. package/server/trade-processor-L3PIQ5TG.js +10 -0
  58. package/server/{trades-store-VY26MWER.js → trades-store-RTTEYMXH.js} +2 -2
  59. package/src/auth/clients-store.ts +4 -4
  60. package/src/auth/code-store.ts +1 -1
  61. package/src/auth/config.ts +11 -12
  62. package/src/auth/login-page.ts +8 -10
  63. package/src/auth/provider.ts +35 -30
  64. package/src/auth/token.ts +17 -15
  65. package/src/db/backtest-schemas.ts +12 -4
  66. package/src/db/connection.ts +107 -40
  67. package/src/db/index.ts +37 -5
  68. package/src/db/json-adapters.ts +22 -31
  69. package/src/db/json-migration.ts +11 -15
  70. package/src/db/json-store.ts +5 -3
  71. package/src/db/market-datasets.ts +48 -15
  72. package/src/db/market-schemas.ts +11 -5
  73. package/src/db/market-views.ts +119 -32
  74. package/src/db/parquet-writer.ts +7 -7
  75. package/src/db/profile-schemas.ts +39 -22
  76. package/src/db/schemas.ts +2 -2
  77. package/src/http-server.ts +7 -12
  78. package/src/index.ts +8 -9
  79. package/src/market/ingestor/index.ts +1 -4
  80. package/src/market/ingestor/market-ingestor.ts +140 -67
  81. package/src/market/ingestor/types.ts +1 -3
  82. package/src/market/stores/chain-sql.ts +2 -8
  83. package/src/market/stores/chain-store.ts +1 -4
  84. package/src/market/stores/duckdb-chain-store.ts +3 -14
  85. package/src/market/stores/duckdb-enriched-store.ts +3 -13
  86. package/src/market/stores/duckdb-quote-store.ts +10 -27
  87. package/src/market/stores/duckdb-spot-store.ts +4 -20
  88. package/src/market/stores/enriched-sql.ts +3 -9
  89. package/src/market/stores/enriched-store.ts +2 -2
  90. package/src/market/stores/parquet-chain-store.ts +5 -22
  91. package/src/market/stores/parquet-enriched-store.ts +4 -16
  92. package/src/market/stores/parquet-oi-daily-store.ts +3 -14
  93. package/src/market/stores/parquet-quote-store.ts +9 -29
  94. package/src/market/stores/parquet-spot-store.ts +14 -33
  95. package/src/market/stores/quote-store.ts +2 -10
  96. package/src/market/stores/spot-sql.ts +3 -15
  97. package/src/market/stores/spot-store.ts +1 -1
  98. package/src/market/tickers/defaults.json +6 -6
  99. package/src/market/tickers/loader.ts +2 -7
  100. package/src/market/tickers/registry.ts +5 -15
  101. package/src/market/tickers/schemas.ts +2 -6
  102. package/src/models/strategy-profile.ts +39 -39
  103. package/src/sync/block-sync.ts +44 -65
  104. package/src/sync/index.ts +1 -4
  105. package/src/sync/metadata.ts +14 -20
  106. package/src/test-exports.ts +127 -123
  107. package/src/tools/analysis.ts +180 -159
  108. package/src/tools/batch-exit-analysis.ts +100 -59
  109. package/src/tools/blocks/analysis.ts +116 -101
  110. package/src/tools/blocks/comparison.ts +281 -364
  111. package/src/tools/blocks/core.ts +208 -253
  112. package/src/tools/blocks/health.ts +571 -563
  113. package/src/tools/blocks/similarity.ts +316 -283
  114. package/src/tools/edge-decay.ts +124 -197
  115. package/src/tools/exit-analysis.ts +130 -77
  116. package/src/tools/greeks-attribution.ts +84 -35
  117. package/src/tools/guides.ts +4 -6
  118. package/src/tools/imports.ts +9 -12
  119. package/src/tools/market-data.ts +1067 -757
  120. package/src/tools/market-enrichment.ts +3 -3
  121. package/src/tools/market-fetch.ts +148 -67
  122. package/src/tools/market-imports.ts +12 -12
  123. package/src/tools/middleware/sync-middleware.ts +5 -6
  124. package/src/tools/performance.ts +185 -302
  125. package/src/tools/profile-analysis.ts +52 -66
  126. package/src/tools/profiles.ts +106 -69
  127. package/src/tools/regime-advisor.ts +20 -45
  128. package/src/tools/replay.ts +81 -77
  129. package/src/tools/reports/discrepancies.ts +298 -328
  130. package/src/tools/reports/fields.ts +7 -25
  131. package/src/tools/reports/helpers.ts +18 -49
  132. package/src/tools/reports/predictive.ts +27 -70
  133. package/src/tools/reports/slippage-trends.ts +315 -345
  134. package/src/tools/reports/slippage.ts +1 -4
  135. package/src/tools/reports/strategy-matches.ts +399 -441
  136. package/src/tools/schema.ts +43 -40
  137. package/src/tools/shared/filters.ts +3 -9
  138. package/src/tools/snapshot.ts +9 -30
  139. package/src/tools/sql.ts +15 -14
  140. package/src/tools/tickers.ts +1 -4
  141. package/src/utils/batch-exit-analysis.ts +31 -42
  142. package/src/utils/black-scholes.ts +39 -29
  143. package/src/utils/block-loader.ts +68 -82
  144. package/src/utils/calibration-probe.ts +1 -2
  145. package/src/utils/chain-loader.ts +3 -3
  146. package/src/utils/csv-discovery.ts +16 -22
  147. package/src/utils/data-quality.ts +24 -36
  148. package/src/utils/exit-triggers.ts +91 -96
  149. package/src/utils/field-timing.ts +94 -79
  150. package/src/utils/filter-predicates.ts +13 -9
  151. package/src/utils/flatfile-importer.ts +94 -64
  152. package/src/utils/greeks-decomposition.ts +152 -100
  153. package/src/utils/iv-solver-pool.ts +55 -25
  154. package/src/utils/iv-solver-worker.ts +5 -5
  155. package/src/utils/market-enricher.ts +528 -497
  156. package/src/utils/market-importer.ts +31 -12
  157. package/src/utils/market-provider.ts +21 -23
  158. package/src/utils/massive-tier.ts +5 -7
  159. package/src/utils/migrate-option-data-helpers.ts +2 -8
  160. package/src/utils/option-quote-greeks.ts +25 -31
  161. package/src/utils/option-time.ts +4 -8
  162. package/src/utils/output-formatter.ts +1 -4
  163. package/src/utils/provider-capabilities.ts +1 -4
  164. package/src/utils/providers/massive.ts +59 -93
  165. package/src/utils/providers/thetadata/backfill.ts +14 -23
  166. package/src/utils/providers/thetadata/client.ts +12 -8
  167. package/src/utils/providers/thetadata/decode.ts +2 -20
  168. package/src/utils/providers/thetadata/endpoints.ts +32 -40
  169. package/src/utils/providers/thetadata/join.ts +11 -10
  170. package/src/utils/providers/thetadata/proto.ts +12 -10
  171. package/src/utils/providers/thetadata/quote-mid-greeks.ts +5 -5
  172. package/src/utils/providers/thetadata.ts +11 -10
  173. package/src/utils/quote-enricher.ts +4 -4
  174. package/src/utils/quote-parquet-projection.ts +3 -11
  175. package/src/utils/sample-date-selector.ts +3 -5
  176. package/src/utils/schema-metadata.ts +102 -70
  177. package/src/utils/ticker.ts +5 -9
  178. package/src/utils/trade-replay.ts +77 -68
  179. package/dist/chunk-4BLCXNQ6.js.map +0 -1
  180. package/dist/chunk-BKQ4PM4Y.js.map +0 -1
  181. package/dist/chunk-FGZH632F.js.map +0 -1
  182. package/dist/chunk-LDKTV7GW.js.map +0 -1
  183. package/dist/chunk-PRAYH3RT.js.map +0 -1
  184. package/dist/chunk-W2PP3LEH.js.map +0 -1
  185. package/dist/chunk-XXYOUIZY.js.map +0 -1
  186. package/dist/daily-log-processor-6MWJ23JK.js +0 -9
  187. package/dist/market-provider-VDRJUEF2.js +0 -16
  188. package/dist/trade-processor-NHU4VWRX.js +0 -9
  189. package/server/chunk-5EBXHT6C.js.map +0 -1
  190. package/server/chunk-72GKJE2U.js.map +0 -1
  191. package/server/chunk-CSDVJPBB.js.map +0 -1
  192. package/server/chunk-FBNDMCT5.js.map +0 -1
  193. package/server/chunk-NRFXAJF7.js.map +0 -1
  194. package/server/chunk-NZO6PT64.js.map +0 -1
  195. package/server/chunk-PNKG7RY7.js.map +0 -1
  196. package/server/chunk-WA5AAPCH.js.map +0 -1
  197. package/server/config-6IZXEFEX.js.map +0 -1
  198. package/server/daily-log-processor-Y3PVSVBM.js +0 -10
  199. package/server/market-provider-VOYYVYWT.js +0 -17
  200. package/server/trade-processor-JWVS37KM.js +0 -10
  201. /package/dist/{daily-log-processor-6MWJ23JK.js.map → daily-log-processor-BY3ISY6K.js.map} +0 -0
  202. /package/dist/{daily-logs-store-D3QC2XPV.js.map → daily-logs-store-3C3OTGPK.js.map} +0 -0
  203. /package/dist/{market-provider-VDRJUEF2.js.map → market-provider-H3ARIVZ4.js.map} +0 -0
  204. /package/dist/{proto-3HZTCWK4.js.map → proto-V23GIZG2.js.map} +0 -0
  205. /package/dist/{sync-PO4IPCYV.js.map → sync-EVLKB3ZJ.js.map} +0 -0
  206. /package/dist/{trade-processor-NHU4VWRX.js.map → trade-processor-EYA3I3XB.js.map} +0 -0
  207. /package/dist/{trades-store-LOL3FQSF.js.map → trades-store-R3NL25T2.js.map} +0 -0
  208. /package/server/{daily-log-processor-Y3PVSVBM.js.map → daily-log-processor-ENEUT22A.js.map} +0 -0
  209. /package/server/{daily-logs-store-NU7M4L5C.js.map → daily-logs-store-YFNXTB7J.js.map} +0 -0
  210. /package/server/{market-provider-VOYYVYWT.js.map → market-provider-B437HKLW.js.map} +0 -0
  211. /package/server/{proto-DWRZJO4E.js.map → proto-YZ4TLX2N.js.map} +0 -0
  212. /package/server/{sync-QFI5L7S7.js.map → sync-V25UQJA3.js.map} +0 -0
  213. /package/server/{trade-processor-JWVS37KM.js.map → trade-processor-L3PIQ5TG.js.map} +0 -0
  214. /package/server/{trades-store-VY26MWER.js.map → trades-store-RTTEYMXH.js.map} +0 -0
@@ -59,34 +59,55 @@ async function mapWithLimit<T, R>(
59
59
  // ---------------------------------------------------------------------------
60
60
 
61
61
  const triggerTypeEnum = z.enum([
62
- 'profitTarget', 'stopLoss', 'trailingStop', 'profitAction',
63
- 'dteExit', 'ditExit', 'clockTimeExit',
64
- 'underlyingPriceMove', 'positionDelta', 'perLegDelta',
65
- 'vixMove', 'vix9dMove', 'vix9dVixRatio',
66
- 'slRatioThreshold', 'slRatioMove',
62
+ "profitTarget",
63
+ "stopLoss",
64
+ "trailingStop",
65
+ "profitAction",
66
+ "dteExit",
67
+ "ditExit",
68
+ "clockTimeExit",
69
+ "underlyingPriceMove",
70
+ "positionDelta",
71
+ "perLegDelta",
72
+ "vixMove",
73
+ "vix9dMove",
74
+ "vix9dVixRatio",
75
+ "slRatioThreshold",
76
+ "slRatioMove",
67
77
  ]);
68
78
 
69
79
  const triggerConfigSchema = z.object({
70
80
  type: triggerTypeEnum,
71
81
  threshold: z.number(),
72
- unit: z.enum(['percent', 'dollar']).default('dollar').optional(),
82
+ unit: z.enum(["percent", "dollar"]).default("dollar").optional(),
73
83
  expiry: z.string().optional(),
74
84
  openDate: z.string().optional(),
75
85
  clockTime: z.string().optional(),
76
86
  trailAmount: z.number().optional(),
77
- steps: z.array(z.object({
78
- armAt: z.number(),
79
- stopAt: z.number(),
80
- closeAllocationPct: z.number().min(0).max(1).optional()
81
- .describe("Fraction of REMAINING position to close at this milestone (0-1)"),
82
- })).optional(),
87
+ steps: z
88
+ .array(
89
+ z.object({
90
+ armAt: z.number(),
91
+ stopAt: z.number(),
92
+ closeAllocationPct: z
93
+ .number()
94
+ .min(0)
95
+ .max(1)
96
+ .optional()
97
+ .describe("Fraction of REMAINING position to close at this milestone (0-1)"),
98
+ }),
99
+ )
100
+ .optional(),
83
101
  spreadWidth: z.number().optional(),
84
102
  contracts: z.number().optional(),
85
- legIndex: z.number().optional()
103
+ legIndex: z
104
+ .number()
105
+ .optional()
86
106
  .describe("0-based leg index for perLegDelta — targets specific leg"),
87
- exitAbove: z.number().optional()
88
- .describe("Fire when value exceeds this (directional, no abs)"),
89
- exitBelow: z.number().optional()
107
+ exitAbove: z.number().optional().describe("Fire when value exceeds this (directional, no abs)"),
108
+ exitBelow: z
109
+ .number()
110
+ .optional()
90
111
  .describe("Fire when value drops below this (directional, no abs)"),
91
112
  });
92
113
 
@@ -97,40 +118,60 @@ const triggerConfigSchema = z.object({
97
118
  export const batchExitAnalysisSchema = z.object({
98
119
  block_id: z.string().describe("Block ID to analyze trades from"),
99
120
 
100
- strategy: z.string().optional()
121
+ strategy: z
122
+ .string()
123
+ .optional()
101
124
  .describe("Filter trades by strategy name (case-insensitive ILIKE)"),
102
125
 
103
- date_range: z.object({
104
- from: z.string().optional().describe("Start date YYYY-MM-DD"),
105
- to: z.string().optional().describe("End date YYYY-MM-DD"),
106
- }).optional().describe("Filter trades by date range"),
126
+ date_range: z
127
+ .object({
128
+ from: z.string().optional().describe("Start date YYYY-MM-DD"),
129
+ to: z.string().optional().describe("End date YYYY-MM-DD"),
130
+ })
131
+ .optional()
132
+ .describe("Filter trades by date range"),
107
133
 
108
- candidate_policy: z.array(triggerConfigSchema)
134
+ candidate_policy: z
135
+ .array(triggerConfigSchema)
109
136
  .describe("Candidate exit policy triggers to evaluate -- same schema as analyze_exit_triggers"),
110
137
 
111
- leg_groups: z.array(z.object({
112
- label: z.string(),
113
- leg_indices: z.array(z.number()),
114
- triggers: z.array(triggerConfigSchema),
115
- })).optional().describe("Per-leg-group exit triggers for multi-structure strategies"),
116
-
117
- baseline_mode: z.enum(['actual', 'holdToEnd']).default('actual')
118
- .describe("'actual' compares candidate vs trade's actual P&L; 'holdToEnd' compares vs last replay timestamp"),
119
-
120
- limit: z.number().min(1).max(200).default(50)
138
+ leg_groups: z
139
+ .array(
140
+ z.object({
141
+ label: z.string(),
142
+ leg_indices: z.array(z.number()),
143
+ triggers: z.array(triggerConfigSchema),
144
+ }),
145
+ )
146
+ .optional()
147
+ .describe("Per-leg-group exit triggers for multi-structure strategies"),
148
+
149
+ baseline_mode: z
150
+ .enum(["actual", "holdToEnd"])
151
+ .default("actual")
152
+ .describe(
153
+ "'actual' compares candidate vs trade's actual P&L; 'holdToEnd' compares vs last replay timestamp",
154
+ ),
155
+
156
+ limit: z
157
+ .number()
158
+ .min(1)
159
+ .max(200)
160
+ .default(50)
121
161
  .describe("Max trades to analyze. Most recent trades selected"),
122
162
 
123
- min_pl: z.number().optional()
124
- .describe("Only include trades with actual P&L >= this value"),
163
+ min_pl: z.number().optional().describe("Only include trades with actual P&L >= this value"),
125
164
 
126
- max_pl: z.number().optional()
127
- .describe("Only include trades with actual P&L <= this value"),
165
+ max_pl: z.number().optional().describe("Only include trades with actual P&L <= this value"),
128
166
 
129
- multiplier: z.number().default(100)
130
- .describe("Contract multiplier (default 100)"),
167
+ multiplier: z.number().default(100).describe("Contract multiplier (default 100)"),
131
168
 
132
- format: z.enum(['summary', 'full']).default('summary')
133
- .describe("'summary' returns aggregate stats + trigger attribution; 'full' adds per-trade breakdown"),
169
+ format: z
170
+ .enum(["summary", "full"])
171
+ .default("summary")
172
+ .describe(
173
+ "'summary' returns aggregate stats + trigger attribution; 'full' adds per-trade breakdown",
174
+ ),
134
175
  });
135
176
 
136
177
  // ---------------------------------------------------------------------------
@@ -140,7 +181,7 @@ export const batchExitAnalysisSchema = z.object({
140
181
  export async function handleBatchExitAnalysis(
141
182
  params: z.infer<typeof batchExitAnalysisSchema>,
142
183
  baseDir: string,
143
- stores: MarketStores, // Phase 4 CONSUMER-01 — threaded through for Wave 2+ rewrite.
184
+ stores: MarketStores, // Phase 4 CONSUMER-01 — threaded through for Wave 2+ rewrite.
144
185
  injectedConn?: import("@duckdb/node-api").DuckDBConnection,
145
186
  ): Promise<BatchExitResult> {
146
187
  const {
@@ -158,7 +199,7 @@ export async function handleBatchExitAnalysis(
158
199
  } = params;
159
200
 
160
201
  // 1. Query trades from DuckDB with deterministic ROW_NUMBER ordering
161
- const conn = injectedConn ?? await getConnection(baseDir);
202
+ const conn = injectedConn ?? (await getConnection(baseDir));
162
203
  const escapedBlockId = block_id.replace(/'/g, "''");
163
204
 
164
205
  // Build WHERE clauses
@@ -193,7 +234,7 @@ export async function handleBatchExitAnalysis(
193
234
  )
194
235
  SELECT trade_idx, pl, date_opened
195
236
  FROM numbered
196
- ${filterClauses.length > 0 ? 'WHERE ' + filterClauses.join(' AND ') : ''}
237
+ ${filterClauses.length > 0 ? "WHERE " + filterClauses.join(" AND ") : ""}
197
238
  ORDER BY date_opened DESC
198
239
  LIMIT ${limit}
199
240
  `;
@@ -226,7 +267,7 @@ export async function handleBatchExitAnalysis(
226
267
  triggerAttribution: [],
227
268
  perTrade: [],
228
269
  baselineMode: baseline_mode,
229
- summary: 'Analyzed 0 trades: no matching trades found.',
270
+ summary: "Analyzed 0 trades: no matching trades found.",
230
271
  };
231
272
  return emptyResult;
232
273
  }
@@ -244,7 +285,7 @@ export async function handleBatchExitAnalysis(
244
285
  async (row): Promise<ReplayOutcome> => {
245
286
  const tradeIdx = Number(row[0] ?? 0);
246
287
  const pl = Number(row[1] ?? 0);
247
- const dateOpened = String(row[2] ?? '');
288
+ const dateOpened = String(row[2] ?? "");
248
289
 
249
290
  try {
250
291
  // Always pass format:'full' to get complete pnlPath for analyzeBatch.
@@ -254,8 +295,8 @@ export async function handleBatchExitAnalysis(
254
295
  block_id,
255
296
  trade_index: tradeIdx,
256
297
  multiplier,
257
- format: 'full',
258
- close_at: 'trade',
298
+ format: "full",
299
+ close_at: "trade",
259
300
  skip_quotes: false,
260
301
  },
261
302
  baseDir,
@@ -283,7 +324,7 @@ export async function handleBatchExitAnalysis(
283
324
  return {
284
325
  ok: false,
285
326
  tradeIndex: Number(row[0] ?? 0),
286
- dateOpened: String(row[2] ?? ''),
327
+ dateOpened: String(row[2] ?? ""),
287
328
  error: err instanceof Error ? err.message : String(err),
288
329
  };
289
330
  }
@@ -308,7 +349,7 @@ export async function handleBatchExitAnalysis(
308
349
  // 3. Build BatchExitConfig
309
350
  const config: BatchExitConfig = {
310
351
  candidatePolicy: candidate_policy as ExitTriggerConfig[],
311
- legGroups: leg_groups?.map(g => ({
352
+ legGroups: leg_groups?.map((g) => ({
312
353
  label: g.label,
313
354
  legIndices: g.leg_indices,
314
355
  triggers: g.triggers as ExitTriggerConfig[],
@@ -332,14 +373,12 @@ export async function handleBatchExitAnalysis(
332
373
  // 6. Load profile context if strategy is specified (per D-16)
333
374
  if (strategy) {
334
375
  try {
335
- const profileConn = injectedConn ?? await getConnection(baseDir);
376
+ const profileConn = injectedConn ?? (await getConnection(baseDir));
336
377
  const profile = await getProfile(profileConn, block_id, strategy, baseDir);
337
378
  if (profile) {
338
379
  result.profileContext = {
339
380
  structureType: profile.structureType,
340
- exitRules: profile.exitRules.map(r =>
341
- r.description ?? `${r.type} ${r.trigger}`
342
- ),
381
+ exitRules: profile.exitRules.map((r) => r.description ?? `${r.type} ${r.trigger}`),
343
382
  };
344
383
  }
345
384
  } catch {
@@ -357,7 +396,7 @@ export async function handleBatchExitAnalysis(
357
396
  export function registerBatchExitAnalysisTools(
358
397
  server: McpServer,
359
398
  baseDir: string,
360
- stores: MarketStores, // Phase 4 CONSUMER-01 — threaded through for Wave 2+ rewrite.
399
+ stores: MarketStores, // Phase 4 CONSUMER-01 — threaded through for Wave 2+ rewrite.
361
400
  ): void {
362
401
  server.registerTool(
363
402
  "batch_exit_analysis",
@@ -378,13 +417,15 @@ export function registerBatchExitAnalysisTools(
378
417
  return createToolOutput(result.summary, result);
379
418
  } catch (error) {
380
419
  return {
381
- content: [{
382
- type: "text" as const,
383
- text: `Error in batch exit analysis: ${(error as Error).message}`,
384
- }],
420
+ content: [
421
+ {
422
+ type: "text" as const,
423
+ text: `Error in batch exit analysis: ${(error as Error).message}`,
424
+ },
425
+ ],
385
426
  isError: true,
386
427
  };
387
428
  }
388
- }
429
+ },
389
430
  );
390
431
  }