@qtsurfer/api-client 0.6.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/README.md +1 -0
- package/dist/index.d.ts +550 -87
- package/dist/index.js +30 -5
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/src/generated/client.gen.ts +16 -6
- package/src/generated/index.ts +2 -2
- package/src/generated/schemas.gen.ts +1444 -867
- package/src/generated/sdk.gen.ts +470 -189
- package/src/generated/types.gen.ts +1326 -897
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:
|
|
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 =
|
|
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?:
|
|
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:
|
|
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?:
|
|
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?:
|
|
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?:
|
|
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?:
|
|
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;
|
|
342
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;
|
|
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:
|
|
380
|
-
objective:
|
|
381
|
-
order:
|
|
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
|
|
@@ -409,7 +604,7 @@ type BacktestJobResult = {
|
|
|
409
604
|
state: JobState;
|
|
410
605
|
};
|
|
411
606
|
/**
|
|
412
|
-
* Execution result map. Always includes core fields (hostName, iops, strategyId, instrument). Yield metrics (pnlTotal, pnlTotalPercent, totalTrades, winRate, equityCurve, etc.) are present when the strategy emitted at least one trade. When signal storage is enabled, includes signal fields described below.
|
|
607
|
+
* Execution result map. Always includes core fields (hostName, iops, strategyId, instrument). Yield metrics (pnlTotal, pnlTotalPercent, totalTrades, winRate, equityCurve, etc.) are present when the strategy emitted at least one trade. When signal storage is enabled, includes signal fields described below. `notices` carries what the run had to say about itself, and is absent when it had nothing.
|
|
413
608
|
*/
|
|
414
609
|
type ResultMap = {
|
|
415
610
|
/**
|
|
@@ -421,13 +616,36 @@ type ResultMap = {
|
|
|
421
616
|
*/
|
|
422
617
|
iops?: number;
|
|
423
618
|
/**
|
|
424
|
-
*
|
|
619
|
+
* **Not the `strategyId` you compiled with** — this is the execution context id,
|
|
620
|
+
* `strategy:<user>:<strategyId>`. The compiled strategy's id is the last `:`-separated
|
|
621
|
+
* segment; that, not this whole string, is what `GET /strategy/{strategyId}` takes.
|
|
622
|
+
*
|
|
623
|
+
* Take the segment after the last `:` rather than counting from the front: the shape has
|
|
624
|
+
* changed once already and callers that indexed a fixed position broke on it.
|
|
625
|
+
*
|
|
425
626
|
*/
|
|
426
627
|
strategyId: string;
|
|
427
628
|
/**
|
|
428
629
|
* The instrument (currency pair) that was backtested
|
|
429
630
|
*/
|
|
430
631
|
instrument: string;
|
|
632
|
+
/**
|
|
633
|
+
* Diagnostics the engine raised over this run, each with `provenance: execute`.
|
|
634
|
+
*
|
|
635
|
+
* **Absent means nothing was raised.** This is the one surface where silence is a real
|
|
636
|
+
* answer: the run happened, over your data, start to finish, and the engine found nothing
|
|
637
|
+
* worth saying. That is not true of the compile path, where an empty list only means a
|
|
638
|
+
* short synthetic series reached nothing — see `GET /strategy/{strategyId}`.
|
|
639
|
+
*
|
|
640
|
+
* Notices are raised on failed and aborted runs too, and those are the ones most worth
|
|
641
|
+
* reading: a run that produced no trades often did so for a reason stated here.
|
|
642
|
+
*
|
|
643
|
+
*/
|
|
644
|
+
notices?: Array<Notice>;
|
|
645
|
+
/**
|
|
646
|
+
* How many notices were dropped past the cap of 50. Absent when none were. A large value usually means one fault repeating per instrument or per parameter vector rather than 50 distinct problems.
|
|
647
|
+
*/
|
|
648
|
+
noticesTruncated?: number;
|
|
431
649
|
/**
|
|
432
650
|
* Total profit and loss in the output currency
|
|
433
651
|
*/
|
|
@@ -483,7 +701,7 @@ type ResultMap = {
|
|
|
483
701
|
/**
|
|
484
702
|
* Upload status. Done = signal file is available at signalsUrl. Failed = upload error (see signalsUploadReason). Skipped = no signals emitted.
|
|
485
703
|
*/
|
|
486
|
-
signalsUpload?:
|
|
704
|
+
signalsUpload?: "Done" | "Failed" | "Skipped";
|
|
487
705
|
/**
|
|
488
706
|
* ISO 8601 timestamp of when the upload completed. Only present when signalsUpload is Done.
|
|
489
707
|
*/
|
|
@@ -507,9 +725,110 @@ type EquityPoint = {
|
|
|
507
725
|
equity: number;
|
|
508
726
|
};
|
|
509
727
|
/**
|
|
510
|
-
* Unique identifier for a compiled strategy
|
|
728
|
+
* Unique identifier for a compiled strategy, derived from the source itself: the same code
|
|
729
|
+
* always yields the same id, for every caller, whatever its formatting. See
|
|
730
|
+
* `POST /strategy` for exactly which rewrites preserve it and which do not.
|
|
731
|
+
*
|
|
511
732
|
*/
|
|
512
733
|
type StrategyId = string;
|
|
734
|
+
/**
|
|
735
|
+
* A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth
|
|
736
|
+
* knowing about how the strategy is wired, not necessarily an error.
|
|
737
|
+
*
|
|
738
|
+
*/
|
|
739
|
+
type Notice = {
|
|
740
|
+
/**
|
|
741
|
+
* Severity as the engine classified it.
|
|
742
|
+
*/
|
|
743
|
+
level: string;
|
|
744
|
+
/**
|
|
745
|
+
* Stable identifier for the kind of finding; safe to match on.
|
|
746
|
+
*/
|
|
747
|
+
code: string;
|
|
748
|
+
/**
|
|
749
|
+
* Human-readable explanation.
|
|
750
|
+
*/
|
|
751
|
+
message: string;
|
|
752
|
+
/**
|
|
753
|
+
* Where it came from, which matters because the two silences differ: an empty list from a
|
|
754
|
+
* real run (`execute`) is a clean bill of health, while an empty list from
|
|
755
|
+
* `compile-dry-run` is only a lower bound over a bounded synthetic series.
|
|
756
|
+
*
|
|
757
|
+
*/
|
|
758
|
+
provenance?: "execute" | "compile-dry-run";
|
|
759
|
+
};
|
|
760
|
+
/**
|
|
761
|
+
* What is known about a registered strategy: that it compiled, and what validating it found.
|
|
762
|
+
*
|
|
763
|
+
* **`validation: passed` does not mean the strategy is correct.** It means the class loaded and
|
|
764
|
+
* survived the first event of a short synthetic run — a floor, not a guarantee. When
|
|
765
|
+
* `dryRunIncomplete` is true it is a lower floor still, because the run did not finish.
|
|
766
|
+
*
|
|
767
|
+
*/
|
|
768
|
+
type StrategyState = {
|
|
769
|
+
strategyId: StrategyId;
|
|
770
|
+
/**
|
|
771
|
+
* * `not_validated` — registered, never checked. `POST /strategy/{strategyId}/validate`
|
|
772
|
+
* checks it.
|
|
773
|
+
* * `pending` — a check was asked for and has not answered yet.
|
|
774
|
+
* * `passed` — the class loaded and survived its first event.
|
|
775
|
+
* * `failed` — it did not; `detail` says how.
|
|
776
|
+
*
|
|
777
|
+
*/
|
|
778
|
+
validation: "not_validated" | "pending" | "passed" | "failed";
|
|
779
|
+
/**
|
|
780
|
+
* When the live compilation was produced.
|
|
781
|
+
*/
|
|
782
|
+
compiledAt?: string;
|
|
783
|
+
/**
|
|
784
|
+
* The market data a strategy needs, read off the compiled class rather than off anything
|
|
785
|
+
* you sent — `TickerStrategy`, `KlineStrategy` and `FundingRateStrategy` each declare one,
|
|
786
|
+
* and a `MultiSourceStrategy` declares a set.
|
|
787
|
+
*
|
|
788
|
+
* **Absent is not "needs nothing".** A strategy always needs market data, so an absent
|
|
789
|
+
* field never means an empty requirement — it means the platform could not establish the
|
|
790
|
+
* answer without constructing your strategy, which it will not do to fill in a field.
|
|
791
|
+
* That happens for a `MultiSourceStrategy`, for a class that overrides
|
|
792
|
+
* `getMarketDataSource()`, and for anything registered before this field existed;
|
|
793
|
+
* re-registering the source fills it in.
|
|
794
|
+
*
|
|
795
|
+
*/
|
|
796
|
+
requiredSources?: Array<"Ticker" | "KLine" | "FundingRate">;
|
|
797
|
+
/**
|
|
798
|
+
* When the verdict was recorded. Absent until there is one.
|
|
799
|
+
*/
|
|
800
|
+
validatedAt?: string;
|
|
801
|
+
/**
|
|
802
|
+
* Why validation failed, or why a queued check has not reported. Present on `failed`, and
|
|
803
|
+
* alongside `validationStalled`.
|
|
804
|
+
*
|
|
805
|
+
*/
|
|
806
|
+
detail?: string;
|
|
807
|
+
/**
|
|
808
|
+
* What the run surfaced. An empty or absent list is not a clean bill of health when
|
|
809
|
+
* `dryRunIncomplete` is true — see that field.
|
|
810
|
+
*
|
|
811
|
+
*/
|
|
812
|
+
notices?: Array<Notice>;
|
|
813
|
+
/**
|
|
814
|
+
* How many notices were dropped past the cap. Absent when none were.
|
|
815
|
+
*/
|
|
816
|
+
noticesTruncated?: number;
|
|
817
|
+
/**
|
|
818
|
+
* The check did not finish its budget — it ran out of time, was refused because the
|
|
819
|
+
* platform was already holding too many unfinishable runs, or hit a failure attributable to
|
|
820
|
+
* the synthetic instrument rather than to your strategy. The verdict stands as far as it
|
|
821
|
+
* went; it simply reached less than a full run would.
|
|
822
|
+
*
|
|
823
|
+
*/
|
|
824
|
+
dryRunIncomplete?: boolean;
|
|
825
|
+
/**
|
|
826
|
+
* A queued check has not reported for far longer than one takes. Nothing is disproved about
|
|
827
|
+
* the strategy — the check has not run. Stop waiting and re-request it later.
|
|
828
|
+
*
|
|
829
|
+
*/
|
|
830
|
+
validationStalled?: boolean;
|
|
831
|
+
};
|
|
513
832
|
type AuthTokenResponse = {
|
|
514
833
|
/**
|
|
515
834
|
* Short-lived HS256 JWT. Send as `Authorization: Bearer <token>` on all other endpoints.
|
|
@@ -518,7 +837,7 @@ type AuthTokenResponse = {
|
|
|
518
837
|
/**
|
|
519
838
|
* Always `Bearer`.
|
|
520
839
|
*/
|
|
521
|
-
token_type:
|
|
840
|
+
token_type: "Bearer";
|
|
522
841
|
/**
|
|
523
842
|
* Seconds until the JWT expires (typically 3600).
|
|
524
843
|
*/
|
|
@@ -530,7 +849,7 @@ type AuthTokenResponse = {
|
|
|
530
849
|
/**
|
|
531
850
|
* Subscription tier this token was issued for. Drives rate limits and feature flags on downstream endpoints.
|
|
532
851
|
*/
|
|
533
|
-
tier:
|
|
852
|
+
tier: "free" | "basic" | "pro" | "elite";
|
|
534
853
|
};
|
|
535
854
|
/**
|
|
536
855
|
* Error envelope returned by `POST /auth/token` when the API key is rejected.
|
|
@@ -539,7 +858,7 @@ type AuthTokenError = {
|
|
|
539
858
|
/**
|
|
540
859
|
* Machine-readable error reason.
|
|
541
860
|
*/
|
|
542
|
-
code:
|
|
861
|
+
code: "invalid_apikey" | "apikey_revoked" | "apikey_expired";
|
|
543
862
|
/**
|
|
544
863
|
* Human-readable description of the failure.
|
|
545
864
|
*/
|
|
@@ -549,7 +868,7 @@ type AuthenticateData = {
|
|
|
549
868
|
body?: never;
|
|
550
869
|
path?: never;
|
|
551
870
|
query?: never;
|
|
552
|
-
url:
|
|
871
|
+
url: "/auth/token";
|
|
553
872
|
};
|
|
554
873
|
type AuthenticateErrors = {
|
|
555
874
|
/**
|
|
@@ -573,7 +892,7 @@ type ListExchangesData = {
|
|
|
573
892
|
body?: never;
|
|
574
893
|
path?: never;
|
|
575
894
|
query?: never;
|
|
576
|
-
url:
|
|
895
|
+
url: "/exchanges";
|
|
577
896
|
};
|
|
578
897
|
type ListExchangesResponses = {
|
|
579
898
|
/**
|
|
@@ -591,7 +910,7 @@ type ListInstrumentsData = {
|
|
|
591
910
|
exchangeId: string;
|
|
592
911
|
};
|
|
593
912
|
query?: never;
|
|
594
|
-
url:
|
|
913
|
+
url: "/exchange/{exchangeId}/instruments";
|
|
595
914
|
};
|
|
596
915
|
type ListInstrumentsErrors = {
|
|
597
916
|
/**
|
|
@@ -617,10 +936,10 @@ type ListSegmentInstrumentsData = {
|
|
|
617
936
|
/**
|
|
618
937
|
* Market segment to list instruments for
|
|
619
938
|
*/
|
|
620
|
-
segment:
|
|
939
|
+
segment: "spot" | "futures";
|
|
621
940
|
};
|
|
622
941
|
query?: never;
|
|
623
|
-
url:
|
|
942
|
+
url: "/exchange/{exchangeId}/{segment}/instruments";
|
|
624
943
|
};
|
|
625
944
|
type ListSegmentInstrumentsErrors = {
|
|
626
945
|
/**
|
|
@@ -665,9 +984,9 @@ type DownloadTickersData = {
|
|
|
665
984
|
* [lastra-convert](https://github.com/QTSurfer/lastra-convert).
|
|
666
985
|
*
|
|
667
986
|
*/
|
|
668
|
-
format?:
|
|
987
|
+
format?: "lastra" | "parquet";
|
|
669
988
|
};
|
|
670
|
-
url:
|
|
989
|
+
url: "/exchange/{exchangeId}/tickers/{base}/{quote}";
|
|
671
990
|
};
|
|
672
991
|
type DownloadTickersErrors = {
|
|
673
992
|
/**
|
|
@@ -723,9 +1042,9 @@ type DownloadKlinesData = {
|
|
|
723
1042
|
* `parquet` returns Parquet via on-the-fly conversion.
|
|
724
1043
|
*
|
|
725
1044
|
*/
|
|
726
|
-
format?:
|
|
1045
|
+
format?: "lastra" | "parquet";
|
|
727
1046
|
};
|
|
728
|
-
url:
|
|
1047
|
+
url: "/exchange/{exchangeId}/klines/{base}/{quote}";
|
|
729
1048
|
};
|
|
730
1049
|
type DownloadKlinesErrors = {
|
|
731
1050
|
/**
|
|
@@ -757,70 +1076,89 @@ type CompileStrategyData = {
|
|
|
757
1076
|
* Raw strategy Java source code
|
|
758
1077
|
*/
|
|
759
1078
|
body: string;
|
|
760
|
-
headers?: {
|
|
761
|
-
/**
|
|
762
|
-
* When `true`, compile asynchronously and return `202` with a `jobId`.
|
|
763
|
-
*/
|
|
764
|
-
'X-Compile-Async'?: boolean;
|
|
765
|
-
};
|
|
766
1079
|
path?: never;
|
|
767
1080
|
query?: never;
|
|
768
|
-
url:
|
|
1081
|
+
url: "/strategy";
|
|
769
1082
|
};
|
|
770
1083
|
type CompileStrategyErrors = {
|
|
771
1084
|
/**
|
|
772
|
-
*
|
|
1085
|
+
* The source is not valid Java; the message carries the compiler diagnostics. Nothing is
|
|
1086
|
+
* registered, so there is no id to look up afterwards.
|
|
1087
|
+
*
|
|
773
1088
|
*/
|
|
774
1089
|
400: ResponseError;
|
|
1090
|
+
/**
|
|
1091
|
+
* Too many compilations in flight. Retry later.
|
|
1092
|
+
*/
|
|
1093
|
+
429: ResponseError;
|
|
775
1094
|
};
|
|
776
1095
|
type CompileStrategyError = CompileStrategyErrors[keyof CompileStrategyErrors];
|
|
777
1096
|
type CompileStrategyResponses = {
|
|
778
1097
|
/**
|
|
779
|
-
*
|
|
1098
|
+
* Compiled and registered
|
|
780
1099
|
*/
|
|
781
1100
|
200: {
|
|
782
1101
|
strategyId: StrategyId;
|
|
783
1102
|
};
|
|
1103
|
+
};
|
|
1104
|
+
type CompileStrategyResponse = CompileStrategyResponses[keyof CompileStrategyResponses];
|
|
1105
|
+
type ValidateStrategyData = {
|
|
1106
|
+
body?: never;
|
|
1107
|
+
path: {
|
|
1108
|
+
/**
|
|
1109
|
+
* The id returned by `POST /strategy`
|
|
1110
|
+
*/
|
|
1111
|
+
strategyId: StrategyId;
|
|
1112
|
+
};
|
|
1113
|
+
query?: never;
|
|
1114
|
+
url: "/strategy/{strategyId}/validate";
|
|
1115
|
+
};
|
|
1116
|
+
type ValidateStrategyErrors = {
|
|
784
1117
|
/**
|
|
785
|
-
*
|
|
1118
|
+
* No such registered strategy for this user
|
|
786
1119
|
*/
|
|
787
|
-
|
|
1120
|
+
404: ResponseError;
|
|
788
1121
|
};
|
|
789
|
-
type
|
|
1122
|
+
type ValidateStrategyError = ValidateStrategyErrors[keyof ValidateStrategyErrors];
|
|
1123
|
+
type ValidateStrategyResponses = {
|
|
1124
|
+
/**
|
|
1125
|
+
* Already validated; the recorded verdict, unchanged
|
|
1126
|
+
*/
|
|
1127
|
+
200: StrategyState;
|
|
1128
|
+
/**
|
|
1129
|
+
* Validation queued. Not a terminal outcome — poll `GET /strategy/{strategyId}` until
|
|
1130
|
+
* `validation` leaves `pending`.
|
|
1131
|
+
*
|
|
1132
|
+
*/
|
|
1133
|
+
202: {
|
|
1134
|
+
strategyId: StrategyId;
|
|
1135
|
+
validation: "pending";
|
|
1136
|
+
};
|
|
1137
|
+
};
|
|
1138
|
+
type ValidateStrategyResponse = ValidateStrategyResponses[keyof ValidateStrategyResponses];
|
|
790
1139
|
type GetStrategyData = {
|
|
791
1140
|
body?: never;
|
|
792
1141
|
path: {
|
|
793
1142
|
/**
|
|
794
|
-
* The id returned by `POST /strategy`
|
|
1143
|
+
* The id returned by `POST /strategy`
|
|
795
1144
|
*/
|
|
796
|
-
strategyId:
|
|
1145
|
+
strategyId: StrategyId;
|
|
797
1146
|
};
|
|
798
1147
|
query?: never;
|
|
799
|
-
url:
|
|
1148
|
+
url: "/strategy/{strategyId}";
|
|
800
1149
|
};
|
|
801
1150
|
type GetStrategyErrors = {
|
|
802
1151
|
/**
|
|
803
|
-
*
|
|
1152
|
+
* No such registered strategy for this user
|
|
804
1153
|
*/
|
|
805
1154
|
404: ResponseError;
|
|
806
1155
|
};
|
|
807
1156
|
type GetStrategyError = GetStrategyErrors[keyof GetStrategyErrors];
|
|
808
1157
|
type GetStrategyResponses = {
|
|
809
1158
|
/**
|
|
810
|
-
* Strategy
|
|
1159
|
+
* Strategy state
|
|
811
1160
|
*/
|
|
812
|
-
200:
|
|
813
|
-
/**
|
|
814
|
-
* Compile job id (only set in async mode)
|
|
815
|
-
*/
|
|
816
|
-
jobId?: string;
|
|
817
|
-
status: 'New' | 'Started' | 'Completed' | 'Aborted' | 'Failed';
|
|
818
|
-
strategyId?: StrategyId;
|
|
819
|
-
/**
|
|
820
|
-
* Compilation error messages when `status` is `Failed`
|
|
821
|
-
*/
|
|
822
|
-
statusDetail?: string | null;
|
|
823
|
-
};
|
|
1161
|
+
200: StrategyState;
|
|
824
1162
|
};
|
|
825
1163
|
type GetStrategyResponse = GetStrategyResponses[keyof GetStrategyResponses];
|
|
826
1164
|
type PrepareBacktestData = {
|
|
@@ -839,7 +1177,7 @@ type PrepareBacktestData = {
|
|
|
839
1177
|
type: DataSourceType;
|
|
840
1178
|
};
|
|
841
1179
|
query?: never;
|
|
842
|
-
url:
|
|
1180
|
+
url: "/backtest/{exchangeId}/{type}/prepare";
|
|
843
1181
|
};
|
|
844
1182
|
type PrepareBacktestErrors = {
|
|
845
1183
|
/**
|
|
@@ -884,7 +1222,7 @@ type GetPrepareStatusData = {
|
|
|
884
1222
|
jobId: string;
|
|
885
1223
|
};
|
|
886
1224
|
query?: never;
|
|
887
|
-
url:
|
|
1225
|
+
url: "/backtest/{exchangeId}/{type}/prepare/{jobId}";
|
|
888
1226
|
};
|
|
889
1227
|
type GetPrepareStatusErrors = {
|
|
890
1228
|
/**
|
|
@@ -915,7 +1253,7 @@ type ExecuteSweepData = {
|
|
|
915
1253
|
requestId: string;
|
|
916
1254
|
};
|
|
917
1255
|
query?: never;
|
|
918
|
-
url:
|
|
1256
|
+
url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}";
|
|
919
1257
|
};
|
|
920
1258
|
type ExecuteSweepErrors = {
|
|
921
1259
|
/**
|
|
@@ -948,7 +1286,7 @@ type CancelSweepData = {
|
|
|
948
1286
|
sweepId: string;
|
|
949
1287
|
};
|
|
950
1288
|
query?: never;
|
|
951
|
-
url:
|
|
1289
|
+
url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}";
|
|
952
1290
|
};
|
|
953
1291
|
type CancelSweepErrors = {
|
|
954
1292
|
/**
|
|
@@ -962,7 +1300,7 @@ type CancelSweepResponses = {
|
|
|
962
1300
|
* Cancellation requested.
|
|
963
1301
|
*/
|
|
964
1302
|
200: {
|
|
965
|
-
status:
|
|
1303
|
+
status: "cancelling";
|
|
966
1304
|
sweepId: string;
|
|
967
1305
|
};
|
|
968
1306
|
};
|
|
@@ -976,13 +1314,17 @@ type GetSweepResultData = {
|
|
|
976
1314
|
sweepId: string;
|
|
977
1315
|
};
|
|
978
1316
|
query?: {
|
|
979
|
-
objective?:
|
|
1317
|
+
objective?: "sharpe" | "sortino" | "pnl" | "maxdd";
|
|
980
1318
|
/**
|
|
981
1319
|
* `natural` is stable materialisation order; `ranked` is the display view.
|
|
982
1320
|
*/
|
|
983
|
-
order?:
|
|
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";
|
|
984
1326
|
};
|
|
985
|
-
url:
|
|
1327
|
+
url: "/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}";
|
|
986
1328
|
};
|
|
987
1329
|
type GetSweepResultErrors = {
|
|
988
1330
|
/**
|
|
@@ -998,6 +1340,36 @@ type GetSweepResultResponses = {
|
|
|
998
1340
|
200: ExecuteSweepResult;
|
|
999
1341
|
};
|
|
1000
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];
|
|
1001
1373
|
type ExecuteBacktestData = {
|
|
1002
1374
|
/**
|
|
1003
1375
|
* Execute task parameters
|
|
@@ -1026,7 +1398,7 @@ type ExecuteBacktestData = {
|
|
|
1026
1398
|
type: DataSourceType;
|
|
1027
1399
|
};
|
|
1028
1400
|
query?: never;
|
|
1029
|
-
url:
|
|
1401
|
+
url: "/backtest/{exchangeId}/{type}/execute";
|
|
1030
1402
|
};
|
|
1031
1403
|
type ExecuteBacktestErrors = {
|
|
1032
1404
|
/**
|
|
@@ -1061,7 +1433,7 @@ type CancelBacktestData = {
|
|
|
1061
1433
|
jobId: string;
|
|
1062
1434
|
};
|
|
1063
1435
|
query?: never;
|
|
1064
|
-
url:
|
|
1436
|
+
url: "/backtest/{exchangeId}/{type}/execute/{jobId}";
|
|
1065
1437
|
};
|
|
1066
1438
|
type CancelBacktestErrors = {
|
|
1067
1439
|
/**
|
|
@@ -1075,7 +1447,7 @@ type CancelBacktestResponses = {
|
|
|
1075
1447
|
* Cancellation request accepted
|
|
1076
1448
|
*/
|
|
1077
1449
|
200: {
|
|
1078
|
-
status?:
|
|
1450
|
+
status?: "cancelling";
|
|
1079
1451
|
jobId?: string;
|
|
1080
1452
|
};
|
|
1081
1453
|
};
|
|
@@ -1097,7 +1469,7 @@ type GetBacktestResultData = {
|
|
|
1097
1469
|
jobId: string;
|
|
1098
1470
|
};
|
|
1099
1471
|
query?: never;
|
|
1100
|
-
url:
|
|
1472
|
+
url: "/backtest/{exchangeId}/{type}/execute/{jobId}";
|
|
1101
1473
|
};
|
|
1102
1474
|
type GetBacktestResultErrors = {
|
|
1103
1475
|
/**
|
|
@@ -1133,7 +1505,7 @@ type GetBacktestResultResponses = {
|
|
|
1133
1505
|
};
|
|
1134
1506
|
type GetBacktestResultResponse = GetBacktestResultResponses[keyof GetBacktestResultResponses];
|
|
1135
1507
|
type ClientOptions = {
|
|
1136
|
-
baseUrl:
|
|
1508
|
+
baseUrl: "https://api.staging.qtsurfer.com/v1" | "https://api.qtsurfer.com/v1" | (string & {});
|
|
1137
1509
|
};
|
|
1138
1510
|
|
|
1139
1511
|
type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = Options$1<TData, ThrowOnError> & {
|
|
@@ -1231,29 +1603,58 @@ declare const downloadTickers: <ThrowOnError extends boolean = false>(options: O
|
|
|
1231
1603
|
*/
|
|
1232
1604
|
declare const downloadKlines: <ThrowOnError extends boolean = false>(options: Options<DownloadKlinesData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<Blob | File, ResponseError, ThrowOnError>;
|
|
1233
1605
|
/**
|
|
1234
|
-
* Compile a strategy
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1606
|
+
* Compile and register a strategy
|
|
1607
|
+
* Compiles raw strategy source and registers it, returning its `strategyId`.
|
|
1608
|
+
*
|
|
1609
|
+
* **This answers one question: is the source valid Java.** It compiles, registers, and hands
|
|
1610
|
+
* back the id — nothing more. Whether the class can actually run is
|
|
1611
|
+
* `POST /strategy/{strategyId}/validate`, and everything known about a strategy, validation
|
|
1612
|
+
* included, is read from `GET /strategy/{strategyId}`. One place to ask, so there is no second
|
|
1613
|
+
* answer to keep in step.
|
|
1614
|
+
*
|
|
1615
|
+
* The `strategyId` is derived from what the code *means*, not from how it is written. Adding a
|
|
1616
|
+
* comment, inserting a blank line, re-indenting, reordering imports, or moving a method around
|
|
1617
|
+
* all return the **same** id — you have not created a second strategy. Renaming a variable,
|
|
1618
|
+
* changing an identifier's case, reordering fields, or reordering statements inside a method
|
|
1619
|
+
* return a **different** one.
|
|
1239
1620
|
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1621
|
+
* Two rules follow, and they are worth designing around:
|
|
1622
|
+
*
|
|
1623
|
+
* - re-submitting a strategy you have only reformatted is free, and gives you back the id you
|
|
1624
|
+
* already had, along with any validation already recorded against it;
|
|
1625
|
+
* - the id says nothing about *behaviour*. Two sources that compute the same thing by
|
|
1626
|
+
* different means are two strategies, because deciding otherwise would mean deciding program
|
|
1627
|
+
* equivalence.
|
|
1242
1628
|
*
|
|
1243
1629
|
*/
|
|
1244
|
-
declare const compileStrategy: <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<
|
|
1630
|
+
declare const compileStrategy: <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<{
|
|
1631
|
+
strategyId: StrategyId;
|
|
1632
|
+
}, ResponseError, ThrowOnError>;
|
|
1245
1633
|
/**
|
|
1246
|
-
*
|
|
1247
|
-
*
|
|
1248
|
-
*
|
|
1634
|
+
* Check that a registered strategy can actually run
|
|
1635
|
+
* Instantiates the compiled class and drives it through a bounded synthetic series, so a wiring
|
|
1636
|
+
* fault surfaces here instead of at your first backtest. The verdict — pass or fail, plus any
|
|
1637
|
+
* engine notices — is recorded and served from `GET /strategy/{strategyId}`.
|
|
1638
|
+
*
|
|
1639
|
+
* **Idempotent.** If a verdict already exists for the current compilation it comes straight
|
|
1640
|
+
* back with `200` and nothing is queued. Otherwise the check is queued and this returns `202`;
|
|
1641
|
+
* poll `GET /strategy/{strategyId}` until `validation` is `passed` or `failed`.
|
|
1642
|
+
*
|
|
1643
|
+
* Recompiling supersedes a verdict, which makes this callable again — the old answer described
|
|
1644
|
+
* bytecode that is no longer what would run.
|
|
1249
1645
|
*
|
|
1250
1646
|
*/
|
|
1251
|
-
declare const
|
|
1252
|
-
|
|
1253
|
-
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
|
|
1647
|
+
declare const validateStrategy: <ThrowOnError extends boolean = false>(options: Options<ValidateStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<ValidateStrategyResponse, ResponseError, ThrowOnError>;
|
|
1648
|
+
/**
|
|
1649
|
+
* Get a strategy by id, including its validation state
|
|
1650
|
+
* Reports that the strategy is registered — implied by a `200` at all — and what validating it
|
|
1651
|
+
* found.
|
|
1652
|
+
*
|
|
1653
|
+
* A `404` means one thing: no such registered strategy for this user. It is never a stale or
|
|
1654
|
+
* expired answer; registration and verdict are stored durably, not cached.
|
|
1655
|
+
*
|
|
1656
|
+
*/
|
|
1657
|
+
declare const getStrategy: <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<StrategyState, ResponseError, ThrowOnError>;
|
|
1257
1658
|
/**
|
|
1258
1659
|
* Prepare backtest data
|
|
1259
1660
|
* Enqueues a prepare task over the requested date range. Returns immediately with a `jobId`;
|
|
@@ -1277,6 +1678,17 @@ declare const getPrepareStatus: <ThrowOnError extends boolean = false>(options:
|
|
|
1277
1678
|
* The backend expands and executes the matrix internally; clients poll the returned
|
|
1278
1679
|
* `sweepId` for incremental results.
|
|
1279
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
|
+
*
|
|
1280
1692
|
*/
|
|
1281
1693
|
declare const executeSweep: <ThrowOnError extends boolean = false>(options: Options<ExecuteSweepData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<ExecuteSweepAccepted, ResponseError, ThrowOnError>;
|
|
1282
1694
|
/**
|
|
@@ -1293,8 +1705,59 @@ declare const cancelSweep: <ThrowOnError extends boolean = false>(options: Optio
|
|
|
1293
1705
|
* display leaderboard. `order=natural` returns every available row, untruncated, ordered by
|
|
1294
1706
|
* deterministic `runIx`; use that view when materialising durable trial rows.
|
|
1295
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
|
+
*
|
|
1296
1732
|
*/
|
|
1297
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>;
|
|
1298
1761
|
/**
|
|
1299
1762
|
* Execute a compiled strategy against a prepared dataset
|
|
1300
1763
|
* Enqueues an execute task that runs the strategy identified by `strategyId` over the data
|
|
@@ -1335,4 +1798,4 @@ declare const getBacktestResult: <ThrowOnError extends boolean = false>(options:
|
|
|
1335
1798
|
|
|
1336
1799
|
declare const client: _hey_api_client_fetch.Client;
|
|
1337
1800
|
|
|
1338
|
-
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 Options, type PrepareBacktestData, type PrepareBacktestError, type PrepareBacktestErrors, type PrepareBacktestResponse, type PrepareBacktestResponses, type PrepareJobState, type PrepareRequest, type ResponseError, type ResultMap, type StrategyId, type SweepAxis, type SweepBaseConfig, type SweepProgress, type SweepRunRow, type SweepSpecRequest, authenticate, cancelBacktest, cancelSweep, client, compileStrategy, downloadKlines, downloadTickers, executeBacktest, executeSweep, getBacktestResult, getPrepareStatus, getStrategy, getSweepResult, listExchanges, listInstruments, listSegmentInstruments, prepareBacktest };
|
|
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 };
|