@qtsurfer/api-client 0.18.0 → 0.19.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 +8 -5
- package/dist/index.d.ts +265 -6
- package/dist/index.js +26 -0
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/src/generated/schemas.gen.ts +302 -3
- package/src/generated/sdk.gen.ts +82 -0
- package/src/generated/types.gen.ts +245 -5
|
@@ -859,6 +859,8 @@ export const SweepBaseConfigSchema = {
|
|
|
859
859
|
format: "double",
|
|
860
860
|
exclusiveMinimum: 0,
|
|
861
861
|
maximum: 100,
|
|
862
|
+
description:
|
|
863
|
+
"Share of the free balance each entry locks, in percent (0-100]. Omitted, a backtest sizes every entry with everything available.",
|
|
862
864
|
},
|
|
863
865
|
},
|
|
864
866
|
} as const;
|
|
@@ -2860,6 +2862,73 @@ export const StartLiveRequestSchema = {
|
|
|
2860
2862
|
description: {
|
|
2861
2863
|
type: "string",
|
|
2862
2864
|
},
|
|
2865
|
+
paper: {
|
|
2866
|
+
$ref: "#/components/schemas/LivePaperConfig",
|
|
2867
|
+
},
|
|
2868
|
+
},
|
|
2869
|
+
} as const;
|
|
2870
|
+
|
|
2871
|
+
export const LivePaperConfigSchema = {
|
|
2872
|
+
type: "object",
|
|
2873
|
+
additionalProperties: false,
|
|
2874
|
+
description: `Paper trading for this run: the same economics as a backtest's \`baseConfig\` (same fields,
|
|
2875
|
+
defaults and limits), plus \`output\`. An empty object takes every default. Each quote
|
|
2876
|
+
currency the run trades gets its own simulated account, opened with \`initialFunding\` in
|
|
2877
|
+
that currency; accounts are never added together. As returned on a run, the block is
|
|
2878
|
+
normalised: \`feeRate\` is resolved into \`buyFeeRate\`/\`sellFeeRate\` and defaults are filled
|
|
2879
|
+
in.
|
|
2880
|
+
`,
|
|
2881
|
+
properties: {
|
|
2882
|
+
initialFunding: {
|
|
2883
|
+
type: "number",
|
|
2884
|
+
format: "double",
|
|
2885
|
+
exclusiveMinimum: 0,
|
|
2886
|
+
maximum: 1000000000,
|
|
2887
|
+
default: 100,
|
|
2888
|
+
description:
|
|
2889
|
+
"Starting capital of each account, in that account's own quote currency.",
|
|
2890
|
+
},
|
|
2891
|
+
feeRate: {
|
|
2892
|
+
type: "number",
|
|
2893
|
+
format: "double",
|
|
2894
|
+
minimum: 0,
|
|
2895
|
+
default: 0.001,
|
|
2896
|
+
description:
|
|
2897
|
+
"Fee rate for both sides (0.001 = 0.1%). Accepted on start; returned resolved into the two fields below.",
|
|
2898
|
+
},
|
|
2899
|
+
buyFeeRate: {
|
|
2900
|
+
type: "number",
|
|
2901
|
+
format: "double",
|
|
2902
|
+
minimum: 0,
|
|
2903
|
+
description: "Buy-side fee rate; overrides `feeRate`.",
|
|
2904
|
+
},
|
|
2905
|
+
sellFeeRate: {
|
|
2906
|
+
type: "number",
|
|
2907
|
+
format: "double",
|
|
2908
|
+
minimum: 0,
|
|
2909
|
+
description: "Sell-side fee rate; overrides `feeRate`.",
|
|
2910
|
+
},
|
|
2911
|
+
feeLeg: {
|
|
2912
|
+
type: "string",
|
|
2913
|
+
enum: ["RECEIVED", "QUOTE", "BASE"],
|
|
2914
|
+
default: "RECEIVED",
|
|
2915
|
+
description:
|
|
2916
|
+
"Which asset fees are charged in. Case-insensitive on start.",
|
|
2917
|
+
},
|
|
2918
|
+
percentAmountToLock: {
|
|
2919
|
+
type: "number",
|
|
2920
|
+
format: "double",
|
|
2921
|
+
exclusiveMinimum: 0,
|
|
2922
|
+
maximum: 100,
|
|
2923
|
+
description:
|
|
2924
|
+
"Share of the account's free balance each entry locks, in percent. Omitted, the strategy's own setting applies, and without one 10%.",
|
|
2925
|
+
},
|
|
2926
|
+
output: {
|
|
2927
|
+
type: "string",
|
|
2928
|
+
enum: ["separate", "mix"],
|
|
2929
|
+
default: "separate",
|
|
2930
|
+
description: `\`separate\` keeps paper output out of the run's signals (read it with \`GET /live/{runId}/paper\`); \`mix\` also interleaves it into the run's signals as \`type: paper\`, right after the signal that caused it.`,
|
|
2931
|
+
},
|
|
2863
2932
|
},
|
|
2864
2933
|
} as const;
|
|
2865
2934
|
|
|
@@ -2979,6 +3048,15 @@ export const LiveRunSchema = {
|
|
|
2979
3048
|
description:
|
|
2980
3049
|
"The sandbox trial's promotion verdict, once one exists. Shape is not yet stabilized as public API — treat as opaque diagnostics.",
|
|
2981
3050
|
},
|
|
3051
|
+
paper: {
|
|
3052
|
+
allOf: [
|
|
3053
|
+
{
|
|
3054
|
+
$ref: "#/components/schemas/LivePaperConfig",
|
|
3055
|
+
},
|
|
3056
|
+
],
|
|
3057
|
+
description:
|
|
3058
|
+
"The run's paper trading configuration as accepted at start, normalised. Absent when the run has no paper trading.",
|
|
3059
|
+
},
|
|
2982
3060
|
},
|
|
2983
3061
|
} as const;
|
|
2984
3062
|
|
|
@@ -3191,6 +3269,217 @@ export const LiveSignalPageSchema = {
|
|
|
3191
3269
|
},
|
|
3192
3270
|
} as const;
|
|
3193
3271
|
|
|
3272
|
+
export const LivePaperSchema = {
|
|
3273
|
+
type: "object",
|
|
3274
|
+
required: ["runId", "stage", "accounts"],
|
|
3275
|
+
properties: {
|
|
3276
|
+
runId: {
|
|
3277
|
+
type: "string",
|
|
3278
|
+
},
|
|
3279
|
+
stage: {
|
|
3280
|
+
type: "string",
|
|
3281
|
+
enum: ["SANDBOX", "LIVE"],
|
|
3282
|
+
},
|
|
3283
|
+
accounts: {
|
|
3284
|
+
type: "array",
|
|
3285
|
+
items: {
|
|
3286
|
+
$ref: "#/components/schemas/LivePaperAccount",
|
|
3287
|
+
},
|
|
3288
|
+
},
|
|
3289
|
+
},
|
|
3290
|
+
} as const;
|
|
3291
|
+
|
|
3292
|
+
export const LivePaperAccountSchema = {
|
|
3293
|
+
type: "object",
|
|
3294
|
+
required: [
|
|
3295
|
+
"currency",
|
|
3296
|
+
"initialFunding",
|
|
3297
|
+
"equity",
|
|
3298
|
+
"realisedPnl",
|
|
3299
|
+
"trades",
|
|
3300
|
+
"gaps",
|
|
3301
|
+
"openPositions",
|
|
3302
|
+
],
|
|
3303
|
+
description: "One simulated account — one per quote currency the run trades.",
|
|
3304
|
+
properties: {
|
|
3305
|
+
currency: {
|
|
3306
|
+
type: "string",
|
|
3307
|
+
description: "The account's quote currency; every amount below is in it.",
|
|
3308
|
+
},
|
|
3309
|
+
initialFunding: {
|
|
3310
|
+
type: "number",
|
|
3311
|
+
format: "double",
|
|
3312
|
+
},
|
|
3313
|
+
equity: {
|
|
3314
|
+
type: "number",
|
|
3315
|
+
format: "double",
|
|
3316
|
+
description: "Latest recorded equity — see `equityKind`.",
|
|
3317
|
+
},
|
|
3318
|
+
equityAtMs: {
|
|
3319
|
+
type: "integer",
|
|
3320
|
+
format: "int64",
|
|
3321
|
+
description:
|
|
3322
|
+
"Market time of that value. Absent while the account holds its starting capital.",
|
|
3323
|
+
},
|
|
3324
|
+
equityKind: {
|
|
3325
|
+
type: "string",
|
|
3326
|
+
enum: ["equity", "mark"],
|
|
3327
|
+
description: `\`equity\` at a closed trade, \`mark\` at a periodic mark-to-market (includes open positions at market price).`,
|
|
3328
|
+
},
|
|
3329
|
+
realisedPnl: {
|
|
3330
|
+
type: "number",
|
|
3331
|
+
format: "double",
|
|
3332
|
+
description: "Sum of the PnL of the closed trades.",
|
|
3333
|
+
},
|
|
3334
|
+
trades: {
|
|
3335
|
+
type: "integer",
|
|
3336
|
+
format: "int64",
|
|
3337
|
+
description: "Closed trades.",
|
|
3338
|
+
},
|
|
3339
|
+
gaps: {
|
|
3340
|
+
type: "integer",
|
|
3341
|
+
description:
|
|
3342
|
+
"Times open positions were lost because the run was restarted with them open.",
|
|
3343
|
+
},
|
|
3344
|
+
openPositions: {
|
|
3345
|
+
type: "array",
|
|
3346
|
+
items: {
|
|
3347
|
+
$ref: "#/components/schemas/LivePaperPosition",
|
|
3348
|
+
},
|
|
3349
|
+
},
|
|
3350
|
+
kpi: {
|
|
3351
|
+
$ref: "#/components/schemas/LivePaperKpi",
|
|
3352
|
+
},
|
|
3353
|
+
},
|
|
3354
|
+
} as const;
|
|
3355
|
+
|
|
3356
|
+
export const LivePaperPositionSchema = {
|
|
3357
|
+
type: "object",
|
|
3358
|
+
required: ["instrument", "base", "cost"],
|
|
3359
|
+
properties: {
|
|
3360
|
+
instrument: {
|
|
3361
|
+
type: "string",
|
|
3362
|
+
example: "BTC/USDT",
|
|
3363
|
+
},
|
|
3364
|
+
base: {
|
|
3365
|
+
type: "number",
|
|
3366
|
+
format: "double",
|
|
3367
|
+
description: "Amount held, in the base asset.",
|
|
3368
|
+
},
|
|
3369
|
+
cost: {
|
|
3370
|
+
type: "number",
|
|
3371
|
+
format: "double",
|
|
3372
|
+
description: "What it cost, in the account's currency.",
|
|
3373
|
+
},
|
|
3374
|
+
},
|
|
3375
|
+
} as const;
|
|
3376
|
+
|
|
3377
|
+
export const LivePaperKpiSchema = {
|
|
3378
|
+
type: "object",
|
|
3379
|
+
description:
|
|
3380
|
+
"The same KPIs a backtest reports, over the trades closed so far. Absent until the first closed trade is recorded.",
|
|
3381
|
+
properties: {
|
|
3382
|
+
totalTrades: {
|
|
3383
|
+
type: "integer",
|
|
3384
|
+
format: "int64",
|
|
3385
|
+
},
|
|
3386
|
+
winCount: {
|
|
3387
|
+
type: "integer",
|
|
3388
|
+
format: "int64",
|
|
3389
|
+
},
|
|
3390
|
+
lossCount: {
|
|
3391
|
+
type: "integer",
|
|
3392
|
+
format: "int64",
|
|
3393
|
+
},
|
|
3394
|
+
winRate: {
|
|
3395
|
+
type: "number",
|
|
3396
|
+
format: "double",
|
|
3397
|
+
description: "Ratio (0.5 = half the trades won).",
|
|
3398
|
+
},
|
|
3399
|
+
pnlTotal: {
|
|
3400
|
+
type: "number",
|
|
3401
|
+
format: "double",
|
|
3402
|
+
},
|
|
3403
|
+
pnlTotalPercent: {
|
|
3404
|
+
type: "number",
|
|
3405
|
+
format: "double",
|
|
3406
|
+
description: "Percent of `initialFunding` (0-100 scale).",
|
|
3407
|
+
},
|
|
3408
|
+
sharpeRatio: {
|
|
3409
|
+
type: ["number", "null"],
|
|
3410
|
+
format: "double",
|
|
3411
|
+
},
|
|
3412
|
+
sortinoRatio: {
|
|
3413
|
+
type: ["number", "null"],
|
|
3414
|
+
format: "double",
|
|
3415
|
+
},
|
|
3416
|
+
cagr: {
|
|
3417
|
+
type: ["number", "null"],
|
|
3418
|
+
format: "double",
|
|
3419
|
+
description: "Ratio (0.15 for 15%).",
|
|
3420
|
+
},
|
|
3421
|
+
maxDrawdown: {
|
|
3422
|
+
type: "number",
|
|
3423
|
+
format: "double",
|
|
3424
|
+
},
|
|
3425
|
+
maxDrawdownPercent: {
|
|
3426
|
+
type: "number",
|
|
3427
|
+
format: "double",
|
|
3428
|
+
description: "Percent (0-100 scale).",
|
|
3429
|
+
},
|
|
3430
|
+
},
|
|
3431
|
+
} as const;
|
|
3432
|
+
|
|
3433
|
+
export const LivePaperEquityPageSchema = {
|
|
3434
|
+
type: "object",
|
|
3435
|
+
required: ["points"],
|
|
3436
|
+
properties: {
|
|
3437
|
+
points: {
|
|
3438
|
+
type: "array",
|
|
3439
|
+
items: {
|
|
3440
|
+
$ref: "#/components/schemas/LivePaperEquityPoint",
|
|
3441
|
+
},
|
|
3442
|
+
},
|
|
3443
|
+
_links: {
|
|
3444
|
+
type: "object",
|
|
3445
|
+
properties: {
|
|
3446
|
+
next: {
|
|
3447
|
+
type: "object",
|
|
3448
|
+
properties: {
|
|
3449
|
+
href: {
|
|
3450
|
+
type: "string",
|
|
3451
|
+
},
|
|
3452
|
+
},
|
|
3453
|
+
},
|
|
3454
|
+
},
|
|
3455
|
+
},
|
|
3456
|
+
},
|
|
3457
|
+
} as const;
|
|
3458
|
+
|
|
3459
|
+
export const LivePaperEquityPointSchema = {
|
|
3460
|
+
type: "object",
|
|
3461
|
+
required: ["currency", "kind", "eventTsMs"],
|
|
3462
|
+
properties: {
|
|
3463
|
+
currency: {
|
|
3464
|
+
type: "string",
|
|
3465
|
+
},
|
|
3466
|
+
kind: {
|
|
3467
|
+
type: "string",
|
|
3468
|
+
enum: ["equity", "mark", "gap"],
|
|
3469
|
+
},
|
|
3470
|
+
eventTsMs: {
|
|
3471
|
+
type: "integer",
|
|
3472
|
+
format: "int64",
|
|
3473
|
+
description: "Market time of the point.",
|
|
3474
|
+
},
|
|
3475
|
+
equity: {
|
|
3476
|
+
type: "number",
|
|
3477
|
+
format: "double",
|
|
3478
|
+
description: "Absent on a `gap`.",
|
|
3479
|
+
},
|
|
3480
|
+
},
|
|
3481
|
+
} as const;
|
|
3482
|
+
|
|
3194
3483
|
export const LiveSignalSchema = {
|
|
3195
3484
|
type: "object",
|
|
3196
3485
|
required: [
|
|
@@ -3230,11 +3519,12 @@ export const LiveSignalSchema = {
|
|
|
3230
3519
|
},
|
|
3231
3520
|
type: {
|
|
3232
3521
|
type: "string",
|
|
3233
|
-
enum: ["hint", "info", "marker", "command"],
|
|
3522
|
+
enum: ["hint", "info", "marker", "command", "paper"],
|
|
3523
|
+
description: `\`paper\` items appear only for a run whose \`paper.output\` is \`mix\`; they are not relayed over the WebSocket channel.`,
|
|
3234
3524
|
},
|
|
3235
3525
|
kind: {
|
|
3236
3526
|
type: ["string", "null"],
|
|
3237
|
-
description: `\`BUY\`/\`SELL\` for a \`hint\`, the command name for a \`command\`,
|
|
3527
|
+
description: `\`BUY\`/\`SELL\` for a \`hint\`, the command name for a \`command\`; for \`paper\`, what the item is: \`fill\`, \`trade\`, \`equity\`, \`mark\`, \`kpi\` or \`gap\`. Absent otherwise.`,
|
|
3238
3528
|
},
|
|
3239
3529
|
eventTsMs: {
|
|
3240
3530
|
type: "integer",
|
|
@@ -3247,7 +3537,16 @@ export const LiveSignalSchema = {
|
|
|
3247
3537
|
description: "Time it was published — always at or after `eventTsMs`.",
|
|
3248
3538
|
},
|
|
3249
3539
|
instrument: {
|
|
3250
|
-
|
|
3540
|
+
anyOf: [
|
|
3541
|
+
{
|
|
3542
|
+
$ref: "#/components/schemas/LiveSignalInstrument",
|
|
3543
|
+
},
|
|
3544
|
+
{
|
|
3545
|
+
type: "null",
|
|
3546
|
+
},
|
|
3547
|
+
],
|
|
3548
|
+
description:
|
|
3549
|
+
"The instrument the signal is about. `null` only for a `paper` item about a whole account (`equity`, `mark`, `kpi`), whose `data.currency` names the account.",
|
|
3251
3550
|
},
|
|
3252
3551
|
order: {
|
|
3253
3552
|
$ref: "#/components/schemas/LiveSignalOrder",
|
package/src/generated/sdk.gen.ts
CHANGED
|
@@ -124,6 +124,12 @@ import type {
|
|
|
124
124
|
GetLiveRunSignalsData,
|
|
125
125
|
GetLiveRunSignalsResponse,
|
|
126
126
|
GetLiveRunSignalsError,
|
|
127
|
+
GetLiveRunPaperData,
|
|
128
|
+
GetLiveRunPaperResponse,
|
|
129
|
+
GetLiveRunPaperError,
|
|
130
|
+
GetLiveRunPaperEquityData,
|
|
131
|
+
GetLiveRunPaperEquityResponse,
|
|
132
|
+
GetLiveRunPaperEquityError,
|
|
127
133
|
MintLiveConnectionTokenData,
|
|
128
134
|
MintLiveConnectionTokenResponse,
|
|
129
135
|
} from "./types.gen";
|
|
@@ -1342,6 +1348,14 @@ export const getLive = <ThrowOnError extends boolean = false>(
|
|
|
1342
1348
|
* the "Live execution" guide linked from this tag's description for the full flow (minting a
|
|
1343
1349
|
* connection token, the channel and RPC method).
|
|
1344
1350
|
*
|
|
1351
|
+
* **Paper trading.** Pass a `paper` block to have the run's hints executed in simulation from
|
|
1352
|
+
* its first tick, as a backtest would execute them: fills, closed trades, equity and KPIs,
|
|
1353
|
+
* with one simulated account per quote currency. Omitted, the run has no paper trading. It
|
|
1354
|
+
* takes the same economics as a backtest's `baseConfig` plus where its output goes; read it
|
|
1355
|
+
* back with `GET /live/{runId}/paper`. A strategy that listens to its own execution events
|
|
1356
|
+
* (it overrides `getExecutionCallback()`) has no other execution venue, so it cannot start
|
|
1357
|
+
* without a `paper` block.
|
|
1358
|
+
*
|
|
1345
1359
|
*/
|
|
1346
1360
|
export const startLive = <ThrowOnError extends boolean = false>(
|
|
1347
1361
|
options: Options<StartLiveData, ThrowOnError>
|
|
@@ -1530,6 +1544,74 @@ export const getLiveRunSignals = <ThrowOnError extends boolean = false>(
|
|
|
1530
1544
|
});
|
|
1531
1545
|
};
|
|
1532
1546
|
|
|
1547
|
+
/**
|
|
1548
|
+
* Read a run's paper trading
|
|
1549
|
+
* The run's paper trading as last recorded: one entry per simulated account (one per quote
|
|
1550
|
+
* currency the run trades — never added together), with its starting capital, current
|
|
1551
|
+
* equity, realised PnL, open positions and KPIs. The KPIs are the same a backtest reports,
|
|
1552
|
+
* computed over the trades closed so far.
|
|
1553
|
+
*
|
|
1554
|
+
* `equity` is the account's latest recorded value: at the last closed trade (`equityKind:
|
|
1555
|
+
* equity`), or the last periodic mark-to-market while positions are open (`equityKind:
|
|
1556
|
+
* mark`, taken every minute of market time). Until either exists the account holds its
|
|
1557
|
+
* starting capital.
|
|
1558
|
+
*
|
|
1559
|
+
* Readable by the run's owner, and by anyone if the run is `public`. A run started without
|
|
1560
|
+
* a `paper` block answers `404`.
|
|
1561
|
+
*
|
|
1562
|
+
*/
|
|
1563
|
+
export const getLiveRunPaper = <ThrowOnError extends boolean = false>(
|
|
1564
|
+
options: Options<GetLiveRunPaperData, ThrowOnError>
|
|
1565
|
+
) => {
|
|
1566
|
+
return (options.client ?? _heyApiClient).get<
|
|
1567
|
+
GetLiveRunPaperResponse,
|
|
1568
|
+
GetLiveRunPaperError,
|
|
1569
|
+
ThrowOnError
|
|
1570
|
+
>({
|
|
1571
|
+
security: [
|
|
1572
|
+
{
|
|
1573
|
+
scheme: "bearer",
|
|
1574
|
+
type: "http",
|
|
1575
|
+
},
|
|
1576
|
+
],
|
|
1577
|
+
url: "/live/{runId}/paper",
|
|
1578
|
+
...options,
|
|
1579
|
+
});
|
|
1580
|
+
};
|
|
1581
|
+
|
|
1582
|
+
/**
|
|
1583
|
+
* Read a run's paper equity curve
|
|
1584
|
+
* The run's paper equity curve, oldest first, page by page. It is kept for the life of the
|
|
1585
|
+
* run, so unlike signals it has no moving window. Points are `equity` at every closed trade,
|
|
1586
|
+
* `mark` every minute of market time while positions are open, and `gap` where the run was
|
|
1587
|
+
* restarted with positions open: those positions are not carried over, so the curve has no
|
|
1588
|
+
* value there.
|
|
1589
|
+
*
|
|
1590
|
+
* `currency` narrows to one account; without it, every account's points come interleaved by
|
|
1591
|
+
* time, each carrying its currency.
|
|
1592
|
+
*
|
|
1593
|
+
* Readable by the run's owner, and by anyone if the run is `public`.
|
|
1594
|
+
*
|
|
1595
|
+
*/
|
|
1596
|
+
export const getLiveRunPaperEquity = <ThrowOnError extends boolean = false>(
|
|
1597
|
+
options: Options<GetLiveRunPaperEquityData, ThrowOnError>
|
|
1598
|
+
) => {
|
|
1599
|
+
return (options.client ?? _heyApiClient).get<
|
|
1600
|
+
GetLiveRunPaperEquityResponse,
|
|
1601
|
+
GetLiveRunPaperEquityError,
|
|
1602
|
+
ThrowOnError
|
|
1603
|
+
>({
|
|
1604
|
+
security: [
|
|
1605
|
+
{
|
|
1606
|
+
scheme: "bearer",
|
|
1607
|
+
type: "http",
|
|
1608
|
+
},
|
|
1609
|
+
],
|
|
1610
|
+
url: "/live/{runId}/paper/equity",
|
|
1611
|
+
...options,
|
|
1612
|
+
});
|
|
1613
|
+
};
|
|
1614
|
+
|
|
1533
1615
|
/**
|
|
1534
1616
|
* Mint a WebSocket connection token
|
|
1535
1617
|
* Mints a short-lived token for the WebSocket connection used to receive a run's signals in
|