@qtsurfer/api-client 0.24.0 → 0.25.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.
@@ -12,6 +12,38 @@ export type ResponseError = {
12
12
  * Error description
13
13
  */
14
14
  message: string;
15
+ /**
16
+ * A stable token naming the cause, for a client to branch on without reading `message`.
17
+ * Present only on an error that has one, and each operation that can return one lists
18
+ * the values it uses. A client treats a value it does not know like an absent `reason`.
19
+ *
20
+ */
21
+ reason?: string;
22
+ next?: ErrorNextCall;
23
+ };
24
+
25
+ /**
26
+ * The call that gets past an error, ready to send: a client that wants the same thing by
27
+ * another route makes this request. Present only on an error that has one.
28
+ *
29
+ */
30
+ export type ErrorNextCall = {
31
+ /**
32
+ * HTTP method of the call.
33
+ */
34
+ method: "GET" | "POST" | "PUT" | "DELETE";
35
+ /**
36
+ * Path of the call, relative to the server URL (the one that already ends in `/v1`).
37
+ */
38
+ path: string;
39
+ /**
40
+ * JSON body of the call, when it has one. Whatever depends on the caller and cannot be
41
+ * known here (such as the `name` of a dataset) is left for the client to add.
42
+ *
43
+ */
44
+ body?: {
45
+ [key: string]: unknown;
46
+ };
15
47
  };
16
48
 
17
49
  /**
@@ -24,6 +56,15 @@ export type ScalarStrategyParamValue = number | string | boolean;
24
56
  */
25
57
  export type Instrument = string;
26
58
 
59
+ /**
60
+ * An exchange's instrument catalogue: centralized-exchange instruments or decentralized-exchange
61
+ * pools. Read `meta.venueType` to distinguish `cex` from `dex`, including when `data` is empty.
62
+ *
63
+ */
64
+ export type InstrumentCatalogueResponse =
65
+ | InstrumentListResponse
66
+ | PoolListResponse;
67
+
27
68
  /**
28
69
  * HAL-style response envelope for the instruments listing
29
70
  */
@@ -52,6 +93,10 @@ export type InstrumentListMeta = {
52
93
  * The market segment served in `data`
53
94
  */
54
95
  segment: "spot" | "futures";
96
+ /**
97
+ * The venue type of the exchange, as `GET /exchanges` lists it. Always `cex` here; a listing of pools says `dex`.
98
+ */
99
+ venueType: "cex";
55
100
  };
56
101
 
57
102
  /**
@@ -72,6 +117,115 @@ export type InstrumentLinks = {
72
117
  futures?: HalLink;
73
118
  };
74
119
 
120
+ /**
121
+ * HAL-style response envelope for the instruments listing of a decentralized exchange, whose instruments are pools
122
+ */
123
+ export type PoolListResponse = {
124
+ /**
125
+ * The pools worth running, the most traded in the last 24 hours first
126
+ */
127
+ data: Array<PoolDetail>;
128
+ meta: PoolListMeta;
129
+ _links: PoolLinks;
130
+ };
131
+
132
+ /**
133
+ * Metadata describing the pools listing of a decentralized exchange
134
+ */
135
+ export type PoolListMeta = {
136
+ /**
137
+ * When this listing was last refreshed. It is refreshed every hour, and the `lastPrice` of each pool is as of this time.
138
+ */
139
+ updatedAt: string;
140
+ /**
141
+ * The exchange the pools belong to
142
+ */
143
+ exchange: string;
144
+ /**
145
+ * The protocol served in `data`, one of the exchange's `segments`
146
+ */
147
+ segment: string;
148
+ /**
149
+ * The venue type of the exchange, as `GET /exchanges` lists it. Always `dex` here; a listing of instruments of a centralized exchange says `cex`.
150
+ */
151
+ venueType: "dex";
152
+ /**
153
+ * A pool with less liquidity than this (in US dollars) is not listed
154
+ */
155
+ minTvlUsd: number;
156
+ /**
157
+ * The most pools the listing has
158
+ */
159
+ limit: number;
160
+ };
161
+
162
+ /**
163
+ * HAL `_links` — protocol discovery for the pools listing of a decentralized exchange
164
+ */
165
+ export type PoolLinks = {
166
+ /**
167
+ * Link to this listing
168
+ */
169
+ self: HalLink;
170
+ [key: string]: HalLink;
171
+ };
172
+
173
+ /**
174
+ * A pool of a decentralized exchange that a live run can read. The listing is a place to start, not the
175
+ * whole market: a live run can read any pool of the protocol, listed or not.
176
+ *
177
+ */
178
+ export type PoolDetail = {
179
+ /**
180
+ * The pool's address, in lower case. It is the value to put in `instruments` of a live run's source.
181
+ */
182
+ id: string;
183
+ /**
184
+ * The pair written `BASE/QUOTE`, the way the signals of a run on this pool name it (`instrument`)
185
+ */
186
+ symbol: string;
187
+ /**
188
+ * Symbol of the base token
189
+ */
190
+ base: string;
191
+ /**
192
+ * Symbol of the quote token
193
+ */
194
+ quote: string;
195
+ /**
196
+ * Address of the base token, in lower case
197
+ */
198
+ baseAddress: string;
199
+ /**
200
+ * Address of the quote token, in lower case
201
+ */
202
+ quoteAddress: string;
203
+ /**
204
+ * The pool's fee tier, in percent (`0.05` is a 0.05 % fee). A protocol can have several pools of the same pair, one per fee tier.
205
+ */
206
+ feePercent: number;
207
+ /**
208
+ * The price of one base token in the quote token, as the signals of a run on this pool name the pair. It is as of `meta.updatedAt`, so up to one hour old. Absent when there is no price for the pool.
209
+ */
210
+ lastPrice?: number;
211
+ /**
212
+ * What traded in the pool over the last 24 hours, in the quote token, the same meaning as `volume24h` of an instrument of a centralized exchange. Absent when the quote token has no dollar price to convert from.
213
+ */
214
+ volume24h?: number;
215
+ /**
216
+ * The liquidity held by the pool, in US dollars
217
+ */
218
+ tvlUsd: number;
219
+ /**
220
+ * What traded in the pool over the last 24 hours, in US dollars
221
+ */
222
+ volume24hUsd: number;
223
+ /**
224
+ * When the pool was created. Absent when it is not known
225
+ */
226
+ createdAt?: string;
227
+ };
228
+
75
229
  /**
76
230
  * HAL `_links` for a strategy — present on a full `StrategyState` body (`GET
77
231
  * /strategy/{strategyId}`, and `POST /strategy/{strategyId}/validate`'s already-validated
@@ -119,6 +273,7 @@ export type Account = {
119
273
  * Your current subscription tier.
120
274
  */
