@qtsurfer/api-client 0.6.0 → 0.7.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 +220 -48
- package/dist/index.js +14 -1
- package/dist/index.js.map +1 -1
- package/package.json +9 -2
- package/src/generated/schemas.gen.ts +173 -4
- package/src/generated/sdk.gen.ts +55 -11
- package/src/generated/types.gen.ts +180 -30
package/dist/index.d.ts
CHANGED
|
@@ -409,7 +409,7 @@ type BacktestJobResult = {
|
|
|
409
409
|
state: JobState;
|
|
410
410
|
};
|
|
411
411
|
/**
|
|
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.
|
|
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. `notices` carries what the run had to say about itself, and is absent when it had nothing.
|
|
413
413
|
*/
|
|
414
414
|
type ResultMap = {
|
|
415
415
|
/**
|
|
@@ -421,13 +421,36 @@ type ResultMap = {
|
|
|
421
421
|
*/
|
|
422
422
|
iops?: number;
|
|
423
423
|
/**
|
|
424
|
-
*
|
|
424
|
+
* **Not the `strategyId` you compiled with** — this is the execution context id,
|
|
425
|
+
* `strategy:<user>:<strategyId>`. The compiled strategy's id is the last `:`-separated
|
|
426
|
+
* segment; that, not this whole string, is what `GET /strategy/{strategyId}` takes.
|
|
427
|
+
*
|
|
428
|
+
* Take the segment after the last `:` rather than counting from the front: the shape has
|
|
429
|
+
* changed once already and callers that indexed a fixed position broke on it.
|
|
430
|
+
*
|
|
425
431
|
*/
|
|
426
432
|
strategyId: string;
|
|
427
433
|
/**
|
|
428
434
|
* The instrument (currency pair) that was backtested
|
|
429
435
|
*/
|
|
430
436
|
instrument: string;
|
|
437
|
+
/**
|
|
438
|
+
* Diagnostics the engine raised over this run, each with `provenance: execute`.
|
|
439
|
+
*
|
|
440
|
+
* **Absent means nothing was raised.** This is the one surface where silence is a real
|
|
441
|
+
* answer: the run happened, over your data, start to finish, and the engine found nothing
|
|
442
|
+
* worth saying. That is not true of the compile path, where an empty list only means a
|
|
443
|
+
* short synthetic series reached nothing — see `GET /strategy/{strategyId}`.
|
|
444
|
+
*
|
|
445
|
+
* Notices are raised on failed and aborted runs too, and those are the ones most worth
|
|
446
|
+
* reading: a run that produced no trades often did so for a reason stated here.
|
|
447
|
+
*
|
|
448
|
+
*/
|
|
449
|
+
notices?: Array<Notice>;
|
|
450
|
+
/**
|
|
451
|
+
* 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.
|
|
452
|
+
*/
|
|
453
|
+
noticesTruncated?: number;
|
|
431
454
|
/**
|
|
432
455
|
* Total profit and loss in the output currency
|
|
433
456
|
*/
|
|
@@ -507,9 +530,110 @@ type EquityPoint = {
|
|
|
507
530
|
equity: number;
|
|
508
531
|
};
|
|
509
532
|
/**
|
|
510
|
-
* Unique identifier for a compiled strategy
|
|
533
|
+
* Unique identifier for a compiled strategy, derived from the source itself: the same code
|
|
534
|
+
* always yields the same id, for every caller, whatever its formatting. See
|
|
535
|
+
* `POST /strategy` for exactly which rewrites preserve it and which do not.
|
|
536
|
+
*
|
|
511
537
|
*/
|
|
512
538
|
type StrategyId = string;
|
|
539
|
+
/**
|
|
540
|
+
* A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth
|
|
541
|
+
* knowing about how the strategy is wired, not necessarily an error.
|
|
542
|
+
*
|
|
543
|
+
*/
|
|
544
|
+
type Notice = {
|
|
545
|
+
/**
|
|
546
|
+
* Severity as the engine classified it.
|
|
547
|
+
*/
|
|
548
|
+
level: string;
|
|
549
|
+
/**
|
|
550
|
+
* Stable identifier for the kind of finding; safe to match on.
|
|
551
|
+
*/
|
|
552
|
+
code: string;
|
|
553
|
+
/**
|
|
554
|
+
* Human-readable explanation.
|
|
555
|
+
*/
|
|
556
|
+
message: string;
|
|
557
|
+
/**
|
|
558
|
+
* Where it came from, which matters because the two silences differ: an empty list from a
|
|
559
|
+
* real run (`execute`) is a clean bill of health, while an empty list from
|
|
560
|
+
* `compile-dry-run` is only a lower bound over a bounded synthetic series.
|
|
561
|
+
*
|
|
562
|
+
*/
|
|
563
|
+
provenance?: 'execute' | 'compile-dry-run';
|
|
564
|
+
};
|
|
565
|
+
/**
|
|
566
|
+
* What is known about a registered strategy: that it compiled, and what validating it found.
|
|
567
|
+
*
|
|
568
|
+
* **`validation: passed` does not mean the strategy is correct.** It means the class loaded and
|
|
569
|
+
* survived the first event of a short synthetic run — a floor, not a guarantee. When
|
|
570
|
+
* `dryRunIncomplete` is true it is a lower floor still, because the run did not finish.
|
|
571
|
+
*
|
|
572
|
+
*/
|
|
573
|
+
type StrategyState = {
|
|
574
|
+
strategyId: StrategyId;
|
|
575
|
+
/**
|
|
576
|
+
* * `not_validated` — registered, never checked. `POST /strategy/{strategyId}/validate`
|
|
577
|
+
* checks it.
|
|
578
|
+
* * `pending` — a check was asked for and has not answered yet.
|
|
579
|
+
* * `passed` — the class loaded and survived its first event.
|
|
580
|
+
* * `failed` — it did not; `detail` says how.
|
|
581
|
+
*
|
|
582
|
+
*/
|
|
583
|
+
validation: 'not_validated' | 'pending' | 'passed' | 'failed';
|
|
584
|
+
/**
|
|
585
|
+
* When the live compilation was produced.
|
|
586
|
+
*/
|
|
587
|
+
compiledAt?: string;
|
|
588
|
+
/**
|
|
589
|
+
* The market data a strategy needs, read off the compiled class rather than off anything
|
|
590
|
+
* you sent — `TickerStrategy`, `KlineStrategy` and `FundingRateStrategy` each declare one,
|
|
591
|
+
* and a `MultiSourceStrategy` declares a set.
|
|
592
|
+
*
|
|
593
|
+
* **Absent is not "needs nothing".** A strategy always needs market data, so an absent
|
|
594
|
+
* field never means an empty requirement — it means the platform could not establish the
|
|
595
|
+
* answer without constructing your strategy, which it will not do to fill in a field.
|
|
596
|
+
* That happens for a `MultiSourceStrategy`, for a class that overrides
|
|
597
|
+
* `getMarketDataSource()`, and for anything registered before this field existed;
|
|
598
|
+
* re-registering the source fills it in.
|
|
599
|
+
*
|
|
600
|
+
*/
|
|
601
|
+
requiredSources?: Array<'Ticker' | 'KLine' | 'FundingRate'>;
|
|
602
|
+
/**
|
|
603
|
+
* When the verdict was recorded. Absent until there is one.
|
|
604
|
+
*/
|
|
605
|
+
validatedAt?: string;
|
|
606
|
+
/**
|
|
607
|
+
* Why validation failed, or why a queued check has not reported. Present on `failed`, and
|
|
608
|
+
* alongside `validationStalled`.
|
|
609
|
+
*
|
|
610
|
+
*/
|
|
611
|
+
detail?: string;
|
|
612
|
+
/**
|
|
613
|
+
* What the run surfaced. An empty or absent list is not a clean bill of health when
|
|
614
|
+
* `dryRunIncomplete` is true — see that field.
|
|
615
|
+
*
|
|
616
|
+
*/
|
|
617
|
+
notices?: Array<Notice>;
|
|
618
|
+
/**
|
|
619
|
+
* How many notices were dropped past the cap. Absent when none were.
|
|
620
|
+
*/
|
|
621
|
+
noticesTruncated?: number;
|
|
622
|
+
/**
|
|
623
|
+
* The check did not finish its budget — it ran out of time, was refused because the
|
|
624
|
+
* platform was already holding too many unfinishable runs, or hit a failure attributable to
|
|
625
|
+
* the synthetic instrument rather than to your strategy. The verdict stands as far as it
|
|
626
|
+
* went; it simply reached less than a full run would.
|
|
627
|
+
*
|
|
628
|
+
*/
|
|
629
|
+
dryRunIncomplete?: boolean;
|
|
630
|
+
/**
|
|
631
|
+
* A queued check has not reported for far longer than one takes. Nothing is disproved about
|
|
632
|
+
* the strategy — the check has not run. Stop waiting and re-request it later.
|
|
633
|
+
*
|
|
634
|
+
*/
|
|
635
|
+
validationStalled?: boolean;
|
|
636
|
+
};
|
|
513
637
|
type AuthTokenResponse = {
|
|
514
638
|
/**
|
|
515
639
|
* Short-lived HS256 JWT. Send as `Authorization: Bearer <token>` on all other endpoints.
|
|
@@ -757,70 +881,89 @@ type CompileStrategyData = {
|
|
|
757
881
|
* Raw strategy Java source code
|
|
758
882
|
*/
|
|
759
883
|
body: string;
|
|
760
|
-
headers?: {
|
|
761
|
-
/**
|
|
762
|
-
* When `true`, compile asynchronously and return `202` with a `jobId`.
|
|
763
|
-
*/
|
|
764
|
-
'X-Compile-Async'?: boolean;
|
|
765
|
-
};
|
|
766
884
|
path?: never;
|
|
767
885
|
query?: never;
|
|
768
886
|
url: '/strategy';
|
|
769
887
|
};
|
|
770
888
|
type CompileStrategyErrors = {
|
|
771
889
|
/**
|
|
772
|
-
*
|
|
890
|
+
* The source is not valid Java; the message carries the compiler diagnostics. Nothing is
|
|
891
|
+
* registered, so there is no id to look up afterwards.
|
|
892
|
+
*
|
|
773
893
|
*/
|
|
774
894
|
400: ResponseError;
|
|
895
|
+
/**
|
|
896
|
+
* Too many compilations in flight. Retry later.
|
|
897
|
+
*/
|
|
898
|
+
429: ResponseError;
|
|
775
899
|
};
|
|
776
900
|
type CompileStrategyError = CompileStrategyErrors[keyof CompileStrategyErrors];
|
|
777
901
|
type CompileStrategyResponses = {
|
|
778
902
|
/**
|
|
779
|
-
*
|
|
903
|
+
* Compiled and registered
|
|
780
904
|
*/
|
|
781
905
|
200: {
|
|
782
906
|
strategyId: StrategyId;
|
|
783
907
|
};
|
|
908
|
+
};
|
|
909
|
+
type CompileStrategyResponse = CompileStrategyResponses[keyof CompileStrategyResponses];
|
|
910
|
+
type ValidateStrategyData = {
|
|
911
|
+
body?: never;
|
|
912
|
+
path: {
|
|
913
|
+
/**
|
|
914
|
+
* The id returned by `POST /strategy`
|
|
915
|
+
*/
|
|
916
|
+
strategyId: StrategyId;
|
|
917
|
+
};
|
|
918
|
+
query?: never;
|
|
919
|
+
url: '/strategy/{strategyId}/validate';
|
|
920
|
+
};
|
|
921
|
+
type ValidateStrategyErrors = {
|
|
784
922
|
/**
|
|
785
|
-
*
|
|
923
|
+
* No such registered strategy for this user
|
|
786
924
|
*/
|
|
787
|
-
|
|
925
|
+
404: ResponseError;
|
|
788
926
|
};
|
|
789
|
-
type
|
|
927
|
+
type ValidateStrategyError = ValidateStrategyErrors[keyof ValidateStrategyErrors];
|
|
928
|
+
type ValidateStrategyResponses = {
|
|
929
|
+
/**
|
|
930
|
+
* Already validated; the recorded verdict, unchanged
|
|
931
|
+
*/
|
|
932
|
+
200: StrategyState;
|
|
933
|
+
/**
|
|
934
|
+
* Validation queued. Not a terminal outcome — poll `GET /strategy/{strategyId}` until
|
|
935
|
+
* `validation` leaves `pending`.
|
|
936
|
+
*
|
|
937
|
+
*/
|
|
938
|
+
202: {
|
|
939
|
+
strategyId: StrategyId;
|
|
940
|
+
validation: 'pending';
|
|
941
|
+
};
|
|
942
|
+
};
|
|
943
|
+
type ValidateStrategyResponse = ValidateStrategyResponses[keyof ValidateStrategyResponses];
|
|
790
944
|
type GetStrategyData = {
|
|
791
945
|
body?: never;
|
|
792
946
|
path: {
|
|
793
947
|
/**
|
|
794
|
-
* The id returned by `POST /strategy`
|
|
948
|
+
* The id returned by `POST /strategy`
|
|
795
949
|
*/
|
|
796
|
-
strategyId:
|
|
950
|
+
strategyId: StrategyId;
|
|
797
951
|
};
|
|
798
952
|
query?: never;
|
|
799
953
|
url: '/strategy/{strategyId}';
|
|
800
954
|
};
|
|
801
955
|
type GetStrategyErrors = {
|
|
802
956
|
/**
|
|
803
|
-
*
|
|
957
|
+
* No such registered strategy for this user
|
|
804
958
|
*/
|
|
805
959
|
404: ResponseError;
|
|
806
960
|
};
|
|
807
961
|
type GetStrategyError = GetStrategyErrors[keyof GetStrategyErrors];
|
|
808
962
|
type GetStrategyResponses = {
|
|
809
963
|
/**
|
|
810
|
-
* Strategy
|
|
964
|
+
* Strategy state
|
|
811
965
|
*/
|
|
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
|
-
};
|
|
966
|
+
200: StrategyState;
|
|
824
967
|
};
|
|
825
968
|
type GetStrategyResponse = GetStrategyResponses[keyof GetStrategyResponses];
|
|
826
969
|
type PrepareBacktestData = {
|
|
@@ -1231,29 +1374,58 @@ declare const downloadTickers: <ThrowOnError extends boolean = false>(options: O
|
|
|
1231
1374
|
*/
|
|
1232
1375
|
declare const downloadKlines: <ThrowOnError extends boolean = false>(options: Options<DownloadKlinesData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<Blob | File, ResponseError, ThrowOnError>;
|
|
1233
1376
|
/**
|
|
1234
|
-
* Compile a strategy
|
|
1235
|
-
*
|
|
1236
|
-
*
|
|
1237
|
-
*
|
|
1238
|
-
*
|
|
1377
|
+
* Compile and register a strategy
|
|
1378
|
+
* Compiles raw strategy source and registers it, returning its `strategyId`.
|
|
1379
|
+
*
|
|
1380
|
+
* **This answers one question: is the source valid Java.** It compiles, registers, and hands
|
|
1381
|
+
* back the id — nothing more. Whether the class can actually run is
|
|
1382
|
+
* `POST /strategy/{strategyId}/validate`, and everything known about a strategy, validation
|
|
1383
|
+
* included, is read from `GET /strategy/{strategyId}`. One place to ask, so there is no second
|
|
1384
|
+
* answer to keep in step.
|
|
1385
|
+
*
|
|
1386
|
+
* The `strategyId` is derived from what the code *means*, not from how it is written. Adding a
|
|
1387
|
+
* comment, inserting a blank line, re-indenting, reordering imports, or moving a method around
|
|
1388
|
+
* all return the **same** id — you have not created a second strategy. Renaming a variable,
|
|
1389
|
+
* changing an identifier's case, reordering fields, or reordering statements inside a method
|
|
1390
|
+
* return a **different** one.
|
|
1391
|
+
*
|
|
1392
|
+
* Two rules follow, and they are worth designing around:
|
|
1393
|
+
*
|
|
1394
|
+
* - re-submitting a strategy you have only reformatted is free, and gives you back the id you
|
|
1395
|
+
* already had, along with any validation already recorded against it;
|
|
1396
|
+
* - the id says nothing about *behaviour*. Two sources that compute the same thing by
|
|
1397
|
+
* different means are two strategies, because deciding otherwise would mean deciding program
|
|
1398
|
+
* equivalence.
|
|
1399
|
+
*
|
|
1400
|
+
*/
|
|
1401
|
+
declare const compileStrategy: <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<{
|
|
1402
|
+
strategyId: StrategyId;
|
|
1403
|
+
}, ResponseError, ThrowOnError>;
|
|
1404
|
+
/**
|
|
1405
|
+
* Check that a registered strategy can actually run
|
|
1406
|
+
* Instantiates the compiled class and drives it through a bounded synthetic series, so a wiring
|
|
1407
|
+
* fault surfaces here instead of at your first backtest. The verdict — pass or fail, plus any
|
|
1408
|
+
* engine notices — is recorded and served from `GET /strategy/{strategyId}`.
|
|
1409
|
+
*
|
|
1410
|
+
* **Idempotent.** If a verdict already exists for the current compilation it comes straight
|
|
1411
|
+
* back with `200` and nothing is queued. Otherwise the check is queued and this returns `202`;
|
|
1412
|
+
* poll `GET /strategy/{strategyId}` until `validation` is `passed` or `failed`.
|
|
1239
1413
|
*
|
|
1240
|
-
*
|
|
1241
|
-
*
|
|
1414
|
+
* Recompiling supersedes a verdict, which makes this callable again — the old answer described
|
|
1415
|
+
* bytecode that is no longer what would run.
|
|
1242
1416
|
*
|
|
1243
1417
|
*/
|
|
1244
|
-
declare const
|
|
1418
|
+
declare const validateStrategy: <ThrowOnError extends boolean = false>(options: Options<ValidateStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<ValidateStrategyResponse, ResponseError, ThrowOnError>;
|
|
1245
1419
|
/**
|
|
1246
|
-
* Get a strategy by id, including its
|
|
1247
|
-
*
|
|
1248
|
-
*
|
|
1420
|
+
* Get a strategy by id, including its validation state
|
|
1421
|
+
* Reports that the strategy is registered — implied by a `200` at all — and what validating it
|
|
1422
|
+
* found.
|
|
1423
|
+
*
|
|
1424
|
+
* A `404` means one thing: no such registered strategy for this user. It is never a stale or
|
|
1425
|
+
* expired answer; registration and verdict are stored durably, not cached.
|
|
1249
1426
|
*
|
|
1250
1427
|
*/
|
|
1251
|
-
declare const getStrategy: <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<
|
|
1252
|
-
jobId?: string;
|
|
1253
|
-
status: "New" | "Started" | "Completed" | "Aborted" | "Failed";
|
|
1254
|
-
strategyId?: StrategyId;
|
|
1255
|
-
statusDetail?: string | null;
|
|
1256
|
-
}, ResponseError, ThrowOnError>;
|
|
1428
|
+
declare const getStrategy: <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => _hey_api_client_fetch.RequestResult<StrategyState, ResponseError, ThrowOnError>;
|
|
1257
1429
|
/**
|
|
1258
1430
|
* Prepare backtest data
|
|
1259
1431
|
* Enqueues a prepare task over the requested date range. Returns immediately with a `jobId`;
|
|
@@ -1335,4 +1507,4 @@ declare const getBacktestResult: <ThrowOnError extends boolean = false>(options:
|
|
|
1335
1507
|
|
|
1336
1508
|
declare const client: _hey_api_client_fetch.Client;
|
|
1337
1509
|
|
|
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 };
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -64,6 +64,18 @@ var compileStrategy = (options) => {
|
|
|
64
64
|
}
|
|
65
65
|
});
|
|
66
66
|
};
|
|
67
|
+
var validateStrategy = (options) => {
|
|
68
|
+
return (options.client ?? client).post({
|
|
69
|
+
security: [
|
|
70
|
+
{
|
|
71
|
+
scheme: "bearer",
|
|
72
|
+
type: "http"
|
|
73
|
+
}
|
|
74
|
+
],
|
|
75
|
+
url: "/strategy/{strategyId}/validate",
|
|
76
|
+
...options
|
|
77
|
+
});
|
|
78
|
+
};
|
|
67
79
|
var getStrategy = (options) => {
|
|
68
80
|
return (options.client ?? client).get({
|
|
69
81
|
security: [
|
|
@@ -201,6 +213,7 @@ export {
|
|
|
201
213
|
listExchanges,
|
|
202
214
|
listInstruments,
|
|
203
215
|
listSegmentInstruments,
|
|
204
|
-
prepareBacktest
|
|
216
|
+
prepareBacktest,
|
|
217
|
+
validateStrategy
|
|
205
218
|
};
|
|
206
219
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/generated/client.gen.ts","../src/generated/sdk.gen.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from './types.gen';\nimport { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from '@hey-api/client-fetch';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions>({\n baseUrl: 'https://api.staging.qtsurfer.com/v1'\n}));","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';\nimport type { AuthenticateData, AuthenticateResponse, AuthenticateError, ListExchangesData, ListExchangesResponse, ListInstrumentsData, ListInstrumentsResponse, ListInstrumentsError, ListSegmentInstrumentsData, ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, DownloadTickersData, DownloadTickersResponse, DownloadTickersError, DownloadKlinesData, DownloadKlinesResponse, DownloadKlinesError, CompileStrategyData, CompileStrategyResponse, CompileStrategyError, GetStrategyData, GetStrategyResponse, GetStrategyError, PrepareBacktestData, PrepareBacktestResponse, PrepareBacktestError, GetPrepareStatusData, GetPrepareStatusResponse, GetPrepareStatusError, ExecuteSweepData, ExecuteSweepResponse, ExecuteSweepError, CancelSweepData, CancelSweepResponse, CancelSweepError, GetSweepResultData, GetSweepResultResponse, GetSweepResultError, ExecuteBacktestData, ExecuteBacktestResponse, ExecuteBacktestError, CancelBacktestData, CancelBacktestResponse, CancelBacktestError, GetBacktestResultData, GetBacktestResultResponse, GetBacktestResultError } from './types.gen';\nimport { client as _heyApiClient } from './client.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\n/**\n * Exchange API key for a short-lived JWT\n * Exchanges a long-lived API key for a short-lived JWT used by every other\n * endpoint. This is the only endpoint that accepts an API key directly —\n * callers should obtain a JWT here, then send it as `Authorization: Bearer\n * <token>` to all other operations.\n *\n * The returned JWT carries the caller's subscription `tier` as a claim and\n * expires after `expires_in` seconds. Callers should refresh the token\n * before expiry (or on a `401` response) by calling this endpoint again.\n *\n */\nexport const authenticate = <ThrowOnError extends boolean = false>(options?: Options<AuthenticateData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).post<AuthenticateResponse, AuthenticateError, ThrowOnError>({\n security: [\n {\n name: 'X-API-Key',\n type: 'apiKey'\n }\n ],\n url: '/auth/token',\n ...options\n });\n};\n\n/**\n * List the available exchanges\n */\nexport const listExchanges = <ThrowOnError extends boolean = false>(options?: Options<ListExchangesData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).get<ListExchangesResponse, unknown, ThrowOnError>({\n url: '/exchanges',\n ...options\n });\n};\n\n/**\n * List an exchange's instruments (default spot segment)\n * \"Give me binance instruments\" — returns the exchange's DEFAULT segment (`spot`)\n * in `data`, each instrument with per-data-type coverage and market info. `meta`\n * confirms the served `segment` (`spot`); HAL `_links` carry `self` plus the\n * `spot` / `futures` segment-discovery links.\n *\n */\nexport const listInstruments = <ThrowOnError extends boolean = false>(options: Options<ListInstrumentsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<ListInstrumentsResponse, ListInstrumentsError, ThrowOnError>({\n url: '/exchange/{exchangeId}/instruments',\n ...options\n });\n};\n\n/**\n * List an exchange segment's instruments\n * Returns the instruments for one market segment of the exchange, each with\n * per-data-type coverage and market info. HAL `_links` carry `self` plus the\n * `spot` / `futures` segment-discovery links; the default-segment shortcut is\n * `GET /exchange/{exchangeId}/instruments` (spot).\n *\n */\nexport const listSegmentInstruments = <ThrowOnError extends boolean = false>(options: Options<ListSegmentInstrumentsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, ThrowOnError>({\n url: '/exchange/{exchangeId}/{segment}/instruments',\n ...options\n });\n};\n\n/**\n * Download one hour of tickers for an instrument as a Lastra segment\n * Serves exactly one hour of raw ticker data for the given instrument on the\n * requested exchange. The payload is a native [Lastra](https://github.com/QTSurfer/lastra-java)\n * file — QTSurfer's columnar format for tick-precision timeseries — with\n * no JSON envelope.\n *\n * One segment = one hour, aligned to UTC. The `hour` query parameter selects\n * the segment and must match `YYYY-MM-DDTHH` (no minutes/seconds, no timezone\n * suffix). Example: `hour=2026-01-15T10` returns `h10.lastra` for\n * 2026-01-15, covering `[10:00:00Z, 11:00:00Z)`. Hours not yet available\n * return `404`.\n *\n * A `format=parquet` query parameter switches the response to on-the-fly\n * Parquet conversion via [lastra-convert](https://github.com/QTSurfer/lastra-convert)\n * for clients that don't yet read Lastra. Lastra is the primary format\n * and cheaper when the client can consume it.\n *\n * Clients:\n * - [lastra-java](https://github.com/QTSurfer/lastra-java) — reference\n * Java reader/writer with per-column codecs (ALP, Gorilla, delta-varint,\n * ZSTD) and CRC32 integrity.\n * - [lastra-ts](https://github.com/QTSurfer/lastra-ts) — TypeScript reader\n * (~4 kB bundle, browser + Node.js).\n * - [duckdb-lastra](https://github.com/QTSurfer/duckdb-lastra) — DuckDB\n * extension for ad-hoc SQL over Lastra files.\n * - [lastra-convert](https://github.com/QTSurfer/lastra-convert) — CLI + Java\n * API for converting to/from Parquet, Reef, and CSV.\n * - `curl -OJ` for offline dumps (the `Content-Disposition` header sets a\n * descriptive filename).\n *\n */\nexport const downloadTickers = <ThrowOnError extends boolean = false>(options: Options<DownloadTickersData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<DownloadTickersResponse, DownloadTickersError, ThrowOnError>({\n url: '/exchange/{exchangeId}/tickers/{base}/{quote}',\n ...options\n });\n};\n\n/**\n * Download one hour of klines for an instrument as a Lastra segment\n * Same shape and semantics as `/exchange/{exchangeId}/tickers/{base}/{quote}`,\n * but serves klines (aggregated bars) instead of raw ticks. One\n * [Lastra](https://github.com/QTSurfer/lastra-java) segment = one hour of\n * klines at the exchange's native kline cadence, aligned to UTC.\n *\n * Klines use the same columnar layout as tickers — readers that handle one\n * format read the other with the same code. Use this endpoint when a\n * per-tick payload would be too large for the window of interest.\n *\n */\nexport const downloadKlines = <ThrowOnError extends boolean = false>(options: Options<DownloadKlinesData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<DownloadKlinesResponse, DownloadKlinesError, ThrowOnError>({\n url: '/exchange/{exchangeId}/klines/{base}/{quote}',\n ...options\n });\n};\n\n/**\n * Compile a strategy from source code\n * Submits raw strategy source for compilation. By default the call is synchronous and returns\n * the `strategyId` once compilation succeeds. Set the header `X-Compile-Async: true` to enqueue\n * the compile task and return immediately with a `jobId` — poll\n * `GET /strategy/{strategyId}` to check status.\n *\n * The `strategyId` is deterministic: the same source for the same user always produces the\n * same id.\n *\n */\nexport const compileStrategy = <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<CompileStrategyResponse, CompileStrategyError, ThrowOnError>({\n bodySerializer: null,\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/strategy',\n ...options,\n headers: {\n 'Content-Type': 'text/plain',\n ...options?.headers\n }\n });\n};\n\n/**\n * Get a strategy by id, including its compile status\n * Polls the status of a strategy compilation. Useful when the strategy was submitted with\n * `X-Compile-Async: true`. Returns the resolved `strategyId` once compilation completes.\n *\n */\nexport const getStrategy = <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetStrategyResponse, GetStrategyError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/strategy/{strategyId}',\n ...options\n });\n};\n\n/**\n * Prepare backtest data\n * Enqueues a prepare task over the requested date range. Returns immediately with a `jobId`;\n * poll `GET /backtest/{exchangeId}/{type}/prepare/{jobId}` for completion.\n *\n * The same params always return the same `jobId` (idempotent). Repeated calls with identical\n * params do not enqueue duplicate work — they reuse the existing job.\n *\n */\nexport const prepareBacktest = <ThrowOnError extends boolean = false>(options: Options<PrepareBacktestData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<PrepareBacktestResponse, PrepareBacktestError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/prepare',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Get the status of a prepare job\n * Retrieves the current state of the prepare job identified by `jobId`.\n * Poll until `status` is `Completed`, `Failed`, or `Aborted`.\n *\n */\nexport const getPrepareStatus = <ThrowOnError extends boolean = false>(options: Options<GetPrepareStatusData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetPrepareStatusResponse, GetPrepareStatusError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/prepare/{jobId}',\n ...options\n });\n};\n\n/**\n * Execute a parameter sweep over prepared data\n * Runs a parameter matrix over the single immutable dataset identified by `requestId`.\n * The backend expands and executes the matrix internally; clients poll the returned\n * `sweepId` for incremental results.\n *\n */\nexport const executeSweep = <ThrowOnError extends boolean = false>(options: Options<ExecuteSweepData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<ExecuteSweepResponse, ExecuteSweepError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Cancel a running parameter sweep\n * Requests cancellation between parameter vectors. Completed rows remain readable.\n */\nexport const cancelSweep = <ThrowOnError extends boolean = false>(options: Options<CancelSweepData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).delete<CancelSweepResponse, CancelSweepError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}',\n ...options\n });\n};\n\n/**\n * Get sweep progress and results\n * Returns incremental sweep progress. The default `ranked` view sorts and may truncate the\n * display leaderboard. `order=natural` returns every available row, untruncated, ordered by\n * deterministic `runIx`; use that view when materialising durable trial rows.\n *\n */\nexport const getSweepResult = <ThrowOnError extends boolean = false>(options: Options<GetSweepResultData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetSweepResultResponse, GetSweepResultError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}',\n ...options\n });\n};\n\n/**\n * Execute a compiled strategy against a prepared dataset\n * Enqueues an execute task that runs the strategy identified by `strategyId` over the data\n * prepared by the prepare job identified by `prepareJobId`. The instrument and date range are\n * recovered from the prepare job — they do not need to be sent again.\n *\n * Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`\n * for the result.\n *\n * The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same\n * `jobId` (idempotent).\n *\n */\nexport const executeBacktest = <ThrowOnError extends boolean = false>(options: Options<ExecuteBacktestData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<ExecuteBacktestResponse, ExecuteBacktestError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/execute',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Cancel a running backtest execution\n * Requests cancellation of the specified execution. The execution\n * status will transition to `Aborted` once the cancellation is\n * processed. Cancellation is asynchronous — poll the GET endpoint\n * to confirm the final status.\n *\n */\nexport const cancelBacktest = <ThrowOnError extends boolean = false>(options: Options<CancelBacktestData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).delete<CancelBacktestResponse, CancelBacktestError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/execute/{jobId}',\n ...options\n });\n};\n\n/**\n * Get the result of a backtest execution job\n * Retrieves the current state and results of the execute job identified by `jobId`.\n * Poll until `state.status` is `Completed`, `Failed`, or `Aborted`.\n *\n * A `202` means the result is not readable yet — keep polling. It is never a terminal\n * outcome, and it carries no `state`, so a poll loop that stops on a terminal status will\n * not stop on it.\n *\n */\nexport const getBacktestResult = <ThrowOnError extends boolean = false>(options: Options<GetBacktestResultData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetBacktestResultResponse, GetBacktestResultError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/execute/{jobId}',\n ...options\n });\n};"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/generated/client.gen.ts","../src/generated/sdk.gen.ts"],"sourcesContent":["// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { ClientOptions } from './types.gen';\nimport { type Config, type ClientOptions as DefaultClientOptions, createClient, createConfig } from '@hey-api/client-fetch';\n\n/**\n * The `createClientConfig()` function will be called on client initialization\n * and the returned object will become the client's initial configuration.\n *\n * You may want to initialize your client this way instead of calling\n * `setConfig()`. This is useful for example if you're using Next.js\n * to ensure your client always has the correct values.\n */\nexport type CreateClientConfig<T extends DefaultClientOptions = ClientOptions> = (override?: Config<DefaultClientOptions & T>) => Config<Required<DefaultClientOptions> & T>;\n\nexport const client = createClient(createConfig<ClientOptions>({\n baseUrl: 'https://api.staging.qtsurfer.com/v1'\n}));","// This file is auto-generated by @hey-api/openapi-ts\n\nimport type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';\nimport type { AuthenticateData, AuthenticateResponse, AuthenticateError, ListExchangesData, ListExchangesResponse, ListInstrumentsData, ListInstrumentsResponse, ListInstrumentsError, ListSegmentInstrumentsData, ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, DownloadTickersData, DownloadTickersResponse, DownloadTickersError, DownloadKlinesData, DownloadKlinesResponse, DownloadKlinesError, CompileStrategyData, CompileStrategyResponse, CompileStrategyError, ValidateStrategyData, ValidateStrategyResponse, ValidateStrategyError, GetStrategyData, GetStrategyResponse, GetStrategyError, PrepareBacktestData, PrepareBacktestResponse, PrepareBacktestError, GetPrepareStatusData, GetPrepareStatusResponse, GetPrepareStatusError, ExecuteSweepData, ExecuteSweepResponse, ExecuteSweepError, CancelSweepData, CancelSweepResponse, CancelSweepError, GetSweepResultData, GetSweepResultResponse, GetSweepResultError, ExecuteBacktestData, ExecuteBacktestResponse, ExecuteBacktestError, CancelBacktestData, CancelBacktestResponse, CancelBacktestError, GetBacktestResultData, GetBacktestResultResponse, GetBacktestResultError } from './types.gen';\nimport { client as _heyApiClient } from './client.gen';\n\nexport type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {\n /**\n * You can provide a client instance returned by `createClient()` instead of\n * individual options. This might be also useful if you want to implement a\n * custom client.\n */\n client?: Client;\n /**\n * You can pass arbitrary values through the `meta` object. This can be\n * used to access values that aren't defined as part of the SDK function.\n */\n meta?: Record<string, unknown>;\n};\n\n/**\n * Exchange API key for a short-lived JWT\n * Exchanges a long-lived API key for a short-lived JWT used by every other\n * endpoint. This is the only endpoint that accepts an API key directly —\n * callers should obtain a JWT here, then send it as `Authorization: Bearer\n * <token>` to all other operations.\n *\n * The returned JWT carries the caller's subscription `tier` as a claim and\n * expires after `expires_in` seconds. Callers should refresh the token\n * before expiry (or on a `401` response) by calling this endpoint again.\n *\n */\nexport const authenticate = <ThrowOnError extends boolean = false>(options?: Options<AuthenticateData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).post<AuthenticateResponse, AuthenticateError, ThrowOnError>({\n security: [\n {\n name: 'X-API-Key',\n type: 'apiKey'\n }\n ],\n url: '/auth/token',\n ...options\n });\n};\n\n/**\n * List the available exchanges\n */\nexport const listExchanges = <ThrowOnError extends boolean = false>(options?: Options<ListExchangesData, ThrowOnError>) => {\n return (options?.client ?? _heyApiClient).get<ListExchangesResponse, unknown, ThrowOnError>({\n url: '/exchanges',\n ...options\n });\n};\n\n/**\n * List an exchange's instruments (default spot segment)\n * \"Give me binance instruments\" — returns the exchange's DEFAULT segment (`spot`)\n * in `data`, each instrument with per-data-type coverage and market info. `meta`\n * confirms the served `segment` (`spot`); HAL `_links` carry `self` plus the\n * `spot` / `futures` segment-discovery links.\n *\n */\nexport const listInstruments = <ThrowOnError extends boolean = false>(options: Options<ListInstrumentsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<ListInstrumentsResponse, ListInstrumentsError, ThrowOnError>({\n url: '/exchange/{exchangeId}/instruments',\n ...options\n });\n};\n\n/**\n * List an exchange segment's instruments\n * Returns the instruments for one market segment of the exchange, each with\n * per-data-type coverage and market info. HAL `_links` carry `self` plus the\n * `spot` / `futures` segment-discovery links; the default-segment shortcut is\n * `GET /exchange/{exchangeId}/instruments` (spot).\n *\n */\nexport const listSegmentInstruments = <ThrowOnError extends boolean = false>(options: Options<ListSegmentInstrumentsData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, ThrowOnError>({\n url: '/exchange/{exchangeId}/{segment}/instruments',\n ...options\n });\n};\n\n/**\n * Download one hour of tickers for an instrument as a Lastra segment\n * Serves exactly one hour of raw ticker data for the given instrument on the\n * requested exchange. The payload is a native [Lastra](https://github.com/QTSurfer/lastra-java)\n * file — QTSurfer's columnar format for tick-precision timeseries — with\n * no JSON envelope.\n *\n * One segment = one hour, aligned to UTC. The `hour` query parameter selects\n * the segment and must match `YYYY-MM-DDTHH` (no minutes/seconds, no timezone\n * suffix). Example: `hour=2026-01-15T10` returns `h10.lastra` for\n * 2026-01-15, covering `[10:00:00Z, 11:00:00Z)`. Hours not yet available\n * return `404`.\n *\n * A `format=parquet` query parameter switches the response to on-the-fly\n * Parquet conversion via [lastra-convert](https://github.com/QTSurfer/lastra-convert)\n * for clients that don't yet read Lastra. Lastra is the primary format\n * and cheaper when the client can consume it.\n *\n * Clients:\n * - [lastra-java](https://github.com/QTSurfer/lastra-java) — reference\n * Java reader/writer with per-column codecs (ALP, Gorilla, delta-varint,\n * ZSTD) and CRC32 integrity.\n * - [lastra-ts](https://github.com/QTSurfer/lastra-ts) — TypeScript reader\n * (~4 kB bundle, browser + Node.js).\n * - [duckdb-lastra](https://github.com/QTSurfer/duckdb-lastra) — DuckDB\n * extension for ad-hoc SQL over Lastra files.\n * - [lastra-convert](https://github.com/QTSurfer/lastra-convert) — CLI + Java\n * API for converting to/from Parquet, Reef, and CSV.\n * - `curl -OJ` for offline dumps (the `Content-Disposition` header sets a\n * descriptive filename).\n *\n */\nexport const downloadTickers = <ThrowOnError extends boolean = false>(options: Options<DownloadTickersData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<DownloadTickersResponse, DownloadTickersError, ThrowOnError>({\n url: '/exchange/{exchangeId}/tickers/{base}/{quote}',\n ...options\n });\n};\n\n/**\n * Download one hour of klines for an instrument as a Lastra segment\n * Same shape and semantics as `/exchange/{exchangeId}/tickers/{base}/{quote}`,\n * but serves klines (aggregated bars) instead of raw ticks. One\n * [Lastra](https://github.com/QTSurfer/lastra-java) segment = one hour of\n * klines at the exchange's native kline cadence, aligned to UTC.\n *\n * Klines use the same columnar layout as tickers — readers that handle one\n * format read the other with the same code. Use this endpoint when a\n * per-tick payload would be too large for the window of interest.\n *\n */\nexport const downloadKlines = <ThrowOnError extends boolean = false>(options: Options<DownloadKlinesData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<DownloadKlinesResponse, DownloadKlinesError, ThrowOnError>({\n url: '/exchange/{exchangeId}/klines/{base}/{quote}',\n ...options\n });\n};\n\n/**\n * Compile and register a strategy\n * Compiles raw strategy source and registers it, returning its `strategyId`.\n *\n * **This answers one question: is the source valid Java.** It compiles, registers, and hands\n * back the id — nothing more. Whether the class can actually run is\n * `POST /strategy/{strategyId}/validate`, and everything known about a strategy, validation\n * included, is read from `GET /strategy/{strategyId}`. One place to ask, so there is no second\n * answer to keep in step.\n *\n * The `strategyId` is derived from what the code *means*, not from how it is written. Adding a\n * comment, inserting a blank line, re-indenting, reordering imports, or moving a method around\n * all return the **same** id — you have not created a second strategy. Renaming a variable,\n * changing an identifier's case, reordering fields, or reordering statements inside a method\n * return a **different** one.\n *\n * Two rules follow, and they are worth designing around:\n *\n * - re-submitting a strategy you have only reformatted is free, and gives you back the id you\n * already had, along with any validation already recorded against it;\n * - the id says nothing about *behaviour*. Two sources that compute the same thing by\n * different means are two strategies, because deciding otherwise would mean deciding program\n * equivalence.\n *\n */\nexport const compileStrategy = <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<CompileStrategyResponse, CompileStrategyError, ThrowOnError>({\n bodySerializer: null,\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/strategy',\n ...options,\n headers: {\n 'Content-Type': 'text/plain',\n ...options?.headers\n }\n });\n};\n\n/**\n * Check that a registered strategy can actually run\n * Instantiates the compiled class and drives it through a bounded synthetic series, so a wiring\n * fault surfaces here instead of at your first backtest. The verdict — pass or fail, plus any\n * engine notices — is recorded and served from `GET /strategy/{strategyId}`.\n *\n * **Idempotent.** If a verdict already exists for the current compilation it comes straight\n * back with `200` and nothing is queued. Otherwise the check is queued and this returns `202`;\n * poll `GET /strategy/{strategyId}` until `validation` is `passed` or `failed`.\n *\n * Recompiling supersedes a verdict, which makes this callable again — the old answer described\n * bytecode that is no longer what would run.\n *\n */\nexport const validateStrategy = <ThrowOnError extends boolean = false>(options: Options<ValidateStrategyData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<ValidateStrategyResponse, ValidateStrategyError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/strategy/{strategyId}/validate',\n ...options\n });\n};\n\n/**\n * Get a strategy by id, including its validation state\n * Reports that the strategy is registered — implied by a `200` at all — and what validating it\n * found.\n *\n * A `404` means one thing: no such registered strategy for this user. It is never a stale or\n * expired answer; registration and verdict are stored durably, not cached.\n *\n */\nexport const getStrategy = <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetStrategyResponse, GetStrategyError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/strategy/{strategyId}',\n ...options\n });\n};\n\n/**\n * Prepare backtest data\n * Enqueues a prepare task over the requested date range. Returns immediately with a `jobId`;\n * poll `GET /backtest/{exchangeId}/{type}/prepare/{jobId}` for completion.\n *\n * The same params always return the same `jobId` (idempotent). Repeated calls with identical\n * params do not enqueue duplicate work — they reuse the existing job.\n *\n */\nexport const prepareBacktest = <ThrowOnError extends boolean = false>(options: Options<PrepareBacktestData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<PrepareBacktestResponse, PrepareBacktestError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/prepare',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Get the status of a prepare job\n * Retrieves the current state of the prepare job identified by `jobId`.\n * Poll until `status` is `Completed`, `Failed`, or `Aborted`.\n *\n */\nexport const getPrepareStatus = <ThrowOnError extends boolean = false>(options: Options<GetPrepareStatusData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetPrepareStatusResponse, GetPrepareStatusError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/prepare/{jobId}',\n ...options\n });\n};\n\n/**\n * Execute a parameter sweep over prepared data\n * Runs a parameter matrix over the single immutable dataset identified by `requestId`.\n * The backend expands and executes the matrix internally; clients poll the returned\n * `sweepId` for incremental results.\n *\n */\nexport const executeSweep = <ThrowOnError extends boolean = false>(options: Options<ExecuteSweepData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<ExecuteSweepResponse, ExecuteSweepError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Cancel a running parameter sweep\n * Requests cancellation between parameter vectors. Completed rows remain readable.\n */\nexport const cancelSweep = <ThrowOnError extends boolean = false>(options: Options<CancelSweepData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).delete<CancelSweepResponse, CancelSweepError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}',\n ...options\n });\n};\n\n/**\n * Get sweep progress and results\n * Returns incremental sweep progress. The default `ranked` view sorts and may truncate the\n * display leaderboard. `order=natural` returns every available row, untruncated, ordered by\n * deterministic `runIx`; use that view when materialising durable trial rows.\n *\n */\nexport const getSweepResult = <ThrowOnError extends boolean = false>(options: Options<GetSweepResultData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetSweepResultResponse, GetSweepResultError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/executeSweep/{requestId}/{sweepId}',\n ...options\n });\n};\n\n/**\n * Execute a compiled strategy against a prepared dataset\n * Enqueues an execute task that runs the strategy identified by `strategyId` over the data\n * prepared by the prepare job identified by `prepareJobId`. The instrument and date range are\n * recovered from the prepare job — they do not need to be sent again.\n *\n * Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`\n * for the result.\n *\n * The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same\n * `jobId` (idempotent).\n *\n */\nexport const executeBacktest = <ThrowOnError extends boolean = false>(options: Options<ExecuteBacktestData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).post<ExecuteBacktestResponse, ExecuteBacktestError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/execute',\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n ...options?.headers\n }\n });\n};\n\n/**\n * Cancel a running backtest execution\n * Requests cancellation of the specified execution. The execution\n * status will transition to `Aborted` once the cancellation is\n * processed. Cancellation is asynchronous — poll the GET endpoint\n * to confirm the final status.\n *\n */\nexport const cancelBacktest = <ThrowOnError extends boolean = false>(options: Options<CancelBacktestData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).delete<CancelBacktestResponse, CancelBacktestError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/execute/{jobId}',\n ...options\n });\n};\n\n/**\n * Get the result of a backtest execution job\n * Retrieves the current state and results of the execute job identified by `jobId`.\n * Poll until `state.status` is `Completed`, `Failed`, or `Aborted`.\n *\n * A `202` means the result is not readable yet — keep polling. It is never a terminal\n * outcome, and it carries no `state`, so a poll loop that stops on a terminal status will\n * not stop on it.\n *\n */\nexport const getBacktestResult = <ThrowOnError extends boolean = false>(options: Options<GetBacktestResultData, ThrowOnError>) => {\n return (options.client ?? _heyApiClient).get<GetBacktestResultResponse, GetBacktestResultError, ThrowOnError>({\n security: [\n {\n scheme: 'bearer',\n type: 'http'\n }\n ],\n url: '/backtest/{exchangeId}/{type}/execute/{jobId}',\n ...options\n });\n};"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@qtsurfer/api-client",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Auto-generated TypeScript API client for the QTSurfer API (from OpenAPI 3.1 spec)",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -22,7 +22,11 @@
|
|
|
22
22
|
"generate": "openapi-ts",
|
|
23
23
|
"build": "tsup",
|
|
24
24
|
"lint": "tsc --noEmit",
|
|
25
|
-
"
|
|
25
|
+
"docs": "typedoc",
|
|
26
|
+
"prepublishOnly": "npm run build",
|
|
27
|
+
"changeset": "changeset",
|
|
28
|
+
"changeset:version": "changeset version",
|
|
29
|
+
"changeset:publish": "changeset publish"
|
|
26
30
|
},
|
|
27
31
|
"repository": {
|
|
28
32
|
"type": "git",
|
|
@@ -47,8 +51,11 @@
|
|
|
47
51
|
"access": "public"
|
|
48
52
|
},
|
|
49
53
|
"devDependencies": {
|
|
54
|
+
"@changesets/changelog-github": "^0.6.0",
|
|
55
|
+
"@changesets/cli": "^2.31.1",
|
|
50
56
|
"@hey-api/openapi-ts": "^0.66",
|
|
51
57
|
"tsup": "^8.5.1",
|
|
58
|
+
"typedoc": "^0.28.20",
|
|
52
59
|
"typescript": "^5.8.0"
|
|
53
60
|
},
|
|
54
61
|
"dependencies": {
|
|
@@ -783,7 +783,7 @@ export const BacktestJobResultSchema = {
|
|
|
783
783
|
|
|
784
784
|
export const ResultMapSchema = {
|
|
785
785
|
type: 'object',
|
|
786
|
-
description: '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.',
|
|
786
|
+
description: '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.',
|
|
787
787
|
required: ['strategyId', 'instrument'],
|
|
788
788
|
properties: {
|
|
789
789
|
hostName: {
|
|
@@ -799,14 +799,41 @@ export const ResultMapSchema = {
|
|
|
799
799
|
},
|
|
800
800
|
strategyId: {
|
|
801
801
|
type: 'string',
|
|
802
|
-
description:
|
|
803
|
-
|
|
802
|
+
description: `**Not the \`strategyId\` you compiled with** — this is the execution context id,
|
|
803
|
+
\`strategy:<user>:<strategyId>\`. The compiled strategy's id is the last \`:\`-separated
|
|
804
|
+
segment; that, not this whole string, is what \`GET /strategy/{strategyId}\` takes.
|
|
805
|
+
|
|
806
|
+
Take the segment after the last \`:\` rather than counting from the front: the shape has
|
|
807
|
+
changed once already and callers that indexed a fixed position broke on it.
|
|
808
|
+
`,
|
|
809
|
+
example: 'strategy:00000000-0000-0000-0000-000000000000:2iyvtenlzh9dabqtxn7nbv'
|
|
804
810
|
},
|
|
805
811
|
instrument: {
|
|
806
812
|
type: 'string',
|
|
807
813
|
description: 'The instrument (currency pair) that was backtested',
|
|
808
814
|
example: 'BTC/USDT'
|
|
809
815
|
},
|
|
816
|
+
notices: {
|
|
817
|
+
type: 'array',
|
|
818
|
+
description: `Diagnostics the engine raised over this run, each with \`provenance: execute\`.
|
|
819
|
+
|
|
820
|
+
**Absent means nothing was raised.** This is the one surface where silence is a real
|
|
821
|
+
answer: the run happened, over your data, start to finish, and the engine found nothing
|
|
822
|
+
worth saying. That is not true of the compile path, where an empty list only means a
|
|
823
|
+
short synthetic series reached nothing — see \`GET /strategy/{strategyId}\`.
|
|
824
|
+
|
|
825
|
+
Notices are raised on failed and aborted runs too, and those are the ones most worth
|
|
826
|
+
reading: a run that produced no trades often did so for a reason stated here.
|
|
827
|
+
`,
|
|
828
|
+
items: {
|
|
829
|
+
'$ref': '#/components/schemas/Notice'
|
|
830
|
+
}
|
|
831
|
+
},
|
|
832
|
+
noticesTruncated: {
|
|
833
|
+
type: 'integer',
|
|
834
|
+
description: '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.',
|
|
835
|
+
example: 3
|
|
836
|
+
},
|
|
810
837
|
pnlTotal: {
|
|
811
838
|
type: 'number',
|
|
812
839
|
format: 'double',
|
|
@@ -939,11 +966,153 @@ export const EquityPointSchema = {
|
|
|
939
966
|
} as const;
|
|
940
967
|
|
|
941
968
|
export const strategyIdSchema = {
|
|
942
|
-
description:
|
|
969
|
+
description: `Unique identifier for a compiled strategy, derived from the source itself: the same code
|
|
970
|
+
always yields the same id, for every caller, whatever its formatting. See
|
|
971
|
+
\`POST /strategy\` for exactly which rewrites preserve it and which do not.
|
|
972
|
+
`,
|
|
943
973
|
type: 'string',
|
|
944
974
|
example: '6bsh31ikwkuivhtgcoa6s4'
|
|
945
975
|
} as const;
|
|
946
976
|
|
|
977
|
+
export const NoticeSchema = {
|
|
978
|
+
type: 'object',
|
|
979
|
+
description: `A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth
|
|
980
|
+
knowing about how the strategy is wired, not necessarily an error.
|
|
981
|
+
`,
|
|
982
|
+
required: ['level', 'code', 'message'],
|
|
983
|
+
properties: {
|
|
984
|
+
level: {
|
|
985
|
+
type: 'string',
|
|
986
|
+
description: 'Severity as the engine classified it.',
|
|
987
|
+
example: 'WARN'
|
|
988
|
+
},
|
|
989
|
+
code: {
|
|
990
|
+
type: 'string',
|
|
991
|
+
description: 'Stable identifier for the kind of finding; safe to match on.',
|
|
992
|
+
example: 'indicator.bar-data-on-ticker-path'
|
|
993
|
+
},
|
|
994
|
+
message: {
|
|
995
|
+
type: 'string',
|
|
996
|
+
description: 'Human-readable explanation.',
|
|
997
|
+
example: 'Indicator requires bar data but is on the ticker path'
|
|
998
|
+
},
|
|
999
|
+
provenance: {
|
|
1000
|
+
type: 'string',
|
|
1001
|
+
enum: ['execute', 'compile-dry-run'],
|
|
1002
|
+
description: `Where it came from, which matters because the two silences differ: an empty list from a
|
|
1003
|
+
real run (\`execute\`) is a clean bill of health, while an empty list from
|
|
1004
|
+
\`compile-dry-run\` is only a lower bound over a bounded synthetic series.
|
|
1005
|
+
`,
|
|
1006
|
+
example: 'compile-dry-run'
|
|
1007
|
+
}
|
|
1008
|
+
}
|
|
1009
|
+
} as const;
|
|
1010
|
+
|
|
1011
|
+
export const StrategyStateSchema = {
|
|
1012
|
+
type: 'object',
|
|
1013
|
+
description: `What is known about a registered strategy: that it compiled, and what validating it found.
|
|
1014
|
+
|
|
1015
|
+
**\`validation: passed\` does not mean the strategy is correct.** It means the class loaded and
|
|
1016
|
+
survived the first event of a short synthetic run — a floor, not a guarantee. When
|
|
1017
|
+
\`dryRunIncomplete\` is true it is a lower floor still, because the run did not finish.
|
|
1018
|
+
`,
|
|
1019
|
+
required: ['strategyId', 'validation'],
|
|
1020
|
+
properties: {
|
|
1021
|
+
strategyId: {
|
|
1022
|
+
'$ref': '#/components/schemas/strategyId'
|
|
1023
|
+
},
|
|
1024
|
+
validation: {
|
|
1025
|
+
type: 'string',
|
|
1026
|
+
enum: ['not_validated', 'pending', 'passed', 'failed'],
|
|
1027
|
+
description: `* \`not_validated\` — registered, never checked. \`POST /strategy/{strategyId}/validate\`
|
|
1028
|
+
checks it.
|
|
1029
|
+
* \`pending\` — a check was asked for and has not answered yet.
|
|
1030
|
+
* \`passed\` — the class loaded and survived its first event.
|
|
1031
|
+
* \`failed\` — it did not; \`detail\` says how.
|
|
1032
|
+
`,
|
|
1033
|
+
example: 'passed'
|
|
1034
|
+
},
|
|
1035
|
+
compiledAt: {
|
|
1036
|
+
type: 'string',
|
|
1037
|
+
format: 'date-time',
|
|
1038
|
+
description: 'When the live compilation was produced.'
|
|
1039
|
+
},
|
|
1040
|
+
requiredSources: {
|
|
1041
|
+
type: 'array',
|
|
1042
|
+
description: `The market data a strategy needs, read off the compiled class rather than off anything
|
|
1043
|
+
you sent — \`TickerStrategy\`, \`KlineStrategy\` and \`FundingRateStrategy\` each declare one,
|
|
1044
|
+
and a \`MultiSourceStrategy\` declares a set.
|
|
1045
|
+
|
|
1046
|
+
**Absent is not "needs nothing".** A strategy always needs market data, so an absent
|
|
1047
|
+
field never means an empty requirement — it means the platform could not establish the
|
|
1048
|
+
answer without constructing your strategy, which it will not do to fill in a field.
|
|
1049
|
+
That happens for a \`MultiSourceStrategy\`, for a class that overrides
|
|
1050
|
+
\`getMarketDataSource()\`, and for anything registered before this field existed;
|
|
1051
|
+
re-registering the source fills it in.
|
|
1052
|
+
`,
|
|
1053
|
+
items: {
|
|
1054
|
+
type: 'string',
|
|
1055
|
+
enum: ['Ticker', 'KLine', 'FundingRate']
|
|
1056
|
+
},
|
|
1057
|
+
example: ['Ticker']
|
|
1058
|
+
},
|
|
1059
|
+
validatedAt: {
|
|
1060
|
+
type: 'string',
|
|
1061
|
+
format: 'date-time',
|
|
1062
|
+
description: 'When the verdict was recorded. Absent until there is one.'
|
|
1063
|
+
},
|
|
1064
|
+
detail: {
|
|
1065
|
+
type: 'string',
|
|
1066
|
+
description: `Why validation failed, or why a queued check has not reported. Present on \`failed\`, and
|
|
1067
|
+
alongside \`validationStalled\`.
|
|
1068
|
+
`
|
|
1069
|
+
},
|
|
1070
|
+
notices: {
|
|
1071
|
+
type: 'array',
|
|
1072
|
+
description: `What the run surfaced. An empty or absent list is not a clean bill of health when
|
|
1073
|
+
\`dryRunIncomplete\` is true — see that field.
|
|
1074
|
+
`,
|
|
1075
|
+
items: {
|
|
1076
|
+
'$ref': '#/components/schemas/Notice'
|
|
1077
|
+
}
|
|
1078
|
+
},
|
|
1079
|
+
noticesTruncated: {
|
|
1080
|
+
type: 'integer',
|
|
1081
|
+
description: 'How many notices were dropped past the cap. Absent when none were.',
|
|
1082
|
+
example: 3
|
|
1083
|
+
},
|
|
1084
|
+
dryRunIncomplete: {
|
|
1085
|
+
type: 'boolean',
|
|
1086
|
+
description: `The check did not finish its budget — it ran out of time, was refused because the
|
|
1087
|
+
platform was already holding too many unfinishable runs, or hit a failure attributable to
|
|
1088
|
+
the synthetic instrument rather than to your strategy. The verdict stands as far as it
|
|
1089
|
+
went; it simply reached less than a full run would.
|
|
1090
|
+
`
|
|
1091
|
+
},
|
|
1092
|
+
validationStalled: {
|
|
1093
|
+
type: 'boolean',
|
|
1094
|
+
description: `A queued check has not reported for far longer than one takes. Nothing is disproved about
|
|
1095
|
+
the strategy — the check has not run. Stop waiting and re-request it later.
|
|
1096
|
+
`
|
|
1097
|
+
}
|
|
1098
|
+
},
|
|
1099
|
+
example: {
|
|
1100
|
+
strategyId: '6bsh31ikwkuivhtgcoa6s4',
|
|
1101
|
+
validation: 'passed',
|
|
1102
|
+
compiledAt: '2026-08-04T16:23:04Z',
|
|
1103
|
+
requiredSources: ['Ticker'],
|
|
1104
|
+
validatedAt: '2026-08-04T16:24:11Z',
|
|
1105
|
+
notices: [
|
|
1106
|
+
{
|
|
1107
|
+
level: 'WARN',
|
|
1108
|
+
code: 'indicator.bar-data-on-ticker-path',
|
|
1109
|
+
message: 'Indicator requires bar data but is on the ticker path',
|
|
1110
|
+
provenance: 'compile-dry-run'
|
|
1111
|
+
}
|
|
1112
|
+
]
|
|
1113
|
+
}
|
|
1114
|
+
} as const;
|
|
1115
|
+
|
|
947
1116
|
export const AuthTokenResponseSchema = {
|
|
948
1117
|
type: 'object',
|
|
949
1118
|
required: ['access_token', 'token_type', 'expires_in', 'tier'],
|
package/src/generated/sdk.gen.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
// This file is auto-generated by @hey-api/openapi-ts
|
|
2
2
|
|
|
3
3
|
import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
|
|
4
|
-
import type { AuthenticateData, AuthenticateResponse, AuthenticateError, ListExchangesData, ListExchangesResponse, ListInstrumentsData, ListInstrumentsResponse, ListInstrumentsError, ListSegmentInstrumentsData, ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, DownloadTickersData, DownloadTickersResponse, DownloadTickersError, DownloadKlinesData, DownloadKlinesResponse, DownloadKlinesError, CompileStrategyData, CompileStrategyResponse, CompileStrategyError, GetStrategyData, GetStrategyResponse, GetStrategyError, PrepareBacktestData, PrepareBacktestResponse, PrepareBacktestError, GetPrepareStatusData, GetPrepareStatusResponse, GetPrepareStatusError, ExecuteSweepData, ExecuteSweepResponse, ExecuteSweepError, CancelSweepData, CancelSweepResponse, CancelSweepError, GetSweepResultData, GetSweepResultResponse, GetSweepResultError, ExecuteBacktestData, ExecuteBacktestResponse, ExecuteBacktestError, CancelBacktestData, CancelBacktestResponse, CancelBacktestError, GetBacktestResultData, GetBacktestResultResponse, GetBacktestResultError } from './types.gen';
|
|
4
|
+
import type { AuthenticateData, AuthenticateResponse, AuthenticateError, ListExchangesData, ListExchangesResponse, ListInstrumentsData, ListInstrumentsResponse, ListInstrumentsError, ListSegmentInstrumentsData, ListSegmentInstrumentsResponse, ListSegmentInstrumentsError, DownloadTickersData, DownloadTickersResponse, DownloadTickersError, DownloadKlinesData, DownloadKlinesResponse, DownloadKlinesError, CompileStrategyData, CompileStrategyResponse, CompileStrategyError, ValidateStrategyData, ValidateStrategyResponse, ValidateStrategyError, GetStrategyData, GetStrategyResponse, GetStrategyError, PrepareBacktestData, PrepareBacktestResponse, PrepareBacktestError, GetPrepareStatusData, GetPrepareStatusResponse, GetPrepareStatusError, ExecuteSweepData, ExecuteSweepResponse, ExecuteSweepError, CancelSweepData, CancelSweepResponse, CancelSweepError, GetSweepResultData, GetSweepResultResponse, GetSweepResultError, ExecuteBacktestData, ExecuteBacktestResponse, ExecuteBacktestError, CancelBacktestData, CancelBacktestResponse, CancelBacktestError, GetBacktestResultData, GetBacktestResultResponse, GetBacktestResultError } from './types.gen';
|
|
5
5
|
import { client as _heyApiClient } from './client.gen';
|
|
6
6
|
|
|
7
7
|
export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
|
|
@@ -142,14 +142,28 @@ export const downloadKlines = <ThrowOnError extends boolean = false>(options: Op
|
|
|
142
142
|
};
|
|
143
143
|
|
|
144
144
|
/**
|
|
145
|
-
* Compile a strategy
|
|
146
|
-
*
|
|
147
|
-
* the `strategyId` once compilation succeeds. Set the header `X-Compile-Async: true` to enqueue
|
|
148
|
-
* the compile task and return immediately with a `jobId` — poll
|
|
149
|
-
* `GET /strategy/{strategyId}` to check status.
|
|
145
|
+
* Compile and register a strategy
|
|
146
|
+
* Compiles raw strategy source and registers it, returning its `strategyId`.
|
|
150
147
|
*
|
|
151
|
-
*
|
|
152
|
-
*
|
|
148
|
+
* **This answers one question: is the source valid Java.** It compiles, registers, and hands
|
|
149
|
+
* back the id — nothing more. Whether the class can actually run is
|
|
150
|
+
* `POST /strategy/{strategyId}/validate`, and everything known about a strategy, validation
|
|
151
|
+
* included, is read from `GET /strategy/{strategyId}`. One place to ask, so there is no second
|
|
152
|
+
* answer to keep in step.
|
|
153
|
+
*
|
|
154
|
+
* The `strategyId` is derived from what the code *means*, not from how it is written. Adding a
|
|
155
|
+
* comment, inserting a blank line, re-indenting, reordering imports, or moving a method around
|
|
156
|
+
* all return the **same** id — you have not created a second strategy. Renaming a variable,
|
|
157
|
+
* changing an identifier's case, reordering fields, or reordering statements inside a method
|
|
158
|
+
* return a **different** one.
|
|
159
|
+
*
|
|
160
|
+
* Two rules follow, and they are worth designing around:
|
|
161
|
+
*
|
|
162
|
+
* - re-submitting a strategy you have only reformatted is free, and gives you back the id you
|
|
163
|
+
* already had, along with any validation already recorded against it;
|
|
164
|
+
* - the id says nothing about *behaviour*. Two sources that compute the same thing by
|
|
165
|
+
* different means are two strategies, because deciding otherwise would mean deciding program
|
|
166
|
+
* equivalence.
|
|
153
167
|
*
|
|
154
168
|
*/
|
|
155
169
|
export const compileStrategy = <ThrowOnError extends boolean = false>(options: Options<CompileStrategyData, ThrowOnError>) => {
|
|
@@ -171,9 +185,39 @@ export const compileStrategy = <ThrowOnError extends boolean = false>(options: O
|
|
|
171
185
|
};
|
|
172
186
|
|
|
173
187
|
/**
|
|
174
|
-
*
|
|
175
|
-
*
|
|
176
|
-
*
|
|
188
|
+
* Check that a registered strategy can actually run
|
|
189
|
+
* Instantiates the compiled class and drives it through a bounded synthetic series, so a wiring
|
|
190
|
+
* fault surfaces here instead of at your first backtest. The verdict — pass or fail, plus any
|
|
191
|
+
* engine notices — is recorded and served from `GET /strategy/{strategyId}`.
|
|
192
|
+
*
|
|
193
|
+
* **Idempotent.** If a verdict already exists for the current compilation it comes straight
|
|
194
|
+
* back with `200` and nothing is queued. Otherwise the check is queued and this returns `202`;
|
|
195
|
+
* poll `GET /strategy/{strategyId}` until `validation` is `passed` or `failed`.
|
|
196
|
+
*
|
|
197
|
+
* Recompiling supersedes a verdict, which makes this callable again — the old answer described
|
|
198
|
+
* bytecode that is no longer what would run.
|
|
199
|
+
*
|
|
200
|
+
*/
|
|
201
|
+
export const validateStrategy = <ThrowOnError extends boolean = false>(options: Options<ValidateStrategyData, ThrowOnError>) => {
|
|
202
|
+
return (options.client ?? _heyApiClient).post<ValidateStrategyResponse, ValidateStrategyError, ThrowOnError>({
|
|
203
|
+
security: [
|
|
204
|
+
{
|
|
205
|
+
scheme: 'bearer',
|
|
206
|
+
type: 'http'
|
|
207
|
+
}
|
|
208
|
+
],
|
|
209
|
+
url: '/strategy/{strategyId}/validate',
|
|
210
|
+
...options
|
|
211
|
+
});
|
|
212
|
+
};
|
|
213
|
+
|
|
214
|
+
/**
|
|
215
|
+
* Get a strategy by id, including its validation state
|
|
216
|
+
* Reports that the strategy is registered — implied by a `200` at all — and what validating it
|
|
217
|
+
* found.
|
|
218
|
+
*
|
|
219
|
+
* A `404` means one thing: no such registered strategy for this user. It is never a stale or
|
|
220
|
+
* expired answer; registration and verdict are stored durably, not cached.
|
|
177
221
|
*
|
|
178
222
|
*/
|
|
179
223
|
export const getStrategy = <ThrowOnError extends boolean = false>(options: Options<GetStrategyData, ThrowOnError>) => {
|
|
@@ -432,7 +432,7 @@ export type BacktestJobResult = {
|
|
|
432
432
|
};
|
|
433
433
|
|
|
434
434
|
/**
|
|
435
|
-
* 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.
|
|
435
|
+
* 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.
|
|
436
436
|
*/
|
|
437
437
|
export type ResultMap = {
|
|
438
438
|
/**
|
|
@@ -444,13 +444,36 @@ export type ResultMap = {
|
|
|
444
444
|
*/
|
|
445
445
|
iops?: number;
|
|
446
446
|
/**
|
|
447
|
-
*
|
|
447
|
+
* **Not the `strategyId` you compiled with** — this is the execution context id,
|
|
448
|
+
* `strategy:<user>:<strategyId>`. The compiled strategy's id is the last `:`-separated
|
|
449
|
+
* segment; that, not this whole string, is what `GET /strategy/{strategyId}` takes.
|
|
450
|
+
*
|
|
451
|
+
* Take the segment after the last `:` rather than counting from the front: the shape has
|
|
452
|
+
* changed once already and callers that indexed a fixed position broke on it.
|
|
453
|
+
*
|
|
448
454
|
*/
|
|
449
455
|
strategyId: string;
|
|
450
456
|
/**
|
|
451
457
|
* The instrument (currency pair) that was backtested
|
|
452
458
|
*/
|
|
453
459
|
instrument: string;
|
|
460
|
+
/**
|
|
461
|
+
* Diagnostics the engine raised over this run, each with `provenance: execute`.
|
|
462
|
+
*
|
|
463
|
+
* **Absent means nothing was raised.** This is the one surface where silence is a real
|
|
464
|
+
* answer: the run happened, over your data, start to finish, and the engine found nothing
|
|
465
|
+
* worth saying. That is not true of the compile path, where an empty list only means a
|
|
466
|
+
* short synthetic series reached nothing — see `GET /strategy/{strategyId}`.
|
|
467
|
+
*
|
|
468
|
+
* Notices are raised on failed and aborted runs too, and those are the ones most worth
|
|
469
|
+
* reading: a run that produced no trades often did so for a reason stated here.
|
|
470
|
+
*
|
|
471
|
+
*/
|
|
472
|
+
notices?: Array<Notice>;
|
|
473
|
+
/**
|
|
474
|
+
* 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.
|
|
475
|
+
*/
|
|
476
|
+
noticesTruncated?: number;
|
|
454
477
|
/**
|
|
455
478
|
* Total profit and loss in the output currency
|
|
456
479
|
*/
|
|
@@ -532,10 +555,113 @@ export type EquityPoint = {
|
|
|
532
555
|
};
|
|
533
556
|
|
|
534
557
|
/**
|
|
535
|
-
* Unique identifier for a compiled strategy
|
|
558
|
+
* Unique identifier for a compiled strategy, derived from the source itself: the same code
|
|
559
|
+
* always yields the same id, for every caller, whatever its formatting. See
|
|
560
|
+
* `POST /strategy` for exactly which rewrites preserve it and which do not.
|
|
561
|
+
*
|
|
536
562
|
*/
|
|
537
563
|
export type StrategyId = string;
|
|
538
564
|
|
|
565
|
+
/**
|
|
566
|
+
* A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth
|
|
567
|
+
* knowing about how the strategy is wired, not necessarily an error.
|
|
568
|
+
*
|
|
569
|
+
*/
|
|
570
|
+
export type Notice = {
|
|
571
|
+
/**
|
|
572
|
+
* Severity as the engine classified it.
|
|
573
|
+
*/
|
|
574
|
+
level: string;
|
|
575
|
+
/**
|
|
576
|
+
* Stable identifier for the kind of finding; safe to match on.
|
|
577
|
+
*/
|
|
578
|
+
code: string;
|
|
579
|
+
/**
|
|
580
|
+
* Human-readable explanation.
|
|
581
|
+
*/
|
|
582
|
+
message: string;
|
|
583
|
+
/**
|
|
584
|
+
* Where it came from, which matters because the two silences differ: an empty list from a
|
|
585
|
+
* real run (`execute`) is a clean bill of health, while an empty list from
|
|
586
|
+
* `compile-dry-run` is only a lower bound over a bounded synthetic series.
|
|
587
|
+
*
|
|
588
|
+
*/
|
|
589
|
+
provenance?: 'execute' | 'compile-dry-run';
|
|
590
|
+
};
|
|
591
|
+
|
|
592
|
+
/**
|
|
593
|
+
* What is known about a registered strategy: that it compiled, and what validating it found.
|
|
594
|
+
*
|
|
595
|
+
* **`validation: passed` does not mean the strategy is correct.** It means the class loaded and
|
|
596
|
+
* survived the first event of a short synthetic run — a floor, not a guarantee. When
|
|
597
|
+
* `dryRunIncomplete` is true it is a lower floor still, because the run did not finish.
|
|
598
|
+
*
|
|
599
|
+
*/
|
|
600
|
+
export type StrategyState = {
|
|
601
|
+
strategyId: StrategyId;
|
|
602
|
+
/**
|
|
603
|
+
* * `not_validated` — registered, never checked. `POST /strategy/{strategyId}/validate`
|
|
604
|
+
* checks it.
|
|
605
|
+
* * `pending` — a check was asked for and has not answered yet.
|
|
606
|
+
* * `passed` — the class loaded and survived its first event.
|
|
607
|
+
* * `failed` — it did not; `detail` says how.
|
|
608
|
+
*
|
|
609
|
+
*/
|
|
610
|
+
validation: 'not_validated' | 'pending' | 'passed' | 'failed';
|
|
611
|
+
/**
|
|
612
|
+
* When the live compilation was produced.
|
|
613
|
+
*/
|
|
614
|
+
compiledAt?: string;
|
|
615
|
+
/**
|
|
616
|
+
* The market data a strategy needs, read off the compiled class rather than off anything
|
|
617
|
+
* you sent — `TickerStrategy`, `KlineStrategy` and `FundingRateStrategy` each declare one,
|
|
618
|
+
* and a `MultiSourceStrategy` declares a set.
|
|
619
|
+
*
|
|
620
|
+
* **Absent is not "needs nothing".** A strategy always needs market data, so an absent
|
|
621
|
+
* field never means an empty requirement — it means the platform could not establish the
|
|
622
|
+
* answer without constructing your strategy, which it will not do to fill in a field.
|
|
623
|
+
* That happens for a `MultiSourceStrategy`, for a class that overrides
|
|
624
|
+
* `getMarketDataSource()`, and for anything registered before this field existed;
|
|
625
|
+
* re-registering the source fills it in.
|
|
626
|
+
*
|
|
627
|
+
*/
|
|
628
|
+
requiredSources?: Array<'Ticker' | 'KLine' | 'FundingRate'>;
|
|
629
|
+
/**
|
|
630
|
+
* When the verdict was recorded. Absent until there is one.
|
|
631
|
+
*/
|
|
632
|
+
validatedAt?: string;
|
|
633
|
+
/**
|
|
634
|
+
* Why validation failed, or why a queued check has not reported. Present on `failed`, and
|
|
635
|
+
* alongside `validationStalled`.
|
|
636
|
+
*
|
|
637
|
+
*/
|
|
638
|
+
detail?: string;
|
|
639
|
+
/**
|
|
640
|
+
* What the run surfaced. An empty or absent list is not a clean bill of health when
|
|
641
|
+
* `dryRunIncomplete` is true — see that field.
|
|
642
|
+
*
|
|
643
|
+
*/
|
|
644
|
+
notices?: Array<Notice>;
|
|
645
|
+
/**
|
|
646
|
+
* How many notices were dropped past the cap. Absent when none were.
|
|
647
|
+
*/
|
|
648
|
+
noticesTruncated?: number;
|
|
649
|
+
/**
|
|
650
|
+
* The check did not finish its budget — it ran out of time, was refused because the
|
|
651
|
+
* platform was already holding too many unfinishable runs, or hit a failure attributable to
|
|
652
|
+
* the synthetic instrument rather than to your strategy. The verdict stands as far as it
|
|
653
|
+
* went; it simply reached less than a full run would.
|
|
654
|
+
*
|
|
655
|
+
*/
|
|
656
|
+
dryRunIncomplete?: boolean;
|
|
657
|
+
/**
|
|
658
|
+
* A queued check has not reported for far longer than one takes. Nothing is disproved about
|
|
659
|
+
* the strategy — the check has not run. Stop waiting and re-request it later.
|
|
660
|
+
*
|
|
661
|
+
*/
|
|
662
|
+
validationStalled?: boolean;
|
|
663
|
+
};
|
|
664
|
+
|
|
539
665
|
export type AuthTokenResponse = {
|
|
540
666
|
/**
|
|
541
667
|
* Short-lived HS256 JWT. Send as `Authorization: Bearer <token>` on all other endpoints.
|
|
@@ -813,12 +939,6 @@ export type CompileStrategyData = {
|
|
|
813
939
|
* Raw strategy Java source code
|
|
814
940
|
*/
|
|
815
941
|
body: string;
|
|
816
|
-
headers?: {
|
|
817
|
-
/**
|
|
818
|
-
* When `true`, compile asynchronously and return `202` with a `jobId`.
|
|
819
|
-
*/
|
|
820
|
-
'X-Compile-Async'?: boolean;
|
|
821
|
-
};
|
|
822
942
|
path?: never;
|
|
823
943
|
query?: never;
|
|
824
944
|
url: '/strategy';
|
|
@@ -826,35 +946,76 @@ export type CompileStrategyData = {
|
|
|
826
946
|
|
|
827
947
|
export type CompileStrategyErrors = {
|
|
828
948
|
/**
|
|
829
|
-
*
|
|
949
|
+
* The source is not valid Java; the message carries the compiler diagnostics. Nothing is
|
|
950
|
+
* registered, so there is no id to look up afterwards.
|
|
951
|
+
*
|
|
830
952
|
*/
|
|
831
953
|
400: ResponseError;
|
|
954
|
+
/**
|
|
955
|
+
* Too many compilations in flight. Retry later.
|
|
956
|
+
*/
|
|
957
|
+
429: ResponseError;
|
|
832
958
|
};
|
|
833
959
|
|
|
834
960
|
export type CompileStrategyError = CompileStrategyErrors[keyof CompileStrategyErrors];
|
|
835
961
|
|
|
836
962
|
export type CompileStrategyResponses = {
|
|
837
963
|
/**
|
|
838
|
-
*
|
|
964
|
+
* Compiled and registered
|
|
839
965
|
*/
|
|
840
966
|
200: {
|
|
841
967
|
strategyId: StrategyId;
|
|
842
968
|
};
|
|
969
|
+
};
|
|
970
|
+
|
|
971
|
+
export type CompileStrategyResponse = CompileStrategyResponses[keyof CompileStrategyResponses];
|
|
972
|
+
|
|
973
|
+
export type ValidateStrategyData = {
|
|
974
|
+
body?: never;
|
|
975
|
+
path: {
|
|
976
|
+
/**
|
|
977
|
+
* The id returned by `POST /strategy`
|
|
978
|
+
*/
|
|
979
|
+
strategyId: StrategyId;
|
|
980
|
+
};
|
|
981
|
+
query?: never;
|
|
982
|
+
url: '/strategy/{strategyId}/validate';
|
|
983
|
+
};
|
|
984
|
+
|
|
985
|
+
export type ValidateStrategyErrors = {
|
|
843
986
|
/**
|
|
844
|
-
*
|
|
987
|
+
* No such registered strategy for this user
|
|
845
988
|
*/
|
|
846
|
-
|
|
989
|
+
404: ResponseError;
|
|
847
990
|
};
|
|
848
991
|
|
|
849
|
-
export type
|
|
992
|
+
export type ValidateStrategyError = ValidateStrategyErrors[keyof ValidateStrategyErrors];
|
|
993
|
+
|
|
994
|
+
export type ValidateStrategyResponses = {
|
|
995
|
+
/**
|
|
996
|
+
* Already validated; the recorded verdict, unchanged
|
|
997
|
+
*/
|
|
998
|
+
200: StrategyState;
|
|
999
|
+
/**
|
|
1000
|
+
* Validation queued. Not a terminal outcome — poll `GET /strategy/{strategyId}` until
|
|
1001
|
+
* `validation` leaves `pending`.
|
|
1002
|
+
*
|
|
1003
|
+
*/
|
|
1004
|
+
202: {
|
|
1005
|
+
strategyId: StrategyId;
|
|
1006
|
+
validation: 'pending';
|
|
1007
|
+
};
|
|
1008
|
+
};
|
|
1009
|
+
|
|
1010
|
+
export type ValidateStrategyResponse = ValidateStrategyResponses[keyof ValidateStrategyResponses];
|
|
850
1011
|
|
|
851
1012
|
export type GetStrategyData = {
|
|
852
1013
|
body?: never;
|
|
853
1014
|
path: {
|
|
854
1015
|
/**
|
|
855
|
-
* The id returned by `POST /strategy`
|
|
1016
|
+
* The id returned by `POST /strategy`
|
|
856
1017
|
*/
|
|
857
|
-
strategyId:
|
|
1018
|
+
strategyId: StrategyId;
|
|
858
1019
|
};
|
|
859
1020
|
query?: never;
|
|
860
1021
|
url: '/strategy/{strategyId}';
|
|
@@ -862,7 +1023,7 @@ export type GetStrategyData = {
|
|
|
862
1023
|
|
|
863
1024
|
export type GetStrategyErrors = {
|
|
864
1025
|
/**
|
|
865
|
-
*
|
|
1026
|
+
* No such registered strategy for this user
|
|
866
1027
|
*/
|
|
867
1028
|
404: ResponseError;
|
|
868
1029
|
};
|
|
@@ -871,20 +1032,9 @@ export type GetStrategyError = GetStrategyErrors[keyof GetStrategyErrors];
|
|
|
871
1032
|
|
|
872
1033
|
export type GetStrategyResponses = {
|
|
873
1034
|
/**
|
|
874
|
-
* Strategy
|
|
1035
|
+
* Strategy state
|
|
875
1036
|
*/
|
|
876
|
-
200:
|
|
877
|
-
/**
|
|
878
|
-
* Compile job id (only set in async mode)
|
|
879
|
-
*/
|
|
880
|
-
jobId?: string;
|
|
881
|
-
status: 'New' | 'Started' | 'Completed' | 'Aborted' | 'Failed';
|
|
882
|
-
strategyId?: StrategyId;
|
|
883
|
-
/**
|
|
884
|
-
* Compilation error messages when `status` is `Failed`
|
|
885
|
-
*/
|
|
886
|
-
statusDetail?: string | null;
|
|
887
|
-
};
|
|
1037
|
+
200: StrategyState;
|
|
888
1038
|
};
|
|
889
1039
|
|
|
890
1040
|
export type GetStrategyResponse = GetStrategyResponses[keyof GetStrategyResponses];
|