bitbank-lab-mcp 0.1.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 (147) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +388 -0
  3. package/assets/lightweight-charts.standalone.js +7 -0
  4. package/bin/bitbank-lab-mcp.js +20 -0
  5. package/lib/cache.ts +70 -0
  6. package/lib/candle-utils.ts +48 -0
  7. package/lib/candle-validate.ts +434 -0
  8. package/lib/conversions.ts +25 -0
  9. package/lib/datetime.ts +157 -0
  10. package/lib/depth-analysis.ts +51 -0
  11. package/lib/error.ts +15 -0
  12. package/lib/formatter.ts +296 -0
  13. package/lib/get-depth.ts +111 -0
  14. package/lib/http.ts +132 -0
  15. package/lib/indicator-config.ts +39 -0
  16. package/lib/indicator_buffer.ts +41 -0
  17. package/lib/indicators.ts +579 -0
  18. package/lib/logger.ts +120 -0
  19. package/lib/ma-snapshot-utils.ts +277 -0
  20. package/lib/math.ts +89 -0
  21. package/lib/pattern-diagrams.ts +562 -0
  22. package/lib/result.ts +104 -0
  23. package/lib/validate.ts +154 -0
  24. package/lib/volatility.ts +132 -0
  25. package/package.json +79 -0
  26. package/src/env.ts +4 -0
  27. package/src/handlers/analyzeCandlePatternsHandler.ts +383 -0
  28. package/src/handlers/analyzeFibonacciHandler.ts +54 -0
  29. package/src/handlers/analyzeIndicatorsHandler.ts +682 -0
  30. package/src/handlers/analyzeMarketSignalHandler.ts +272 -0
  31. package/src/handlers/analyzeMyPortfolioHandler.ts +800 -0
  32. package/src/handlers/detectPatternsHandler.ts +77 -0
  33. package/src/handlers/detectPatternsViewsHandler.ts +518 -0
  34. package/src/handlers/getTickersJpyHandler.ts +145 -0
  35. package/src/handlers/getVolatilityMetricsHandler.ts +234 -0
  36. package/src/handlers/portfolio/calc.ts +549 -0
  37. package/src/handlers/portfolio/fetch.ts +318 -0
  38. package/src/handlers/portfolio/types.ts +170 -0
  39. package/src/handlers/renderChartSvgHandler.ts +69 -0
  40. package/src/handlers/runBacktestHandler.ts +70 -0
  41. package/src/http.ts +107 -0
  42. package/src/private/auth.ts +104 -0
  43. package/src/private/client.ts +298 -0
  44. package/src/private/config.ts +25 -0
  45. package/src/private/confirmation.ts +185 -0
  46. package/src/private/schemas.ts +866 -0
  47. package/src/prompts.ts +2296 -0
  48. package/src/resources/app-resources.ts +79 -0
  49. package/src/schema/analysis.ts +942 -0
  50. package/src/schema/backtest.ts +100 -0
  51. package/src/schema/base.ts +88 -0
  52. package/src/schema/candle-validate.ts +135 -0
  53. package/src/schema/chart.ts +399 -0
  54. package/src/schema/index.ts +11 -0
  55. package/src/schema/indicators.ts +125 -0
  56. package/src/schema/market-data.ts +298 -0
  57. package/src/schema/patterns.ts +382 -0
  58. package/src/schema/types.ts +97 -0
  59. package/src/schemas.d.ts +37 -0
  60. package/src/schemas.ts +7 -0
  61. package/src/server.ts +405 -0
  62. package/src/tool-definition.ts +44 -0
  63. package/src/tool-registry.ts +174 -0
  64. package/src/types/express-shim.d.ts +9 -0
  65. package/src/types/schemas.generated.d.ts +23 -0
  66. package/tools/analyze_bb_snapshot.ts +385 -0
  67. package/tools/analyze_candle_patterns.ts +810 -0
  68. package/tools/analyze_currency_strength.ts +273 -0
  69. package/tools/analyze_ema_snapshot.ts +183 -0
  70. package/tools/analyze_fibonacci.ts +530 -0
  71. package/tools/analyze_ichimoku_snapshot.ts +606 -0
  72. package/tools/analyze_indicators.ts +691 -0
  73. package/tools/analyze_market_signal.ts +665 -0
  74. package/tools/analyze_mtf_fibonacci.ts +273 -0
  75. package/tools/analyze_mtf_sma.ts +175 -0
  76. package/tools/analyze_sma_snapshot.ts +146 -0
  77. package/tools/analyze_stoch_snapshot.ts +276 -0
  78. package/tools/analyze_support_resistance.ts +817 -0
  79. package/tools/analyze_volume_profile.ts +546 -0
  80. package/tools/chart/ichimoku-cloud.ts +113 -0
  81. package/tools/chart/render-depth.ts +139 -0
  82. package/tools/chart/render-sub-panels.ts +208 -0
  83. package/tools/chart/svg-utils.ts +102 -0
  84. package/tools/detect_macd_cross.ts +691 -0
  85. package/tools/detect_patterns.ts +424 -0
  86. package/tools/detect_whale_events.ts +181 -0
  87. package/tools/get_candles.ts +487 -0
  88. package/tools/get_flow_metrics.ts +596 -0
  89. package/tools/get_orderbook.ts +540 -0
  90. package/tools/get_ticker.ts +132 -0
  91. package/tools/get_tickers_jpy.ts +240 -0
  92. package/tools/get_transactions.ts +209 -0
  93. package/tools/get_volatility_metrics.ts +302 -0
  94. package/tools/patterns/aftermath.ts +212 -0
  95. package/tools/patterns/config.ts +151 -0
  96. package/tools/patterns/detect_doubles.ts +650 -0
  97. package/tools/patterns/detect_hs.ts +635 -0
  98. package/tools/patterns/detect_pennants.ts +373 -0
  99. package/tools/patterns/detect_triangles.ts +820 -0
  100. package/tools/patterns/detect_triples.ts +633 -0
  101. package/tools/patterns/detect_wedges.ts +1072 -0
  102. package/tools/patterns/helpers.ts +517 -0
  103. package/tools/patterns/index.ts +40 -0
  104. package/tools/patterns/regression.ts +153 -0
  105. package/tools/patterns/smoothing.ts +168 -0
  106. package/tools/patterns/swing.ts +91 -0
  107. package/tools/patterns/types.ts +193 -0
  108. package/tools/prepare_chart_data.ts +294 -0
  109. package/tools/prepare_depth_data.ts +189 -0
  110. package/tools/private/analyze_my_portfolio.ts +21 -0
  111. package/tools/private/cancel_order.ts +127 -0
  112. package/tools/private/cancel_orders.ts +121 -0
  113. package/tools/private/create_order.ts +236 -0
  114. package/tools/private/get_margin_positions.ts +134 -0
  115. package/tools/private/get_margin_status.ts +155 -0
  116. package/tools/private/get_margin_trade_history.ts +156 -0
  117. package/tools/private/get_my_assets.ts +207 -0
  118. package/tools/private/get_my_deposit_withdrawal.ts +500 -0
  119. package/tools/private/get_my_orders.ts +157 -0
  120. package/tools/private/get_my_trade_history.ts +229 -0
  121. package/tools/private/get_order.ts +95 -0
  122. package/tools/private/get_orders_info.ts +90 -0
  123. package/tools/private/preview_cancel_order.ts +172 -0
  124. package/tools/private/preview_cancel_orders.ts +137 -0
  125. package/tools/private/preview_order.ts +292 -0
  126. package/tools/render_candle_pattern_diagram.ts +389 -0
  127. package/tools/render_chart_svg.ts +799 -0
  128. package/tools/render_depth_svg.ts +274 -0
  129. package/tools/trading_process/index.ts +7 -0
  130. package/tools/trading_process/lib/backtest_engine.ts +252 -0
  131. package/tools/trading_process/lib/equity.ts +131 -0
  132. package/tools/trading_process/lib/fetch_candles.ts +181 -0
  133. package/tools/trading_process/lib/sma.ts +62 -0
  134. package/tools/trading_process/lib/strategies/bb_breakout.ts +141 -0
  135. package/tools/trading_process/lib/strategies/index.ts +52 -0
  136. package/tools/trading_process/lib/strategies/macd_cross.ts +256 -0
  137. package/tools/trading_process/lib/strategies/rsi.ts +133 -0
  138. package/tools/trading_process/lib/strategies/sma_cross.ts +214 -0
  139. package/tools/trading_process/lib/strategies/types.ts +118 -0
  140. package/tools/trading_process/lib/svg_to_png.ts +64 -0
  141. package/tools/trading_process/render_backtest_chart_generic.ts +729 -0
  142. package/tools/trading_process/run_backtest.ts +243 -0
  143. package/tools/trading_process/types.ts +85 -0
  144. package/tools/validate_candle_data.ts +260 -0
  145. package/tsconfig.json +17 -0
  146. package/ui/cancel-confirm/dist/cancel-confirm.html +99 -0
  147. package/ui/order-confirm/dist/order-confirm.html +99 -0