121
275
  tier: string;
276
+ scopes: KeyScopes;
122
277
  /**
123
278
  * Maximum number of strategy executions (and sweeps) you can have running at the same time
124
279
  * through the API. Starting one past this number is answered with `429`, whose message
@@ -238,6 +393,10 @@ export type InstrumentDetail = {
238
393
  * Instrument identifier (e.g. currency pair)
239
394
  */
240
395
  id: string;
396
+ /**
397
+ * The instrument's name, the same as `id`. A pool of a decentralized exchange has the same field (`PoolDetail`), so both listings are read alike.
398
+ */
399
+ symbol: string;
241
400
  /**
242
401
  * Base currency
243
402
  */
@@ -246,13 +405,17 @@ export type InstrumentDetail = {
246
405
  * Quote currency
247
406
  */
248
407
  quote: string;
408
+ /**
409
+ * Settlement currency. Present on a futures instrument only.
410
+ */
411
+ settle?: string;
249
412
  coverage?: InstrumentCoverage;
250
413
  /**
251
- * Last traded price
414
+ * Last traded price. Absent for an instrument with no recent price.
252
415
  */
253
416
  lastPrice?: number;
254
417
  /**
255
- * Trading volume in the last 24 hours (in quote currency)
418
+ * Trading volume in the last 24 hours (in quote currency). Absent for an instrument with no recent volume.
256
419
  */
257
420
  volume24h?: number;
258
421
  };
@@ -305,6 +468,18 @@ export type Exchange = {
305
468
  * Description of the exchange
306
469
  */
307
470
  description?: string;
471
+ /**
472
+ * Venue category, written as the `venueType` of a live run's source: `cex` is a centralized exchange and `dex` a decentralized one. A `dex` exchange has no market data to prepare or backtest, so its id is not valid in the routes that take an `exchangeId`, except the two instruments routes, which list its pools (the instrument of a run on it is a pool's address).
473
+ */
474
+ venueType: "cex" | "dex";
475
+ /**
476
+ * The segments the exchange offers, written as in the path of `GET /exchange/{exchangeId}/{segment}/instruments` and as the `segment` of a live run's source. For a `cex` exchange, its market segments (`spot`, `futures`: the ones its instrument catalogues are served under); for a `dex` exchange, the protocols whose pools a run can read.
477
+ */
478
+ segments: Array<string>;
479
+ /**
480
+ * The segments among `segments` for which live data is published, so the ones a live run can read: a live run on any other segment of the exchange is refused with `400`. It can be empty (an exchange whose live data is not published yet).
481
+ */
482
+ liveSegments: Array<string>;
308
483
  };
309
484
 
310
485
  /**
@@ -372,11 +547,10 @@ export type PrepareRequest = {
372
547
  * * Managed exchange, `ticker` or `funding` — one of `1s`, `5s`, `1m`, `3m`, `5m`, `15m`,
373
548
  * `30m`, `1h`, `2h`, `4h`, `8h`, `12h`, `1d`, `1w`, `1q`; any other label returns `400`.
374
549
  * Omitted = `1s`, the publisher's native cadence.
375
- * * Managed exchange, `kline` — one of `1s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d`;
376
- * any other label, including `5s`, `3m` and `8h`, returns `400` and names the accepted
377
- * ones. Omitted = `1s`. This is the width of the bars a run reads: it is chosen here,
378
- * once, and the same strategy can be run at several cadences by preparing the range at
379
- * each.
550
+ * * Managed exchange, `kline` — the same labels as above, `1s` to `1q`; a label that is
551
+ * not a whole number of seconds returns `400`. Omitted = `1s`. This is the width of the
552
+ * bars a run reads: it is chosen here, once, and the same strategy can be run at
553
+ * several cadences by preparing the range at each.
380
554
  * * Dataset (`exchangeId: user`) — omitted = the dataset version's own discovered
381
555
  * `cadence` (see `DatasetVersion.cadence`), served as-is. Any cadence equal to or
382
556
  * coarser than it and an exact multiple of it is accepted, including ones outside the
@@ -1340,9 +1514,11 @@ export type Dataset = {
1340
1514
  */
