@qtsurfer/api-client 0.9.0 → 0.11.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.
@@ -23,15 +23,23 @@ import type {
23
23
  DownloadKlinesData,
24
24
  DownloadKlinesResponse,
25
25
  DownloadKlinesError,
26
+ ListStrategiesData,
27
+ ListStrategiesResponse,
26
28
  CompileStrategyData,
27
29
  CompileStrategyResponse,
28
30
  CompileStrategyError,
29
31
  ValidateStrategyData,
30
32
  ValidateStrategyResponse,
31
33
  ValidateStrategyError,
34
+ DeleteStrategyData,
35
+ DeleteStrategyResponse,
36
+ DeleteStrategyError,
32
37
  GetStrategyData,
33
38
  GetStrategyResponse,
34
39
  GetStrategyError,
40
+ GetStrategyCodeData,
41
+ GetStrategyCodeResponse,
42
+ GetStrategyCodeError,
35
43
  PrepareBacktestData,
36
44
  PrepareBacktestResponse,
37
45
  PrepareBacktestError,
@@ -59,6 +67,23 @@ import type {
59
67
  GetBacktestResultData,
60
68
  GetBacktestResultResponse,
61
69
  GetBacktestResultError,
70
+ ListDatasetsData,
71
+ ListDatasetsResponse,
72
+ CreateDatasetData,
73
+ CreateDatasetResponse,
74
+ CreateDatasetError,
75
+ DeleteDatasetData,
76
+ DeleteDatasetResponse,
77
+ DeleteDatasetError,
78
+ GetDatasetData,
79
+ GetDatasetResponse,
80
+ GetDatasetError,
81
+ FinalizeDatasetUploadData,
82
+ FinalizeDatasetUploadResponse,
83
+ FinalizeDatasetUploadError,
84
+ GetDatasetUploadData,
85
+ GetDatasetUploadResponse,
86
+ GetDatasetUploadError,
62
87
  } from "./types.gen";
63
88
  import { client as _heyApiClient } from "./client.gen";
64
89
 
@@ -238,6 +263,35 @@ export const downloadKlines = <ThrowOnError extends boolean = false>(
238
263
  });
239
264
  };
240
265
 
266
+ /**
267
+ * List your registered strategies
268
+ * Every strategy you have registered and not deleted, most recently compiled first.
269
+ *
270
+ * Each entry carries the same provenance `GET /strategy/{strategyId}` does — `compiledAt`,
271
+ * `requiredSources` — but not its validation state, so listing stays cheap regardless of how
272
+ * many strategies you have. Check a specific strategy's validation with `GET
273
+ * /strategy/{strategyId}`.
274
+ *
275
+ */
276
+ export const listStrategies = <ThrowOnError extends boolean = false>(
277
+ options?: Options<ListStrategiesData, ThrowOnError>
278
+ ) => {
279
+ return (options?.client ?? _heyApiClient).get<
280
+ ListStrategiesResponse,
281
+ unknown,
282
+ ThrowOnError
283
+ >({
284
+ security: [
285
+ {
286
+ scheme: "bearer",
287
+ type: "http",
288
+ },
289
+ ],
290
+ url: "/strategies",
291
+ ...options,
292
+ });
293
+ };
294
+
241
295
  /**
242
296
  * Compile and register a strategy
243
297
  * Compiles raw strategy source and registers it, returning its `strategyId`.
@@ -320,6 +374,39 @@ export const validateStrategy = <ThrowOnError extends boolean = false>(
320
374
  });
321
375
  };
322
376
 
377
+ /**
378
+ * Release a registered strategy
379
+ * Removes a strategy from `GET /strategy/{strategyId}` and `GET /strategies`. This is not
380
+ * undone by re-submitting the same source to `POST /strategy` — that registers a new
381
+ * strategy, with a new id.
382
+ *
383
+ * **Backtests you already ran against this strategy are unaffected.** Deleting it stops it
384
+ * from counting against your account and stops you from validating or re-running it under
385
+ * this id — it does not erase what already happened.
386
+ *
387
+ * Only removes a strategy you registered yourself. If you copied someone else's strategy
388
+ * (a shared/marketplace listing), deleting your copy never affects theirs, or anyone else's.
389
+ *
390
+ */
391
+ export const deleteStrategy = <ThrowOnError extends boolean = false>(
392
+ options: Options<DeleteStrategyData, ThrowOnError>
393
+ ) => {
394
+ return (options.client ?? _heyApiClient).delete<
395
+ DeleteStrategyResponse,
396
+ DeleteStrategyError,
397
+ ThrowOnError
398
+ >({
399
+ security: [
400
+ {
401
+ scheme: "bearer",
402
+ type: "http",
403
+ },
404
+ ],
405
+ url: "/strategy/{strategyId}",
406
+ ...options,
407
+ });
408
+ };
409
+
323
410
  /**
324
411
  * Get a strategy by id, including its validation state
325
412
  * Reports that the strategy is registered — implied by a `200` at all — and what validating it
@@ -348,6 +435,36 @@ export const getStrategy = <ThrowOnError extends boolean = false>(
348
435
  });
349
436
  };
350
437
 
438
+ /**
439
+ * Get a registered strategy's source, if you still have one to read
440
+ * The exact source you last submitted for this id — the same text `POST /strategy` derives
441
+ * `strategyId` from, whitespace and comments included.
442
+ *
443
+ * **"If available", not "always".** A strategy you resolve only through a shared/marketplace
444
+ * listing you copied by reference carries no source of its own, and reads as a `404` here the
445
+ * same as a `strategyId` you never registered — that is the honest answer either way, since
446
+ * from this endpoint's point of view nothing is there to return.
447
+ *
448
+ */
449
+ export const getStrategyCode = <ThrowOnError extends boolean = false>(
450
+ options: Options<GetStrategyCodeData, ThrowOnError>
451
+ ) => {
452
+ return (options.client ?? _heyApiClient).get<
453
+ GetStrategyCodeResponse,
454
+ GetStrategyCodeError,
455
+ ThrowOnError
456
+ >({
457
+ security: [
458
+ {
459
+ scheme: "bearer",
460
+ type: "http",
461
+ },
462
+ ],
463
+ url: "/strategy/{strategyId}/code",
464
+ ...options,
465
+ });
466
+ };
467
+
351
468
  /**
352
469
  * Prepare backtest data
353
470
  * Enqueues a prepare task over the requested date range. Returns immediately with a `jobId`;
@@ -356,6 +473,11 @@ export const getStrategy = <ThrowOnError extends boolean = false>(
356
473
  * The same params always return the same `jobId` (idempotent). Repeated calls with identical
357
474
  * params do not enqueue duplicate work — they reuse the existing job.
358
475
  *
476
+ * **`exchangeId: user` is reserved for your own uploaded data.** Instead of a managed
477
+ * exchange, it prepares from a dataset you created via `POST /datasets` (see the **Dataset**
478
+ * endpoints) — send `datasetId` in place of `instrument`. See `PrepareRequest` below for the
479
+ * two request shapes.
480
+ *
359
481
  */
