@qtsurfer/api-client 0.7.0 → 0.8.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.
@@ -1,21 +1,82 @@
1
1
  // This file is auto-generated by @hey-api/openapi-ts
2
2
 
3
- import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
4
- import type { AuthenticateData, AuthenticateResponse, AuthenticateError, ListExchangesData, ListExchangesResponse, ListInstrumentsData, ListInstrumentsResponse, ListInstrumentsError, ListSegmentInstrumentsData, ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, DownloadTickersData, DownloadTickersResponse, DownloadTickersError, DownloadKlinesData, DownloadKlinesResponse, DownloadKlinesError, CompileStrategyData, CompileStrategyResponse, CompileStrategyError, ValidateStrategyData, ValidateStrategyResponse, ValidateStrategyError, GetStrategyData, GetStrategyResponse, GetStrategyError, PrepareBacktestData, PrepareBacktestResponse, PrepareBacktestError, GetPrepareStatusData, GetPrepareStatusResponse, GetPrepareStatusError, ExecuteSweepData, ExecuteSweepResponse, ExecuteSweepError, CancelSweepData, CancelSweepResponse, CancelSweepError, GetSweepResultData, GetSweepResultResponse, GetSweepResultError, ExecuteBacktestData, ExecuteBacktestResponse, ExecuteBacktestError, CancelBacktestData, CancelBacktestResponse, CancelBacktestError, GetBacktestResultData, GetBacktestResultResponse, GetBacktestResultError } from './types.gen';
5
- import { client as _heyApiClient } from './client.gen';
3
+ import type {
4
+ Options as ClientOptions,
5
+ TDataShape,
6
+ Client,
7
+ } from "@hey-api/client-fetch";
8
+ import type {
9
+ AuthenticateData,
10
+ AuthenticateResponse,
11
+ AuthenticateError,
12
+ ListExchangesData,
13
+ ListExchangesResponse,
14
+ ListInstrumentsData,
15
+ ListInstrumentsResponse,
16
+ ListInstrumentsError,
17
+ ListSegmentInstrumentsData,
18
+ ListSegmentInstrumentsResponse,
19
+ ListSegmentInstrumentsError,
20
+ DownloadTickersData,
21
+ DownloadTickersResponse,
22
+ DownloadTickersError,
23
+ DownloadKlinesData,
24
+ DownloadKlinesResponse,
25
+ DownloadKlinesError,
26
+ CompileStrategyData,
27
+ CompileStrategyResponse,
28
+ CompileStrategyError,
29
+ ValidateStrategyData,
30
+ ValidateStrategyResponse,
31
+ ValidateStrategyError,
32
+ GetStrategyData,
33
+ GetStrategyResponse,
34
+ GetStrategyError,
35
+ PrepareBacktestData,
36
+ PrepareBacktestResponse,
37
+ PrepareBacktestError,
38
+ GetPrepareStatusData,
39
+ GetPrepareStatusResponse,
40
+ GetPrepareStatusError,
41
+ ExecuteSweepData,
42
+ ExecuteSweepResponse,
43
+ ExecuteSweepError,
44
+ CancelSweepData,
45
+ CancelSweepResponse,
46
+ CancelSweepError,
47
+ GetSweepResultData,
48
+ GetSweepResultResponse,
49
+ GetSweepResultError,
50
+ GetSweepSensitivityData,
51
+ GetSweepSensitivityResponse,
52
+ GetSweepSensitivityError,
53
+ ExecuteBacktestData,
54
+ ExecuteBacktestResponse,
55
+ ExecuteBacktestError,
56
+ CancelBacktestData,
57
+ CancelBacktestResponse,
58
+ CancelBacktestError,
59
+ GetBacktestResultData,
60
+ GetBacktestResultResponse,
61
+ GetBacktestResultError,
62
+ } from "./types.gen";
63
+ import { client as _heyApiClient } from "./client.gen";
6
64
 