1341
1515
  name: string;
1342
1516
  /**
1343
- * `ticker` for an upload or a `dex` import with no `cadence` requested (native per-trade
1344
- * data). `klines` for a `dex` import that requested a candle `cadence` — pre-aggregated
1345
- * bars rather than raw ticks. Purely informational; both shapes are read the same way.
1517
+ * `ticker` for an upload, a `dex` import with no `cadence` requested (native per-trade
1518
+ * data) or a `cex` import with `dataType: ticker`. `klines` for a `dex` import that
1519
+ * requested a candle `cadence` — pre-aggregated bars rather than raw ticks — or a `cex`
1520
+ * import with `dataType: klines`. Purely informational; both shapes are read the same
1521
+ * way.
1346
1522
  *
1347
1523
  */
1348
1524
  type: "ticker" | "klines";
@@ -1534,11 +1710,12 @@ export type DatasetVersion = {
1534
1710
  rows?: number;
1535
1711
  /**
1536
1712
  * The cadence discovered from the data's own timestamps. Either a fixed grid — `1s`,
1537
- * `5s`, `15s`, `1m`, `5m`, `15m`, `30m`, `1h`, `4h`, `1d` — when at least half the
1538
- * intervals between consecutive rows fall on that step (small clock jitter tolerated), or
1539
- * `rt`: native data at the rate it was captured, each row at its own timestamp with no
1540
- * fixed step — per-trade on-chain swaps, block-spaced or sub-second ticks, irregular
1541
- * intervals. An `rt` dataset can be resampled to any fixed cadence at prepare time.
1713
+ * `5s`, `15s`, `1m`, `3m`, `5m`, `15m`, `30m`, `1h`, `2h`, `4h`, `8h`, `12h`, `1d`,
1714
+ * `1w` — when at least half the intervals between consecutive rows fall on that step
1715
+ * (small clock jitter tolerated), or `rt`: native data at the rate it was captured, each
1716
+ * row at its own timestamp with no fixed step — per-trade on-chain swaps, block-spaced
1717
+ * or sub-second ticks, irregular intervals. An `rt` dataset can be resampled to any
1718
+ * fixed cadence at prepare time.
1542
1719
  *
1543
1720
  */
1544
1721
  cadence?: string;
@@ -1613,7 +1790,8 @@ export type DatasetUploadState = {
1613
1790
 
1614
1791
  /**
1615
1792
  * `POST /datasets/imports`'s request body. A common block plus one type-specific block,
1616
- * selected by `type` — `dex` is the only value today.
1793
+ * selected by `type`: `dex` (block `dex`) or `cex` (block `cex`), the two `venueType`s of
1794
+ * `GET /exchanges`.
1617
1795
  *
1618
1796
  */
1619
1797
  export type DatasetImportRequest = {
@@ -1633,21 +1811,54 @@ export type DatasetImportRequest = {
1633
1811
  */
1634
1812
  to: string;
1635
1813
  /**
1636
- * Optional. Omitted/blank keeps native per-trade event cadence — each swap at its own
1637
- * timestamp, so the resulting version's `cadence` is `rt` unless the swaps happen to sit
1638
- * on a fixed grid (see `DatasetVersion.cadence`). Set to `1s`, `1m` or
1639
- * `5m` instead to get pre-aggregated candles at that width rather than raw trades (the
1640
- * resulting dataset's `type` becomes `klines`); any other value is `400`. Not every
1641
- * network supports every cadence — an unsupported combination fails asynchronously, not
1642
- * at request time (see `DatasetImportState.error`).
1814
+ * Optional; what it means, and what it accepts, depends on `type`. Any other value is
1815
+ * `400`.
1816
+ *
1817
+ * * `dex` — omitted/blank keeps native per-trade event cadence: each swap at its own
1818
+ * timestamp, so the resulting version's `cadence` is `rt` unless the swaps happen to
1819
+ * sit on a fixed grid (see `DatasetVersion.cadence`). Set to `1s`, `1m` or `5m`
1820
+ * instead to get pre-aggregated candles at that width rather than raw trades (the
1821
+ * resulting dataset's `type` becomes `klines`). Not every network supports every
1822
+ * cadence — an unsupported combination fails asynchronously, not at request time (see
1823
+ * `DatasetImportState.error`).
1824
+ * * `cex` — one of `1s`, `5s`, `1m`, `3m`, `5m`, `15m`, `30m`, `1h`, `2h`, `4h`, `8h`,
1825
+ * `12h`, `1d`, `1w`, `1q`, whether `dataType` is `ticker` or `klines`. Omitted = the
1826
+ * finest cadence every part of the range holds.
1827
+ *
1828
+ * For `cex` the bars are built from the finest data every part of the range holds. A
1829
+ * `cadence` finer than that, or not an exact multiple of it, fails the import
1830
+ * asynchronously (`failed`; the `error` names the finest cadence the range holds) rather
1831
+ * than returning a dataset with a different cadence from the one asked for. So a range
1832
+ * whose history changes cadence part-way (from `1m` to `1s`, say) comes out entirely at
1833
+ * the coarser one when `cadence` is omitted: the dataset has no gap that is only a
1834
+ * change of cadence.
1643
1835
  *
1644
1836
  */
1645
- cadence?: "1s" | "1m" | "5m";
1646
- /**
1647
- * The source to fetch from. `dex` is the only value today.
1837
+ cadence?:
1838
+ | "1s"
1839
+ | "5s"
1840
+ | "1m"
1841
+ | "3m"
1842
+ | "5m"
1843
+ | "15m"
1844
+ | "30m"
1845
+ | "1h"
1846
+ | "2h"
1847
+ | "4h"
1848
+ | "8h"
1849
+ | "12h"
1850
+ | "1d"
1851
+ | "1w"
1852
+ | "1q";
1853
+ /**
1854
+ * The kind of venue to import from, the same two values as the `venueType` of
1855
+ * `GET /exchanges`: `dex` — a pool/pair's own on-chain market (block `dex`) — or `cex` —
1856
+ * a centralized exchange's market history (block `cex`).
1857
+ *
1648
1858
  */
1649
- type: "dex";
1859
+ type: "dex" | "cex";
1650
1860
  dex?: DatasetImportDexRequest;
1861
+ cex?: DatasetImportCexRequest;
1651
1862
  };
1652
1863
 
1653
1864
  /**
@@ -1691,6 +1902,33 @@ export type DatasetImportDexRequest = {
1691
1902
  factory?: string;
1692
1903
  };
1693
1904
 
1905
+ /**
1906
+ * The `cex` source's own fields — required when `type` is `cex`. They name a market the way
1907
+ * `GET /exchanges` and the instruments routes do: `exchange` is the `id` of a centralized
1908
+ * exchange, `segment` one of its `segments`.
1909
+ *
1910
+ */
1911
+ export type DatasetImportCexRequest = {
1912
+ /**
1913
+ * The id of a centralized exchange (`venueType` `cex`) of `GET /exchanges`, lower-case.
1914
+ * A decentralized exchange's id is `400`: import its pools with `type: dex`.
1915
+ *
1916
+ */
1917
+ exchange: string;
1918
+ /**
1919
+ * The market segment, one of the exchange's `segments`. `spot` is the only segment a
1920
+ * `cex` import takes today, which matches `instrument` being a plain spot pair.
1921
+ *
1922
+ */
1923
+ segment: "spot";
1924
+ /**
1925
+ * What to import, and the resulting dataset's `type`: `ticker` — the exchange's ticker
1926
+ * series — or `klines` — its aggregated bars (open, high, low, close and volume).
1927
+ *
1928
+ */
1929
+ dataType: "ticker" | "klines";
1930
+ };
1931
+
1694
1932
  /**
1695
1933
  * The response to `POST /datasets/imports` — the dataset now exists, and its fetch has started.
1696
1934
  */
@@ -1739,7 +1977,8 @@ export type DatasetImportState = {
1739
1977
  /**
1740
1978
  * A human-readable reason, present when `status` is `failed` — an unresolvable
1741
1979
  * pool/pair, no data in the requested range, a range older than the configured source
1742
- * retains, the fetch exceeding your tier's time ceiling, or any of
1980
+ * retains, a `cex` `cadence` finer than the range holds (the message names the finest
1981
+ * one), the fetch exceeding your tier's time ceiling, or any of
1743
1982
  * `DatasetUploadState.error`'s own ingest-side reasons once fetching hands off to it.
1744
1983
  * Durably recorded, same as on the upload path.
1745
1984
  *
@@ -1751,6 +1990,19 @@ export type DatasetImportState = {
1751
1990
  version?: DatasetVersion;
1752
1991
  };
1753
1992
 
1993
+ /**
1994
+ * What your API key may do, as a map from a resource to the actions allowed on it. Names are
1995
+ * lower case: `{ "backtests": ["read", "write", "execute"], "exchanges": ["read"] }`. A scope
1996
+ * is a resource and an action: a resource is listed only with at least one action, and a key
1997
+ * with no scope is `{}`. `GET /account` and `POST /auth/token` return the same map for the
1998
+ * same key. The API reports the scopes of a key; it does not yet refuse an operation because
1999
+ * a scope is missing.
2000
+ *
2001
+ */
2002
+ export type KeyScopes = {
2003
+ [key: string]: Array<string>;
2004
+ };
2005
+
1754
2006
  export type AuthTokenResponse = {
1755
2007
  /**
1756
2008
  * Short-lived HS256 JWT. Send as `Authorization: Bearer <token>` on all other endpoints.
@@ -1764,10 +2016,7 @@ export type AuthTokenResponse = {
1764
2016
  * Seconds until the JWT expires (typically 3600).
1765
2017
  */
1766
2018
  expires_in: number;
1767
- /**
1768
- * Scopes granted to this token. Reserved for future use; currently always empty.
1769
- */
1770
- scopes?: Array<string>;
2019
+ scopes?: KeyScopes;
1771
2020
  /**
1772
2021
  * Subscription tier this token was issued for. Drives rate limits and feature flags on downstream endpoints.
1773
2022
  */
@@ -1775,13 +2024,17 @@ export type AuthTokenResponse = {
1775
2024
  };
1776
2025
 
1777
2026
  /**
1778
- * Error envelope returned by `POST /auth/token` when the API key is rejected.
2027
+ * Error envelope returned by `POST /auth/token` when the API key is rejected (`401`) or carries no scopes where scopes are required (`403`).
1779
2028
  */
1780
2029
  export type AuthTokenError = {
1781
2030
  /**
1782
2031
  * Machine-readable error reason.
1783
2032
  */
1784
- code: "invalid_apikey" | "apikey_revoked" | "apikey_expired";
2033
+ code:
2034
+ | "invalid_apikey"
2035
+ | "apikey_revoked"
2036
+ | "apikey_expired"
2037
+ | "apikey_without_scopes";
1785
2038
  /**
1786
2039
  * Human-readable description of the failure.
1787
2040
  */
@@ -1793,17 +2046,23 @@ export type AuthTokenError = {
1793
2046
  */
1794
2047
  export type LiveSource = {
1795
2048
  /**
1796
- * Venue category. `cx` (centralized exchange) is the only one live runs support today.
2049
+ * Venue category. `cex` is a centralized exchange and `dex` is one pool on a decentralized exchange, which takes its own `exchange`, `segment`, `type` and `instruments` (see "Sources" in the Live execution guide). `cx` and `dx`, the spellings used before, are still read as `cex` and `dex`; the run always reports the new ones.
2050
+ */
2051
+ venueType: "cex" | "dex";
2052
+ /**
2053
+ * The exchange id, as `GET /exchanges` lists it. For a `dex` source, the chain the pool is on; `robinhood` is the only one today.
1797
2054
  */
1798
- venueType: string;
1799
2055
  exchange: string;
2056
+ /**
2057
+ * The segment, as `GET /exchanges` lists it for that exchange, among its `liveSegments` (a segment with no live data is refused with `400`). For a `cex` source, the market segment (`spot` today); for a `dex` source, the protocol of the pool, `uniswap-v3` the only one today.
2058
+ */
1800
2059
  segment: string;
1801
2060
  /**
1802
- * Both `ticker` and `kline` connect to the lightest (fastest) cadence available for the exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet.
2061
+ * Both `ticker` and `kline` connect to the lightest (fastest) cadence available for the exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet. A `dex` source supports only `kline`: one candle per second of the pool's trades.
1803
2062
  */
1804
2063
  type: "ticker" | "kline";
1805
2064
  /**
1806
- * The instruments the run reads. For a run started with a list, that list as sent; for one started without `instruments`, or with `["*"]`, what the start resolved: the list of pairs the compilation of the strategy records as the instruments it accepts, when it records one, or `["*"]` for every instrument the exchange/segment offers (tier-gated). An entry is written `BASE/QUOTE` and either side can be `*` to mean any, such as any base paired with USDT. Symbols are not case-sensitive and spaces around them are ignored, so `btc/usdt` and `BTC/USDT` are the same instrument.
2065
+ * The instruments the run reads. For a run started with a list, that list as sent; for one started without `instruments`, or with `["*"]`, what the start resolved: the list of pairs the compilation of the strategy records as the instruments it accepts, when it records one, or `["*"]` for every instrument the exchange/segment offers (tier-gated). An entry is written `BASE/QUOTE` and either side can be `*` to mean any, such as any base paired with USDT. Symbols are not case-sensitive and spaces around them are ignored, so `btc/usdt` and `BTC/USDT` are the same instrument. A `dex` source holds exactly one entry, the address of its pool.
1807
2066
  */
1808
2067
  instruments: Array<string>;
1809
2068
  };
@@ -1813,17 +2072,23 @@ export type LiveSource = {
1813
2072
  */
1814
2073
  export type LiveSourceRequest = {
1815
2074
  /**
1816
- * Venue category. `cx` (centralized exchange) is the only one live runs support today.
2075
+ * Venue category. `cex` is a centralized exchange and `dex` is one pool on a decentralized exchange, which takes its own `exchange`, `segment`, `type` and `instruments` (see "Sources" in the Live execution guide). `cx` and `dx`, the spellings used before, are still read as `cex` and `dex`; the run always reports the new ones.
2076
+ */
2077
+ venueType: "cex" | "dex";
2078
+ /**
2079
+ * The exchange id, as `GET /exchanges` lists it. For a `dex` source, the chain the pool is on; `robinhood` is the only one today.
1817
2080
  */
1818
- venueType: string;
1819
2081
  exchange: string;
2082
+ /**
2083
+ * The segment, as `GET /exchanges` lists it for that exchange, among its `liveSegments` (a segment with no live data is refused with `400`). For a `cex` source, the market segment (`spot` today); for a `dex` source, the protocol of the pool, `uniswap-v3` the only one today.
2084
+ */
1820
2085
  segment: string;
1821
2086
  /**
1822
- * Both `ticker` and `kline` connect to the lightest (fastest) cadence available for the exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet.
2087
+ * Both `ticker` and `kline` connect to the lightest (fastest) cadence available for the exchange — today, 1 tick/second on every supported exchange. Choosing a specific cadence is not offered yet. A `dex` source supports only `kline`: one candle per second of the pool's trades.
1823
2088
  */
1824
2089
  type: "ticker" | "kline";
1825
2090
  /**
1826
- * Which instruments the run reads. A QTScript strategy can declare which instruments it accepts with an `instruments` line in its source. When the compilation of the strategy records that selection as a list of pairs, leaving `instruments` out, or sending `["*"]`, takes that list; otherwise the run reads every instrument the exchange/segment offers. A list of instruments is taken as sent, and `[]` and `null` are refused with `400`. An entry is written `BASE/QUOTE`; either side can be `*` to mean any: any base can be paired with USDT, and BTC can be paired with any quote. Entries are not case-sensitive and spaces around them are ignored, so `btc/usdt` and `BTC/USDT` are the same instrument. An entry that is not of that form (no `/`, an empty side, a `.` or a space inside a side, or a `*` mixed with other characters of a side) makes the run fail when it starts. Plan limits: a list with an entry that has a `*` on a side counts like `["*"]` and only plans that include the wildcard accept it; the other entries are counted one by one. The instruments the run actually reads come back in the run's `sources`.
2091
+ * Which instruments the run reads. A QTScript strategy can declare which instruments it accepts with an `instruments` line in its source. When the compilation of the strategy records that selection as a list of pairs, leaving `instruments` out, or sending `["*"]`, takes that list; otherwise the run reads every instrument the exchange/segment offers. A list of instruments is taken as sent, and `[]` and `null` are refused with `400`. An entry is written `BASE/QUOTE`; either side can be `*` to mean any: any base can be paired with USDT, and BTC can be paired with any quote. Entries are not case-sensitive and spaces around them are ignored, so `btc/usdt` and `BTC/USDT` are the same instrument. An entry that is not of that form (no `/`, an empty side, a `.` or a space inside a side, or a `*` mixed with other characters of a side) makes the run fail when it starts. Plan limits: a list with an entry that has a `*` on a side counts like `["*"]` and only plans that include the wildcard accept it; the other entries are counted one by one. The instruments the run actually reads come back in the run's `sources`. A `dex` source needs exactly one entry, the address of its pool (`0x` and 40 hexadecimal digits, not case-sensitive): it cannot be left out and `*` is not accepted.
1827
2092
  */
1828
2093
  instruments?: Array<string>;
1829
2094
  };
@@ -1980,12 +2245,15 @@ export type LiveRun = {
1980
2245
  * stack trace or an internal message. Either `resource: ...` (the platform stopped the run for
1981
2246
  * exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for
1982
2247
  * a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's
1983
- * definition was refused, the run could not start after several attempts, the strategy failed while
1984
- * processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow:
2248
+ * definition was refused, the pool address of a `dex` run is not a pool of its protocol on its chain,
2249
+ * the platform has no room to follow the pool of a `dex` run, the run could not start after several
2250
+ * attempts, the strategy failed while processing data, the run lost its data feed, or the generic
2251
+ * `The run failed.`. The set may grow:
1985
2252
  * read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays
1986
2253
  * `desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your
1987
- * live-run limit) until then; one that can never run because its strategy cannot consume its source
1988
- * type is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
2254
+ * live-run limit) until then; one that cannot run, and will not by waiting, because its strategy cannot
2255
+ * consume its source type or because the pool of a `dex` run is not a pool or has no room to be followed,
2256
+ * is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
1989
2257
  *
1990
2258
  */
1991
2259
  reason?: string;
@@ -2162,12 +2430,15 @@ export type LiveRunSummary = {
2162
2430
  * stack trace or an internal message. Either `resource: ...` (the platform stopped the run for
2163
2431
  * exceeding its resource allowance; the text says which limit) or one of a fixed set of sentences for
2164
2432
  * a `FAILED` run: the strategy cannot consume the source type the run was started with, the run's
2165
- * definition was refused, the run could not start after several attempts, the strategy failed while
2166
- * processing data, the run lost its data feed, or the generic `The run failed.`. The set may grow:
2433
+ * definition was refused, the pool address of a `dex` run is not a pool of its protocol on its chain,
2434
+ * the platform has no room to follow the pool of a `dex` run, the run could not start after several
2435
+ * attempts, the strategy failed while processing data, the run lost its data feed, or the generic
2436
+ * `The run failed.`. The set may grow:
2167
2437
  * read an unrecognised sentence as a failure and do not parse it. A `FAILED` run usually stays
2168
2438
  * `desired: RUNNING` until you stop it, and counts as active (`409` on a new start, and toward your
2169
- * live-run limit) until then; one that can never run because its strategy cannot consume its source
2170
- * type is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
2439
+ * live-run limit) until then; one that cannot run, and will not by waiting, because its strategy cannot
2440
+ * consume its source type or because the pool of a `dex` run is not a pool or has no room to be followed,
2441
+ * is stopped by the platform itself (`desired: STOPPED`), so it holds no place.
2171
2442
  *
2172
2443
  */
2173
2444
  reason?: string;
@@ -2452,6 +2723,10 @@ export type AuthenticateErrors = {
2452
2723
  * API key is invalid, revoked, or expired.
2453
2724
  */
2454
2725
  401: AuthTokenError;
2726
+ /**
2727
+ * The API key is valid but carries no scopes, and this deployment requires them.
2728
+ */
2729
+ 403: AuthTokenError;
2455
2730
  /**
2456
2731
  * Rate limit exceeded for this API key.
2457
2732
  */
@@ -2534,7 +2809,11 @@ export type ListInstrumentsData = {
2534
2809
 
2535
2810
  export type ListInstrumentsErrors = {
2536
2811
  /**
2537
- * Exchange not found or instrument catalog not available
2812
+ * The exchange is not one `GET /exchanges` lists
2813
+ */
2814
+ 400: ResponseError;
2815
+ /**
2816
+ * The instrument catalog is not available
2538
2817
  */
2539
2818
  404: ResponseError;
2540
2819
  };
@@ -2544,9 +2823,9 @@ export type ListInstrumentsError =
2544
2823
 
2545
2824
  export type ListInstrumentsResponses = {
2546
2825
  /**
2547
- * The default (spot) segment's instruments in `data`, `meta`, and HAL `_links` (self + spot/futures segment discovery)
2826
+ * The default (spot) segment's instruments in `data`, `meta`, and HAL `_links` (self + spot/futures segment discovery); for a decentralized exchange, its pools
2548
2827
  */
2549
- 200: InstrumentListResponse;
2828
+ 200: InstrumentCatalogueResponse;
2550
2829
  };
2551
2830
 
2552
2831
  export type ListInstrumentsResponse =
@@ -2560,9 +2839,9 @@ export type ListSegmentInstrumentsData = {
2560
2839
  */
2561
2840
  exchangeId: string;
2562
2841
  /**
2563
- * Market segment to list instruments for
2842
+ * The segment to list instruments for, one of the exchange's `segments` in `GET /exchanges`; `spot` or `futures` for a centralized exchange, a protocol (`uniswap-v3`) for a decentralized one
2564
2843
  */
2565
- segment: "spot" | "futures";
2844
+ segment: string;
2566
2845
  };
2567
2846
  query?: never;
2568
2847
  url: "/exchange/{exchangeId}/{segment}/instruments";
@@ -2570,7 +2849,11 @@ export type ListSegmentInstrumentsData = {
2570
2849
 
2571
2850
  export type ListSegmentInstrumentsErrors = {
2572
2851
  /**
2573
- * Exchange, segment, or instrument catalog not found
2852
+ * The exchange is not one `GET /exchanges` lists, or the segment is not one the exchange has (`spot` or `futures` for a centralized exchange, a protocol for a decentralized one)
2853
+ */
2854
+ 400: ResponseError;
2855
+ /**
2856
+ * The instrument catalog is not available
2574
2857
  */
2575
2858
  404: ResponseError;
2576
2859
  };
@@ -2582,7 +2865,7 @@ export type ListSegmentInstrumentsResponses = {
2582
2865
  /**
2583
2866
  * An object with a `data` array of instrument details (each with per-data-type coverage) and a `meta` block
2584
2867
  */
2585
- 200: InstrumentListResponse;
2868
+ 200: InstrumentCatalogueResponse;
2586
2869
  };
2587
2870
 
2588
2871
  export type ListSegmentInstrumentsResponse =
@@ -2624,17 +2907,29 @@ export type DownloadTickersData = {
2624
2907
 
2625
2908
  export type DownloadTickersErrors = {
2626
2909
  /**
2627
- * Missing or malformed parameters (e.g. `hour` not `YYYY-MM-DDTHH`).
2910
+ * Missing or malformed parameters (e.g. `hour` not `YYYY-MM-DDTHH`), an `hour` in the
2911
+ * future, or an hour older than the last 7 days (`reason: OUTSIDE_WINDOW`, with `next`).
2912
+ *
2628
2913
  */
2629
2914
  400: ResponseError;
2630
2915
  /**
2631
- * No Lastra segment exists for the requested instrument/hour.
2916
+ * No segment for the requested instrument/hour. `reason: NOT_YET_AVAILABLE` — the hour
2917
+ * is not stored yet and no provisional answer was given for it (the answer carries
2918
+ * `Retry-After`); `reason: NO_DATA` — the hour is stored and holds nothing for this
2919
+ * instrument.
2920
+ *
2632
2921
  */
2633
2922
  404: ResponseError;
2634
2923
  /**
2635
2924
  * Unexpected I/O error serving the file.
2636
2925
  */
2637
2926
  500: ResponseError;
2927
+ /**
2928
+ * Reads are being limited (of stored or of provisional data) and this one was not served
2929
+ * (`reason: TEMPORARILY_UNAVAILABLE`). Ask again after the `Retry-After` delay.
2930
+ *
2931
+ */
2932
+ 503: ResponseError;
2638
2933
  };
2639
2934
 
2640
2935
  export type DownloadTickersError =
@@ -2643,9 +2938,10 @@ export type DownloadTickersError =
2643
2938
  export type DownloadTickersResponses = {
2644
2939
  /**
2645
2940
  * One hour of tickers for the instrument. `Content-Type` is
2646
- * `application/vnd.lastra` by default or
2941
+ * `application/vnd.qtsurfer.lastra` by default or
2647
2942
  * `application/vnd.apache.parquet` when `format=parquet` was
2648
- * requested.
2943
+ * requested. The hour in progress, or one that has ended and is not stored yet, may be
2944
+ * provisional where the service gives provisional answers: see `X-Data-Status`.
2649
2945
  *
2650
2946
  */
2651
2947
  200: Blob | File;
@@ -2689,17 +2985,29 @@ export type DownloadKlinesData = {
2689
2985
 
2690
2986
  export type DownloadKlinesErrors = {
2691
2987
  /**
2692
- * Missing or malformed parameters (e.g. `hour` not `YYYY-MM-DDTHH`).
2988
+ * Missing or malformed parameters (e.g. `hour` not `YYYY-MM-DDTHH`), an `hour` in the
2989
+ * future, or an hour older than the last 7 days (`reason: OUTSIDE_WINDOW`, with `next`).
2990
+ *
2693
2991
  */
2694
2992
  400: ResponseError;
2695
2993
  /**
2696
- * No Lastra segment exists for the requested instrument/hour.
2994
+ * No segment for the requested instrument/hour. `reason: NOT_YET_AVAILABLE` — the hour
2995
+ * is not stored yet and no provisional answer was given for it (the answer carries
2996
+ * `Retry-After`); `reason: NO_DATA` — the hour is stored and holds nothing for this
2997
+ * instrument.
2998
+ *
2697
2999
  */
2698
3000
  404: ResponseError;
2699
3001
  /**
2700
3002
  * Unexpected I/O error serving the file.
2701
3003
  */
2702
3004
  500: ResponseError;
3005
+ /**
3006
+ * Reads are being limited (of stored or of provisional data) and this one was not served
3007
+ * (`reason: TEMPORARILY_UNAVAILABLE`). Ask again after the `Retry-After` delay.
3008
+ *
3009
+ */
3010
+ 503: ResponseError;
2703
3011
  };
2704
3012
 
2705
3013
  export type DownloadKlinesError =
@@ -2708,8 +3016,10 @@ export type DownloadKlinesError =
2708
3016
  export type DownloadKlinesResponses = {
2709
3017
  /**
2710
3018
  * One hour of klines for the instrument. `Content-Type` is
2711
- * `application/vnd.lastra` by default or
2712
- * `application/vnd.apache.parquet` when `format=parquet`.
3019
+ * `application/vnd.qtsurfer.lastra` by default or
3020
+ * `application/vnd.apache.parquet` when `format=parquet` was
3021
+ * requested. The hour in progress, or one that has ended and is not stored yet, may be
3022
+ * provisional where the service gives provisional answers: see `X-Data-Status`.
2713
3023
  *
2714
3024
  */
2715
3025
  200: Blob | File;
@@ -3741,6 +4051,15 @@ export type ImportDatasetErrors = {
3741
4051
  * `cadence`, whether that combination is actually servable on the requested `network` —
3742
4052
  * is checked later, asynchronously — see the `failed` status on the poll endpoint below.
3743
4053
  *
4054
+ * For `type: cex`: no `cex` block, or its `exchange` is not a centralized exchange of
4055
+ * `GET /exchanges` (a decentralized one is `400` too — use `type: dex`), `segment` is not
4056
+ * `spot` (the only segment a `cex` import takes today), `dataType` is not `ticker` or
4057
+ * `klines`, or
4058
+ * `cadence` is not one of the values a `cex` import takes (see `DatasetImportRequest`).
4059
+ * Whether the range holds data, and whether it holds data fine enough for the `cadence`
4060
+ * asked, is checked later, asynchronously — see the `failed` status on the poll endpoint
4061
+ * below.
4062
+ *
3744
4063
  */
3745
4064
  400: ResponseError;
3746
4065
  /**
@@ -3879,7 +4198,7 @@ export type StartLiveData = {
3879
4198
 
3880
4199
  export type StartLiveErrors = {
3881
4200
  /**
3882
- * 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. An `instruments` that is empty or `null`.
4201
+ * Malformed `sources` (not exactly one entry, missing field, unsupported `type`), a `venueType`, `exchange` and `segment` that `GET /exchanges` does not list together, or a segment with no live data (the message names what it lists), 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. An `instruments` that is empty or `null`.
3883
4202
  */
3884
4203
  400: ResponseError;
3885
4204
  /**