360
482
  export const prepareBacktest = <ThrowOnError extends boolean = false>(
361
483
  options: Options<PrepareBacktestData, ThrowOnError>
@@ -385,6 +507,9 @@ export const prepareBacktest = <ThrowOnError extends boolean = false>(
385
507
  * Retrieves the current state of the prepare job identified by `jobId`.
386
508
  * Poll until `status` is `Completed`, `Failed`, or `Aborted`.
387
509
  *
510
+ * For a dataset prepare (`exchangeId: user`), coverage is reported against the dataset's own
511
+ * cadence grid instead of hours — see `cadence`/`gaps`/`largestGapSteps` on `PrepareJobState`.
512
+ *
388
513
  */
389
514
  export const getPrepareStatus = <ThrowOnError extends boolean = false>(
390
515
  options: Options<GetPrepareStatusData, ThrowOnError>
@@ -576,6 +701,9 @@ export const getSweepSensitivity = <ThrowOnError extends boolean = false>(
576
701
  * The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same
577
702
  * `jobId` (idempotent).
578
703
  *
704
+ * Works unchanged for a dataset-backed prepare (`exchangeId: user`) — the request body is
705
+ * identical either way, since the instrument and range are recovered from `prepareJobId`.
706
+ *
579
707
  */
580
708
  export const executeBacktest = <ThrowOnError extends boolean = false>(
581
709
  options: Options<ExecuteBacktestData, ThrowOnError>
@@ -655,3 +783,172 @@ export const getBacktestResult = <ThrowOnError extends boolean = false>(
655
783
  ...options,
656
784
  });
657
785
  };
786
+
787
+ /**
788
+ * List your datasets
789
+ * Every dataset you have created and not deleted, most recently created first. Never a `404`
790
+ * — an empty array if you have none, same convention as `GET /strategies`.
791
+ *
792
+ */
793
+ export const listDatasets = <ThrowOnError extends boolean = false>(
794
+ options?: Options<ListDatasetsData, ThrowOnError>
795
+ ) => {
796
+ return (options?.client ?? _heyApiClient).get<
797
+ ListDatasetsResponse,
798
+ unknown,
799
+ ThrowOnError
800
+ >({
801
+ security: [
802
+ {
803
+ scheme: "bearer",
804
+ type: "http",
805
+ },
806
+ ],
807
+ url: "/datasets",
808
+ ...options,
809
+ });
810
+ };
811
+
812
+ /**
813
+ * Create a dataset and get a URL to upload it to
814
+ * Creates a dataset AND its first upload session in one call — a presigned URL your client
815
+ * PUTs the file to directly, no API credentials involved in that PUT. Call
816
+ * `POST /datasets/{datasetId}/uploads/{uploadId}/finalize` once the upload completes to kick
817
+ * off ingest.
818
+ *
819
+ * v1 is ticker data only — `type` is not a request field, it is always `"ticker"` in the
820
+ * response. `instrument` must be a plain spot pair (`BASE/QUOTE`, exactly one `/`); derivative
821
+ * forms (e.g. `BTC/USDT:USDT`) are rejected.
822
+ *
823
+ * **Upload format.** A CSV with a header row. Required columns: `timestamp` (ISO-8601, or
824
+ * numeric epoch seconds/millis/micros — detected from the first row, then enforced for every
825
+ * later row), `close`. Optional columns: `open`, `high`, `low`, `volume`, `quoteVolume`,
826
+ * `bid`, `bidSize`, `ask`, `askSize`. Cadence and timestamp unit are discovered from the data,
827
+ * not declared.
828
+ *
829
+ */
830
+ export const createDataset = <ThrowOnError extends boolean = false>(
831
+ options: Options<CreateDatasetData, ThrowOnError>
832
+ ) => {
833
+ return (options.client ?? _heyApiClient).post<
834
+ CreateDatasetResponse,
835
+ CreateDatasetError,
836
+ ThrowOnError
837
+ >({
838
+ security: [
839
+ {
840
+ scheme: "bearer",
841
+ type: "http",
842
+ },
843
+ ],
844
+ url: "/datasets",
845
+ ...options,
846
+ headers: {
847
+ "Content-Type": "application/json",
848
+ ...options?.headers,
849
+ },
850
+ });
851
+ };
852
+
853
+ /**
854
+ * Delete a dataset
855
+ * Soft-delete — the dataset stops appearing in `GET /datasets`/`GET /datasets/{datasetId}` and
856
+ * can no longer be prepared from, but its object data is reclaimed later rather than purged
857
+ * inline, so a backtest already running against one of its versions is not disrupted.
858
+ *
859
+ */
860
+ export const deleteDataset = <ThrowOnError extends boolean = false>(
861
+ options: Options<DeleteDatasetData, ThrowOnError>
862
+ ) => {
863
+ return (options.client ?? _heyApiClient).delete<
864
+ DeleteDatasetResponse,
865
+ DeleteDatasetError,
866
+ ThrowOnError
867
+ >({
868
+ security: [
869
+ {
870
+ scheme: "bearer",
871
+ type: "http",
872
+ },
873
+ ],
874
+ url: "/datasets/{datasetId}",
875
+ ...options,
876
+ });
877
+ };
878
+
879
+ /**
880
+ * Get a dataset by id
881
+ * Detail for one dataset, plus a self link.
882
+ */
883
+ export const getDataset = <ThrowOnError extends boolean = false>(
884
+ options: Options<GetDatasetData, ThrowOnError>
885
+ ) => {
886
+ return (options.client ?? _heyApiClient).get<
887
+ GetDatasetResponse,
888
+ GetDatasetError,
889
+ ThrowOnError
890
+ >({
891
+ security: [
892
+ {
893
+ scheme: "bearer",
894
+ type: "http",
895
+ },
896
+ ],
897
+ url: "/datasets/{datasetId}",
898
+ ...options,
899
+ });
900
+ };
901
+
902
+ /**
903
+ * Finalize an uploaded file and start ingest
904
+ * Call once the file has been PUT to the `upload.url` from `POST /datasets`. Enqueues ingest
905
+ * and returns immediately; poll
906
+ * `GET /datasets/{datasetId}/uploads/{uploadId}` for the result.
907
+ *
908
+ * Idempotent — a repeat finalize of the same upload returns the same `jobId` rather than
909
+ * enqueueing a second ingest.
910
+ *
911
+ */
912
+ export const finalizeDatasetUpload = <ThrowOnError extends boolean = false>(
913
+ options: Options<FinalizeDatasetUploadData, ThrowOnError>
914
+ ) => {
915
+ return (options.client ?? _heyApiClient).post<
916
+ FinalizeDatasetUploadResponse,
917
+ FinalizeDatasetUploadError,
918
+ ThrowOnError
919
+ >({
920
+ security: [
921
+ {
922
+ scheme: "bearer",
923
+ type: "http",
924
+ },
925
+ ],
926
+ url: "/datasets/{datasetId}/uploads/{uploadId}/finalize",
927
+ ...options,
928
+ });
929
+ };
930
+
931
+ /**
932
+ * Get the state of an upload/ingest
933
+ * Poll after `POST .../finalize` until `status` is `ready` or `failed`. Also reports
934
+ * `uploading` (finalize not called yet, but the file was PUT) before you finalize at all.
935
+ *
936
+ */
937
+ export const getDatasetUpload = <ThrowOnError extends boolean = false>(
938
+ options: Options<GetDatasetUploadData, ThrowOnError>
939
+ ) => {
940
+ return (options.client ?? _heyApiClient).get<
941
+ GetDatasetUploadResponse,
942
+ GetDatasetUploadError,
943
+ ThrowOnError
944
+ >({
945
+ security: [
946
+ {
947
+ scheme: "bearer",
948
+ type: "http",
949
+ },
950
+ ],
951
+ url: "/datasets/{datasetId}/uploads/{uploadId}",
952
+ ...options,
953
+ });
954
+ };