@qtsurfer/api-client 0.15.0 → 0.17.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.
@@ -163,6 +163,174 @@ export const HalLinkSchema = {
163
163
  },
164
164
  } as const;
165
165
 
166
+ export const AccountSchema = {
167
+ type: "object",
168
+ description: `Your identity and tier limits. No database call behind this one — safe to fetch on every
169
+ page load. Live usage against these limits is a separate resource, \`GET /account/usage\`,
170
+ deliberately: usage changes on every upload/execution and costs a query to compute, this
171
+ one doesn't.
172
+ `,
173
+ required: [
174
+ "userId",
175
+ "tier",
176
+ "maxDatasets",
177
+ "maxDatasetBytes",
178
+ "maxTotalStorageBytes",
179
+ "_links",
180
+ ],
181
+ properties: {
182
+ userId: {
183
+ type: "string",
184
+ description: "Your account id — the JWT `sub` claim.",
185
+ example: "00000000-0000-0000-0000-000000000000",
186
+ },
187
+ tier: {
188
+ type: "string",
189
+ description: "Your current subscription tier.",
190
+ example: "free",
191
+ },
192
+ maxDatasets: {
193
+ type: "integer",
194
+ description: "Maximum number of active datasets your tier allows.",
195
+ example: 3,
196
+ },
197
+ maxDatasetBytes: {
198
+ type: "integer",
199
+ format: "int64",
200
+ description: "Maximum size, in bytes, of a single dataset version.",
201
+ example: 52428800,
202
+ },
203
+ maxTotalStorageBytes: {
204
+ type: "integer",
205
+ format: "int64",
206
+ description: `Maximum combined storage, in bytes, across every dataset, strategy-execution signal,
207
+ and registered strategy on your account — one shared pool, not a separate cap per
208
+ resource type, since they all compete for the same underlying storage. See \`GET
209
+ /account/usage\`'s \`storageBytesUsed\` for your current usage against this number.
210
+ `,
211
+ example: 104857600,
212
+ },
213
+ _links: {
214
+ $ref: "#/components/schemas/AccountLinks",
215
+ },
216
+ },
217
+ } as const;
218
+
219
+ export const AccountLinksSchema = {
220
+ description: "HAL `_links` for `GET /account`",
221
+ type: "object",
222
+ required: ["self", "usage"],
223
+ properties: {
224
+ self: {
225
+ allOf: [
226
+ {
227
+ $ref: "#/components/schemas/HalLink",
228
+ },
229
+ ],
230
+ description: "Link to this resource.",
231
+ },
232
+ usage: {
233
+ allOf: [
234
+ {
235
+ $ref: "#/components/schemas/HalLink",
236
+ },
237
+ ],
238
+ description: "Link to your live usage, `GET /account/usage`.",
239
+ },
240
+ },
241
+ } as const;
242
+
243
+ export const AccountUsageSchema = {
244
+ type: "object",
245
+ description: `Your live usage of the shared storage pool \`GET /account\`'s \`maxTotalStorageBytes\` caps.
246
+ Not guaranteed real-time — a just-completed upload or strategy execution may take a short
247
+ moment to be reflected here.
248
+ `,
249
+ required: [
250
+ "datasetsUsed",
251
+ "datasetBytesUsed",
252
+ "signalsUsed",
253
+ "signalBytesUsed",
254
+ "strategiesUsed",
255
+ "strategyBytesUsed",
256
+ "storageBytesUsed",
257
+ "_links",
258
+ ],
259
+ properties: {
260
+ datasetsUsed: {
261
+ type: "integer",
262
+ description:
263
+ "Active datasets counted — the same set `GET /account`'s `maxDatasets` limits.",
264
+ example: 2,
265
+ },
266
+ datasetBytesUsed: {
267
+ type: "integer",
268
+ format: "int64",
269
+ description: "Combined bytes of every active dataset's current version.",
270
+ example: 15728640,
271
+ },
272
+ signalsUsed: {
273
+ type: "integer",
274
+ description: "Recorded strategy-execution signal uploads.",
275
+ example: 1,
276
+ },
277
+ signalBytesUsed: {
278
+ type: "integer",
279
+ format: "int64",
280
+ description: "Combined bytes of every recorded signal upload.",
281
+ example: 524288,
282
+ },
283
+ strategiesUsed: {
284
+ type: "integer",
285
+ description: "Registered strategies (see `GET /strategies`).",
286
+ example: 4,
287
+ },
288
+ strategyBytesUsed: {
289
+ type: "integer",
290
+ format: "int64",
291
+ description: `Combined bytes of each registered strategy's source plus its latest compiled
292
+ bytecode. Superseded (non-latest) compilations aren't counted.
293
+ `,
294
+ example: 40960,
295
+ },
296
+ storageBytesUsed: {
297
+ type: "integer",
298
+ format: "int64",
299
+ description: `\`datasetBytesUsed + signalBytesUsed + strategyBytesUsed\` — the number checked
300
+ against \`GET /account\`'s \`maxTotalStorageBytes\`.
301
+ `,
302
+ example: 16293888,
303
+ },
304
+ _links: {
305
+ $ref: "#/components/schemas/AccountUsageLinks",
306
+ },
307
+ },
308
+ } as const;
309
+
310
+ export const AccountUsageLinksSchema = {
311
+ description: "HAL `_links` for `GET /account/usage`",
312
+ type: "object",
313
+ required: ["self", "account"],
314
+ properties: {
315
+ self: {
316
+ allOf: [
317
+ {
318
+ $ref: "#/components/schemas/HalLink",
319
+ },
320
+ ],
321
+ description: "Link to this resource.",
322
+ },
323
+ account: {
324
+ allOf: [
325
+ {
326
+ $ref: "#/components/schemas/HalLink",
327
+ },
328
+ ],
329
+ description: "Link to your tier limits, `GET /account`.",
330
+ },
331
+ },
332
+ } as const;
333
+
166
334
  export const InstrumentDetailSchema = {
167
335
  description:
168
336
  "Exchange instrument with per-data-type coverage and market info",
@@ -277,8 +445,17 @@ export const ExchangeSchema = {
277
445
 
278
446
  export const DataSourceTypeSchema = {
279
447
  type: "string",
280
- description: "Managed exchange data sources available for backtesting.",
281
- enum: ["ticker"],
448
+ description: `Managed exchange data sources available for backtesting.
449
+
450
+ * \`ticker\` — trades. Can be prepared, executed and swept.
451
+ * \`kline\` — aggregated bars (candlesticks). Can be prepared, executed and swept. A run reads
452
+ bars of the \`cadence\` the data was prepared at: you choose the bar width when you prepare,
453
+ and the strategy does not fix it. See \`PrepareRequest.cadence\` for the accepted values.
454
+ * \`funding\` — funding rates. Can be **prepared but not executed or swept yet**: a \`funding\`
455
+ request to \`execute\` or \`executeSweep\` is rejected with \`400\` before anything is queued,
456
+ and the message names the sources that can be run.
457
+ `,
458
+ enum: ["ticker", "kline", "funding"],
282
459
  example: "ticker",
283
460
  } as const;
284
461
 
@@ -340,9 +517,14 @@ resampling the source and stored alongside the native blob in cache. A target fi
340
517
  than the source, or not an exact multiple of it, returns \`400\`. What's accepted, and
341
518
  what omitting it means, depends on the source:
342
519
 
343
- * Managed exchange — one of \`1s\`, \`5s\`, \`1m\`, \`3m\`, \`5m\`, \`15m\`, \`30m\`, \`1h\`, \`2h\`,
344
- \`4h\`, \`8h\`, \`12h\`, \`1d\`, \`1w\`, \`1q\`; any other label returns \`400\`. Omitted = \`1s\`,
345
- the publisher's native cadence.
520
+ * Managed exchange, \`ticker\` or \`funding\` — one of \`1s\`, \`5s\`, \`1m\`, \`3m\`, \`5m\`, \`15m\`,
521
+ \`30m\`, \`1h\`, \`2h\`, \`4h\`, \`8h\`, \`12h\`, \`1d\`, \`1w\`, \`1q\`; any other label returns \`400\`.
522
+ Omitted = \`1s\`, the publisher's native cadence.
523
+ * Managed exchange, \`kline\` — one of \`1s\`, \`1m\`, \`5m\`, \`15m\`, \`30m\`, \`1h\`, \`4h\`, \`1d\`;
524
+ any other label, including \`5s\`, \`3m\` and \`8h\`, returns \`400\` and names the accepted
525
+ ones. Omitted = \`1s\`. This is the width of the bars a run reads: it is chosen here,
526
+ once, and the same strategy can be run at several cadences by preparing the range at
527
+ each.
346
528
  * Dataset (\`exchangeId: user\`) — omitted = the dataset version's own discovered
347
529
  \`cadence\` (see \`DatasetVersion.cadence\`), served as-is. Any cadence equal to or
348
530
  coarser than it and an exact multiple of it is accepted, including ones outside the
@@ -369,7 +551,7 @@ export const JobStateSchema = {
369
551
  description:
370
552
  "Identifier for the job's execution context. Its current shape is a colon-delimited string encoding the data source type, an internal user id, the exchange, the job id, and the instrument — but that structure is not a committed contract and may change without notice. Treat it as an opaque token: store and pass it back, don't parse it.",
371
553
  example:
372
- "jctx:ticker:76b90203-03c2-46f6-b366-9944f167e818:binance:5ikyamio8b3v9wcnfxztzg:btc/usdt:0vicnz3thzhrqvfczks1pu",
554
+ "jctx:ticker:00000000-0000-0000-0000-000000000000:binance:5ikyamio8b3v9wcnfxztzg:btc/usdt:0vicnz3thzhrqvfczks1pu",
373
555
  },
374
556
  status: {
375
557
  type: "string",
@@ -1712,8 +1894,9 @@ export const EquityCurveResultSchema = {
1712
1894
 
1713
1895
  export const strategyIdSchema = {
1714
1896
  description: `Unique identifier for a compiled strategy, derived from the source itself: the same code
1715
- always yields the same id, for every caller, whatever its formatting. See
1716
- \`POST /strategy\` for exactly which rewrites preserve it and which do not.
1897
+ always yields the same id, for every caller. How much formatting the id ignores depends on
1898
+ the language — see \`POST /strategy\` for exactly which rewrites preserve it and which do
1899
+ not.
1717
1900
  `,
1718
1901
  type: "string",
1719
1902
  example: "6bsh31ikwkuivhtgcoa6s4",
@@ -1964,11 +2147,12 @@ export const DatasetSchema = {
1964
2147
  description: `A dataset's own metadata — not its data. \`currentVersionId\` is what a prepare against
1965
2148
  \`exchangeId: user\` reads by default; see \`DatasetVersion\` for what a version carries.
1966
2149
 
1967
- \`from\`/\`to\`/\`cadence\` mirror that current version's own discovered range and cadence, so
1968
- you don't need a second call to \`GET /datasets/{datasetId}/uploads/{uploadId}\` just to see
1969
- what a dataset covers. Absent until a version exists.
2150
+ \`from\`/\`to\`/\`cadence\`/\`timestampUnit\`/\`bytes\`/\`rows\`/\`gaps\`/\`largestGapSteps\` mirror that
2151
+ current version's own discovered range, cadence, timestamp unit and metrics, so you don't
2152
+ need a second call to \`GET /datasets/{datasetId}/uploads/{uploadId}\` just to see what a
2153
+ dataset covers.
1970
2154
  `,
1971
- required: ["datasetId", "name", "type", "instrument", "createdAt"],
2155
+ required: ["datasetId", "name", "type", "instrument", "createdAt", "status"],
1972
2156
  properties: {
1973
2157
  datasetId: {
1974
2158
  type: "string",
@@ -2035,6 +2219,56 @@ a version exists.
2035
2219
  `,
2036
2220
  example: "1m",
2037
2221
  },
2222
+ timestampUnit: {
2223
+ type: "string",
2224
+ enum: ["iso", "s", "ms", "us"],
2225
+ description: `\`currentVersionId\`'s own timestamp unit (see \`DatasetVersion.timestampUnit\`) — decode
2226
+ the \`timestamp\` column of \`dataUrl\`'s file accordingly. Present only when \`status\` is
2227
+ \`ready\`.
2228
+ `,
2229
+ example: "iso",
2230
+ },
2231
+ status: {
2232
+ type: "string",
2233
+ enum: ["ready", "failed", "pending"],
2234
+ description: `* \`ready\` — \`currentVersionId\` is set; \`from\`/\`to\`/\`cadence\`/\`bytes\`/\`rows\`/\`gaps\`/
2235
+ \`largestGapSteps\` describe it.
2236
+ * \`failed\` — the most recent upload/import attempt failed. \`currentVersionId\` and the
2237
+ fields above are absent — there is nothing to read yet. See \`error\`.
2238
+ * \`pending\` — nothing has ever been attempted (just created, or an upload was never
2239
+ finalized).
2240
+ `,
2241
+ example: "ready",
2242
+ },
2243
+ bytes: {
2244
+ type: "integer",
2245
+ description: `Size of \`currentVersionId\`'s own stored file. Present only when \`status\` is \`ready\` —
2246
+ see \`DatasetVersion.bytes\` for what it measures exactly.
2247
+ `,
2248
+ example: 4831022,
2249
+ },
2250
+ rows: {
2251
+ type: "integer",
2252
+ description: `\`currentVersionId\`'s own row count. Present only when \`status\` is \`ready\`.`,
2253
+ example: 86400,
2254
+ },
2255
+ gaps: {
2256
+ type: "integer",
2257
+ description: `\`currentVersionId\`'s own gap count at its discovered cadence. Present only when \`status\` is \`ready\`.`,
2258
+ example: 0,
2259
+ },
2260
+ largestGapSteps: {
2261
+ type: "integer",
2262
+ description: `\`currentVersionId\`'s own largest gap, in units of its discovered cadence step. Present only when \`status\` is \`ready\`.`,
2263
+ example: 0,
2264
+ },
2265
+ error: {
2266
+ type: "string",
2267
+ description: `A human-readable reason the most recent upload/import attempt failed. Present only
2268
+ when \`status\` is \`failed\`.
2269
+ `,
2270
+ example: "line 3: column 'close' is not a number: not-a-number",
2271
+ },
2038
2272
  },
2039
2273
  } as const;
2040
2274
 
@@ -2064,8 +2298,9 @@ session, not in one shot like a browser upload.
2064
2298
  enum: ["lastra", "parquet"],
2065
2299
  description: `Which format \`dataUrl\` is actually in — check this rather than assuming it
2066
2300
  matches how you uploaded it. \`lastra\` — our native columnar format — for a CSV (or
2067
- gzip/zip of one) upload, always converted on ingest. \`parquet\` for a parquet
2068
- upload, stored as-is today.
2301
+ gzip/zip of one) upload, always converted on ingest, or for a lastra upload,
2302
+ stored as-is (the value alone doesn't tell you which). \`parquet\` for a parquet
2303
+ upload, also stored as-is today.
2069
2304
  `,
2070
2305
  example: "lastra",
2071
2306
  },
@@ -2244,8 +2479,9 @@ an extended viewing session, not in one shot like a browser upload.
2244
2479
  enum: ["lastra", "parquet"],
2245
2480
  description: `Which format \`dataUrl\` is actually in — check this rather than assuming it matches
2246
2481
  how you uploaded it. \`lastra\` — our native columnar format — for a CSV (or gzip/zip
2247
- of one) upload, always converted on ingest. \`parquet\` for a parquet upload, stored
2248
- as-is today.
2482
+ of one) upload, always converted on ingest, or for a lastra upload, stored as-is
2483
+ (the value alone doesn't tell you which). \`parquet\` for a parquet upload, also
2484
+ stored as-is today.
2249
2485
  `,
2250
2486
  example: "lastra",
2251
2487
  },
