@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.
package/dist/index.d.ts CHANGED
@@ -44,7 +44,7 @@ type InstrumentListMeta = {
44
44
  /**
45
45
  * The market segment served in `data`
46
46
  */
47
- segment: 'spot' | 'futures';
47
+ segment: "spot" | "futures";
48
48
  };
49
49
  /**
50
50
  * HAL `_links` — segment discovery for the instruments listing
@@ -152,7 +152,7 @@ type Exchange = {
152
152
  /**
153
153
  * Managed exchange data sources available for backtesting.
154
154
  */
155
- type DataSourceType = 'ticker';
155
+ type DataSourceType = "ticker";
156
156
  type PrepareRequest = {
157
157
  instrument: Instrument;
158
158
  /**
@@ -179,7 +179,7 @@ type PrepareRequest = {
179
179
  * labels return `400`.
180
180
  *
181
181
  */
182
- cadence?: '1s' | '5s' | '1m' | '5m' | '15m' | '1h' | '4h' | '1d';
182
+ cadence?: "1s" | "5s" | "1m" | "5m" | "15m" | "1h" | "4h" | "1d";
183
183
  };
184
184
  /**
185
185
  * Information about a single job
@@ -196,7 +196,7 @@ type JobState = {
196
196
  * `PrepareJobState.coverageRatio`, not by polling.
197
197
  *
198
198
  */
199
- status: 'New' | 'Started' | 'Completed' | 'Aborted' | 'Failed';
199
+ status: "New" | "Started" | "Completed" | "Aborted" | "Failed";
200
200
  /**
201
201
  * Detailed status information, if available
202
202
  */
@@ -270,7 +270,7 @@ type PrepareJobState = JobState & {
270
270
  * instrument did not trade that hour. `unknown`: no data to classify by.
271
271
  *
272
272
  */
273
- rationale?: 'pending_conversion' | 'low_activity' | 'unknown';
273
+ rationale?: "pending_conversion" | "low_activity" | "unknown";
274
274
  }>;
275
275
  };
276
276
  /**
@@ -284,7 +284,7 @@ type SweepAxis = {
284
284
  values: Array<number | boolean>;
285
285
  };
286
286
  type SweepSpecRequest = {
287
- sampler?: 'grid' | 'random' | 'lhs';
287
+ sampler?: "grid" | "random" | "lhs";
288
288
  /**
289
289
  * Reproducibility seed. If omitted, the server generates one with Java's
290
290
  * `L64X128MixRandom` generator and returns the effective value. The range
@@ -296,7 +296,7 @@ type SweepSpecRequest = {
296
296
  * Number of samples for `random` and `lhs`; ignored by `grid`.
297
297
  */
298
298
  samples?: number;
299
- objective?: 'sharpe' | 'sortino' | 'pnl' | 'maxdd';
299
+ objective?: "sharpe" | "sortino" | "pnl" | "maxdd";
300
300
  params: {
301
301
  [key: string]: SweepAxis;
302
302
  };
@@ -306,7 +306,7 @@ type SweepBaseConfig = {
306
306
  feeRate?: number;
307
307
  buyFeeRate?: number;
308
308
  sellFeeRate?: number;
309
- feeLeg?: 'RECEIVED' | 'QUOTE' | 'BASE';
309
+ feeLeg?: "RECEIVED" | "QUOTE" | "BASE";
310
310
  percentAmountToLock?: number;
311
311
  };