7
- export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
8
- /**
9
- * You can provide a client instance returned by `createClient()` instead of
10
- * individual options. This might be also useful if you want to implement a
11
- * custom client.
12
- */
13
- client?: Client;
14
- /**
15
- * You can pass arbitrary values through the `meta` object. This can be
16
- * used to access values that aren't defined as part of the SDK function.
17
- */
18
- meta?: Record<string, unknown>;
65
+ export type Options<
66
+ TData extends TDataShape = TDataShape,
67
+ ThrowOnError extends boolean = boolean
68
+ > = ClientOptions<TData, ThrowOnError> & {
69
+ /**
70
+ * You can provide a client instance returned by `createClient()` instead of
71
+ * individual options. This might be also useful if you want to implement a
72
+ * custom client.
73
+ */
74
+ client?: Client;
75
+ /**
76
+ * You can pass arbitrary values through the `meta` object. This can be
77
+ * used to access values that aren't defined as part of the SDK function.
78
+ */
79
+ meta?: Record<string, unknown>;
19
80
  };
20
81
 
21
82
  /**
@@ -30,27 +91,39 @@ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends
30
91
  * before expiry (or on a `401` response) by calling this endpoint again.
31
92
  *
32
93
  */
33
- export const authenticate = <ThrowOnError extends boolean = false>(options?: Options<AuthenticateData, ThrowOnError>) => {
34
- return (options?.client ?? _heyApiClient).post<AuthenticateResponse, AuthenticateError, ThrowOnError>({
35
- security: [
36
- {
37
- name: 'X-API-Key',
38
- type: 'apiKey'
39
- }
40
- ],
41
- url: '/auth/token',
42
- ...options
43
- });
94
+ export const authenticate = <ThrowOnError extends boolean = false>(
95
+ options?: Options<AuthenticateData, ThrowOnError>
96
+ ) => {
97
+ return (options?.client ?? _heyApiClient).post<
98
+ AuthenticateResponse,
99
+ AuthenticateError,
100
+ ThrowOnError
101
+ >({
102
+ security: [
103
+ {
104
+ name: "X-API-Key",
105
+ type: "apiKey",
106
+ },
107
+ ],
108
+ url: "/auth/token",
109
+ ...options,
110
+ });
44
111
  };
45
112
 
46
113
  /**
47
114
  * List the available exchanges
48
115
  */
49
- export const listExchanges = <ThrowOnError extends boolean = false>(options?: Options<ListExchangesData, ThrowOnError>) => {
50
- return (options?.client ?? _heyApiClient).get<ListExchangesResponse, unknown, ThrowOnError>({
51
- url: '/exchanges',
52
- ...options
53
- });
116
+ export const listExchanges = <ThrowOnError extends boolean = false>(
117
+ options?: Options<ListExchangesData, ThrowOnError>
118
+ ) => {
119
+ return (options?.client ?? _heyApiClient).get<
120
+ ListExchangesResponse,
121
+ unknown,
122
+ ThrowOnError
123
+ >({
124
+ url: "/exchanges",
125
+ ...options,
126
+ });
54
127
  };
55
128
 
56
129
  /**
@@ -61,11 +134,17 @@ export const listExchanges = <ThrowOnError extends boolean = false>(options?: Op
61
134
  * `spot` / `futures` segment-discovery links.
62
135
  *
63
136
  */
64
- export const listInstruments = <ThrowOnError extends boolean = false>(options: Options<ListInstrumentsData, ThrowOnError>) => {
65
- return (options.client ?? _heyApiClient).get<ListInstrumentsResponse, ListInstrumentsError, ThrowOnError>({
66
- url: '/exchange/{exchangeId}/instruments',
67
- ...options
68
- });
137
+ export const listInstruments = <ThrowOnError extends boolean = false>(
138
+ options: Options<ListInstrumentsData, ThrowOnError>
139
+ ) => {
140
+ return (options.client ?? _heyApiClient).get<
141
+ ListInstrumentsResponse,
142
+ ListInstrumentsError,
143
+ ThrowOnError
144
+ >({
145
+ url: "/exchange/{exchangeId}/instruments",
146
+ ...options,
147
+ });
69
148
  };
70
149
 
71
150
  /**
@@ -76,11 +155,17 @@ export const listInstruments = <ThrowOnError extends boolean = false>(options: O
76
155
  * `GET /exchange/{exchangeId}/instruments` (spot).
77
156
  *
78
157
  */
79
- export const listSegmentInstruments = <ThrowOnError extends boolean = false>(options: Options<ListSegmentInstrumentsData, ThrowOnError>) => {
80
- return (options.client ?? _heyApiClient).get<ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, ThrowOnError>({
81
- url: '/exchange/{exchangeId}/{segment}/instruments',
82
- ...options
83
- });
158
+ export const listSegmentInstruments = <ThrowOnError extends boolean = false>(
159
+ options: Options<ListSegmentInstrumentsData, ThrowOnError>
160
+ ) => {
161
+ return (options.client ?? _heyApiClient).get<
162
+ ListSegmentInstrumentsResponse,
163
+ ListSegmentInstrumentsError,
164
+ ThrowOnError
165
+ >({
166
+ url: "/exchange/{exchangeId}/{segment}/instruments",
167
+ ...options,
168
+ });
84
169
  };
85
170
 
86
171
  /**
@@ -115,11 +200,17 @@ export const listSegmentInstruments = <ThrowOnError extends boolean = false>(opt
115
200
  * descriptive filename).
116
201
  *
117
202
  */
118
- export const downloadTickers = <ThrowOnError extends boolean = false>(options: Options<DownloadTickersData, ThrowOnError>) => {
119
- return (options.client ?? _heyApiClient).get<DownloadTickersResponse, DownloadTickersError, ThrowOnError>({
120
- url: '/exchange/{exchangeId}/tickers/{base}/{quote}',
121
- ...options
122
- });
203
+ export const downloadTickers = <ThrowOnError extends boolean = false>(
204
+ options: Options<DownloadTickersData, ThrowOnError>
205
+ ) => {
206
+ return (options.client ?? _heyApiClient).get<
207
+ DownloadTickersResponse,
208
+ DownloadTickersError,
209
+ ThrowOnError
210
+ >({
211
+ url: "/exchange/{exchangeId}/tickers/{base}/{quote}",
212
+ ...options,
213
+ });
123
214
  };
124
215
 
125
216
  /**
@@ -134,11 +225,17 @@ export const downloadTickers = <ThrowOnError extends boolean = false>(options: O
134
225
  * per-tick payload would be too large for the window of interest.
135
226
  *
136
227
  */
137
- export const downloadKlines = <ThrowOnError extends boolean = false>(options: Options<DownloadKlinesData, ThrowOnError>) => {
138
- return (options.client ?? _heyApiClient).get<DownloadKlinesResponse, DownloadKlinesError, ThrowOnError>({
139
- url: '/exchange/{exchangeId}/klines/{base}/{quote}',
140
- ...options
141
- });
228
+ export const downloadKlines = <ThrowOnError extends boolean = false>(
229
+ options: Options<DownloadKlinesData, ThrowOnError>
230
+ ) => {
231
+ return (options.client ?? _heyApiClient).get<
232
+ DownloadKlinesResponse,
233
+ DownloadKlinesError,
234
+ ThrowOnError
235
+ >({
236
+ url: "/exchange/{exchangeId}/klines/{base}/{quote}",
237
+ ...options,
238
+ });
142
239
  };
143
240
 
144
241
  /**
@@ -166,22 +263,28 @@ export const downloadKlines = <ThrowOnError extends boolean = false>(options: Op
166
263
  * equivalence.
167
264
  *
168
265
  */
169
- export const compileStrategy = <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => {
170
- return (options.client ?? _heyApiClient).post<CompileStrategyResponse, CompileStrategyError, ThrowOnError>({
171
- bodySerializer: null,
172
- security: [
173
- {
174
- scheme: 'bearer',
175
- type: 'http'
176
- }
177
- ],
178
- url: '/strategy',
179
- ...options,
180
- headers: {
181
- 'Content-Type': 'text/plain',
182
- ...options?.headers
183
- }
184
- });
266
+ export const compileStrategy = <ThrowOnError extends boolean = false>(
267
+ options: Options<CompileStrategyData, ThrowOnError>
268
+ ) => {
269
+ return (options.client ?? _heyApiClient).post<
270
+ CompileStrategyResponse,
271
+ CompileStrategyError,
272
+ ThrowOnError
273
+ >({
274
+ bodySerializer: null,
275
+ security: [
276
+ {
277
+ scheme: "bearer",
278
+ type: "http",
279
+ },
280
+ ],
281
+ url: "/strategy",
282
+ ...options,
283
+ headers: {
284
+ "Content-Type": "text/plain",
285
+ ...options?.headers,
286
+ },
287
+ });
185
288
  };
186
289
 
187
290
  /**
@@ -198,17 +301,23 @@ export const compileStrategy = <ThrowOnError extends boolean = false>(options: O
198
301
  * bytecode that is no longer what would run.
199
302
  *
200
303
  */
201
- export const validateStrategy = <ThrowOnError extends boolean = false>(options: Options<ValidateStrategyData, ThrowOnError>) => {
202
- return (options.client ?? _heyApiClient).post<ValidateStrategyResponse, ValidateStrategyError, ThrowOnError>({
203
- security: [
204
- {
205
- scheme: 'bearer',
206
- type: 'http'
207
- }
208
- ],
209
- url: '/strategy/{strategyId}/validate',
210
- ...options
211
- });
304
+ export const validateStrategy = <ThrowOnError extends boolean = false>(
305
+ options: Options<ValidateStrategyData, ThrowOnError>
306
+ ) => {
307
+ return (options.client ?? _heyApiClient).post<
308
+ ValidateStrategyResponse,
309
+ ValidateStrategyError,
310
+ ThrowOnError
311
+ >({
312
+ security: [
313
+ {
314
+ scheme: "bearer",
315
+ type: "http",
316
+ },
317
+ ],
318
+ url: "/strategy/{strategyId}/validate",
319
+ ...options,
320
+ });
212
321
  };
213
322
 
214
323
  /**
@@ -220,17 +329,23 @@ export const validateStrategy = <ThrowOnError extends boolean = false>(options:
220
329
  * expired answer; registration and verdict are stored durably, not cached.
221
330
  *
222
331
  */
223
- export const getStrategy = <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => {
224
- return (options.client ?? _heyApiClient).get<GetStrategyResponse, GetStrategyError, ThrowOnError>({
225
- security: [
226
- {
227
- scheme: 'bearer',
228
- type: 'http'
229
- }
230
- ],
231
- url: '/strategy/{strategyId}',
232
- ...options
233
- });
332
+ export const getStrategy = <ThrowOnError extends boolean = false>(
333
+ options: Options<GetStrategyData, ThrowOnError>
334
+ ) => {
335
+ return (options.client ?? _heyApiClient).get<
336
+ GetStrategyResponse,
337
+ GetStrategyError,
338
+ ThrowOnError
339
+ >({
340
+ security: [
341
+ {
342
+ scheme: "bearer",
343
+ type: "http",
344
+ },
345
+ ],
346
+ url: "/strategy/{strategyId}",
347
+ ...options,
348
+ });
234
349
  };
235
350
 
236
351
  /**
@@ -242,21 +357,27 @@ export const getStrategy = <ThrowOnError extends boolean = false>(options: Optio
242
357
  * params do not enqueue duplicate work — they reuse the existing job.
243
358
  *
244
359
  */
245
- export const prepareBacktest = <ThrowOnError extends boolean = false>(options: Options<PrepareBacktestData, ThrowOnError>) => {
246
- return (options.client ?? _heyApiClient).post<PrepareBacktestResponse, PrepareBacktestError, ThrowOnError>({
247
- security: [
248
- {
249
- scheme: 'bearer',
250
- type: 'http'
251
- }
252
- ],
253
- url: '/backtest/{exchangeId}/{type}/prepare',
254
- ...options,
255
- headers: {
256
- 'Content-Type': 'application/json',
257
- ...options?.headers
258
- }
259
- });
360
+ export const prepareBacktest = <ThrowOnError extends boolean = false>(
361
+ options: Options<PrepareBacktestData, ThrowOnError>
362
+ ) => {
363
+ return (options.client ?? _heyApiClient).post<
364
+ PrepareBacktestResponse,
365
+ PrepareBacktestError,
366
+ ThrowOnError
367
+ >({
368
+ security: [
369
+ {
370
+ scheme: "bearer",
371
+ type: "http",
372
+ },
373
+ ],
374
+ url: "/backtest/{exchangeId}/{type}/prepare",
375
+ ...options,
376
+ headers: {
377
+ "Content-Type": "application/json",
378
+ ...options?.headers,
379
+ },
380
+ });
260
381
  };
261
382
 
262
383
  /**
@@ -265,17 +386,23 @@ export const prepareBacktest = <ThrowOnError extends boolean = false>(options: O
265
386
  * Poll until `status` is `Completed`, `Failed`, or `Aborted`.
266
387
  *
267
388
  */
268
- export const getPrepareStatus = <ThrowOnError extends boolean = false>(options: Options<GetPrepareStatusData, ThrowOnError>) => {
269
- return (options.client ?? _heyApiClient).get<GetPrepareStatusResponse, GetPrepareStatusError, ThrowOnError>({
270
- security: [
271
- {
272
- scheme: 'bearer',
273
- type: 'http'
274
- }
275
- ],
276
- url: '/backtest/{exchangeId}/{type}/prepare/{jobId}',
277
- ...options
278
- });
389
+ export const getPrepareStatus = <ThrowOnError extends boolean = false>(
390
+ options: Options<GetPrepareStatusData, ThrowOnError>
391
+ ) => {
392
+ return (options.client ?? _heyApiClient).get<
393
+ GetPrepareStatusResponse,
394
+ GetPrepareStatusError,
395
+ ThrowOnError
396
+ >({
397
+ security: [
398
+ {
399
+ scheme: "bearer",
400
+ type: "http",
401
+ },
402
+ ],
403
+ url: "/backtest/{exchangeId}/{type}/prepare/{jobId}",
404
+ ...options,
405
+ });
279
406
  };
280
407
 
281
408
  /**
@@ -284,39 +411,62 @@ export const getPrepareStatus = <ThrowOnError extends boolean = false>(options:
284
411
  * The backend expands and executes the matrix internally; clients poll the returned
285
412
  * `sweepId` for incremental results.
286
413
  *
414
+ * Supplying `walkForward` runs the sweep in a different mode entirely. Instead of scoring
415
+ * every parameter vector once over the whole range, the data is split into F sequential
416
+ * folds; each fold optimizes the full grid on its own window and then scores only its winner
417
+ * on the window immediately after — data that winner was not chosen on. It answers a harder
418
+ * question than a leaderboard: not "which parameters won", but "does re-optimizing this
419
+ * periodically actually work". Omit the block and nothing changes, including the response.
420
+ *
421
+ * The cost is the reason it is opt-in rather than always on: F folds × N vectors, so a
422
+ * 4-fold run over a 500-point grid is 2004 backtests where the plain sweep is 500. The
423
+ * request is rejected when `folds × totalRuns` exceeds the server's sweep budget.
424
+ *
287
425
  */
288
- export const executeSweep = <ThrowOnError extends boolean = false>(options: Options<ExecuteSweepData, ThrowOnError>) => {
289
- return (options.client ?? _heyApiClient).post<ExecuteSweepResponse, ExecuteSweepError, ThrowOnError>({
290
- security: [
291
- {
292
- scheme: 'bearer',
293
- type: 'http'
294
- }
295
- ],
296
- url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}',
297
- ...options,
298
- headers: {
299
- 'Content-Type': 'application/json',
300
- ...options?.headers
301
- }
302
- });
426
+ export const executeSweep = <ThrowOnError extends boolean = false>(
427
+ options: Options<ExecuteSweepData, ThrowOnError>
428
+ ) => {
429
+ return (options.client ?? _heyApiClient).post<
430
+ ExecuteSweepResponse,
431
+ ExecuteSweepError,
432
+ ThrowOnError
433
+ >({
434
+ security: [
435
+ {
436
+ scheme: "bearer",
437
+ type: "http",
438
+ },
439
+ ],
440
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}",
441
+ ...options,
442
+ headers: {
443
+ "Content-Type": "application/json",
444
+ ...options?.headers,
445
+ },
446
+ });
303
447
  };
304
448
 
305
449
  /**
306
450
  * Cancel a running parameter sweep
307
451
  * Requests cancellation between parameter vectors. Completed rows remain readable.
308
452
  */
309
- export const cancelSweep = <ThrowOnError extends boolean = false>(options: Options<CancelSweepData, ThrowOnError>) => {
310
- return (options.client ?? _heyApiClient).delete<CancelSweepResponse, CancelSweepError, ThrowOnError>({
311
- security: [
312
- {
313
- scheme: 'bearer',
314
- type: 'http'
315
- }
316
- ],
317
- url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}',
318
- ...options
319
- });
453
+ export const cancelSweep = <ThrowOnError extends boolean = false>(
454
+ options: Options<CancelSweepData, ThrowOnError>
455
+ ) => {
456
+ return (options.client ?? _heyApiClient).delete<
457
+ CancelSweepResponse,
458
+ CancelSweepError,
459
+ ThrowOnError
460
+ >({
461
+ security: [
462
+ {
463
+ scheme: "bearer",
464
+ type: "http",
465
+ },
466
+ ],
467
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}",
468
+ ...options,
469
+ });
320
470
  };
321
471
 
322
472
  /**
@@ -325,18 +475,87 @@ export const cancelSweep = <ThrowOnError extends boolean = false>(options: Optio
325
475
  * display leaderboard. `order=natural` returns every available row, untruncated, ordered by
326
476
  * deterministic `runIx`; use that view when materialising durable trial rows.
327
477
  *
478
+ * The `ranked` view is ordered by **plateau score** by default, not by the raw objective. A
479
+ * plateau score is the objective of the worst run in a parameter point's immediate
480
+ * neighbourhood, so a point scores well only if the region around it also does — the highest
481
+ * raw score is frequently a spike that does not survive the parameters moving slightly. Pass
482
+ * `ranking=raw` for the unadjusted objective order.
483
+ *
484
+ * Rows in the `ranked` view carry `plateauScore` and `neighbourCount` when plateau ranking
485
+ * applied. Read them together: `neighbourCount: 0` means the point had no neighbours to
486
+ * compare against, so its plateau score is unevidenced rather than confirmed. Sweeps
487
+ * submitted before plateau ranking existed have no stored parameter grid to rebuild a
488
+ * neighbourhood from and are always ranked raw; the response's `ranking` field says which
489
+ * ordering was actually used.
490
+ *
491
+ * A sweep submitted with `walkForward` answers in a different shape, and the `walkForward`
492
+ * field on the response is what tells the two apart — it appears as soon as the sweep is
493
+ * accepted, before any fold has finished, so it is safe to branch on while polling. There
494
+ * the leaderboard is one row per completed fold: that fold's winner as it scored
495
+ * **out-of-sample**, with `runIx` carrying the fold index rather than a grid position. The
496
+ * in-sample runs behind those winners are not retained — they are an optimization's working
497
+ * set, and only the winner survives its fold. `ranking` is always `raw` and no plateau, DSR
498
+ * or PBO figure is reported: the out-of-sample scores are already the honest number, and
499
+ * layering a certification computed over F observations on top of them would overstate what
500
+ * was measured.
501
+ *
328
502
  */
329
- export const getSweepResult = <ThrowOnError extends boolean = false>(options: Options<GetSweepResultData, ThrowOnError>) => {
330
- return (options.client ?? _heyApiClient).get<GetSweepResultResponse, GetSweepResultError, ThrowOnError>({
331
- security: [
332
- {
333
- scheme: 'bearer',
334
- type: 'http'
335
- }
336
- ],
337
- url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}',
338
- ...options
339
- });
503
+ export const getSweepResult = <ThrowOnError extends boolean = false>(
504
+ options: Options<GetSweepResultData, ThrowOnError>
505
+ ) => {
506
+ return (options.client ?? _heyApiClient).get<
507
+ GetSweepResultResponse,
508
+ GetSweepResultError,
509
+ ThrowOnError
510
+ >({
511
+ security: [
512
+ {
513
+ scheme: "bearer",
514
+ type: "http",
515
+ },
516
+ ],
517
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}",
518
+ ...options,
519
+ });
520
+ };
521
+
522
+ /**
523
+ * Get sweep sensitivity surfaces
524
+ * How the objective moves as each parameter moves — the question a leaderboard cannot answer.
525
+ * A leaderboard says which point won; a sweep can spend its entire budget on an axis that
526
+ * never moved the objective at all, and showing only the top rows hides that completely.
527
+ *
528
+ * A **marginal** takes one axis and collapses every other one: for each value of that axis,
529
+ * it aggregates every run that used it, whatever the rest of the parameters were. A flat
530
+ * marginal means the axis is irrelevant over the range swept. `best`, `mean` and `worst` are
531
+ * all reported because them disagreeing is itself the signal — a value with a high `best` and
532
+ * a poor `mean` works only in specific company, which is an interaction between parameters
533
+ * and would be invisible behind a single number.
534
+ *
535
+ * A **heatmap** does the same over a pair of axes, where that interaction becomes visible
536
+ * directly.
537
+ *
538
+ * Served from the sweep's stored rows: no re-run, no engine call, and it works on a sweep
539
+ * still in flight — the aggregates then describe the runs finished so far. Aborted runs are
540
+ * excluded throughout, since a run that threw measured nothing and counting it as a bad
541
+ * outcome would invent evidence against a parameter value that was never really tested.
542
+ *
543
+ * This is a separate endpoint rather than extra fields on the result view because the
544
+ * two-dimensional half is quadratic in the axis count (N axes give N(N-1)/2 surfaces, each
545
+ * the product of two axes' value counts) and is not wanted on the poll that drives progress.
546
+ *
547
+ */
548
+ export const getSweepSensitivity = <ThrowOnError extends boolean = false>(
549
+ options: Options<GetSweepSensitivityData, ThrowOnError>
550
+ ) => {
551
+ return (options.client ?? _heyApiClient).get<
552
+ GetSweepSensitivityResponse,
553
+ GetSweepSensitivityError,
554
+ ThrowOnError
555
+ >({
556
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}/sensitivity",
557
+ ...options,
558
+ });
340
559
  };
341
560
 
342
561
  /**
@@ -352,21 +571,27 @@ export const getSweepResult = <ThrowOnError extends boolean = false>(options: Op
352
571
  * `jobId` (idempotent).
353
572
  *
354
573
  */
355
- export const executeBacktest = <ThrowOnError extends boolean = false>(options: Options<ExecuteBacktestData, ThrowOnError>) => {
356
- return (options.client ?? _heyApiClient).post<ExecuteBacktestResponse, ExecuteBacktestError, ThrowOnError>({
357
- security: [
358
- {
359
- scheme: 'bearer',
360
- type: 'http'
361
- }
362
- ],
363
- url: '/backtest/{exchangeId}/{type}/execute',
364
- ...options,
365
- headers: {
366
- 'Content-Type': 'application/json',
367
- ...options?.headers
368
- }
369
- });
574
+ export const executeBacktest = <ThrowOnError extends boolean = false>(
575
+ options: Options<ExecuteBacktestData, ThrowOnError>
576
+ ) => {
577
+ return (options.client ?? _heyApiClient).post<
578
+ ExecuteBacktestResponse,
579
+ ExecuteBacktestError,
580
+ ThrowOnError
581
+ >({
582
+ security: [
583
+ {
584
+ scheme: "bearer",
585
+ type: "http",
586
+ },
587
+ ],
588
+ url: "/backtest/{exchangeId}/{type}/execute",
589
+ ...options,
590
+ headers: {
591
+ "Content-Type": "application/json",
592
+ ...options?.headers,
593
+ },
594
+ });
370
595
  };
371
596
 
372
597
  /**
@@ -377,17 +602,23 @@ export const executeBacktest = <ThrowOnError extends boolean = false>(options: O
377
602
  * to confirm the final status.
378
603
  *
379
604
  */
380
- export const cancelBacktest = <ThrowOnError extends boolean = false>(options: Options<CancelBacktestData, ThrowOnError>) => {
381
- return (options.client ?? _heyApiClient).delete<CancelBacktestResponse, CancelBacktestError, ThrowOnError>({
382
- security: [
383
- {
384
- scheme: 'bearer',
385
- type: 'http'
386
- }
387
- ],
388
- url: '/backtest/{exchangeId}/{type}/execute/{jobId}',
389
- ...options
390
- });
605
+ export const cancelBacktest = <ThrowOnError extends boolean = false>(
606
+ options: Options<CancelBacktestData, ThrowOnError>
607
+ ) => {
608
+ return (options.client ?? _heyApiClient).delete<
609
+ CancelBacktestResponse,
610
+ CancelBacktestError,
611
+ ThrowOnError
612
+ >({
613
+ security: [
614
+ {
615
+ scheme: "bearer",
616
+ type: "http",
617
+ },
618
+ ],
619
+ url: "/backtest/{exchangeId}/{type}/execute/{jobId}",
620
+ ...options,
621
+ });
391
622
  };
392
623
 
393
624
  /**
@@ -400,15 +631,21 @@ export const cancelBacktest = <ThrowOnError extends boolean = false>(options: Op
400
631
  * not stop on it.
401
632
  *
402
633
  */
403
- export const getBacktestResult = <ThrowOnError extends boolean = false>(options: Options<GetBacktestResultData, ThrowOnError>) => {
404
- return (options.client ?? _heyApiClient).get<GetBacktestResultResponse, GetBacktestResultError, ThrowOnError>({
405
- security: [
406
- {
407
- scheme: 'bearer',
408
- type: 'http'
409
- }
410
- ],
411
- url: '/backtest/{exchangeId}/{type}/execute/{jobId}',
412
- ...options
413
- });
414
- };
634
+ export const getBacktestResult = <ThrowOnError extends boolean = false>(
635
+ options: Options<GetBacktestResultData, ThrowOnError>
636
+ ) => {
637
+ return (options.client ?? _heyApiClient).get<
638
+ GetBacktestResultResponse,
639
+ GetBacktestResultError,
640
+ ThrowOnError
641
+ >({
642
+ security: [
643
+ {
644
+ scheme: "bearer",
645
+ type: "http",
646
+ },
647
+ ],
648
+ url: "/backtest/{exchangeId}/{type}/execute/{jobId}",
649
+ ...options,
650
+ });
651
+ };