@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.
@@ -175,6 +175,10 @@ export type Options<
175
175
  * expires after `expires_in` seconds. Callers should refresh the token
176
176
  * before expiry (or on a `401` response) by calling this endpoint again.
177
177
  *
178
+ * The answer's `scopes` say what the key may do. Where a deployment requires scopes, a key
179
+ * that carries none is refused with `403` and the code `apikey_without_scopes`: create a key
180
+ * with at least one scope.
181
+ *
178
182
  */
179
183
  export const authenticate = <ThrowOnError extends boolean = false>(
180
184
  options?: Options<AuthenticateData, ThrowOnError>
@@ -251,6 +255,18 @@ export const getAccountUsage = <ThrowOnError extends boolean = false>(
251
255
 
252
256
  /**
253
257
  * List the available exchanges
258
+ * The exchanges the platform knows, centralized and decentralized, each with its `venueType` and the
259
+ * `segments` it offers. Ids, venue types and segments are lower-case, and are written the same way
260
+ * wherever the API takes them: `/exchange/binance/spot/instruments`, and the `exchange`, `venueType`
261
+ * and `segment` of a live run's source.
262
+ *
263
+ * `venueType` is `cex` for a centralized exchange and `dex` for a decentralized one. The `segments` of a
264
+ * `cex` exchange are the market segments its instrument catalogues are served under (`spot`, `futures`);
265
+ * its `liveSegments`, among them, are those a live run can read, because live data is published for them.
266
+ * A `dex` exchange has no market data to prepare or backtest, so its id is `400` in the routes that take an
267
+ * `exchangeId`, except the two instruments routes: its `segments` are the protocols whose pools a run can
268
+ * read, and those routes list the pools, since the instrument of a run on it is a pool's address.
269
+ *
254
270
  */
255
271
  export const listExchanges = <ThrowOnError extends boolean = false>(
256
272
  options?: Options<ListExchangesData, ThrowOnError>
@@ -272,6 +288,10 @@ export const listExchanges = <ThrowOnError extends boolean = false>(
272
288
  * confirms the served `segment` (`spot`); HAL `_links` carry `self` plus the
273
289
  * `spot` / `futures` segment-discovery links.
274
290
  *
291
+ * For a decentralized exchange (`venueType` `dex` in `GET /exchanges`) the instruments are its pools,
292
+ * each a `PoolDetail`, and the default segment is the first one the exchange lists (`uniswap-v3` for
293
+ * `robinhood`).
294
+ *
275
295
  */
276
296
  export const listInstruments = <ThrowOnError extends boolean = false>(
277
297
  options: Options<ListInstrumentsData, ThrowOnError>
@@ -293,6 +313,11 @@ export const listInstruments = <ThrowOnError extends boolean = false>(
293
313
  * `spot` / `futures` segment-discovery links; the default-segment shortcut is
294
314
  * `GET /exchange/{exchangeId}/instruments` (spot).
295
315
  *
316
+ * For a decentralized exchange the segments are its protocols (`uniswap-v3` for `robinhood`) and the
317
+ * instruments are its pools, each a `PoolDetail`: the 50 with most volume in the last 24 hours among
318
+ * those with at least 10,000 US dollars of liquidity, refreshed every hour. The list is a place to
319
+ * start, not the whole market: a live run can read any pool of the protocol, listed or not.
320
+ *
296
321
  */
297
322
  export const listSegmentInstruments = <ThrowOnError extends boolean = false>(
298
323
  options: Options<ListSegmentInstrumentsData, ThrowOnError>
@@ -316,9 +341,33 @@ export const listSegmentInstruments = <ThrowOnError extends boolean = false>(
316
341
  *
317
342
  * One segment = one hour, aligned to UTC. The `hour` query parameter selects
318
343
  * the segment and must match `YYYY-MM-DDTHH` (no minutes/seconds, no timezone
319
- * suffix). Example: `hour=2026-01-15T10` returns `h10.lastra` for
320
- * 2026-01-15, covering `[10:00:00Z, 11:00:00Z)`. Hours not yet available
321
- * return `404`.
344
+ * suffix). Example: `hour=2026-10-15T10` is the segment `h10.lastra` of
345
+ * 2026-10-15, covering `[10:00:00Z, 11:00:00Z)`. The hour has to be one of the last 7 days (see
346
+ * below): read the example as the shape of the value.
347
+ *
348
+ * **Which hours.** The last 7 days: an hour that started no more than 7 days before the
349
+ * request and has ended. This route gives one hour of one instrument, fast; it is not how to
350
+ * get older history or a range. An older hour is `400` with `reason: OUTSIDE_WINDOW`, and the
351
+ * error carries `next`, the `POST /datasets/imports` request that imports exactly that hour
352
+ * as a dataset (add a `name`); a longer span is imported the same way, within your plan's
353
+ * limits.
354
+ *
355
+ * **The hour in progress and the last hours.** The hour in progress, and an hour that has ended
356
+ * but is not stored yet, can be answered with what has been received so far, marked provisional:
357
+ * `200` with `X-Data-Status: provisional` and `X-Data-Through`, the instant of the last row.
358
+ * Not every deployment of the service gives provisional answers: where it does not, those hours
359
+ * are `404` with `reason: NOT_YET_AVAILABLE` and a `Retry-After`, and a client that needs them
360
+ * handles both. A provisional answer is not to keep: it can still grow, and the stored hour
361
+ * replaces it once there is one. It takes seconds to build, longer the further the hour has gone,
362
+ * and the service limits how many it builds at once (`503` with `Retry-After`). When there is
363
+ * nothing to give, because the instrument has no rows in the hour yet or what has been received
364
+ * does not reach back to the start of the hour, the answer is also `404` with
365
+ * `reason: NOT_YET_AVAILABLE`.
366
+ *
367
+ * **Timestamps.** In a Lastra response the `ts` column holds microseconds since the epoch,
368
+ * declared by `ts_unit: micros` in the column's metadata and by the response header
369
+ * `X-Ts-Unit: micros`. In a Parquet response the timestamp column is a `TIMESTAMP` in
370
+ * milliseconds.
322
371
  *
323
372
  * A `format=parquet` query parameter switches the response to on-the-fly
324
373
  * Parquet conversion via [lastra-convert](https://github.com/QTSurfer/lastra-convert)
@@ -363,6 +412,9 @@ export const downloadTickers = <ThrowOnError extends boolean = false>(
363
412
  * format read the other with the same code. Use this endpoint when a
364
413
  * per-tick payload would be too large for the window of interest.
365
414
  *
415
+ * The hours served (the last 7 days; the hour in progress and the last hours may be provisional), the timestamps
416
+ * (`ts` in microseconds, `X-Ts-Unit: micros`) and the errors are those of the tickers route.
417
+ *
366
418
  */
367
419
  export const downloadKlines = <ThrowOnError extends boolean = false>(
368
420
  options: Options<DownloadKlinesData, ThrowOnError>
@@ -1236,8 +1288,18 @@ export const getDatasetUpload = <ThrowOnError extends boolean = false>(
1236
1288
  * as a dataset version indistinguishable from an uploaded one once it's ready. Poll
1237
1289
  * `GET /datasets/{datasetId}/imports/{importId}` for progress.
1238
1290
  *
1239
- * `type` selects the source. `dex` — history over a pool/pair's own on-chain market — is the
1240
- * only value today; other source types join this same endpoint later.
1291
+ * `type` selects the kind of venue the history comes from, with the same two values as the
1292
+ * `venueType` of `GET /exchanges`: `dex` — history over a pool/pair's own on-chain market —
1293
+ * and `cex` — the history of a centralized exchange's market, kept by the platform. Each
1294
+ * has its own block (`dex`, `cex`). The exchange id of a `cex` import has to be a centralized
1295
+ * exchange of `GET /exchanges`; a decentralized one (`robinhood`, say) is `400`, and is imported
1296
+ * with `type: dex`.
1297
+ *
1298
+ * A `cex` import covers one instrument over a range: the API reads that range of the
1299
+ * exchange's history, builds the bars of the requested `cadence` from the finest data it has
1300
+ * for it, and stores the result as a dataset version, exactly as for an upload. `cex.dataType`
1301
+ * picks tickers or klines and is also the resulting dataset's `type`. The range is capped by
1302
+ * your tier like any import (`maxImportRangeHours` of `GET /account`).
1241
1303
  *
1242
1304
  * A `dex` import has two data shapes, chosen by the top-level `cadence`:
1243
1305
  *
@@ -1388,7 +1450,16 @@ export const getLive = <ThrowOnError extends boolean = false>(
1388
1450
  * (fastest) cadence available for the exchange — today that is 1 tick/second on every
1389
1451
  * supported exchange; choosing among several cadences is not offered yet.
1390
1452
  *
1391
- * `instruments` can be left out. A QTScript strategy can declare which instruments it accepts with an `instruments`
1453
+ * `venueType` is `cex` (a centralized exchange) or `dex` (one pool on a decentralized exchange). A `dex` source reads one
1454
+ * pool, takes only `kline`, and needs the pool's address as its single instrument. See the "Live execution" guide,
1455
+ * "Sources".
1456
+ *
1457
+ * `venueType`, `exchange` and `segment` have to be ones `GET /exchanges` lists together: the exchange under that
1458
+ * venue type, and the segment among its `liveSegments`. Case and the spaces around a value do not matter, and the
1459
+ * run reports them back in lower case (`cx`, the older spelling of `cex`, is still read). Anything else is refused
1460
+ * with `400`, naming what the list has.
1461
+ *
1462
+ * `instruments` can be left out, except for a `dex` source. A QTScript strategy can declare which instruments it accepts with an `instruments`
1392
1463
  * line in its source; when the compilation of the strategy records that selection as a list of pairs, a
1393
1464
  * start that leaves `instruments` out, or sends `["*"]`, takes that list, and otherwise the run reads every
1394
1465
  * instrument the exchange/segment offers. A list you send is taken as sent. Either side of an entry can be `*`