312
312
  type ExecuteSweepRequest = {
@@ -325,6 +325,21 @@ type ExecuteSweepRequest = {
325
325
  * Trials below this trade count are flagged but remain in the results.
326
326
  */
327
327
  minTradeFloor?: number;
328
+ walkForward?: WalkForwardRequest;
329
+ };
330
+ /**
331
+ * Opt in to walk-forward validation. Present, the sweep runs as F sequential folds and the result gains a `walkForward` section; absent, nothing about the sweep changes. Two requests that differ only in this block are two different sweeps and do not deduplicate against each other.
332
+ */
333
+ type WalkForwardRequest = {
334
+ /**
335
+ * How many sequential optimize-then-score windows to run. Two is the minimum for a reason, and it is structural rather than a tuning choice: parameter drift is measured between consecutive fold winners, and a single fold — one train/test split with no sequence — has no consecutive pair to compare, so it would report the strongest possible stability having measured nothing.
336
+ * The upper bound is a server setting (12 by default) and is deliberately not pinned here, since a spec that hardcodes a tunable limit lies the day it is raised. Exceeding it, or exceeding the sweep budget once multiplied by the grid size, is a 400.
337
+ */
338
+ folds: number;
339
+ /**
340
+ * Share of the session each fold spends optimizing; the remainder is where its winner is scored. Lower values leave more data to be scored on and, on short sessions, are also what lets the requested fold count tile the data at all.
341
+ */
342
+ inSamplePct?: number;
328
343
  };
329
344
  type ExecuteSweepAccepted = {
330
345
  sweepId: string;
@@ -339,13 +354,51 @@ type ExecuteSweepAccepted = {
339
354
  * False when an identical sweep already exists and was not enqueued again.
340
355
  */
341
356
  queued: boolean;
357
+ walkForward?: WalkForwardAccepted;
358
+ };
359
+ /**
360
+ * Echo of the accepted walk-forward configuration, present only when the submit carried one. `inSamplePct` is the resolved value, so a request that omitted it can see what it got.
361
+ */
362
+ type WalkForwardAccepted = {
363
+ folds: number;
364
+ inSamplePct: number;
365
+ /**
366
+ * What this sweep actually costs, `folds × (grid size + 1)` — the in-sample runs for every fold plus each fold's one out-of-sample run. Deliberately distinct from the top-level `totalRuns`, which stays the size of the grid that was submitted.
367
+ */
368
+ totalRuns: number;
342
369
  };
370
+ /**
371
+ * How far along a sweep is, and — when the sweep is still running — enough to tell a healthy one from a stuck one. The counts partition the shards (or, for a walk-forward sweep, the folds): every unit is either finished, failed, waiting to be retried, or not yet started.
372
+ */
343
373
  type SweepProgress = {
344
374
  done: number;
345
375
  total: number;
376
+ /**
377
+ * Individual runs that executed and aborted. A row-level count: a shard that fails before producing any rows leaves this at 0, which is why `failedShards` exists alongside it.
378
+ */
346
379
  aborted: number;
347
380
  shardCount: number;
348
381
  pendingShards: number;
382
+ /**
383
+ * Shards (or folds) that failed and will not be retried. Distinct from `aborted`: this counts whole units that never reported, not runs that ran badly.
384
+ */
385
+ failedShards: number;
386
+ /**
387
+ * Units whose last attempt failed on something transient — an I/O error, a worker that died mid-read — and which are queued to be attempted again. Not counted as failures, because they have not failed yet; a sweep with a non-zero value here is still expected to complete.
388
+ */
389
+ retrying: number;
390
+ /**
391
+ * Units that have not reported anything yet. Covers both work still queued behind other work and work claimed by a worker that stopped before it began, which is why a sweep with a persistent value here and a rising `stalledSeconds` is worth looking at.
392
+ */
393
+ notStarted: number;
394
+ /**
395
+ * Seconds since anything last advanced. Omitted on a finished sweep, where it would only measure how long ago it finished, and on sweeps submitted before this field existed.
396
+ */
397
+ stalledSeconds?: number;
398
+ /**
399
+ * Rough seconds remaining, extrapolated from the rate observed so far and assuming nothing else competes for workers. Runs conservative in practice — it has measured 2–5× long when a sweep spent part of its life waiting to be retried, since that wait dilutes the observed rate. **Omitted, never zero, when it cannot be computed**: a sweep with nothing finished yet has no rate to extrapolate from, and a zero would read as "about to finish". Excludes queue wait entirely; `retrying` and `stalledSeconds` are where that shows up.
400
+ */
401
+ etaSeconds?: number;
349
402
  };
350
403
  type SweepRunRow = {
351
404
  /**
@@ -356,6 +409,18 @@ type SweepRunRow = {
356
409
  * Present only in the `ranked` view.
357
410
  */
358
411
  rank?: number;
412
+ /**
413
+ * The objective of the worst run in this point's immediate neighbourhood — how well the region around it holds up, not how well it scored itself. Present only in the `ranked` view when plateau ranking applied. Always read together with `neighbourCount`.
414
+ */
415
+ plateauScore?: number;
416
+ /**
417
+ * How many neighbouring parameter points backed the `plateauScore`. Zero means the point had no neighbours in the grid, so its score is unevidenced rather than confirmed — the value alone cannot be distinguished from a genuinely robust one.
418
+ */
419
+ neighbourCount?: number;
420
+ /**
421
+ * Probability that this run's Sharpe reflects real edge rather than the best draw from however many parameter vectors were tried. Above ~0.95 the result survives the multiple-testing correction; near 0.5 or below it is indistinguishable from the best of a pile of coin flips. Absent on aborted runs, and on sweeps with too few trials to establish any dispersion to deflate against.
422
+ */
423
+ deflatedSharpe?: number;
359
424
  params: {
360
425
  [key: string]: unknown;
361
426
  };
@@ -374,11 +439,79 @@ type SweepRunRow = {
374
439
  aborted: boolean;
375
440
  runtimeMs: number;
376
441
  };
442
+ /**
443
+ * Sensitivity aggregates over a sweep's stored rows. Marginals are always complete; heatmaps may be capped, in which case `heatmapsTruncated` is true.
444
+ */
445
+ type SweepSensitivity = {
446
+ sweepId?: string;
447
+ status?: "RUNNING" | "COMPLETED" | "PARTIAL" | "CANCELLED";
448
+ objective?: "sharpe" | "sortino" | "pnl" | "maxdd";
449
+ /**
450
+ * Rows available when this was computed. Grows while a sweep is still running.
451
+ */
452
+ rowsAnalysed?: number;
453
+ marginals?: Array<SweepMarginal>;
454
+ heatmaps?: Array<SweepHeatmap>;
455
+ /**
456
+ * True when at least one two-parameter surface was left out to stay inside the response budget. Told explicitly because a silently short list would read as "these are all the interactions", which is the wrong thing to conclude from a sensitivity view.
457
+ */
458
+ heatmapsTruncated?: boolean;
459
+ };
460
+ /**
461
+ * One axis, with every other axis collapsed away.
462
+ */
463
+ type SweepMarginal = {
464
+ param?: string;
465
+ points?: Array<SweepMarginalPoint>;
466
+ };
467
+ /**
468
+ * How the objective behaved at one value of one axis. `best` and `mean` disagreeing is informative rather than noise: a high `best` with a poor `mean` marks a value that only works alongside particular settings of the other axes.
469
+ */
470
+ type SweepMarginalPoint = {
471
+ /**
472
+ * The axis value, as it appears in a run's parameters.
473
+ */
474
+ value?: unknown;
475
+ /**
476
+ * Non-aborted runs that used this value.
477
+ */
478
+ count?: number;
479
+ best?: number;
480
+ mean?: number;
481
+ worst?: number;
482
+ };
483
+ /**
484
+ * The surface for one pair of axes, with all others collapsed away.
485
+ */
486
+ type SweepHeatmap = {
487
+ paramA?: string;
488
+ paramB?: string;
489
+ cells?: Array<SweepHeatmapCell>;
490
+ };
491
+ type SweepHeatmapCell = {
492
+ valueA?: unknown;
493
+ valueB?: unknown;
494
+ count?: number;
495
+ best?: number;
496
+ mean?: number;
497
+ };
377
498
  type ExecuteSweepResult = {
378
499
  sweepId: string;
379
- status: 'RUNNING' | 'COMPLETED' | 'PARTIAL' | 'CANCELLED';
380
- objective: 'sharpe' | 'sortino' | 'pnl' | 'maxdd';
381
- order: 'ranked' | 'natural';
500
+ status: "RUNNING" | "COMPLETED" | "PARTIAL" | "CANCELLED";
501
+ objective: "sharpe" | "sortino" | "pnl" | "maxdd";
502
+ order: "ranked" | "natural";
503
+ /**
504
+ * Which ordering was actually applied, which is not always the one requested: a sweep with no stored parameter grid cannot be plateau-ranked and falls back to `raw`. Always `raw` when `order=natural`.
505
+ */
506
+ ranking?: "plateau" | "raw";
507
+ /**
508
+ * Probability of backtest overfitting for the sweep as a whole, by combinatorially symmetric cross-validation: how often the configuration that won in-sample lands below median out-of-sample. Above ~0.5 the sweep is selecting noise, whatever its top row says. Computed once when the last shard finishes, so it is absent while the sweep is still running and on sweeps too small for the statistic to mean anything.
509
+ */
510
+ pbo?: number;
511
+ /**
512
+ * How many train/test splits the `pbo` figure was averaged over.
513
+ */
514
+ pboSplits?: number;
382
515
  progress: SweepProgress;
383
516
  /**
384
517
  * Total result rows currently available.
@@ -389,6 +522,68 @@ type ExecuteSweepResult = {
389
522
  */
390
523
  truncated: boolean;
391
524
  leaderboard: Array<SweepRunRow>;
525
+ walkForward?: WalkForwardResult;
526
+ };
527
+ /**
528
+ * Present only on a sweep submitted with `walkForward`, and present from acceptance onward — its presence, not its contents, is what identifies a walk-forward sweep. `completedFolds` is 0 while the first fold is still running.
529
+ */
530
+ type WalkForwardResult = {
531
+ /**
532
+ * Folds requested at submit.
533
+ */
534
+ folds: number;
535
+ /**
536
+ * Resolved in-sample share each fold optimized on.
537
+ */
538
+ inSamplePct?: number;
539
+ /**
540
+ * Folds that have finished and reported a winner.
541
+ */
542
+ completedFolds: number;
543
+ /**
544
+ * Mean normalized lattice distance between consecutive fold winners. Low is good: winners that stay in a tight band fold after fold are evidence the parameter means something, while winners that jump across the grid every time are the sweep re-fitting noise, and that backtest will not survive contact with live data. **Absent is not zero** — the field is omitted whenever the figure could not be computed (fewer than two folds finished, no stored grid to place winners on), because zero is itself a meaningful reading here and a placeholder would be indistinguishable from perfect stability.
545
+ */
546
+ paramDrift?: number;
547
+ /**
548
+ * One entry per completed fold, oldest first.
549
+ */
550
+ results: Array<WalkForwardFold>;
551
+ };
552
+ /**
553
+ * What one fold concluded. The out-of-sample row is the answer; the in-sample figure is only there to be compared against it, since any grid produces a flattering in-sample winner — that is what optimizing does. The gap between them is the whole reading.
554
+ */
555
+ type WalkForwardFold = {
556
+ /**
557
+ * Position in the walk-forward sequence, oldest first.
558
+ */
559
+ foldIx: number;
560
+ /**
561
+ * First index of the optimization window, into the prepared session.
562
+ */
563
+ inSampleFrom: number;
564
+ /**
565
+ * End of the optimization window, exclusive — and where scoring begins.
566
+ */
567
+ inSampleTo: number;
568
+ /**
569
+ * End of the scoring window, exclusive.
570
+ */
571
+ outOfSampleTo: number;
572
+ /**
573
+ * The parameter vector that won this fold's optimization window.
574
+ */
575
+ params: {
576
+ [key: string]: unknown;
577
+ };
578
+ /**
579
+ * How that winner scored on the window it was chosen on.
580
+ */
581
+ inSampleSharpe: number;
582
+ outOfSample: SweepRunRow;
583
+ /**
584
+ * Vectors this fold evaluated in-sample before picking its winner.
585
+ */
586
+ vectorsRun: number;
392
587
  };
393
588
  /**
394
589
  * Response returned by async endpoints (`202 Accepted`). The `jobId` is deterministic for the
@@ -506,7 +701,7 @@ type ResultMap = {
506
701
  /**
507
702
  * Upload status. Done = signal file is available at signalsUrl. Failed = upload error (see signalsUploadReason). Skipped = no signals emitted.
508
703
  */
509
- signalsUpload?: 'Done' | 'Failed' | 'Skipped';
704
+ signalsUpload?: "Done" | "Failed" | "Skipped";
510
705
  /**
511
706
  * ISO 8601 timestamp of when the upload completed. Only present when signalsUpload is Done.
512
707
  */
@@ -560,7 +755,7 @@ type Notice = {
560
755
  * `compile-dry-run` is only a lower bound over a bounded synthetic series.
561
756
  *
562
757
  */
563
- provenance?: 'execute' | 'compile-dry-run';
758
+ provenance?: "execute" | "compile-dry-run";
564
759
  };
565
760
  /**
566
761
  * What is known about a registered strategy: that it compiled, and what validating it found.
@@ -580,7 +775,7 @@ type StrategyState = {
580
775
  * * `failed` — it did not; `detail` says how.
581
776
  *
582
777
  */
583
- validation: 'not_validated' | 'pending' | 'passed' | 'failed';
778
+ validation: "not_validated" | "pending" | "passed" | "failed";
584
779
  /**
585
780
  * When the live compilation was produced.
586
781
  */
@@ -598,7 +793,7 @@ type StrategyState = {
598
793
  * re-registering the source fills it in.
599
794
  *
600
795
  */
601
- requiredSources?: Array<'Ticker' | 'KLine' | 'FundingRate'>;
796
+ requiredSources?: Array<"Ticker" | "KLine" | "FundingRate">;
602
797
  /**
603
798
  * When the verdict was recorded. Absent until there is one.
604
799
  */
@@ -642,7 +837,7 @@ type AuthTokenResponse = {
642
837
  /**
643
838
  * Always `Bearer`.
644
839
  */
645
- token_type: 'Bearer';
840
+ token_type: "Bearer";
646
841
  /**
647
842
  * Seconds until the JWT expires (typically 3600).
648
843
  */
@@ -654,7 +849,7 @@ type AuthTokenResponse = {
654
849
  /**
655
850
  * Subscription tier this token was issued for. Drives rate limits and feature flags on downstream endpoints.
656
851
  */
657
- tier: 'free' | 'basic' | 'pro' | 'elite';
852
+ tier: "free" | "basic" | "pro" | "elite";
658
853
  };
659
854
  /**
660
855
  * Error envelope returned by `POST /auth/token` when the API key is rejected.
@@ -663,7 +858,7 @@ type AuthTokenError = {
663
858
  /**
664
859
  * Machine-readable error reason.
665
860
  */
666
- code: 'invalid_apikey' | 'apikey_revoked' | 'apikey_expired';
861
+ code: "invalid_apikey" | "apikey_revoked" | "apikey_expired";
667
862
  /**
668
863
  * Human-readable description of the failure.
669
864
  */
@@ -673,7 +868,7 @@ type AuthenticateData = {
673
868
  body?: never;
674
869
  path?: never;
675
870
  query?: never;
676
- url: '/auth/token';
871
+ url: "/auth/token";
677
872
  };
678
873
  type AuthenticateErrors = {
679
874
  /**
@@ -697,7 +892,7 @@ type ListExchangesData = {
697
892
  body?: never;
698
893
  path?: never;
699
894
  query?: never;
700
- url: '/exchanges';
895
+ url: "/exchanges";
701
896
  };
702
897
  type ListExchangesResponses = {
703
898
  /**
@@ -715,7 +910,7 @@ type ListInstrumentsData = {
715
910
  exchangeId: string;
716
911
  };
717
912
  query?: never;
718
- url: '/exchange/{exchangeId}/instruments';
913
+ url: "/exchange/{exchangeId}/instruments";
719
914
  };
720
915
  type ListInstrumentsErrors = {
721
916
  /**
@@ -741,10 +936,10 @@ type ListSegmentInstrumentsData = {
741
936
  /**
742
937
  * Market segment to list instruments for
743
938
  */
744
- segment: 'spot' | 'futures';
939
+ segment: "spot" | "futures";
745
940
  };
746
941
  query?: never;
747
- url: '/exchange/{exchangeId}/{segment}/instruments';
942
+ url: "/exchange/{exchangeId}/{segment}/instruments";
748
943
  };
749
944
  type ListSegmentInstrumentsErrors = {
750
945
  /**
@@ -789,9 +984,9 @@ type DownloadTickersData = {
789
984
  * [lastra-convert](https://github.com/QTSurfer/lastra-convert).
790
985
  *
791
986
  */
792
- format?: 'lastra' | 'parquet';
987
+ format?: "lastra" | "parquet";
793
988
  };
794
- url: '/exchange/{exchangeId}/tickers/{base}/{quote}';
989
+ url: "/exchange/{exchangeId}/tickers/{base}/{quote}";
795
990
  };
796
991
  type DownloadTickersErrors = {
797
992
  /**
@@ -847,9 +1042,9 @@ type DownloadKlinesData = {
847
1042
  * `parquet` returns Parquet via on-the-fly conversion.
848
1043
  *
849
1044
  */
850
- format?: 'lastra' | 'parquet';
1045
+ format?: "lastra" | "parquet";
851
1046
  };
852
- url: '/exchange/{exchangeId}/klines/{base}/{quote}';
1047
+ url: "/exchange/{exchangeId}/klines/{base}/{quote}";
853
1048
  };
854
1049
  type DownloadKlinesErrors = {
855
1050
  /**
@@ -883,7 +1078,7 @@ type CompileStrategyData = {
883
1078
  body: string;
884
1079
  path?: never;
885
1080
  query?: never;
886
- url: '/strategy';
1081
+ url: "/strategy";
887
1082
  };
888
1083
  type CompileStrategyErrors = {
889
1084
  /**
@@ -916,7 +1111,7 @@ type ValidateStrategyData = {
916
1111
  strategyId: StrategyId;
917
1112
  };
918
1113
  query?: never;
919
- url: '/strategy/{strategyId}/validate';
1114
+ url: "/strategy/{strategyId}/validate";
920
1115
  };
921
1116
  type ValidateStrategyErrors = {
922
1117
  /**
@@ -937,7 +1132,7 @@ type ValidateStrategyResponses = {
937
1132
  */
938
1133
  202: {
939
1134
  strategyId: StrategyId;
940
- validation: 'pending';
1135
+ validation: "pending";
941
1136
  };
942
1137
  };
943
1138
  type ValidateStrategyResponse = ValidateStrategyResponses[keyof ValidateStrategyResponses];
@@ -950,7 +1145,7 @@ type GetStrategyData = {
950
1145
  strategyId: StrategyId;
951
1146
  };
952
1147
  query?: never;
953
- url: '/strategy/{strategyId}';
1148
+ url: "/strategy/{strategyId}";
954
1149
  };
955
1150
  type GetStrategyErrors = {
956
1151
  /**
@@ -982,7 +1177,7 @@ type PrepareBacktestData = {
982
1177
  type: DataSourceType;
983
1178
  };
984
1179
  query?: never;
985
- url: '/backtest/{exchangeId}/{type}/prepare';
1180
+ url: "/backtest/{exchangeId}/{type}/prepare";
986
1181
  };
987
1182
  type PrepareBacktestErrors = {
988
1183
  /**
@@ -1027,7 +1222,7 @@ type GetPrepareStatusData = {
1027
1222
  jobId: string;
1028
1223
  };
1029
1224
  query?: never;
1030
- url: '/backtest/{exchangeId}/{type}/prepare/{jobId}';
1225
+ url: "/backtest/{exchangeId}/{type}/prepare/{jobId}";
1031
1226
  };
1032
1227
  type GetPrepareStatusErrors = {
1033
1228
  /**
@@ -1058,7 +1253,7 @@ type ExecuteSweepData = {
1058
1253
  requestId: string;
1059
1254
  };
1060
1255
  query?: never;
1061
- url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}';
1256
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}";
1062
1257
  };
1063
1258
  type ExecuteSweepErrors = {
1064
1259
  /**
@@ -1091,7 +1286,7 @@ type CancelSweepData = {
1091
1286
  sweepId: string;
1092
1287
  };
1093
1288
  query?: never;
1094
- url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}';
1289
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}";
1095
1290
  };
1096
1291
  type CancelSweepErrors = {
1097
1292
  /**
@@ -1105,7 +1300,7 @@ type CancelSweepResponses = {
1105
1300
  * Cancellation requested.
1106
1301
  */
1107
1302
  200: {
1108
- status: 'cancelling';
1303
+ status: "cancelling";
1109
1304
  sweepId: string;
1110
1305
  };
1111
1306
  };
@@ -1119,13 +1314,17 @@ type GetSweepResultData = {
1119
1314
  sweepId: string;
1120
1315
  };
1121
1316
  query?: {
1122
- objective?: 'sharpe' | 'sortino' | 'pnl' | 'maxdd';
1317
+ objective?: "sharpe" | "sortino" | "pnl" | "maxdd";
1123
1318
  /**
1124
1319
  * `natural` is stable materialisation order; `ranked` is the display view.
1125
1320
  */
1126
- order?: 'ranked' | 'natural';
1321
+ order?: "ranked" | "natural";
1322
+ /**
1323
+ * How the `ranked` view is ordered. `plateau` prefers points whose neighbourhood also scores well; `raw` uses the objective alone. Ignored when `order=natural`, which is always ordered by `runIx`.
1324
+ */
1325
+ ranking?: "plateau" | "raw";
1127
1326
  };
1128
- url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}';
1327
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}";
1129
1328
  };