@@ -2549,3 +2785,474 @@ export const AuthTokenErrorSchema = {
2549
2785
  },
2550
2786
  },
2551
2787
  } as const;
2788
+
2789
+ export const LiveSourceSchema = {
2790
+ type: "object",
2791
+ required: ["venueType", "exchange", "segment", "type", "instruments"],
2792
+ description:
2793
+ "One market feed a live run consumes. Exactly one entry per run today.",
2794
+ properties: {
2795
+ venueType: {
2796
+ type: "string",
2797
+ example: "cx",
2798
+ description:
2799
+ "Venue category. `cx` (centralized exchange) is the only one live runs support today.",
2800
+ },
2801
+ exchange: {
2802
+ type: "string",
2803
+ example: "binance",
2804
+ },
2805
+ segment: {
2806
+ type: "string",
2807
+ example: "spot",
2808
+ },
2809
+ type: {
2810
+ type: "string",
2811
+ enum: ["ticker", "kline"],
2812
+ description:
2813
+ "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.",
2814
+ },
2815
+ instruments: {
2816
+ type: "array",
2817
+ items: {
2818
+ type: "string",
2819
+ },
2820
+ example: ["BTC/USDT"],
2821
+ description:
2822
+ 'Instrument symbols, or `["*"]` for every instrument the exchange/segment offers (tier-gated).',
2823
+ },
2824
+ },
2825
+ } as const;
2826
+
2827
+ export const StartLiveRequestSchema = {
2828
+ type: "object",
2829
+ required: ["sources"],
2830
+ properties: {
2831
+ sources: {
2832
+ type: "array",
2833
+ minItems: 1,
2834
+ maxItems: 1,
2835
+ items: {
2836
+ $ref: "#/components/schemas/LiveSource",
2837
+ },
2838
+ },
2839
+ params: {
2840
+ type: "object",
2841
+ description:
2842
+ "Strategy parameters to start with. Opaque key/value pairs — see this strategy's own `declaredProperties` (from `POST /strategy`) for the keys it accepts.",
2843
+ additionalProperties: true,
2844
+ },
2845
+ visibility: {
2846
+ type: "string",
2847
+ enum: ["private", "public"],
2848
+ default: "private",
2849
+ description:
2850
+ "A `public` run appears in `GET /live/public` and its signal channel accepts subscriptions from anyone, not only you.",
2851
+ },
2852
+ relay: {
2853
+ type: "boolean",
2854
+ default: false,
2855
+ description: `Request that this run's signals be relayed over its WebSocket channel once it reaches the \`live\` stage — see the "Live execution" guide. Has no effect while the run is still in the \`sandbox\` stage, regardless of this value.`,
2856
+ },
2857
+ name: {
2858
+ type: "string",
2859
+ },
2860
+ description: {
2861
+ type: "string",
2862
+ },
2863
+ },
2864
+ } as const;
2865
+
2866
+ export const UpdateLiveRequestSchema = {
2867
+ type: "object",
2868
+ properties: {
2869
+ visibility: {
2870
+ type: "string",
2871
+ enum: ["private", "public"],
2872
+ },
2873
+ name: {
2874
+ type: "string",
2875
+ },
2876
+ description: {
2877
+ type: "string",
2878
+ },
2879
+ },
2880
+ } as const;
2881
+
2882
+ export const UpdateLiveParamsRequestSchema = {
2883
+ type: "object",
2884
+ required: ["params"],
2885
+ properties: {
2886
+ params: {
2887
+ type: "object",
2888
+ additionalProperties: true,
2889
+ description:
2890
+ "Must be non-empty; every key must be a property your strategy declares.",
2891
+ },
2892
+ },
2893
+ } as const;
2894
+
2895
+ export const LiveRunSchema = {
2896
+ type: "object",
2897
+ required: [
2898
+ "strategyId",
2899
+ "runId",
2900
+ "visibility",
2901
+ "stage",
2902
+ "state",
2903
+ "desired",
2904
+ "sources",
2905
+ "params",
2906
+ "paramsVersion",
2907
+ "relay",
2908
+ "startedAtMs",
2909
+ ],
2910
+ description:
2911
+ "A live run's full state, as returned by starting, reading, or stopping it through its strategy.",
2912
+ properties: {
2913
+ strategyId: {
2914
+ $ref: "#/components/schemas/strategyId",
2915
+ },
2916
+ runId: {
2917
+ type: "string",
2918
+ description:
2919
+ "This run's own id — its canonical identity for `PATCH`/`PUT .../params` and for `GET /live/public`.",
2920
+ },
2921
+ name: {
2922
+ type: "string",
2923
+ },
2924
+ description: {
2925
+ type: "string",
2926
+ },
2927
+ visibility: {
2928
+ type: "string",
2929
+ enum: ["private", "public"],
2930
+ },
2931
+ stage: {
2932
+ type: "string",
2933
+ enum: ["SANDBOX", "LIVE"],
2934
+ description:
2935
+ "A new run always starts `SANDBOX` — a trial run compared against a second execution for agreement — and moves to `LIVE` once it passes.",
2936
+ },
2937
+ state: {
2938
+ type: "string",
2939
+ description: `\`STARTING\` until first observed running; otherwise the runner's own reported state (e.g. \`RUNNING\`).`,
2940
+ },
2941
+ desired: {
2942
+ type: "string",
2943
+ enum: ["RUNNING", "STOPPED"],
2944
+ description:
2945
+ "What you last asked for. `state` can lag this briefly after `DELETE`.",
2946
+ },
2947
+ reason: {
2948
+ type: "string",
2949
+ description:
2950
+ "Present only when the run stopped because it exceeded its resource allowance.",
2951
+ },
2952
+ sources: {
2953
+ type: "array",
2954
+ items: {
2955
+ $ref: "#/components/schemas/LiveSource",
2956
+ },
2957
+ },
2958
+ params: {
2959
+ type: "object",
2960
+ additionalProperties: true,
2961
+ },
2962
+ paramsVersion: {
2963
+ type: "integer",
2964
+ description:
2965
+ "Increments on every accepted `PUT .../params` call, including one that resends the current values.",
2966
+ },
2967
+ relay: {
2968
+ type: "boolean",
2969
+ description: `Whether this run's signals are being relayed over the WebSocket channel described in the "Live execution" guide, right now. This is the effective value — \`false\` on a \`sandbox\` run regardless of what was requested at start; matches the requested value once \`stage\` reaches \`live\`.`,
2970
+ },
2971
+ startedAtMs: {
2972
+ type: "integer",
2973
+ format: "int64",
2974
+ description: "Epoch milliseconds.",
2975
+ },
2976
+ gate: {
2977
+ type: "object",
2978
+ additionalProperties: true,
2979
+ description:
2980
+ "The sandbox trial's promotion verdict, once one exists. Shape is not yet stabilized as public API — treat as opaque diagnostics.",
2981
+ },
2982
+ },
2983
+ } as const;
2984
+
2985
+ export const LiveRunCompactSchema = {
2986
+ type: "object",
2987
+ required: ["runId", "visibility", "stage", "state", "sources"],
2988
+ description:
2989
+ "A run's state as returned by `PATCH /live/{runId}` — narrower than `LiveRun` (no `strategyId`, `params`, or `desired`), since this endpoint is addressed by `runId` alone.",
2990
+ properties: {
2991
+ runId: {
2992
+ type: "string",
2993
+ },
2994
+ name: {
2995
+ type: "string",
2996
+ },
2997
+ description: {
2998
+ type: "string",
2999
+ },
3000
+ visibility: {
3001
+ type: "string",
3002
+ enum: ["private", "public"],
3003
+ },
3004
+ stage: {
3005
+ type: "string",
3006
+ enum: ["SANDBOX", "LIVE"],
3007
+ },
3008
+ state: {
3009
+ type: "string",
3010
+ },
3011
+ sources: {
3012
+ type: "array",
3013
+ items: {
3014
+ $ref: "#/components/schemas/LiveSource",
3015
+ },
3016
+ },
3017
+ },
3018
+ } as const;
3019
+
3020
+ export const PublicLiveRunSchema = {
3021
+ type: "object",
3022
+ required: ["runId", "sources", "state", "createdAtMs"],
3023
+ description:
3024
+ "A run as it appears in `GET /live/public` — never reveals who owns it or which strategy it runs.",
3025
+ properties: {
3026
+ runId: {
3027
+ type: "string",
3028
+ },
3029
+ name: {
3030
+ type: "string",
3031
+ },
3032
+ description: {
3033
+ type: "string",
3034
+ },
3035
+ sources: {
3036
+ type: "array",
3037
+ items: {
3038
+ $ref: "#/components/schemas/LiveSource",
3039
+ },
3040
+ },
3041
+ state: {
3042
+ type: "string",
3043
+ },
3044
+ createdAtMs: {
3045
+ type: "integer",
3046
+ format: "int64",
3047
+ },
3048
+ },
3049
+ } as const;
3050
+
3051
+ export const PublicLiveListResponseSchema = {
3052
+ type: "object",
3053
+ required: ["runs"],
3054
+ properties: {
3055
+ runs: {
3056
+ type: "array",
3057
+ items: {
3058
+ $ref: "#/components/schemas/PublicLiveRun",
3059
+ },
3060
+ },
3061
+ _links: {
3062
+ $ref: "#/components/schemas/PublicLiveListLinks",
3063
+ },
3064
+ },
3065
+ } as const;
3066
+
3067
+ export const PublicLiveListLinksSchema = {
3068
+ type: "object",
3069
+ description: "Present only when another page exists.",
3070
+ properties: {
3071
+ next: {
3072
+ $ref: "#/components/schemas/PublicLiveNextLink",
3073
+ },
3074
+ },
3075
+ } as const;
3076
+
3077
+ export const PublicLiveNextLinkSchema = {
3078
+ type: "object",
3079
+ properties: {
3080
+ href: {
3081
+ type: "string",
3082
+ },
3083
+ },
3084
+ } as const;
3085
+
3086
+ export const LiveSignalPageSchema = {
3087
+ type: "object",
3088
+ required: ["signals"],
3089
+ description: "One page of a run's recorded signals, oldest first.",
3090
+ properties: {
3091
+ signals: {
3092
+ type: "array",
3093
+ items: {
3094
+ $ref: "#/components/schemas/LiveSignal",
3095
+ },
3096
+ },
3097
+ availableSinceMs: {
3098
+ type: "integer",
3099
+ format: "int64",
3100
+ description:
3101
+ "The oldest moment this run's signals can still be read from. Absent when the run has produced nothing yet. It moves forward over time as older signals are discarded, so a `sinceMs` earlier than this is served from here instead.",
3102
+ },
3103
+ _links: {
3104
+ $ref: "#/components/schemas/PublicLiveListLinks",
3105
+ },
3106
+ },
3107
+ } as const;
3108
+
3109
+ export const LiveSignalSchema = {
3110
+ type: "object",
3111
+ required: [
3112
+ "v",
3113
+ "signalId",
3114
+ "runId",
3115
+ "stage",
3116
+ "type",
3117
+ "eventTsMs",
3118
+ "emittedAtMs",
3119
+ "instrument",
3120
+ "digest",
3121
+ ],
3122
+ description:
3123
+ "One signal, in the same shape the real-time signal channel delivers.",
3124
+ properties: {
3125
+ v: {
3126
+ type: "integer",
3127
+ description: "Envelope schema version.",
3128
+ },
3129
+ signalId: {
3130
+ type: "string",
3131
+ description:
3132
+ "Stable id for this exact signal — dedupe on it across reconnects or overlapping reads.",
3133
+ },
3134
+ runId: {
3135
+ type: "string",
3136
+ },
3137
+ stage: {
3138
+ type: "string",
3139
+ enum: ["sandbox", "live"],
3140
+ description: "The stage the run was in when this signal was produced.",
3141
+ },
3142
+ paramsVersion: {
3143
+ type: "integer",
3144
+ description: "The parameter set in force when this signal was produced.",
3145
+ },
3146
+ type: {
3147
+ type: "string",
3148
+ enum: ["hint", "info", "marker", "command"],
3149
+ },
3150
+ kind: {
3151
+ type: ["string", "null"],
3152
+ description: `\`BUY\`/\`SELL\` for a \`hint\`, the command name for a \`command\`, absent otherwise.`,
3153
+ },
3154
+ eventTsMs: {
3155
+ type: "integer",
3156
+ format: "int64",
3157
+ description: "Market time the signal was produced.",
3158
+ },
3159
+ emittedAtMs: {
3160
+ type: "integer",
3161
+ format: "int64",
3162
+ description: "Time it was published — always at or after `eventTsMs`.",
3163
+ },
3164
+ instrument: {
3165
+ $ref: "#/components/schemas/LiveSignalInstrument",
3166
+ },
3167
+ order: {
3168
+ $ref: "#/components/schemas/LiveSignalOrder",
3169
+ },
3170
+ data: {
3171
+ type: "object",
3172
+ additionalProperties: true,
3173
+ description: "The signal's own free-form payload.",
3174
+ },
3175
+ regenerated: {
3176
+ type: "boolean",
3177
+ description: `\`true\` only for a signal republished to fill a gap in the record.`,
3178
+ },
3179
+ digest: {
3180
+ type: "string",
3181
+ description:
3182
+ "Content hash, for checking that two independent deliveries of the same signal agree.",
3183
+ },
3184
+ },
3185
+ } as const;
3186
+
3187
+ export const LiveSignalInstrumentSchema = {
3188
+ type: "object",
3189
+ properties: {
3190
+ exchange: {
3191
+ type: "string",
3192
+ },
3193
+ segment: {
3194
+ type: "string",
3195
+ },
3196
+ symbol: {
3197
+ type: "string",
3198
+ description: "Slashed form, e.g. `BTC/USDT`.",
3199
+ },
3200
+ },
3201
+ } as const;
3202
+
3203
+ export const LiveSignalOrderSchema = {
3204
+ type: ["object", "null"],
3205
+ description: "Present only for a `hint`.",
3206
+ properties: {
3207
+ orderKind: {
3208
+ type: "string",
3209
+ },
3210
+ price: {
3211
+ type: ["string", "null"],
3212
+ },
3213
+ amount: {
3214
+ type: ["string", "null"],
3215
+ },
3216
+ stopPrice: {
3217
+ type: ["string", "null"],
3218
+ },
3219
+ trailPct: {
3220
+ type: ["string", "null"],
3221
+ },
3222
+ },
3223
+ } as const;
3224
+
3225
+ export const LiveConnectionTokenSchema = {
3226
+ type: "object",
3227
+ required: ["token", "expiresAtMs"],
3228
+ properties: {
3229
+ token: {
3230
+ type: "string",
3231
+ description:
3232
+ 'Pass as the `token` field of the WebSocket `connect` command — see the "Live execution" guide.',
3233
+ },
3234
+ expiresAtMs: {
3235
+ type: "integer",
3236
+ format: "int64",
3237
+ },
3238
+ },
3239
+ } as const;
3240
+
3241
+ export const LiveParamsUpdateResultSchema = {
3242
+ type: "object",
3243
+ required: ["runId", "paramsVersion", "effectiveAtMs"],
3244
+ properties: {
3245
+ runId: {
3246
+ type: "string",
3247
+ },
3248
+ paramsVersion: {
3249
+ type: "integer",
3250
+ },
3251
+ effectiveAtMs: {
3252
+ type: "integer",
3253
+ format: "int64",
3254
+ description:
3255
+ "Epoch milliseconds — the earliest moment the new values are guaranteed to be in effect.",
3256
+ },
3257
+ },
3258
+ } as const;