@qtsurfer/api-client 0.10.0 → 0.12.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.
- package/README.md +9 -2
- package/dist/index.d.ts +713 -24
- package/dist/index.js +95 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/generated/schemas.gen.ts +608 -32
- package/src/generated/sdk.gen.ts +242 -2
- package/src/generated/types.gen.ts +680 -21
|
@@ -269,10 +269,36 @@ export const DataSourceTypeSchema = {
|
|
|
269
269
|
|
|
270
270
|
export const PrepareRequestSchema = {
|
|
271
271
|
type: "object",
|
|
272
|
-
|
|
272
|
+
description: `Two shapes, chosen by the \`exchangeId\` path segment. Against a managed exchange,
|
|
273
|
+
\`instrument\` is required and \`datasetId\`/\`datasetVersionId\` are ignored. Against the
|
|
274
|
+
reserved \`exchangeId: user\`, send \`datasetId\` instead of \`instrument\` — \`instrument\` is
|
|
275
|
+
ignored there, since it comes from the dataset itself.
|
|
276
|
+
`,
|
|
277
|
+
required: ["from", "to"],
|
|
273
278
|
properties: {
|
|
274
279
|
instrument: {
|
|
275
|
-
|
|
280
|
+
allOf: [
|
|
281
|
+
{
|
|
282
|
+
$ref: "#/components/schemas/Instrument",
|
|
283
|
+
},
|
|
284
|
+
],
|
|
285
|
+
description: `Required unless \`exchangeId\` is the reserved value \`user\`, in which case send
|
|
286
|
+
\`datasetId\` instead.
|
|
287
|
+
`,
|
|
288
|
+
},
|
|
289
|
+
datasetId: {
|
|
290
|
+
type: "string",
|
|
291
|
+
description: `Only for \`exchangeId: user\`: the id of a dataset created via \`POST /datasets\`, in place
|
|
292
|
+
of \`instrument\`. Ignored against a managed exchange.
|
|
293
|
+
`,
|
|
294
|
+
example: "ds_3f9a1c2e7b0d4a5f",
|
|
295
|
+
},
|
|
296
|
+
datasetVersionId: {
|
|
297
|
+
type: "string",
|
|
298
|
+
description: `Only for \`exchangeId: user\`, and optional even then: pins a specific past version of
|
|
299
|
+
the dataset instead of its current one. Defaults to the dataset's current version.
|
|
300
|
+
`,
|
|
301
|
+
example: "dsv_8e2b4f19c6a03d7e",
|
|
276
302
|
},
|
|
277
303
|
from: {
|
|
278
304
|
type: "string",
|
|
@@ -300,7 +326,23 @@ resampling and stored alongside the native blob in cache. Coarser-than-
|
|
|
300
326
|
source values must be exact multiples of the source cadence — invalid
|
|
301
327
|
labels return \`400\`.
|
|
302
328
|
`,
|
|
303
|
-
enum: [
|
|
329
|
+
enum: [
|
|
330
|
+
"1s",
|
|
331
|
+
"5s",
|
|
332
|
+
"1m",
|
|
333
|
+
"3m",
|
|
334
|
+
"5m",
|
|
335
|
+
"15m",
|
|
336
|
+
"30m",
|
|
337
|
+
"1h",
|
|
338
|
+
"2h",
|
|
339
|
+
"4h",
|
|
340
|
+
"8h",
|
|
341
|
+
"12h",
|
|
342
|
+
"1d",
|
|
343
|
+
"1w",
|
|
344
|
+
"1q",
|
|
345
|
+
],
|
|
304
346
|
default: "1s",
|
|
305
347
|
},
|
|
306
348
|
},
|
|
@@ -363,12 +405,19 @@ is always terminal (\`Completed\`) — decide from
|
|
|
363
405
|
} as const;
|
|
364
406
|
|
|
365
407
|
export const PrepareJobStateSchema = {
|
|
366
|
-
description: `State of a single-instrument prepare job — the \`JobState\` shape plus a
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
408
|
+
description: `State of a single-instrument prepare job — the \`JobState\` shape plus a coverage summary.
|
|
409
|
+
A single-instrument prepare is always terminal (\`status: Completed\`): the client decides
|
|
410
|
+
what to do from \`coverageRatio\` (e.g. execute if it is at or above a chosen threshold)
|
|
411
|
+
rather than polling for missing hours that may never arrive — a missing hour for one
|
|
412
|
+
instrument usually means low activity, not missing data.
|
|
413
|
+
|
|
414
|
+
**Two coverage shapes, by exchange vs. dataset.** Against a managed exchange, coverage is
|
|
415
|
+
walked hour by hour: \`totalHours\`/\`hoursWithData\`/\`hoursWithoutData\`. Against a
|
|
416
|
+
dataset-backed prepare (\`exchangeId: user\`), coverage is reported on the dataset's own
|
|
417
|
+
cadence grid instead — hour-walking a daily dataset would report \`1/24\` and read as
|
|
418
|
+
broken — via \`cadence\`/\`gaps\`/\`largestGapSteps\`; \`totalHours\`/\`hoursWithData\`/
|
|
419
|
+
\`hoursWithoutData\` are absent in that case. \`dataFrom\`/\`dataTo\`/\`coverageRatio\` are present
|
|
420
|
+
either way, computed accordingly.
|
|
372
421
|
`,
|
|
373
422
|
allOf: [
|
|
374
423
|
{
|
|
@@ -396,25 +445,54 @@ activity, not missing data.
|
|
|
396
445
|
format: "double",
|
|
397
446
|
minimum: 0,
|
|
398
447
|
maximum: 1,
|
|
399
|
-
description:
|
|
400
|
-
fraction of hours in the requested range that have served
|
|
448
|
+
description: `Against a managed exchange: \`hoursWithData / totalHours\` in \`[0,1]\` (\`1.0\` when
|
|
449
|
+
\`totalHours\` is 0), the fraction of hours in the requested range that have served
|
|
450
|
+
data. Against a dataset (\`exchangeId: user\`): \`rows / expectedStepsAtCadence\`
|
|
451
|
+
over the dataset version's own range — echoing what ingest computed once, not
|
|
452
|
+
recomputed against a narrower prepare request.
|
|
401
453
|
`,
|
|
402
454
|
example: 0.994,
|
|
403
455
|
},
|
|
404
456
|
totalHours: {
|
|
405
457
|
type: "integer",
|
|
406
|
-
description:
|
|
458
|
+
description: `Number of whole hours in the requested prepare range. Managed exchanges only —
|
|
459
|
+
absent for a dataset-backed prepare.
|
|
460
|
+
`,
|
|
407
461
|
example: 168,
|
|
408
462
|
},
|
|
409
463
|
hoursWithData: {
|
|
410
464
|
type: "integer",
|
|
411
|
-
description:
|
|
465
|
+
description: `Number of hours in the range that have data. Managed exchanges only — absent for
|
|
466
|
+
a dataset-backed prepare.
|
|
467
|
+
`,
|
|
412
468
|
example: 167,
|
|
413
469
|
},
|
|
470
|
+
cadence: {
|
|
471
|
+
type: "string",
|
|
472
|
+
description: `The dataset version's own discovered cadence (e.g. \`1m\`, \`1h\`). Only present for a
|
|
473
|
+
dataset-backed prepare (\`exchangeId: user\`).
|
|
474
|
+
`,
|
|
475
|
+
example: "1m",
|
|
476
|
+
},
|
|
477
|
+
gaps: {
|
|
478
|
+
type: "integer",
|
|
479
|
+
description: `Number of gaps in the dataset version at its own cadence, as discovered at ingest
|
|
480
|
+
time. Only present for a dataset-backed prepare.
|
|
481
|
+
`,
|
|
482
|
+
example: 0,
|
|
483
|
+
},
|
|
484
|
+
largestGapSteps: {
|
|
485
|
+
type: "integer",
|
|
486
|
+
description: `The largest gap in the dataset version, in units of its own cadence step. Only
|
|
487
|
+
present for a dataset-backed prepare.
|
|
488
|
+
`,
|
|
489
|
+
example: 0,
|
|
490
|
+
},
|
|
414
491
|
hoursWithoutData: {
|
|
415
492
|
type: "array",
|
|
416
|
-
description:
|
|
417
|
-
|
|
493
|
+
description: `One entry per hour in the range that has no data, with a rationale. Managed
|
|
494
|
+
exchanges only — absent for a dataset-backed prepare.
|
|
495
|
+
`,
|
|
418
496
|
items: {
|
|
419
497
|
type: "object",
|
|
420
498
|
properties: {
|
|
@@ -627,9 +705,76 @@ export const ExecuteSweepRequestSchema = {
|
|
|
627
705
|
walkForward: {
|
|
628
706
|
$ref: "#/components/schemas/WalkForwardRequest",
|
|
629
707
|
},
|
|
708
|
+
equityCurve: {
|
|
709
|
+
$ref: "#/components/schemas/EquityCurveRequest",
|
|
710
|
+
},
|
|
630
711
|
},
|
|
631
712
|
} as const;
|
|
632
713
|
|
|
714
|
+
export const EquityCurveOptionsSchema = {
|
|
715
|
+
type: "object",
|
|
716
|
+
description:
|
|
717
|
+
"Requested equity-curve transform, applied server-side in a fixed pipeline order: `resample` (point count) then `differential` (encoding) then `outMode` (JSON shape) — each stage assumes the previous one already ran. A server-side size guard can still force a smaller/deflated shape above its thresholds regardless of what is requested here — see `EquityCurveMeta` for what actually happened.",
|
|
718
|
+
properties: {
|
|
719
|
+
resample: {
|
|
720
|
+
type: "integer",
|
|
721
|
+
minimum: 2,
|
|
722
|
+
description:
|
|
723
|
+
"Downsample to at most this many points (extrema-preserving — the global max/min and the exact first/last point are always kept). Omit for no downsampling.",
|
|
724
|
+
},
|
|
725
|
+
differential: {
|
|
726
|
+
type: "boolean",
|
|
727
|
+
default: false,
|
|
728
|
+
description:
|
|
729
|
+
"Delta-encode both fields from the second (post-resample) point onward.",
|
|
730
|
+
},
|
|
731
|
+
outMode: {
|
|
732
|
+
allOf: [
|
|
733
|
+
{
|
|
734
|
+
$ref: "#/components/schemas/EquityCurveOutMode",
|
|
735
|
+
},
|
|
736
|
+
],
|
|
737
|
+
default: "ARRAY",
|
|
738
|
+
description: "Requested JSON shape.",
|
|
739
|
+
},
|
|
740
|
+
},
|
|
741
|
+
} as const;
|
|
742
|
+
|
|
743
|
+
export const EquityCurveRequestSchema = {
|
|
744
|
+
allOf: [
|
|
745
|
+
{
|
|
746
|
+
$ref: "#/components/schemas/EquityCurveOptions",
|
|
747
|
+
},
|
|
748
|
+
{
|
|
749
|
+
type: "object",
|
|
750
|
+
properties: {
|
|
751
|
+
mode: {
|
|
752
|
+
type: "string",
|
|
753
|
+
enum: ["auto", "topN", "topPct", "none"],
|
|
754
|
+
default: "auto",
|
|
755
|
+
description:
|
|
756
|
+
"Which trials keep their per-point equity curve. `auto` retains curves only while the accumulated size stays within server limits; `topN`/`topPct` retain curves for the best-ranked trials explicitly; `none` retains no curves.",
|
|
757
|
+
},
|
|
758
|
+
n: {
|
|
759
|
+
type: "integer",
|
|
760
|
+
minimum: 1,
|
|
761
|
+
description: "Trial count to retain when mode is topN.",
|
|
762
|
+
},
|
|
763
|
+
maxPct: {
|
|
764
|
+
type: "number",
|
|
765
|
+
format: "double",
|
|
766
|
+
exclusiveMinimum: 0,
|
|
767
|
+
maximum: 100,
|
|
768
|
+
description:
|
|
769
|
+
"Top percentage of trials to retain when mode is topPct.",
|
|
770
|
+
},
|
|
771
|
+
},
|
|
772
|
+
},
|
|
773
|
+
],
|
|
774
|
+
description:
|
|
775
|
+
"Selection (`mode`/`n`/`maxPct`) plus the transform preference (`resample`/`differential`/`outMode`) applied by `GET .../equityCurve` whenever ITS OWN query params are absent, for a curve this sweep retained. The transform half never affects retention or `sweepId` — a caller can always override it per-request at read time regardless of what was submitted here.",
|
|
776
|
+
} as const;
|
|
777
|
+
|
|
633
778
|
export const WalkForwardRequestSchema = {
|
|
634
779
|
type: "object",
|
|
635
780
|
description:
|
|
@@ -871,6 +1016,15 @@ export const SweepRunRowSchema = {
|
|
|
871
1016
|
type: "integer",
|
|
872
1017
|
format: "int64",
|
|
873
1018
|
},
|
|
1019
|
+
equityCurve: {
|
|
1020
|
+
allOf: [
|
|
1021
|
+
{
|
|
1022
|
+
$ref: "#/components/schemas/EquityCurveResult",
|
|
1023
|
+
},
|
|
1024
|
+
],
|
|
1025
|
+
description:
|
|
1026
|
+
"Present only when this trial's curve was selected (`equityCurve.mode` was `topN`/`topPct` on the request, and this row ranked among the winners) — absent, not null, otherwise; a run that was never spilled and one that was spilled but not selected look identical here. Always a pointer today (`url` present, no inline points): a sweep's curves live in a spill store, not the response, until fetched separately. `GET` the `url` to fetch the curve itself; its own `meta` there is the real, possibly size-guarded outcome, while this outer `meta` is a raw, untransformed preview from selection time and can differ.",
|
|
1027
|
+
},
|
|
874
1028
|
},
|
|
875
1029
|
} as const;
|
|
876
1030
|
|
|
@@ -1008,6 +1162,7 @@ export const ExecuteSweepResultSchema = {
|
|
|
1008
1162
|
"leaderboardSize",
|
|
1009
1163
|
"truncated",
|
|
1010
1164
|
"leaderboard",
|
|
1165
|
+
"state",
|
|
1011
1166
|
],
|
|
1012
1167
|
properties: {
|
|
1013
1168
|
sweepId: {
|
|
@@ -1016,6 +1171,8 @@ export const ExecuteSweepResultSchema = {
|
|
|
1016
1171
|
status: {
|
|
1017
1172
|
type: "string",
|
|
1018
1173
|
enum: ["RUNNING", "COMPLETED", "PARTIAL", "CANCELLED"],
|
|
1174
|
+
description:
|
|
1175
|
+
"The sweep's own status vocabulary — not the same set `state.status` below uses. See `state` for why.",
|
|
1019
1176
|
},
|
|
1020
1177
|
objective: {
|
|
1021
1178
|
type: "string",
|
|
@@ -1070,6 +1227,17 @@ First failure wins and later ones are not recorded, so on a sweep where several
|
|
|
1070
1227
|
walkForward: {
|
|
1071
1228
|
$ref: "#/components/schemas/WalkForwardResult",
|
|
1072
1229
|
},
|
|
1230
|
+
state: {
|
|
1231
|
+
allOf: [
|
|
1232
|
+
{
|
|
1233
|
+
$ref: "#/components/schemas/JobState",
|
|
1234
|
+
},
|
|
1235
|
+
],
|
|
1236
|
+
description: `The same \`JobState\` shape a single-execute \`BacktestJobResult\` carries — not a sweep-specific lookalike, the actual type, so field names and timestamp formatting match exactly.
|
|
1237
|
+
\`state.status\` uses \`JobState\`'s own vocabulary (\`New\`/\`Started\`/\`Completed\`/ \`Aborted\`/\`Failed\`), mapped from the sweep's \`status\` field above rather than copying it: \`PARTIAL\` and \`CANCELLED\` both map to \`Aborted\`, because a sweep's \`PARTIAL\` is already terminal (some shards finished, some failed, nothing more is coming) unlike a single job's non-terminal \`Partial\`, which has no equivalent here at all.
|
|
1238
|
+
\`state.completed\` is real ticks processed on a plain sweep. On a \`walkForward\` sweep it is currently always \`0\` — the walk-forward fold runner was not wired to count ticks when this shipped, unlike the plain shard path.
|
|
1239
|
+
\`state.size\` is always \`0\` on every path (single execute, plain sweep, walk-forward alike) — nothing populates it anywhere yet. That is a known gap across the whole API, not a sweep-specific omission.`,
|
|
1240
|
+
},
|
|
1073
1241
|
},
|
|
1074
1242
|
} as const;
|
|
1075
1243
|
|
|
@@ -1311,26 +1479,36 @@ reading: a run that produced no trades often did so for a reason stated here.
|
|
|
1311
1479
|
example: 8.75,
|
|
1312
1480
|
},
|
|
1313
1481
|
equityCurve: {
|
|
1314
|
-
|
|
1315
|
-
description:
|
|
1316
|
-
"Equity curve over the backtest. Element 0 is an anchor at the backtest `from` with `initialCapital`; the remaining points are one sample per emitted yield, in order. Use it to plot the strategy's running equity without re-deriving it from the yield history.",
|
|
1317
|
-
items: {
|
|
1318
|
-
$ref: "#/components/schemas/EquityPoint",
|
|
1319
|
-
},
|
|
1320
|
-
example: [
|
|
1321
|
-
{
|
|
1322
|
-
timestamp: 1700000000000,
|
|
1323
|
-
equity: 100,
|
|
1324
|
-
},
|
|
1325
|
-
{
|
|
1326
|
-
timestamp: 1700000060000,
|
|
1327
|
-
equity: 110.5,
|
|
1328
|
-
},
|
|
1482
|
+
allOf: [
|
|
1329
1483
|
{
|
|
1330
|
-
|
|
1331
|
-
equity: 90.25,
|
|
1484
|
+
$ref: "#/components/schemas/EquityCurveResult",
|
|
1332
1485
|
},
|
|
1333
1486
|
],
|
|
1487
|
+
description:
|
|
1488
|
+
"Equity curve over the backtest. `points[0]` (or `timestamps[0]`/`equities[0]` in `SHORT` mode) is an anchor at the backtest `from` with `initialCapital`; the remaining points are one sample per emitted yield, in order. Use it to plot the strategy's running equity without re-deriving it from the yield history. Always inline for a plain backtest today — never a pointer (`url`); that shape exists only for a sweep row's top-N winners.",
|
|
1489
|
+
example: {
|
|
1490
|
+
points: [
|
|
1491
|
+
{
|
|
1492
|
+
timestamp: 1700000000000,
|
|
1493
|
+
equity: 100,
|
|
1494
|
+
},
|
|
1495
|
+
{
|
|
1496
|
+
timestamp: 1700000060000,
|
|
1497
|
+
equity: 110.5,
|
|
1498
|
+
},
|
|
1499
|
+
{
|
|
1500
|
+
timestamp: 1700000120000,
|
|
1501
|
+
equity: 90.25,
|
|
1502
|
+
},
|
|
1503
|
+
],
|
|
1504
|
+
meta: {
|
|
1505
|
+
inputPointCount: 3,
|
|
1506
|
+
outputPointCount: 3,
|
|
1507
|
+
resampled: false,
|
|
1508
|
+
differential: false,
|
|
1509
|
+
outMode: "ARRAY",
|
|
1510
|
+
},
|
|
1511
|
+
},
|
|
1334
1512
|
},
|
|
1335
1513
|
signalCount: {
|
|
1336
1514
|
type: "integer",
|
|
@@ -1397,6 +1575,104 @@ export const EquityPointSchema = {
|
|
|
1397
1575
|
},
|
|
1398
1576
|
} as const;
|
|
1399
1577
|
|
|
1578
|
+
export const EquityCurveOutModeSchema = {
|
|
1579
|
+
type: "string",
|
|
1580
|
+
enum: ["ARRAY", "SHORT"],
|
|
1581
|
+
description:
|
|
1582
|
+
"JSON shape for an equity curve's points. `ARRAY` is `[{timestamp, equity}, ...]`; `SHORT` is `{timestamps: [...], equities: [...]}` (parallel arrays, no repeated key text). The one schema shared by every place `outMode` appears, request or response, so the two cannot drift to different value sets.",
|
|
1583
|
+
} as const;
|
|
1584
|
+
|
|
1585
|
+
export const EquityCurveMetaSchema = {
|
|
1586
|
+
type: "object",
|
|
1587
|
+
description:
|
|
1588
|
+
"What the transform pipeline actually did, computed from the observed outcome — never a copy of what was requested. Lets a caller detect a forced or no-op transform (e.g. a `resample` ceiling already above the curve's size is a legal no-op, reported honestly as `resampled: false`).",
|
|
1589
|
+
required: [
|
|
1590
|
+
"inputPointCount",
|
|
1591
|
+
"outputPointCount",
|
|
1592
|
+
"resampled",
|
|
1593
|
+
"differential",
|
|
1594
|
+
"outMode",
|
|
1595
|
+
],
|
|
1596
|
+
properties: {
|
|
1597
|
+
inputPointCount: {
|
|
1598
|
+
type: "integer",
|
|
1599
|
+
description: "Size of the curve the transform pipeline received.",
|
|
1600
|
+
example: 100000,
|
|
1601
|
+
},
|
|
1602
|
+
outputPointCount: {
|
|
1603
|
+
type: "integer",
|
|
1604
|
+
description:
|
|
1605
|
+
"Size after the full pipeline (resample, then differential, then outMode).",
|
|
1606
|
+
example: 100,
|
|
1607
|
+
},
|
|
1608
|
+
resampled: {
|
|
1609
|
+
type: "boolean",
|
|
1610
|
+
description:
|
|
1611
|
+
"True only if the resample stage actually changed the point count.",
|
|
1612
|
+
},
|
|
1613
|
+
differential: {
|
|
1614
|
+
type: "boolean",
|
|
1615
|
+
description:
|
|
1616
|
+
"True only if delta-encoding actually ran. Requesting it on a curve of 0 or 1 points has nothing to encode, so it does not run even if asked.",
|
|
1617
|
+
},
|
|
1618
|
+
outMode: {
|
|
1619
|
+
allOf: [
|
|
1620
|
+
{
|
|
1621
|
+
$ref: "#/components/schemas/EquityCurveOutMode",
|
|
1622
|
+
},
|
|
1623
|
+
],
|
|
1624
|
+
description:
|
|
1625
|
+
"The actual JSON shape served. Present even when the points themselves are not (a pointer curve, `EquityCurveResult.url`) — a caller resolving that URL separately still needs to know how to parse what it gets back before fetching it. May override an explicit request above a server-side size threshold; this field, not the request, is the source of truth for what shape actually came back.",
|
|
1626
|
+
example: "ARRAY",
|
|
1627
|
+
},
|
|
1628
|
+
},
|
|
1629
|
+
} as const;
|
|
1630
|
+
|
|
1631
|
+
export const EquityCurveResultSchema = {
|
|
1632
|
+
type: "object",
|
|
1633
|
+
description:
|
|
1634
|
+
"An equity curve, shaped per `meta.outMode`: `points` when `ARRAY`, `timestamps` + `equities` (parallel arrays) when `SHORT`. Used identically wherever a curve is returned — a plain backtest's inline `equityCurve` and a sweep row's `equityCurve` are the same type. `url` is present *instead of* any points when the curve is served by pointer rather than inline (a sweep row's top-N winners only): `GET` it separately to fetch this exact same shape with the points populated.",
|
|
1635
|
+
required: ["meta"],
|
|
1636
|
+
properties: {
|
|
1637
|
+
meta: {
|
|
1638
|
+
$ref: "#/components/schemas/EquityCurveMeta",
|
|
1639
|
+
},
|
|
1640
|
+
points: {
|
|
1641
|
+
type: "array",
|
|
1642
|
+
description:
|
|
1643
|
+
"Present when `meta.outMode` is `ARRAY` and the curve is inline (not a pointer).",
|
|
1644
|
+
items: {
|
|
1645
|
+
$ref: "#/components/schemas/EquityPoint",
|
|
1646
|
+
},
|
|
1647
|
+
},
|
|
1648
|
+
timestamps: {
|
|
1649
|
+
type: "array",
|
|
1650
|
+
description:
|
|
1651
|
+
"Present when `meta.outMode` is `SHORT` and the curve is inline (not a pointer).",
|
|
1652
|
+
items: {
|
|
1653
|
+
type: "integer",
|
|
1654
|
+
format: "int64",
|
|
1655
|
+
},
|
|
1656
|
+
},
|
|
1657
|
+
equities: {
|
|
1658
|
+
type: "array",
|
|
1659
|
+
description:
|
|
1660
|
+
"Present when `meta.outMode` is `SHORT` and the curve is inline (not a pointer), parallel to `timestamps` (same index, same point).",
|
|
1661
|
+
items: {
|
|
1662
|
+
type: "number",
|
|
1663
|
+
format: "double",
|
|
1664
|
+
},
|
|
1665
|
+
},
|
|
1666
|
+
url: {
|
|
1667
|
+
type: "string",
|
|
1668
|
+
description:
|
|
1669
|
+
"Present only for a sweep row's pointer curve. `GET` this to fetch the curve itself, in this exact `{points|timestamps+equities, meta}` shape — `meta` there is the real, possibly size-guarded outcome; this outer `meta` is a raw, untransformed preview from the moment the sweep selected this trial's curve, and the two can legitimately differ.",
|
|
1670
|
+
example:
|
|
1671
|
+
"/v1/backtest/binance/ticker/executeSweep/req-1/swp_test/runs/3/equityCurve",
|
|
1672
|
+
},
|
|
1673
|
+
},
|
|
1674
|
+
} as const;
|
|
1675
|
+
|
|
1400
1676
|
export const strategyIdSchema = {
|
|
1401
1677
|
description: `Unique identifier for a compiled strategy, derived from the source itself: the same code
|
|
1402
1678
|
always yields the same id, for every caller, whatever its formatting. See
|
|
@@ -1406,6 +1682,68 @@ always yields the same id, for every caller, whatever its formatting. See
|
|
|
1406
1682
|
example: "6bsh31ikwkuivhtgcoa6s4",
|
|
1407
1683
|
} as const;
|
|
1408
1684
|
|
|
1685
|
+
export const DeclaredPropertySchema = {
|
|
1686
|
+
type: "object",
|
|
1687
|
+
description: `One property name \`POST /strategy\` could establish without constructing the strategy —
|
|
1688
|
+
either declared with \`@StrategyProperty\` on the compiled source, or one of the small set of
|
|
1689
|
+
base properties every strategy carries (\`amnt\`, \`enabled\`, \`multiEntry\`, ...).
|
|
1690
|
+
|
|
1691
|
+
**Best-effort, not exhaustive.** A property registered through an attached risk/backtest
|
|
1692
|
+
config needs a live instance to discover and is not listed here. Use this to catch a typo'd
|
|
1693
|
+
sweep key before submitting, not as the definitive list of what a sweep will accept — a
|
|
1694
|
+
name absent from this list may still be valid.
|
|
1695
|
+
`,
|
|
1696
|
+
required: ["name"],
|
|
1697
|
+
properties: {
|
|
1698
|
+
name: {
|
|
1699
|
+
type: "string",
|
|
1700
|
+
description:
|
|
1701
|
+
"The key a sweep or execute param map uses for this property.",
|
|
1702
|
+
example: "rsi.period",
|
|
1703
|
+
},
|
|
1704
|
+
description: {
|
|
1705
|
+
type: "string",
|
|
1706
|
+
description: "Human-readable label, as declared.",
|
|
1707
|
+
example: "RSI period",
|
|
1708
|
+
},
|
|
1709
|
+
defaultValue: {
|
|
1710
|
+
type: "string",
|
|
1711
|
+
description: `The declared default, as a string, if one was given. Absent, not null, when none was
|
|
1712
|
+
declared.
|
|
1713
|
+
`,
|
|
1714
|
+
example: "14",
|
|
1715
|
+
},
|
|
1716
|
+
reflected: {
|
|
1717
|
+
type: "boolean",
|
|
1718
|
+
description: `Whether a value for this key is injected into the strategy's field (\`true\`) or only
|
|
1719
|
+
available through the property map (\`false\`).
|
|
1720
|
+
`,
|
|
1721
|
+
example: true,
|
|
1722
|
+
},
|
|
1723
|
+
min: {
|
|
1724
|
+
type: "number",
|
|
1725
|
+
format: "double",
|
|
1726
|
+
description:
|
|
1727
|
+
"Suggested sweep/range minimum, if declared. Advisory only, never validated.",
|
|
1728
|
+
example: 2,
|
|
1729
|
+
},
|
|
1730
|
+
max: {
|
|
1731
|
+
type: "number",
|
|
1732
|
+
format: "double",
|
|
1733
|
+
description:
|
|
1734
|
+
"Suggested sweep/range maximum, if declared. Advisory only, never validated.",
|
|
1735
|
+
example: 50,
|
|
1736
|
+
},
|
|
1737
|
+
step: {
|
|
1738
|
+
type: "number",
|
|
1739
|
+
format: "double",
|
|
1740
|
+
description:
|
|
1741
|
+
"Suggested sweep/range step, if declared. Advisory only, never validated.",
|
|
1742
|
+
example: 1,
|
|
1743
|
+
},
|
|
1744
|
+
},
|
|
1745
|
+
} as const;
|
|
1746
|
+
|
|
1409
1747
|
export const NoticeSchema = {
|
|
1410
1748
|
type: "object",
|
|
1411
1749
|
description: `A diagnostic the engine raised while the strategy ran. Advisory: it describes something worth
|
|
@@ -1584,6 +1922,244 @@ the strategy — the check has not run. Stop waiting and re-request it later.
|
|
|
1584
1922
|
},
|
|
1585
1923
|
} as const;
|
|
1586
1924
|
|
|
1925
|
+
export const DatasetSchema = {
|
|
1926
|
+
type: "object",
|
|
1927
|
+
description: `A dataset's own metadata — not its data. \`currentVersionId\` is what a prepare against
|
|
1928
|
+
\`exchangeId: user\` reads by default; see \`DatasetVersion\` for what a version carries.
|
|
1929
|
+
|
|
1930
|
+
\`from\`/\`to\`/\`cadence\` mirror that current version's own discovered range and cadence, so
|
|
1931
|
+
you don't need a second call to \`GET /datasets/{datasetId}/uploads/{uploadId}\` just to see
|
|
1932
|
+
what a dataset covers. Absent until a version exists.
|
|
1933
|
+
`,
|
|
1934
|
+
required: ["datasetId", "name", "type", "instrument", "createdAt"],
|
|
1935
|
+
properties: {
|
|
1936
|
+
datasetId: {
|
|
1937
|
+
type: "string",
|
|
1938
|
+
description: "Opaque id, returned by `POST /datasets`.",
|
|
1939
|
+
example: "ds_3f9a1c2e7b0d4a5f",
|
|
1940
|
+
},
|
|
1941
|
+
name: {
|
|
1942
|
+
type: "string",
|
|
1943
|
+
description: "Unique among your datasets.",
|
|
1944
|
+
example: "My BTC ticks",
|
|
1945
|
+
},
|
|
1946
|
+
type: {
|
|
1947
|
+
type: "string",
|
|
1948
|
+
enum: ["ticker"],
|
|
1949
|
+
description: "Always `ticker` in v1.",
|
|
1950
|
+
example: "ticker",
|
|
1951
|
+
},
|
|
1952
|
+
instrument: {
|
|
1953
|
+
$ref: "#/components/schemas/Instrument",
|
|
1954
|
+
},
|
|
1955
|
+
createdAt: {
|
|
1956
|
+
type: "string",
|
|
1957
|
+
format: "date-time",
|
|
1958
|
+
description: "When the dataset was created.",
|
|
1959
|
+
example: "2026-08-20T09:00:00Z",
|
|
1960
|
+
},
|
|
1961
|
+
currentVersionId: {
|
|
1962
|
+
type: "string",
|
|
1963
|
+
description: `The id of the most recently finalized, successfully ingested version. Absent until at
|
|
1964
|
+
least one upload has finished ingesting.
|
|
1965
|
+
`,
|
|
1966
|
+
example: "dsv_8e2b4f19c6a03d7e",
|
|
1967
|
+
},
|
|
1968
|
+
updatedAt: {
|
|
1969
|
+
type: "string",
|
|
1970
|
+
format: "date-time",
|
|
1971
|
+
description:
|
|
1972
|
+
"When `currentVersionId` last changed. Absent until it has a value.",
|
|
1973
|
+
example: "2026-08-20T09:04:12Z",
|
|
1974
|
+
},
|
|
1975
|
+
from: {
|
|
1976
|
+
type: "string",
|
|
1977
|
+
format: "date-time",
|
|
1978
|
+
description: `Start of \`currentVersionId\`'s own data range, as discovered at ingest time. Absent
|
|
1979
|
+
until a version exists.
|
|
1980
|
+
`,
|
|
1981
|
+
example: "2026-03-01T00:00:00Z",
|
|
1982
|
+
},
|
|
1983
|
+
to: {
|
|
1984
|
+
type: "string",
|
|
1985
|
+
format: "date-time",
|
|
1986
|
+
description: `End of \`currentVersionId\`'s own data range, as discovered at ingest time. Absent until
|
|
1987
|
+
a version exists.
|
|
1988
|
+
`,
|
|
1989
|
+
example: "2026-03-08T00:00:00Z",
|
|
1990
|
+
},
|
|
1991
|
+
cadence: {
|
|
1992
|
+
type: "string",
|
|
1993
|
+
description: `\`currentVersionId\`'s own discovered bar cadence (e.g. \`1s\`, \`1m\`, \`1h\`). Absent until a
|
|
1994
|
+
version exists.
|
|
1995
|
+
`,
|
|
1996
|
+
example: "1m",
|
|
1997
|
+
},
|
|
1998
|
+
},
|
|
1999
|
+
} as const;
|
|
2000
|
+
|
|
2001
|
+
export const DatasetWithLinksSchema = {
|
|
2002
|
+
description:
|
|
2003
|
+
"A `Dataset` plus a self link. Returned by `GET /datasets/{datasetId}`.",
|
|
2004
|
+
allOf: [
|
|
2005
|
+
{
|
|
2006
|
+
$ref: "#/components/schemas/Dataset",
|
|
2007
|
+
},
|
|
2008
|
+
{
|
|
2009
|
+
type: "object",
|
|
2010
|
+
properties: {
|
|
2011
|
+
_links: {
|
|
2012
|
+
type: "object",
|
|
2013
|
+
properties: {
|
|
2014
|
+
self: {
|
|
2015
|
+
type: "object",
|
|
2016
|
+
properties: {
|
|
2017
|
+
href: {
|
|
2018
|
+
type: "string",
|
|
2019
|
+
example: "/v1/datasets/ds_3f9a1c2e7b0d4a5f",
|
|
2020
|
+
},
|
|
2021
|
+
},
|
|
2022
|
+
},
|
|
2023
|
+
},
|
|
2024
|
+
},
|
|
2025
|
+
},
|
|
2026
|
+
},
|
|
2027
|
+
],
|
|
2028
|
+
} as const;
|
|
2029
|
+
|
|
2030
|
+
export const DatasetCreatedSchema = {
|
|
2031
|
+
description: `A \`Dataset\` plus the first upload session — the presigned URL to PUT the file to.
|
|
2032
|
+
`,
|
|
2033
|
+
allOf: [
|
|
2034
|
+
{
|
|
2035
|
+
$ref: "#/components/schemas/Dataset",
|
|
2036
|
+
},
|
|
2037
|
+
{
|
|
2038
|
+
type: "object",
|
|
2039
|
+
required: ["uploadId", "upload"],
|
|
2040
|
+
properties: {
|
|
2041
|
+
uploadId: {
|
|
2042
|
+
type: "string",
|
|
2043
|
+
description: `Identifies this upload session. Pass to
|
|
2044
|
+
\`POST /datasets/{datasetId}/uploads/{uploadId}/finalize\` once the PUT completes.
|
|
2045
|
+
`,
|
|
2046
|
+
example: "up_1a2b3c4d5e6f7a8b",
|
|
2047
|
+
},
|
|
2048
|
+
upload: {
|
|
2049
|
+
type: "object",
|
|
2050
|
+
required: ["url", "expiresInMinutes"],
|
|
2051
|
+
properties: {
|
|
2052
|
+
url: {
|
|
2053
|
+
type: "string",
|
|
2054
|
+
description: `Presigned URL. \`PUT\` the raw CSV file here directly — no \`Authorization\`
|
|
2055
|
+
header, no other API credentials.
|
|
2056
|
+
`,
|
|
2057
|
+
example:
|
|
2058
|
+
"https://storage.qtsurfer.com/00000000-.../uploads/up_1a2b3c4d5e6f7a8b/raw.csv?X-Amz-...",
|
|
2059
|
+
},
|
|
2060
|
+
expiresInMinutes: {
|
|
2061
|
+
type: "integer",
|
|
2062
|
+
description: "How long `url` stays valid.",
|
|
2063
|
+
example: 15,
|
|
2064
|
+
},
|
|
2065
|
+
},
|
|
2066
|
+
},
|
|
2067
|
+
},
|
|
2068
|
+
},
|
|
2069
|
+
],
|
|
2070
|
+
} as const;
|
|
2071
|
+
|
|
2072
|
+
export const DatasetVersionSchema = {
|
|
2073
|
+
type: "object",
|
|
2074
|
+
description: `One successfully ingested upload. Cadence and timestamp unit are discovered from the file,
|
|
2075
|
+
not declared by the caller.
|
|
2076
|
+
`,
|
|
2077
|
+
required: ["datasetId"],
|
|
2078
|
+
properties: {
|
|
2079
|
+
datasetId: {
|
|
2080
|
+
type: "string",
|
|
2081
|
+
example: "ds_3f9a1c2e7b0d4a5f",
|
|
2082
|
+
},
|
|
2083
|
+
id: {
|
|
2084
|
+
type: "string",
|
|
2085
|
+
description:
|
|
2086
|
+
"The version id. Pass as `datasetVersionId` on `POST .../prepare` to pin it.",
|
|
2087
|
+
example: "dsv_8e2b4f19c6a03d7e",
|
|
2088
|
+
},
|
|
2089
|
+
bytes: {
|
|
2090
|
+
type: "integer",
|
|
2091
|
+
description: "Size of the uploaded file.",
|
|
2092
|
+
example: 4831022,
|
|
2093
|
+
},
|
|
2094
|
+
rows: {
|
|
2095
|
+
type: "integer",
|
|
2096
|
+
description: "Number of data rows.",
|
|
2097
|
+
example: 86400,
|
|
2098
|
+
},
|
|
2099
|
+
cadence: {
|
|
2100
|
+
type: "string",
|
|
2101
|
+
description: "The discovered bar cadence (e.g. `1s`, `1m`, `1h`).",
|
|
2102
|
+
example: "1s",
|
|
2103
|
+
},
|
|
2104
|
+
timestampUnit: {
|
|
2105
|
+
type: "string",
|
|
2106
|
+
enum: ["iso", "s", "ms", "us"],
|
|
2107
|
+
description: `The unit the \`timestamp\` column was uploaded in — ISO-8601, or the epoch band its
|
|
2108
|
+
numeric values fell in (seconds, millis, or micros).
|
|
2109
|
+
`,
|
|
2110
|
+
example: "iso",
|
|
2111
|
+
},
|
|
2112
|
+
gaps: {
|
|
2113
|
+
type: "integer",
|
|
2114
|
+
description: "Number of gaps at the discovered cadence.",
|
|
2115
|
+
example: 0,
|
|
2116
|
+
},
|
|
2117
|
+
largestGapSteps: {
|
|
2118
|
+
type: "integer",
|
|
2119
|
+
description: "The largest gap, in units of the discovered cadence step.",
|
|
2120
|
+
example: 0,
|
|
2121
|
+
},
|
|
2122
|
+
},
|
|
2123
|
+
} as const;
|
|
2124
|
+
|
|
2125
|
+
export const DatasetUploadStateSchema = {
|
|
2126
|
+
type: "object",
|
|
2127
|
+
description: `Progress of one upload, from staged through ingest. Postgres-backed once a version exists,
|
|
2128
|
+
so \`ready\`/\`failed\` are permanent answers; \`uploading\`/\`ingesting\` reflect in-flight state
|
|
2129
|
+
that can itself age out — see the \`404\` case on \`GET .../uploads/{uploadId}\`.
|
|
2130
|
+
`,
|
|
2131
|
+
required: ["uploadId", "status"],
|
|
2132
|
+
properties: {
|
|
2133
|
+
uploadId: {
|
|
2134
|
+
type: "string",
|
|
2135
|
+
example: "up_1a2b3c4d5e6f7a8b",
|
|
2136
|
+
},
|
|
2137
|
+
status: {
|
|
2138
|
+
type: "string",
|
|
2139
|
+
enum: ["uploading", "ingesting", "ready", "failed"],
|
|
2140
|
+
description: `* \`uploading\` — the file was PUT to the presigned URL, but \`finalize\` has not been
|
|
2141
|
+
called yet.
|
|
2142
|
+
* \`ingesting\` — \`finalize\` was called; the worker is parsing and validating the file.
|
|
2143
|
+
* \`ready\` — ingested successfully. \`version\` carries the result.
|
|
2144
|
+
* \`failed\` — ingest rejected the file (e.g. bad CSV contract, mixed timestamp units).
|
|
2145
|
+
`,
|
|
2146
|
+
example: "ready",
|
|
2147
|
+
},
|
|
2148
|
+
jobId: {
|
|
2149
|
+
type: "string",
|
|
2150
|
+
description: "The ingest job id, while `status` is `ingesting`.",
|
|
2151
|
+
},
|
|
2152
|
+
version: {
|
|
2153
|
+
allOf: [
|
|
2154
|
+
{
|
|
2155
|
+
$ref: "#/components/schemas/DatasetVersion",
|
|
2156
|
+
},
|
|
2157
|
+
],
|
|
2158
|
+
description: "Present when `status` is `ready` or `failed`.",
|
|
2159
|
+
},
|
|
2160
|
+
},
|
|
2161
|
+
} as const;
|
|
2162
|
+
|
|
1587
2163
|
export const AuthTokenResponseSchema = {
|
|
1588
2164
|
type: "object",
|
|
1589
2165
|
required: ["access_token", "token_type", "expires_in", "tier"],
|