1130
1329
  type GetSweepResultErrors = {
1131
1330
  /**
@@ -1141,6 +1340,36 @@ type GetSweepResultResponses = {
1141
1340
  200: ExecuteSweepResult;
1142
1341
  };
1143
1342
  type GetSweepResultResponse = GetSweepResultResponses[keyof GetSweepResultResponses];
1343
+ type GetSweepSensitivityData = {
1344
+ body?: never;
1345
+ path: {
1346
+ exchangeId: string;
1347
+ type: DataSourceType;
1348
+ requestId: string;
1349
+ sweepId: string;
1350
+ };
1351
+ query?: {
1352
+ /**
1353
+ * Which metric to aggregate. Defaults to the objective the sweep was submitted with.
1354
+ */
1355
+ objective?: "sharpe" | "sortino" | "pnl" | "maxdd";
1356
+ };
1357
+ url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}/sensitivity";
1358
+ };
1359
+ type GetSweepSensitivityErrors = {
1360
+ /**
1361
+ * Sweep not found or expired.
1362
+ */
1363
+ 404: ResponseError;
1364
+ };
1365
+ type GetSweepSensitivityError = GetSweepSensitivityErrors[keyof GetSweepSensitivityErrors];
1366
+ type GetSweepSensitivityResponses = {
1367
+ /**
1368
+ * Sensitivity aggregates over the rows available so far.
1369
+ */
1370
+ 200: SweepSensitivity;
1371
+ };
1372
+ type GetSweepSensitivityResponse = GetSweepSensitivityResponses[keyof GetSweepSensitivityResponses];
1144
1373
  type ExecuteBacktestData = {
1145
1374
  /**
1146
1375
  * Execute task parameters
@@ -1169,7 +1398,7 @@ type ExecuteBacktestData = {
1169
1398
  type: DataSourceType;
1170
1399
  };
1171
1400
  query?: never;
1172
- url: '/backtest/{exchangeId}/{type}/execute';
1401
+ url: "/backtest/{exchangeId}/{type}/execute";
1173
1402
  };
1174
1403
  type ExecuteBacktestErrors = {
1175
1404
  /**
@@ -1204,7 +1433,7 @@ type CancelBacktestData = {
1204
1433
  jobId: string;
1205
1434
  };
1206
1435
  query?: never;
1207
- url: '/backtest/{exchangeId}/{type}/execute/{jobId}';
1436
+ url: "/backtest/{exchangeId}/{type}/execute/{jobId}";
1208
1437
  };
1209
1438
  type CancelBacktestErrors = {
1210
1439
  /**
@@ -1218,7 +1447,7 @@ type CancelBacktestResponses = {
1218
1447
  * Cancellation request accepted
1219
1448
  */
1220
1449
  200: {
1221
- status?: 'cancelling';
1450
+ status?: "cancelling";
1222
1451
  jobId?: string;
1223
1452
  };
1224
1453
  };
