@qtsurfer/api-client 0.20.0 → 0.22.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.
@@ -115,6 +115,9 @@ import type {
115
115
  ListPublicLiveData,
116
116
  ListPublicLiveResponse,
117
117
  ListPublicLiveError,
118
+ GetLiveRunData,
119
+ GetLiveRunResponse,
120
+ GetLiveRunError,
118
121
  UpdateLiveData,
119
122
  UpdateLiveResponse,
120
123
  UpdateLiveError,
@@ -124,6 +127,12 @@ import type {
124
127
  SendLiveCommandData,
125
128
  SendLiveCommandResponse,
126
129
  SendLiveCommandError,
130
+ RevokeLiveStreamData,
131
+ RevokeLiveStreamResponse,
132
+ RevokeLiveStreamError,
133
+ RotateLiveStreamData,
134
+ RotateLiveStreamResponse,
135
+ RotateLiveStreamError,
127
136
  GetLiveRunSignalsData,
128
137
  GetLiveRunSignalsResponse,
129
138
  GetLiveRunSignalsError,
@@ -1289,7 +1298,8 @@ export const getDatasetImport = <ThrowOnError extends boolean = false>(
1289
1298
  * Requests a stop. The run winds down at its own next check-in rather than instantly —
1290
1299
  * poll `GET`/`PATCH` `.../live` and expect `state` to remain `RUNNING` for a short window
1291
1300
  * after `desired` flips to `STOPPED`. Calling this again on an already-stopped run is not an
1292
- * error; it returns the same (unchanged) state.
1301
+ * error; it returns the same (unchanged) state. A stopped run has no stream: its `streamUrl`, if it had one,
1302
+ * stops working and is not in this response.
1293
1303
  *
1294
1304
  */
1295
1305
  export const stopLive = <ThrowOnError extends boolean = false>(
@@ -1315,7 +1325,12 @@ export const stopLive = <ThrowOnError extends boolean = false>(
1315
1325
  * Get this strategy's current (or most recent) live run
1316
1326
  * The run you last started for this strategy — its most complete state, including `params`
1317
1327
  * and the promotion `gate` once the sandbox trial has one to report. Returns the run's last
1318
- * known state even after it has stopped; this endpoint never disappears history.
1328
+ * known state even after it has stopped; this endpoint never disappears history. When the run was started
1329
+ * with a `stream`, `streamUrl` is here too while the run is running and your plan allows it.
1330
+ *
1331
+ * While the run is being executed it also carries `stats`, the run's latest counters (updates
1332
+ * processed, rate, instruments seen), refreshed about once a minute. Starting or stopping a run
1333
+ * does not return them; read them here.
1319
1334
  *
1320
1335
  */
1321
1336
  export const getLive = <ThrowOnError extends boolean = false>(
@@ -1372,6 +1387,19 @@ export const getLive = <ThrowOnError extends boolean = false>(
1372
1387
  * (it overrides `getExecutionCallback()`) has no other execution venue, so it cannot start
1373
1388
  * without a `paper` block.
1374
1389
  *
1390
+ * **Warming up.** Pass `warmFrom` to choose how many seconds before its start the run replays the market
1391
+ * feed from, so that its indicators and windows have history when the first live tick arrives. `0` replays
1392
+ * nothing: the run delivers its first signal as soon as it is running, but its indicators start empty and the
1393
+ * first bar of a window can be partial. Omitted, the platform replays from the start of the current 15-minute
1394
+ * block, which is between 0 and 900 seconds before the run's start, so the first bar of a 15-minute window is
1395
+ * complete. The value in effect, yours or the platform's, comes back as `warmFrom`. It can be set only here,
1396
+ * when the run is started. See the "Live execution" guide, "Warming up".
1397
+ *
1398
+ * **A plain WebSocket stream.** Pass `stream: true` to get a secret URL for this run's signals that a simple
1399
+ * client, or a service that passes them on to others, can open as an ordinary WebSocket, from the sandbox stage
1400
+ * on. The URL is in the response (`streamUrl`) and in `GET /strategy/{strategyId}/live`; treat it like a
1401
+ * password. See the "Live execution" guide.
1402
+ *
1375
1403
  */
1376
1404
  export const startLive = <ThrowOnError extends boolean = false>(
1377
1405
  options: Options<StartLiveData, ThrowOnError>
@@ -1444,6 +1472,40 @@ export const listPublicLive = <ThrowOnError extends boolean = false>(
1444
1472
  });
1445
1473
  };
1446
1474
 
1475
+ /**
1476
+ * Read one of your runs by its id
1477
+ * Owner only, addressed by `runId` directly rather than through its strategy: the run's own
1478
+ * canonical identity, which is what `POST`/`GET`/`DELETE` `.../live`, `GET /live` and
1479
+ * `GET /live/public` all hand out. Use it to re-read one specific run — including one you
1480
+ * stopped long ago or that is no longer your strategy's most recent — without paging through
1481
+ * `GET /live`.
1482
+ *
1483
+ * Returns the same state as `GET /strategy/{strategyId}/live` (`strategyId` is the strategy's
1484
+ * id, and `stats` is there too), plus `updatedAtMs`: when the run last changed, from any cause — a
1485
+ * state change, a promotion, a parameter update, a stop. A refresh of `stats` is not a change of
1486
+ * the run and does not move `updatedAtMs`. A run that is public is reachable by others through
1487
+ * `GET /live/public`, never through this route.
1488
+ *
1489
+ */
1490
+ export const getLiveRun = <ThrowOnError extends boolean = false>(
1491
+ options: Options<GetLiveRunData, ThrowOnError>
1492
+ ) => {
1493
+ return (options.client ?? _heyApiClient).get<
1494
+ GetLiveRunResponse,
1495
+ GetLiveRunError,
1496
+ ThrowOnError
1497
+ >({
1498
+ security: [
1499
+ {
1500
+ scheme: "bearer",
1501
+ type: "http",
1502
+ },
1503
+ ],
1504
+ url: "/live/{runId}",
1505
+ ...options,
1506
+ });
1507
+ };
1508
+
1447
1509
  /**
1448
1510
  * Change a run's visibility, name, or description
1449
1511
  * Owner only, addressed by `runId` directly rather than through its strategy — this is a
@@ -1555,6 +1617,63 @@ export const sendLiveCommand = <ThrowOnError extends boolean = false>(
1555
1617
  });
1556
1618
  };
1557
1619
 
1620
+ /**
1621
+ * Revoke a run's stream URL
1622
+ * Revokes a run's stream URL **for good**: connections open on it are closed within about 15 seconds and it
1623
+ * answers `404` from then on. The run itself is not touched, and a stream cannot be added to it again; start
1624
+ * the run again with `stream: true` for a new URL. Owner only, and always allowed, whatever your plan or the
1625
+ * run's state. Repeating it is not an error.
1626
+ *
1627
+ */
1628
+ export const revokeLiveStream = <ThrowOnError extends boolean = false>(
1629
+ options: Options<RevokeLiveStreamData, ThrowOnError>
1630
+ ) => {
1631
+ return (options.client ?? _heyApiClient).delete<
1632
+ RevokeLiveStreamResponse,
1633
+ RevokeLiveStreamError,
1634
+ ThrowOnError
1635
+ >({
1636
+ security: [
1637
+ {
1638
+ scheme: "bearer",
1639
+ type: "http",
1640
+ },
1641
+ ],
1642
+ url: "/live/{runId}/stream",
1643
+ ...options,
1644
+ });
1645
+ };
1646
+
1647
+ /**
1648
+ * Rotate a run's stream URL
1649
+ * Gives a run a **new** stream URL and retires the old one: connections open on the old URL are closed
1650
+ * within about 15 seconds and the old URL answers `404` from then on. Use it when the URL may have leaked.
1651
+ * Owner only, and only for a run that is running and was started with `stream: true` (the URL cannot be added
1652
+ * to a run later, and a revoked one cannot be brought back). The plan is checked again: a plan that may not
1653
+ * broadcast gets `429`.
1654
+ *
1655
+ * See the "Live execution" guide, "A plain WebSocket stream of a run".
1656
+ *
1657
+ */
1658
+ export const rotateLiveStream = <ThrowOnError extends boolean = false>(
1659
+ options: Options<RotateLiveStreamData, ThrowOnError>
1660
+ ) => {
1661
+ return (options.client ?? _heyApiClient).post<
1662
+ RotateLiveStreamResponse,
1663
+ RotateLiveStreamError,
1664
+ ThrowOnError
1665
+ >({
1666
+ security: [
1667
+ {
1668
+ scheme: "bearer",
1669
+ type: "http",
1670
+ },
1671
+ ],
1672
+ url: "/live/{runId}/stream",
1673
+ ...options,
1674
+ });
1675
+ };
1676
+
1558
1677
  /**
1559
1678
  * Read a run's signals
1560
1679
  * Returns one page of the signals a run has already produced, newest-last, optionally from a
@@ -1821,6 +1821,31 @@ export type StartLiveRequest = {
1821
1821
  * Request that this run's signals be relayed over its WebSocket channel, from its first signal — in the `sandbox` stage too, where only you can subscribe to it. See the "Live execution" guide.
1822
1822
  */
1823
1823
  relay?: boolean;
1824
+ /**
1825
+ * Ask for a **stream URL**: a secret address that a simple client, or a service that passes your signals
1826
+ * on to others, can open as a plain WebSocket to receive this run's signals as they are produced, one JSON
1827
+ * text frame per signal, with none of the live-execution protocol around it. The URL comes back as
1828
+ * `streamUrl` in the response to this call. Available from the `sandbox` stage on, on the plans that may
1829
+ * broadcast; any other plan gets `429`. It can be asked for **only when the run is started** (not added
1830
+ * later), and it also turns `relay` on. See the "Live execution" guide, "A plain WebSocket stream of a run".
1831
+ *
1832
+ */
1833
+ stream?: boolean;
1834
+ /**
1835
+ * How many seconds before the run's start to replay the market feed from, so the strategy's indicators and
1836
+ * windows have history when its first live tick arrives. `0` replays nothing: the run delivers its first
1837
+ * signal as soon as it is running, but its indicators start empty and the first bar of a window can be
1838
+ * partial. Omitted, the platform replays from the start of the current 15-minute block: between 0 and 900
1839
+ * seconds before the run's start, depending on when it starts (0 if it starts exactly on a quarter hour),
1840
+ * so the first bar of a 15-minute window is complete. The value in effect, the one you sent or the one the
1841
+ * platform chose, is reported back as `warmFrom` on the run. Signals about the replayed time
1842
+ * are not pushed on the run's channel or stream: they describe events from before the run started.
1843
+ * It can be set **only when the run is started**: it is not a parameter of `PUT /live/{runId}/params`, and
1844
+ * changing it means stopping the run and starting it again. Anything that is not an integer from 0 to 3600
1845
+ * is `400`. See the "Live execution" guide, "Warming up".
1846
+ *
1847
+ */
1848
+ warmFrom?: number;
1824
1849
  name?: string;
1825
1850
  description?: string;
1826
1851
  paper?: LivePaperConfig;
@@ -1895,7 +1920,7 @@ export type SendLiveCommandRequest = {
1895
1920
  };
1896
1921
 
1897
1922
  /**
1898
- * A live run's full state, as returned by starting, reading, or stopping it through its strategy.
1923
+ * A live run's full state, as returned by stopping it through its strategy, and the base of the representations returned by starting and by reading it. `warmFrom` is declared by those two (`LiveRunWithStream` and `LiveRunDetail`) and not here, because the response to stopping a run does not carry it.
1899
1924
  */
1900
1925
  export type LiveRun = {
1901
1926
  strategyId: StrategyId;
@@ -1958,6 +1983,109 @@ export type LiveRun = {
1958
1983
  * The run's paper trading configuration as accepted at start, normalised. Absent when the run has no paper trading.
1959
1984
  */
1960
1985
  paper?: LivePaperConfig;
1986
+ /**
1987
+ * The run's latest counters. Returned by the two reads, `GET /strategy/{strategyId}/live` and
1988
+ * `GET /live/{runId}`; never by starting or stopping a run. Absent until the first snapshot exists
1989
+ * (a run that has just started), and absent is not zero.
1990
+ *
1991
+ */
1992
+ stats?: LiveRunStats;
1993
+ };
1994
+
1995
+ /**
1996
+ * What a run has been doing, as of its last snapshot. The platform refreshes it about once a minute
1997
+ * while the run is being executed, so `opsPerSecond` is an average over that interval, not an
1998
+ * instantaneous rate.
1999
+ *
2000
+ */
2001
+ export type LiveRunStats = {
2002
+ /**
2003
+ * Updates of instruments the run has accepted since it started executing. It can start again from zero if the run is restarted.
2004
+ */
2005
+ processed: number;
2006
+ /**
2007
+ * Updates accepted per second over the last refresh interval. `0` when none arrived.
2008
+ */
2009
+ opsPerSecond: number;
2010
+ /**
2011
+ * How many distinct instruments the run has received an update for.
2012
+ */
2013
+ instrumentsSeen: number;
2014
+ /**
2015
+ * Epoch milliseconds when these counters were last written.
2016
+ */
2017
+ asOfMs: number;
2018
+ /**
2019
+ * Epoch milliseconds of the last snapshot in which `processed` had grown. Absent until the run has
2020
+ * processed anything. A run fed by a source that updates rarely (a funding rate, for example) can
2021
+ * stay flat for hours: that is how such a run behaves, not a fault.
2022
+ *
2023
+ */
2024
+ progressedAtMs?: number;
2025
+ /**
2026
+ * `true` when the run is meant to be running (`desired` is `RUNNING`) and its counters have not
2027
+ * been refreshed for several refresh intervals: the platform has stopped updating them, which is
2028
+ * worth checking against `state`. `false` otherwise. A run whose `processed` is flat is not stale;
2029
+ * `progressedAtMs` is how to tell it apart.
2030
+ *
2031
+ */
2032
+ stale: boolean;
2033
+ };
2034
+
2035
+ /**
2036
+ * The `warmFrom` in effect for this run, in seconds: the one requested when the run was started or, when none was, the one the platform chose (the distance from the run's start back to the start of the current 15-minute block, 0 to 900). It is never `null`. It is present on every run started since the field exists and absent from a run started before it existed. It never changes while the run exists.
2037
+ */
2038
+ export type WarmFrom = number;
2039
+
2040
+ /**
2041
+ * A run as returned by `GET /live/{runId}`, the full state of `LiveRun` plus when it last changed.
2042
+ */
2043
+ export type LiveRunDetail = LiveRun & {
2044
+ warmFrom?: WarmFrom;
2045
+ /**
2046
+ * Epoch milliseconds of the run's last change, from any cause. It only moves forward, so of two reads of the same run the one with the larger value is the newer.
2047
+ */
2048
+ updatedAtMs: number;
2049
+ };
2050
+
2051
+ /**
2052
+ * A run as `LiveRun` describes it, plus its `warmFrom` (absent only for a run started before the field existed) and its `streamUrl` when it has one. It is what **starting a run** and
2053
+ * `GET /strategy/{strategyId}/live` return: your own run, read with your own credentials. Stopping a run
2054
+ * returns `LiveRun`, which carries neither `warmFrom` nor the URL, and `GET /live/{runId}` returns `LiveRunDetail`, which carries `warmFrom` and never the URL.
2055
+ *
2056
+ */
2057
+ export type LiveRunWithStream = LiveRun & {
2058
+ warmFrom?: WarmFrom;
2059
+ /**
2060
+ * The run's secret stream URL (`wss://…`). **Treat it like a password**: anyone who holds it can read
2061
+ * this run's signals, from the sandbox stage on. Present only when the run was started with
2062
+ * `stream: true`, is wanted running, has not had its stream revoked, and your plan still lets you
2063
+ * broadcast; absent otherwise (a plan that lets you broadcast again gets the same URL back). Rotate
2064
+ * it with `POST /live/{runId}/stream` if it leaks, revoke it with `DELETE /live/{runId}/stream`.
2065
+ *
2066
+ */
2067
+ streamUrl?: string;
2068
+ };
2069
+
2070
+ /**
2071
+ * A run's new stream URL, as returned by `POST /live/{runId}/stream`.
2072
+ */
2073
+ export type LiveStreamUrl = {
2074
+ /**
2075
+ * The run's new secret stream URL. The previous one has stopped working.
2076
+ */
2077
+ streamUrl: string;
2078
+ };
2079
+
2080
+ /**
2081
+ * What `DELETE /live/{runId}/stream` returns.
2082
+ */
2083
+ export type LiveStreamRevoked = {
2084
+ runId: string;
2085
+ /**
2086
+ * Always `true`.
2087
+ */
2088
+ revoked: boolean;
1961
2089
  };
1962
2090
 
1963
2091
  /**
@@ -3698,9 +3826,9 @@ export type GetLiveError = GetLiveErrors[keyof GetLiveErrors];
3698
3826
 
3699
3827
  export type GetLiveResponses = {
3700
3828
  /**
3701
- * The run's current state
3829
+ * The run's current state, with its `streamUrl` when it has one
3702
3830
  */
3703
- 200: LiveRun;
3831
+ 200: LiveRunWithStream;
3704
3832
  };
3705
3833
 
3706
3834
  export type GetLiveResponse = GetLiveResponses[keyof GetLiveResponses];
@@ -3719,7 +3847,7 @@ export type StartLiveData = {
3719
3847
 
3720
3848
  export type StartLiveErrors = {
3721
3849
  /**
3722
- * Malformed `sources` (not exactly one entry, missing field, unsupported `type`), a `type` the strategy cannot consume (a ticker strategy with a `kline` source, or the reverse; the message names both), an invalid `visibility`, an invalid `paper` block (an unknown field, a wrong type or an out-of-range value), or no `paper` block for a strategy that listens to its own execution events.
3850
+ * Malformed `sources` (not exactly one entry, missing field, unsupported `type`), a `type` the strategy cannot consume (a ticker strategy with a `kline` source, or the reverse; the message names both), an invalid `visibility`, an invalid `paper` block (an unknown field, a wrong type or an out-of-range value), or no `paper` block for a strategy that listens to its own execution events. A `relay` or `stream` that is not `true` or `false`, or a `stream` where streams are not available yet. A `warmFrom` that is not an integer from 0 to 3600.
3723
3851
  */
3724
3852
  400: ResponseError;
3725
3853
  /**
@@ -3731,9 +3859,10 @@ export type StartLiveErrors = {
3731
3859
  */
3732
3860
  409: ResponseError;
3733
3861
  /**
3734
- * Your plan does not include live runs, would exceed your concurrent-run or
3735
- * instrument-count limit, or the platform is at capacity right now. Carries a
3736
- * `Retry-After` header.
3862
+ * One of two kinds. **Your plan** does not include live runs, would exceed your concurrent-run or
3863
+ * instrument-count limit, or does not let you ask for a `stream`: the message names your plan, and
3864
+ * retrying will not help until something changes, so there is no `Retry-After`. Or **the platform is at
3865
+ * capacity** right now: a `Retry-After` header says when to try again.
3737
3866
  *
3738
3867
  */
3739
3868
  429: ResponseError;
@@ -3743,9 +3872,9 @@ export type StartLiveError = StartLiveErrors[keyof StartLiveErrors];
3743
3872
 
3744
3873
  export type StartLiveResponses = {
3745
3874
  /**
3746
- * Started — the run's own state, in the sandbox stage
3875
+ * Started — the run's own state, in the sandbox stage, with its `streamUrl` when you asked for a stream
3747
3876
  */
3748
- 201: LiveRun;
3877
+ 201: LiveRunWithStream;
3749
3878
  };
3750
3879
 
3751
3880
  export type StartLiveResponse = StartLiveResponses[keyof StartLiveResponses];
@@ -3820,6 +3949,36 @@ export type ListPublicLiveResponses = {
3820
3949
  export type ListPublicLiveResponse =
3821
3950
  ListPublicLiveResponses[keyof ListPublicLiveResponses];
3822
3951
 
3952
+ export type GetLiveRunData = {
3953
+ body?: never;
3954
+ path: {
3955
+ /**
3956
+ * The `runId` from `POST`/`GET`/`DELETE` `.../live`, from `GET /live` or from `GET /live/public`
3957
+ */
3958
+ runId: string;
3959
+ };
3960
+ query?: never;
3961
+ url: "/live/{runId}";
3962
+ };
3963
+
3964
+ export type GetLiveRunErrors = {
3965
+ /**
3966
+ * No such run, or you do not own it — the two look identical on purpose.
3967
+ */
3968
+ 404: ResponseError;
3969
+ };
3970
+
3971
+ export type GetLiveRunError = GetLiveRunErrors[keyof GetLiveRunErrors];
3972
+
3973
+ export type GetLiveRunResponses = {
3974
+ /**
3975
+ * The run
3976
+ */
3977
+ 200: LiveRunDetail;
3978
+ };
3979
+
3980
+ export type GetLiveRunResponse = GetLiveRunResponses[keyof GetLiveRunResponses];
3981
+
3823
3982
  export type UpdateLiveData = {
3824
3983
  body?: UpdateLiveRequest;
3825
3984
  path: {
@@ -3940,6 +4099,78 @@ export type SendLiveCommandResponses = {
3940
4099
  export type SendLiveCommandResponse =
3941
4100
  SendLiveCommandResponses[keyof SendLiveCommandResponses];
3942
4101
 
4102
+ export type RevokeLiveStreamData = {
4103
+ body?: never;
4104
+ path: {
4105
+ runId: string;
4106
+ };
4107
+ query?: never;
4108
+ url: "/live/{runId}/stream";
4109
+ };
4110
+
4111
+ export type RevokeLiveStreamErrors = {
4112
+ /**
4113
+ * No such run, or you do not own it.
4114
+ */
4115
+ 404: ResponseError;
4116
+ /**
4117
+ * The run was started without a stream, so there is nothing to revoke.
4118
+ */
4119
+ 409: ResponseError;
4120
+ };
4121
+
4122
+ export type RevokeLiveStreamError =
4123
+ RevokeLiveStreamErrors[keyof RevokeLiveStreamErrors];
4124
+
4125
+ export type RevokeLiveStreamResponses = {
4126
+ /**
4127
+ * Revoked (or already revoked).
4128
+ */
4129
+ 200: LiveStreamRevoked;
4130
+ };
4131
+
4132
+ export type RevokeLiveStreamResponse =
4133
+ RevokeLiveStreamResponses[keyof RevokeLiveStreamResponses];
4134
+
4135
+ export type RotateLiveStreamData = {
4136
+ body?: never;
4137
+ path: {
4138
+ runId: string;
4139
+ };
4140
+ query?: never;
4141
+ url: "/live/{runId}/stream";
4142
+ };
4143
+
4144
+ export type RotateLiveStreamErrors = {
4145
+ /**
4146
+ * No such run, or you do not own it.
4147
+ */
4148
+ 404: ResponseError;
4149
+ /**
4150
+ * One of three reasons, each its own message: the run was started without a stream; its stream was
4151
+ * revoked (a revoked stream cannot be restored: start the run again with a stream); or the run is stopped.
4152
+ *
4153
+ */
4154
+ 409: ResponseError;
4155
+ /**
4156
+ * Your plan does not let you broadcast a run's signals. The message names your plan; retrying will not help until it changes, so there is no `Retry-After`.
4157
+ */
4158
+ 429: ResponseError;
4159
+ };
4160
+
4161
+ export type RotateLiveStreamError =
4162
+ RotateLiveStreamErrors[keyof RotateLiveStreamErrors];
4163
+
4164
+ export type RotateLiveStreamResponses = {
4165
+ /**
4166
+ * The new URL.
4167
+ */
4168
+ 200: LiveStreamUrl;
4169
+ };
4170
+
4171
+ export type RotateLiveStreamResponse =
4172
+ RotateLiveStreamResponses[keyof RotateLiveStreamResponses];
4173
+
3943
4174
  export type GetLiveRunSignalsData = {
3944
4175
  body?: never;
3945
4176
  path: {