@@ -0,0 +1,399 @@
1
+ import { z } from 'zod';
2
+ import { CandleSchema, CandleTypeEnum, NumericSeriesSchema } from './base.js';
3
+
4
+ // ChartIndicators shape
5
+ export const IchimokuSeriesSchema = z.object({
6
+ ICHI_tenkan: NumericSeriesSchema,
7
+ ICHI_kijun: NumericSeriesSchema,
8
+ ICHI_spanA: NumericSeriesSchema,
9
+ ICHI_spanB: NumericSeriesSchema,
10
+ ICHI_chikou: NumericSeriesSchema,
11
+ });
12
+
13
+ export const BollingerBandsSeriesSchema = z.object({
14
+ BB_upper: NumericSeriesSchema,
15
+ BB_middle: NumericSeriesSchema,
16
+ BB_lower: NumericSeriesSchema,
17
+ BB1_upper: NumericSeriesSchema,
18
+ BB1_middle: NumericSeriesSchema,
19
+ BB1_lower: NumericSeriesSchema,
20
+ BB2_upper: NumericSeriesSchema,
21
+ BB2_middle: NumericSeriesSchema,
22
+ BB2_lower: NumericSeriesSchema,
23
+ BB3_upper: NumericSeriesSchema,
24
+ BB3_middle: NumericSeriesSchema,
25
+ BB3_lower: NumericSeriesSchema,
26
+ });
27
+
28
+ export const SmaSeriesFixedSchema = z.object({
29
+ SMA_5: NumericSeriesSchema,
30
+ SMA_20: NumericSeriesSchema,
31
+ SMA_25: NumericSeriesSchema,
32
+ SMA_50: NumericSeriesSchema,
33
+ SMA_75: NumericSeriesSchema,
34
+ SMA_200: NumericSeriesSchema,
35
+ });
36
+
37
+ export const EmaSeriesFixedSchema = z.object({
38
+ EMA_12: NumericSeriesSchema,
39
+ EMA_26: NumericSeriesSchema,
40
+ EMA_50: NumericSeriesSchema,
41
+ EMA_200: NumericSeriesSchema,
42
+ });
43
+
44
+ export const ChartIndicatorsSchema = IchimokuSeriesSchema.merge(BollingerBandsSeriesSchema)
45
+ .merge(SmaSeriesFixedSchema)
46
+ .merge(EmaSeriesFixedSchema)
47
+ .extend({
48
+ RSI_14: z.number().nullable().optional(),
49
+ RSI_14_series: NumericSeriesSchema.optional(),
50
+ macd_series: z
51
+ .object({
52
+ line: NumericSeriesSchema,
53
+ signal: NumericSeriesSchema,
54
+ hist: NumericSeriesSchema,
55
+ })
56
+ .optional(),
57
+ stoch_k_series: NumericSeriesSchema.optional(),
58
+ stoch_d_series: NumericSeriesSchema.optional(),
59
+ });
60
+
61
+ export const ChartMetaSchema = z.object({
62
+ pastBuffer: z.number().optional(),
63
+ shift: z.number().optional(),
64
+ });
65
+
66
+ export const ChartStatsSchema = z.object({
67
+ min: z.number(),
68
+ max: z.number(),
69
+ avg: z.number(),
70
+ volume_avg: z.number(),
71
+ });
72
+
73
+ export const ChartPayloadSchema = z
74
+ .object({
75
+ candles: z.array(CandleSchema),
76
+ indicators: ChartIndicatorsSchema,
77
+ meta: ChartMetaSchema.optional(),
78
+ stats: ChartStatsSchema.optional(),
79
+ })
80
+ .superRefine((val, ctx) => {
81
+ const len = val.candles.length;
82
+ const seriesKeys = [
83
+ 'SMA_5',
84
+ 'SMA_20',
85
+ 'SMA_25',
86
+ 'SMA_50',
87
+ 'SMA_75',
88
+ 'SMA_200',
89
+ 'EMA_12',
90
+ 'EMA_26',
91
+ 'EMA_50',
92
+ 'EMA_200',
93
+ 'BB_upper',
94
+ 'BB_middle',
95
+ 'BB_lower',
96
+ 'BB1_upper',
97
+ 'BB1_middle',
98
+ 'BB1_lower',
99
+ 'BB2_upper',
100
+ 'BB2_middle',
101
+ 'BB2_lower',
102
+ 'BB3_upper',
103
+ 'BB3_middle',
104
+ 'BB3_lower',
105
+ 'ICHI_tenkan',
106
+ 'ICHI_kijun',
107
+ 'ICHI_spanA',
108
+ 'ICHI_spanB',
109
+ 'ICHI_chikou',
110
+ ];
111
+ for (const key of seriesKeys) {
112
+ const indicators = val.indicators as Record<string, unknown>;
113
+ const arr = indicators[key];
114
+ if (!Array.isArray(arr) || arr.length !== len) {
115
+ ctx.addIssue({
116
+ code: z.ZodIssueCode.custom,
117
+ message: `Indicator series '${key}' must have length ${len}`,
118
+ path: ['indicators', key],
119
+ });
120
+ }
121
+ }
122
+ });
123
+
124
+ // ── prepare_chart_data ──
125
+
126
+ /** 選択可能な指標グループ */
127
+ export const ChartIndicatorGroupEnum = z.enum([
128
+ 'SMA_5',
129
+ 'SMA_20',
130
+ 'SMA_25',
131
+ 'SMA_50',
132
+ 'SMA_75',
133
+ 'SMA_200',
134
+ 'EMA_12',
135
+ 'EMA_26',
136
+ 'EMA_50',
137
+ 'EMA_200',
138
+ 'BB',
139
+ 'ICHIMOKU',
140
+ 'RSI',
141
+ 'MACD',
142
+ 'STOCH',
143
+ ]);
144
+
145
+ export const PrepareChartDataInputSchema = z.object({
146
+ pair: z.string().optional().default('btc_jpy'),
147
+ type: CandleTypeEnum.optional().default('1day'),
148
+ limit: z.number().int().min(5).max(500).optional().default(30),
149
+ indicators: z.array(ChartIndicatorGroupEnum).optional(),
150
+ tz: z
151
+ .string()
152
+ .optional()
153
+ .default('Asia/Tokyo')
154
+ .describe(
155
+ 'タイムゾーン(デフォルト: Asia/Tokyo)。times をローカル時刻に変換し、labels(短縮表示文字列)も付加する。空文字でUTCのみ',
156
+ ),
157
+ });
158
+
159
+ /** コンパクトな数値配列(null 許容) */
160
+ const CompactSeriesSchema = z.array(z.union([z.number(), z.null()]));
161
+
162
+ /** MACD サブパネル(コンパクト形式) */
163
+ const CompactMacdSubPanelSchema = z.object({
164
+ line: CompactSeriesSchema,
165
+ signal: CompactSeriesSchema,
166
+ hist: CompactSeriesSchema,
167
+ });
168
+
169
+ export const PrepareChartDataOutputSchema = z.object({
170
+ ok: z.literal(true),
171
+ summary: z.string(),
172
+ data: z.object({
173
+ /** 共有タイムスタンプ配列 */
174
+ times: z.array(z.string()),
175
+ /** 表示用短縮ラベル(tz 指定時のみ)。例: ["17:00", "18:00", ...] or ["03/16 17:00", ...] */
176
+ labels: z.array(z.string()).optional(),
177
+ /** candles 配列の各要素の意味: ["open","high","low","close","volume"] */
178
+ candleFormat: z.array(z.string()),
179
+ /** OHLCV タプル配列: [[open, high, low, close, volume], ...] */
180
+ candles: z.array(z.array(z.number())),
181
+ /** メインパネル指標(indicators 指定時のみ) */
182
+ series: z.record(z.string(), CompactSeriesSchema).optional(),
183
+ /** サブパネル指標(indicators 指定時のみ) */
184
+ subPanels: z
185
+ .object({
186
+ RSI_14: CompactSeriesSchema.optional(),
187
+ MACD: CompactMacdSubPanelSchema.optional(),
188
+ STOCH_K: CompactSeriesSchema.optional(),
189
+ STOCH_D: CompactSeriesSchema.optional(),
190
+ })
191
+ .optional(),
192
+ }),
193
+ meta: z.object({
194
+ pair: z.string(),
195
+ type: CandleTypeEnum,
196
+ count: z.number(),
197
+ indicators: z.array(z.string()),
198
+ /** 出来高の単位(ペアのベース通貨。例: btc_jpy → "BTC") */
199
+ volumeUnit: z.string(),
200
+ }),
201
+ });
202
+
203
+ // ── prepare_depth_data ──
204
+
205
+ export const PrepareDepthDataInputSchema = z.object({
206
+ pair: z.string().optional().default('btc_jpy'),
207
+ levels: z
208
+ .number()
209
+ .int()
210
+ .min(10)
211
+ .max(1000)
212
+ .optional()
213
+ .default(200)
214
+ .describe('取得する最大レベル数(片側)。10〜1000 の整数、デフォルト 200'),
215
+ bandPct: z
216
+ .number()
217
+ .positive()
218
+ .max(1)
219
+ .optional()
220
+ .default(0.01)
221
+ .describe('mid を中心とした ±range 比率。0.01 = ±1%。デフォルト 0.01'),
222
+ });
223
+
224
+ /** [price, cumulativeVolume] のタプル */
225
+ const DepthStepTupleSchema = z.tuple([z.number(), z.number()]);
226
+
227
+ export const PrepareDepthDataOutputSchema = z.object({
228
+ ok: z.literal(true),
229
+ summary: z.string(),
230
+ data: z.object({
231
+ bids: z.array(DepthStepTupleSchema),
232
+ asks: z.array(DepthStepTupleSchema),
233
+ bestBid: z.number().nullable(),
234
+ bestAsk: z.number().nullable(),
235
+ mid: z.number().nullable(),
236
+ spread: z.number().nullable(),
237
+ spreadPct: z.number().nullable(),
238
+ totalBidVolume: z.number(),
239
+ totalAskVolume: z.number(),
240
+ band: z.object({
241
+ pct: z.number(),
242
+ bidVolume: z.number(),
243
+ askVolume: z.number(),
244
+ ratio: z.number().nullable(),
245
+ }),
246
+ timestamp: z.number(),
247
+ isoTime: z.string().nullable(),
248
+ }),
249
+ meta: z.object({
250
+ pair: z.string(),
251
+ fetchedAt: z.string(),
252
+ levels: z.object({ bids: z.number().int(), asks: z.number().int() }),
253
+ volumeUnit: z.string(),
254
+ }),
255
+ });
256
+
257
+ /** render_chart_svg で使用可能なインジケーター */
258
+ export const RenderChartSvgIndicatorEnum = z.enum([
259
+ 'SMA_5',
260
+ 'SMA_20',
261
+ 'SMA_25',
262
+ 'SMA_50',
263
+ 'SMA_75',
264
+ 'SMA_200',
265
+ 'EMA_12',
266
+ 'EMA_26',
267
+ 'EMA_50',
268
+ 'EMA_200',
269
+ 'BB',
270
+ 'BB_EXTENDED',
271
+ 'ICHIMOKU',
272
+ 'ICHIMOKU_EXTENDED',
273
+ ]);
274
+
275
+ export const RenderChartSvgInputSchema = z
276
+ .object({
277
+ pair: z.string().optional().default('btc_jpy'),
278
+ type: CandleTypeEnum.optional().default('1day'),
279
+ // impl default is 60; align contract to tool behavior
280
+ limit: z.number().int().min(5).max(365).optional().default(60),
281
+ // main series style: candles (default) or line (close-only)
282
+ style: z.enum(['candles', 'line', 'depth']).optional().default('candles'),
283
+ depth: z.object({ levels: z.number().int().min(10).max(500).optional().default(200) }).optional(),
284
+ // ── 統一インジケーター指定(推奨) ──
285
+ indicators: z
286
+ .array(RenderChartSvgIndicatorEnum)
287
+ .optional()
288
+ .default([])
289
+ .describe(
290
+ 'Indicators to overlay. Do NOT set unless the user explicitly requests them. Default: [] (none).\n' +
291
+ 'Available: SMA_5, SMA_20, SMA_25, SMA_50, SMA_75, SMA_200, EMA_12, EMA_26, EMA_50, EMA_200, BB, BB_EXTENDED, ICHIMOKU, ICHIMOKU_EXTENDED',
292
+ ),
293
+ // ── 後方互換(deprecated: 新規利用は indicators を使用) ──
294
+ withSMA: z.array(z.number().int()).optional().default([]),
295
+ withEMA: z.array(z.number().int()).optional().default([]),
296
+ withBB: z.boolean().optional().default(false),
297
+ bbMode: z.enum(['default', 'extended', 'light', 'full']).optional().default('default'),
298
+ withIchimoku: z.boolean().optional().default(false),
299
+ ichimoku: z
300
+ .object({
301
+ mode: z.enum(['default', 'extended']).optional().default('default'),
302
+ withChikou: z.boolean().optional(),
303
+ })
304
+ .optional(),
305
+ // 軽量化のため凡例は既定でオフ
306
+ withLegend: z.boolean().optional().default(false),
307
+ // 軽量化オプション
308
+ svgPrecision: z.number().int().min(0).max(3).optional().default(1).describe('Coordinate rounding decimals (0-3).'),
309
+ svgMinify: z.boolean().optional().default(true).describe('Minify SVG text by stripping whitespace where safe.'),
310
+ simplifyTolerance: z
311
+ .number()
312
+ .min(0)
313
+ .optional()
314
+ .default(0.5)
315
+ .describe('Line simplification tolerance in pixels (0 disables).'),
316
+ viewBoxTight: z.boolean().optional().default(true).describe('Use tighter paddings to reduce empty margins.'),
317
+ barWidthRatio: z.number().min(0.1).max(0.9).optional().describe('Width ratio of each candle body (slot fraction).'),
318
+ yPaddingPct: z.number().min(0).max(0.2).optional().describe('Vertical padding ratio to expand y-range.'),
319
+ // サブパネル(価格パネルの下に独立Y軸で描画)
320
+ subPanels: z
321
+ .array(z.enum(['macd', 'rsi', 'volume']))
322
+ .optional()
323
+ .default([])
324
+ .describe('サブパネル: macd(MACD線+シグナル+ヒストグラム), rsi(RSI 14 + 70/30ゾーン), volume(出来高バー)'),
325
+ // X軸ラベルのタイムゾーン
326
+ tz: z.string().optional().default('Asia/Tokyo').describe('X軸ラベルのタイムゾーン(例: Asia/Tokyo, UTC)'),
327
+ // Optional pattern overlays (ranges/annotations)
328
+ overlays: z
329
+ .object({
330
+ ranges: z
331
+ .array(
332
+ z.object({
333
+ start: z.string(),
334
+ end: z.string(),
335
+ color: z.string().optional(),
336
+ label: z.string().optional(),
337
+ }),
338
+ )
339
+ .optional(),
340
+ annotations: z.array(z.object({ isoTime: z.string(), text: z.string() })).optional(),
341
+ depth_zones: z
342
+ .array(
343
+ z.object({ low: z.number(), high: z.number(), color: z.string().optional(), label: z.string().optional() }),
344
+ )
345
+ .optional(),
346
+ })
347
+ .optional(),
348
+ })
349
+ .superRefine((val, ctx) => {
350
+ // indicators 配列から一目均衡表の有無を判定
351
+ const hasIchimokuViaIndicators =
352
+ val.indicators?.includes('ICHIMOKU') || val.indicators?.includes('ICHIMOKU_EXTENDED');
353
+ const hasIchimoku = val.withIchimoku || hasIchimokuViaIndicators;
354
+ const hasBBViaIndicators = val.indicators?.includes('BB') || val.indicators?.includes('BB_EXTENDED');
355
+ const hasSMAViaIndicators = val.indicators?.some((i: string) => i.startsWith('SMA_'));
356
+
357
+ if (hasIchimoku) {
358
+ if ((Array.isArray(val.withSMA) && val.withSMA.length > 0) || hasSMAViaIndicators) {
359
+ ctx.addIssue({
360
+ code: z.ZodIssueCode.custom,
361
+ path: ['indicators'],
362
+ message: 'ICHIMOKU と SMA は同時に指定できません',
363
+ });
364
+ }
365
+ if (val.withBB === true || hasBBViaIndicators) {
366
+ ctx.addIssue({
367
+ code: z.ZodIssueCode.custom,
368
+ path: ['indicators'],
369
+ message: 'ICHIMOKU と BB は同時に指定できません',
370
+ });
371
+ }
372
+ }
373
+ });
374
+
375
+ // Optional: output contract (not enforced by SDK at runtime, but useful for validation/tests)
376
+ export const RenderChartSvgOutputSchema = z.object({
377
+ ok: z.literal(true).or(z.literal(false)),
378
+ summary: z.string(),
379
+ data: z
380
+ .object({
381
+ svg: z.string().optional(),
382
+ legend: z.record(z.string(), z.string()).optional(),
383
+ })
384
+ .or(z.object({})),
385
+ meta: z
386
+ .object({
387
+ pair: z.string(),
388
+ type: CandleTypeEnum,
389
+ limit: z.number().optional(),
390
+ indicators: z.array(z.string()).optional(),
391
+ bbMode: z.enum(['default', 'extended']).optional(),
392
+ range: z.object({ start: z.string(), end: z.string() }).optional(),
393
+ sizeBytes: z.number().optional(),
394
+ layerCount: z.number().optional(),
395
+ fallback: z.string().optional(),
396
+ warnings: z.array(z.string()).optional(),
397
+ })
398
+ .optional(),
399
+ });
@@ -0,0 +1,11 @@
1
+ // Barrel re-export — all domain schema modules
2
+
3
+ export * from './analysis.js';
4
+ export * from './backtest.js';
5
+ export * from './base.js';
6
+ export * from './candle-validate.js';
7
+ export * from './chart.js';
8
+ export * from './indicators.js';
9
+ export * from './market-data.js';
10
+ export * from './patterns.js';
11
+ export * from './types.js';
@@ -0,0 +1,125 @@
1
+ import { z } from 'zod';
2
+ import {
3
+ BaseMetaSchema,
4
+ BasePairInputSchema,
5
+ CandleSchema,
6
+ CandleTypeEnum,
7
+ NumericSeriesSchema,
8
+ TrendLabelEnum,
9
+ toolResultSchema,
10
+ } from './base.js';
11
+ import { ChartIndicatorsSchema, ChartMetaSchema, ChartStatsSchema } from './chart.js';
12
+
13
+ export const IndicatorsInternalSchema = z.object({
14
+ SMA_5: z.number().nullable().optional(),
15
+ SMA_20: z.number().nullable().optional(),
16
+ SMA_25: z.number().nullable().optional(),
17
+ SMA_50: z.number().nullable().optional(),
18
+ SMA_75: z.number().nullable().optional(),
19
+ SMA_200: z.number().nullable().optional(),
20
+ RSI_14: z.number().nullable().optional(),
21
+ RSI_14_series: NumericSeriesSchema.optional(),
22
+ BB_upper: z.number().nullable().optional(),
23
+ BB_middle: z.number().nullable().optional(),
24
+ BB_lower: z.number().nullable().optional(),
25
+ BB1_upper: z.number().nullable().optional(),
26
+ BB1_middle: z.number().nullable().optional(),
27
+ BB1_lower: z.number().nullable().optional(),
28
+ BB2_upper: z.number().nullable().optional(),
29
+ BB2_middle: z.number().nullable().optional(),
30
+ BB2_lower: z.number().nullable().optional(),
31
+ BB3_upper: z.number().nullable().optional(),
32
+ BB3_middle: z.number().nullable().optional(),
33
+ BB3_lower: z.number().nullable().optional(),
34
+ ICHIMOKU_conversion: z.number().nullable().optional(),
35
+ ICHIMOKU_base: z.number().nullable().optional(),
36
+ ICHIMOKU_spanA: z.number().nullable().optional(),
37
+ ICHIMOKU_spanB: z.number().nullable().optional(),
38
+ bb1_series: z
39
+ .object({ upper: NumericSeriesSchema, middle: NumericSeriesSchema, lower: NumericSeriesSchema })
40
+ .optional(),
41
+ bb2_series: z
42
+ .object({ upper: NumericSeriesSchema, middle: NumericSeriesSchema, lower: NumericSeriesSchema })
43
+ .optional(),
44
+ bb3_series: z
45
+ .object({ upper: NumericSeriesSchema, middle: NumericSeriesSchema, lower: NumericSeriesSchema })
46
+ .optional(),
47
+ ichi_series: z
48
+ .object({
49
+ tenkan: NumericSeriesSchema,
50
+ kijun: NumericSeriesSchema,
51
+ spanA: NumericSeriesSchema,
52
+ spanB: NumericSeriesSchema,
53
+ chikou: NumericSeriesSchema,
54
+ })
55
+ .optional(),
56
+ sma_5_series: NumericSeriesSchema.optional(),
57
+ sma_20_series: NumericSeriesSchema.optional(),
58
+ sma_25_series: NumericSeriesSchema.optional(),
59
+ sma_50_series: NumericSeriesSchema.optional(),
60
+ sma_75_series: NumericSeriesSchema.optional(),
61
+ sma_200_series: NumericSeriesSchema.optional(),
62
+ // EMA latest values
63
+ EMA_12: z.number().nullable().optional(),
64
+ EMA_26: z.number().nullable().optional(),
65
+ EMA_50: z.number().nullable().optional(),
66
+ EMA_200: z.number().nullable().optional(),
67
+ // EMA series
68
+ ema_12_series: NumericSeriesSchema.optional(),
69
+ ema_26_series: NumericSeriesSchema.optional(),
70
+ ema_50_series: NumericSeriesSchema.optional(),
71
+ ema_200_series: NumericSeriesSchema.optional(),
72
+ // MACD latest values
73
+ MACD_line: z.number().nullable().optional(),
74
+ MACD_signal: z.number().nullable().optional(),
75
+ MACD_hist: z.number().nullable().optional(),
76
+ // series (optional)
77
+ macd_series: z
78
+ .object({ line: NumericSeriesSchema, signal: NumericSeriesSchema, hist: NumericSeriesSchema })
79
+ .optional(),
80
+ // Classic Stochastic Oscillator
81
+ STOCH_K: z.number().nullable().optional(),
82
+ STOCH_D: z.number().nullable().optional(),
83
+ STOCH_prevK: z.number().nullable().optional(),
84
+ STOCH_prevD: z.number().nullable().optional(),
85
+ stoch_k_series: NumericSeriesSchema.optional(),
86
+ stoch_d_series: NumericSeriesSchema.optional(),
87
+ // Stochastic RSI
88
+ STOCH_RSI_K: z.number().nullable().optional(),
89
+ STOCH_RSI_D: z.number().nullable().optional(),
90
+ STOCH_RSI_prevK: z.number().nullable().optional(),
91
+ STOCH_RSI_prevD: z.number().nullable().optional(),
92
+ // OBV (On-Balance Volume)
93
+ OBV: z.number().nullable().optional(),
94
+ OBV_SMA20: z.number().nullable().optional(),
95
+ OBV_prevObv: z.number().nullable().optional(),
96
+ OBV_trend: z.enum(['rising', 'falling', 'flat']).nullable().optional(),
97
+ });
98
+
99
+ export const GetIndicatorsDataSchema = z.object({
100
+ summary: z.string(),
101
+ raw: z.unknown(),
102
+ normalized: z.array(CandleSchema),
103
+ indicators: IndicatorsInternalSchema,
104
+ trend: TrendLabelEnum,
105
+ chart: z.object({
106
+ candles: z.array(CandleSchema),
107
+ indicators: ChartIndicatorsSchema,
108
+ meta: ChartMetaSchema,
109
+ stats: ChartStatsSchema,
110
+ }),
111
+ });
112
+
113
+ export const GetIndicatorsMetaSchema = BaseMetaSchema.extend({
114
+ type: CandleTypeEnum,
115
+ count: z.number(),
116
+ requiredCount: z.number(),
117
+ warnings: z.array(z.string()).optional(),
118
+ });
119
+
120
+ export const GetIndicatorsInputSchema = BasePairInputSchema.extend({
121
+ type: CandleTypeEnum.optional().default('1day'),
122
+ limit: z.number().int().min(1).max(1000).optional(),
123
+ });
124
+
125
+ export const GetIndicatorsOutputSchema = toolResultSchema(GetIndicatorsDataSchema, GetIndicatorsMetaSchema);