@@ -1240,7 +1469,7 @@ type GetBacktestResultData = {
1240
1469
  jobId: string;
1241
1470
  };
1242
1471
  query?: never;
1243
- url: '/backtest/{exchangeId}/{type}/execute/{jobId}';
1472
+ url: "/backtest/{exchangeId}/{type}/execute/{jobId}";
1244
1473
  };
1245
1474
  type GetBacktestResultErrors = {
1246
1475
  /**
@@ -1276,7 +1505,7 @@ type GetBacktestResultResponses = {
1276
1505
  };
1277
1506
  type GetBacktestResultResponse = GetBacktestResultResponses[keyof GetBacktestResultResponses];
1278
1507
  type ClientOptions = {
1279
- baseUrl: 'https://api.staging.qtsurfer.com/v1' | 'https://api.qtsurfer.com/v1' | (string & {});
1508
+ baseUrl: "https://api.staging.qtsurfer.com/v1" | "https://api.qtsurfer.com/v1" | (string & {});
1280
1509
  };
1281
1510
 
1282
1511
  type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options$1<TData, ThrowOnError> & {
@@ -1449,6 +1678,17 @@ declare const getPrepareStatus: <ThrowOnError extends boolean = false>(options:
1449
1678
  * The backend expands and executes the matrix internally; clients poll the returned
1450
1679
  * `sweepId` for incremental results.
1451
1680
  *
1681
+ * Supplying `walkForward` runs the sweep in a different mode entirely. Instead of scoring
1682
+ * every parameter vector once over the whole range, the data is split into F sequential
1683
+ * folds; each fold optimizes the full grid on its own window and then scores only its winner
1684
+ * on the window immediately after — data that winner was not chosen on. It answers a harder
1685
+ * question than a leaderboard: not "which parameters won", but "does re-optimizing this
1686
+ * periodically actually work". Omit the block and nothing changes, including the response.
1687
+ *
1688
+ * The cost is the reason it is opt-in rather than always on: F folds × N vectors, so a
1689
+ * 4-fold run over a 500-point grid is 2004 backtests where the plain sweep is 500. The
1690
+ * request is rejected when `folds × totalRuns` exceeds the server's sweep budget.
1691
+ *
1452
1692
  */
1453
1693
  declare const executeSweep: <ThrowOnError extends boolean = false>(options: Options<ExecuteSweepData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<ExecuteSweepAccepted, ResponseError, ThrowOnError>;
1454
1694
  /**
@@ -1465,8 +1705,59 @@ declare const cancelSweep: <ThrowOnError extends boolean = false>(options: Optio
1465
1705
  * display leaderboard. `order=natural` returns every available row, untruncated, ordered by
1466
1706
  * deterministic `runIx`; use that view when materialising durable trial rows.
1467
1707
  *
1708
+ * The `ranked` view is ordered by **plateau score** by default, not by the raw objective. A
1709
+ * plateau score is the objective of the worst run in a parameter point's immediate
1710
+ * neighbourhood, so a point scores well only if the region around it also does — the highest
1711
+ * raw score is frequently a spike that does not survive the parameters moving slightly. Pass
1712
+ * `ranking=raw` for the unadjusted objective order.
1713
+ *
1714
+ * Rows in the `ranked` view carry `plateauScore` and `neighbourCount` when plateau ranking
1715
+ * applied. Read them together: `neighbourCount: 0` means the point had no neighbours to
1716
+ * compare against, so its plateau score is unevidenced rather than confirmed. Sweeps
1717
+ * submitted before plateau ranking existed have no stored parameter grid to rebuild a
1718
+ * neighbourhood from and are always ranked raw; the response's `ranking` field says which
1719
+ * ordering was actually used.
1720
+ *
1721
+ * A sweep submitted with `walkForward` answers in a different shape, and the `walkForward`
1722
+ * field on the response is what tells the two apart — it appears as soon as the sweep is
1723
+ * accepted, before any fold has finished, so it is safe to branch on while polling. There
1724
+ * the leaderboard is one row per completed fold: that fold's winner as it scored
1725
+ * **out-of-sample**, with `runIx` carrying the fold index rather than a grid position. The
1726
+ * in-sample runs behind those winners are not retained — they are an optimization's working
1727
+ * set, and only the winner survives its fold. `ranking` is always `raw` and no plateau, DSR
1728
+ * or PBO figure is reported: the out-of-sample scores are already the honest number, and
1729
+ * layering a certification computed over F observations on top of them would overstate what
1730
+ * was measured.
1731
+ *
1468
1732
  */
1469
1733
  declare const getSweepResult: <ThrowOnError extends boolean = false>(options: Options<GetSweepResultData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<ExecuteSweepResult, ResponseError, ThrowOnError>;
1734
+ /**
1735
+ * Get sweep sensitivity surfaces
1736
+ * How the objective moves as each parameter moves — the question a leaderboard cannot answer.
1737
+ * A leaderboard says which point won; a sweep can spend its entire budget on an axis that
1738
+ * never moved the objective at all, and showing only the top rows hides that completely.
1739
+ *
1740
+ * A **marginal** takes one axis and collapses every other one: for each value of that axis,
1741
+ * it aggregates every run that used it, whatever the rest of the parameters were. A flat
1742
+ * marginal means the axis is irrelevant over the range swept. `best`, `mean` and `worst` are
1743
+ * all reported because them disagreeing is itself the signal — a value with a high `best` and
1744
+ * a poor `mean` works only in specific company, which is an interaction between parameters
1745
+ * and would be invisible behind a single number.
1746
+ *
1747
+ * A **heatmap** does the same over a pair of axes, where that interaction becomes visible
1748
+ * directly.
1749
+ *
1750
+ * Served from the sweep's stored rows: no re-run, no engine call, and it works on a sweep
1751
+ * still in flight — the aggregates then describe the runs finished so far. Aborted runs are
1752
+ * excluded throughout, since a run that threw measured nothing and counting it as a bad
1753
+ * outcome would invent evidence against a parameter value that was never really tested.
1754
+ *
1755
+ * This is a separate endpoint rather than extra fields on the result view because the
1756
+ * two-dimensional half is quadratic in the axis count (N axes give N(N-1)/2 surfaces, each
1757
+ * the product of two axes' value counts) and is not wanted on the poll that drives progress.
1758
+ *
1759
+ */
1760
+ declare const getSweepSensitivity: <ThrowOnError extends boolean = false>(options: Options<GetSweepSensitivityData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<SweepSensitivity, ResponseError, ThrowOnError>;
1470
1761
  /**
1471
1762
  * Execute a compiled strategy against a prepared dataset
1472
1763
  * Enqueues an execute task that runs the strategy identified by `strategyId` over the data
@@ -1507,4 +1798,4 @@ declare const getBacktestResult: <ThrowOnError extends boolean = false>(options:
1507
1798
 
1508
1799
  declare const client: _hey_api_client_fetch.Client;
1509
1800
 
1510
- export { type AcceptedJob, type AuthTokenError, type AuthTokenResponse, type AuthenticateData, type AuthenticateError, type AuthenticateErrors, type AuthenticateResponse, type AuthenticateResponses, type BacktestJobResult, type CancelBacktestData, type CancelBacktestError, type CancelBacktestErrors, type CancelBacktestResponse, type CancelBacktestResponses, type CancelSweepData, type CancelSweepError, type CancelSweepErrors, type CancelSweepResponse, type CancelSweepResponses, type ClientOptions, type CompileStrategyData, type CompileStrategyError, type CompileStrategyErrors, type CompileStrategyResponse, type CompileStrategyResponses, type CoverageWindow, type DataSourceType, type DownloadKlinesData, type DownloadKlinesError, type DownloadKlinesErrors, type DownloadKlinesResponse, type DownloadKlinesResponses, type DownloadTickersData, type DownloadTickersError, type DownloadTickersErrors, type DownloadTickersResponse, type DownloadTickersResponses, type EquityPoint, type Exchange, type ExecuteBacktestData, type ExecuteBacktestError, type ExecuteBacktestErrors, type ExecuteBacktestResponse, type ExecuteBacktestResponses, type ExecuteSweepAccepted, type ExecuteSweepData, type ExecuteSweepError, type ExecuteSweepErrors, type ExecuteSweepRequest, type ExecuteSweepResponse, type ExecuteSweepResponses, type ExecuteSweepResult, type GetBacktestResultData, type GetBacktestResultError, type GetBacktestResultErrors, type GetBacktestResultResponse, type GetBacktestResultResponses, type GetPrepareStatusData, type GetPrepareStatusError, type GetPrepareStatusErrors, type GetPrepareStatusResponse, type GetPrepareStatusResponses, type GetStrategyData, type GetStrategyError, type GetStrategyErrors, type GetStrategyResponse, type GetStrategyResponses, type GetSweepResultData, type GetSweepResultError, type GetSweepResultErrors, type GetSweepResultResponse, type GetSweepResultResponses, type HalLink, type Instrument, type InstrumentCoverage, type InstrumentDetail, type InstrumentLinks, type InstrumentListMeta, type InstrumentListResponse, type JobState, type ListExchangesData, type ListExchangesResponse, type ListExchangesResponses, type ListInstrumentsData, type ListInstrumentsError, type ListInstrumentsErrors, type ListInstrumentsResponse, type ListInstrumentsResponses, type ListSegmentInstrumentsData, type ListSegmentInstrumentsError, type ListSegmentInstrumentsErrors, type ListSegmentInstrumentsResponse, type ListSegmentInstrumentsResponses, type Notice, type Options, type PrepareBacktestData, type PrepareBacktestError, type PrepareBacktestErrors, type PrepareBacktestResponse, type PrepareBacktestResponses, type PrepareJobState, type PrepareRequest, type ResponseError, type ResultMap, type StrategyId, type StrategyState, type SweepAxis, type SweepBaseConfig, type SweepProgress, type SweepRunRow, type SweepSpecRequest, type ValidateStrategyData, type ValidateStrategyError, type ValidateStrategyErrors, type ValidateStrategyResponse, type ValidateStrategyResponses, authenticate, cancelBacktest, cancelSweep, client, compileStrategy, downloadKlines, downloadTickers, executeBacktest, executeSweep, getBacktestResult, getPrepareStatus, getStrategy, getSweepResult, listExchanges, listInstruments, listSegmentInstruments, prepareBacktest, validateStrategy };
1801
+ export { type AcceptedJob, type AuthTokenError, type AuthTokenResponse, type AuthenticateData, type AuthenticateError, type AuthenticateErrors, type AuthenticateResponse, type AuthenticateResponses, type BacktestJobResult, type CancelBacktestData, type CancelBacktestError, type CancelBacktestErrors, type CancelBacktestResponse, type CancelBacktestResponses, type CancelSweepData, type CancelSweepError, type CancelSweepErrors, type CancelSweepResponse, type CancelSweepResponses, type ClientOptions, type CompileStrategyData, type CompileStrategyError, type CompileStrategyErrors, type CompileStrategyResponse, type CompileStrategyResponses, type CoverageWindow, type DataSourceType, type DownloadKlinesData, type DownloadKlinesError, type DownloadKlinesErrors, type DownloadKlinesResponse, type DownloadKlinesResponses, type DownloadTickersData, type DownloadTickersError, type DownloadTickersErrors, type DownloadTickersResponse, type DownloadTickersResponses, type EquityPoint, type Exchange, type ExecuteBacktestData, type ExecuteBacktestError, type ExecuteBacktestErrors, type ExecuteBacktestResponse, type ExecuteBacktestResponses, type ExecuteSweepAccepted, type ExecuteSweepData, type ExecuteSweepError, type ExecuteSweepErrors, type ExecuteSweepRequest, type ExecuteSweepResponse, type ExecuteSweepResponses, type ExecuteSweepResult, type GetBacktestResultData, type GetBacktestResultError, type GetBacktestResultErrors, type GetBacktestResultResponse, type GetBacktestResultResponses, type GetPrepareStatusData, type GetPrepareStatusError, type GetPrepareStatusErrors, type GetPrepareStatusResponse, type GetPrepareStatusResponses, type GetStrategyData, type GetStrategyError, type GetStrategyErrors, type GetStrategyResponse, type GetStrategyResponses, type GetSweepResultData, type GetSweepResultError, type GetSweepResultErrors, type GetSweepResultResponse, type GetSweepResultResponses, type GetSweepSensitivityData, type GetSweepSensitivityError, type GetSweepSensitivityErrors, type GetSweepSensitivityResponse, type GetSweepSensitivityResponses, type HalLink, type Instrument, type InstrumentCoverage, type InstrumentDetail, type InstrumentLinks, type InstrumentListMeta, type InstrumentListResponse, type JobState, type ListExchangesData, type ListExchangesResponse, type ListExchangesResponses, type ListInstrumentsData, type ListInstrumentsError, type ListInstrumentsErrors, type ListInstrumentsResponse, type ListInstrumentsResponses, type ListSegmentInstrumentsData, type ListSegmentInstrumentsError, type ListSegmentInstrumentsErrors, type ListSegmentInstrumentsResponse, type ListSegmentInstrumentsResponses, type Notice, type Options, type PrepareBacktestData, type PrepareBacktestError, type PrepareBacktestErrors, type PrepareBacktestResponse, type PrepareBacktestResponses, type PrepareJobState, type PrepareRequest, type ResponseError, type ResultMap, type StrategyId, type StrategyState, type SweepAxis, type SweepBaseConfig, type SweepHeatmap, type SweepHeatmapCell, type SweepMarginal, type SweepMarginalPoint, type SweepProgress, type SweepRunRow, type SweepSensitivity, type SweepSpecRequest, type ValidateStrategyData, type ValidateStrategyError, type ValidateStrategyErrors, type ValidateStrategyResponse, type ValidateStrategyResponses, type WalkForwardAccepted, type WalkForwardFold, type WalkForwardRequest, type WalkForwardResult, authenticate, cancelBacktest, cancelSweep, client, compileStrategy, downloadKlines, downloadTickers, executeBacktest, executeSweep, getBacktestResult, getPrepareStatus, getStrategy, getSweepResult, getSweepSensitivity, listExchanges, listInstruments, listSegmentInstruments, prepareBacktest, validateStrategy };