@qtsurfer/api-client 0.1.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.
@@ -0,0 +1,296 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ export const ResponseErrorSchema = {
4
+ description: 'General response error',
5
+ type: 'object',
6
+ required: ['code', 'message'],
7
+ properties: {
8
+ code: {
9
+ description: 'Status code',
10
+ type: 'integer',
11
+ example: 400
12
+ },
13
+ message: {
14
+ description: 'Error description',
15
+ type: 'string',
16
+ example: 'Invalid request'
17
+ }
18
+ }
19
+ } as const;
20
+
21
+ export const InstrumentSchema = {
22
+ description: 'Exchange instrument identifier (e.g. a currency pair)',
23
+ type: 'string',
24
+ example: 'BTC/USDT'
25
+ } as const;
26
+
27
+ export const InstrumentDetailSchema = {
28
+ description: 'Exchange instrument with data availability and market info',
29
+ type: 'object',
30
+ required: ['id', 'base', 'quote'],
31
+ properties: {
32
+ id: {
33
+ type: 'string',
34
+ description: 'Instrument identifier (e.g. currency pair)',
35
+ example: 'BTC/USDT'
36
+ },
37
+ base: {
38
+ type: 'string',
39
+ description: 'Base currency',
40
+ example: 'BTC'
41
+ },
42
+ quote: {
43
+ type: 'string',
44
+ description: 'Quote currency',
45
+ example: 'USDT'
46
+ },
47
+ dataFrom: {
48
+ type: 'string',
49
+ format: 'date-time',
50
+ description: 'Earliest timestamp with quality-verified data available for backtesting',
51
+ example: '2026-03-17T00:00:00Z'
52
+ },
53
+ dataTo: {
54
+ type: 'string',
55
+ format: 'date-time',
56
+ description: 'Latest timestamp with quality-verified data available for backtesting',
57
+ example: '2026-03-31T18:00:00Z'
58
+ },
59
+ lastPrice: {
60
+ type: 'number',
61
+ format: 'double',
62
+ description: 'Last traded price',
63
+ example: 84250.5
64
+ },
65
+ volume24h: {
66
+ type: 'number',
67
+ format: 'double',
68
+ description: 'Trading volume in the last 24 hours (in quote currency)',
69
+ example: 1234567.89
70
+ }
71
+ }
72
+ } as const;
73
+
74
+ export const ExchangeSchema = {
75
+ description: 'Exchange service provider',
76
+ type: 'object',
77
+ required: ['id', 'name'],
78
+ properties: {
79
+ id: {
80
+ description: 'Unique identifier for the exchange',
81
+ type: 'string',
82
+ example: 'binance'
83
+ },
84
+ name: {
85
+ description: 'Name of the exchange',
86
+ type: 'string',
87
+ example: 'Binance'
88
+ },
89
+ description: {
90
+ description: 'Description of the exchange',
91
+ type: 'string',
92
+ example: 'Binance cryptocurrency exchange'
93
+ }
94
+ }
95
+ } as const;
96
+
97
+ export const DataSourceTypeSchema = {
98
+ type: 'string',
99
+ description: 'Managed exchange data sources available for backtesting. Currently only ticker is supported; kline and funding rate support is planned.',
100
+ enum: ['ticker'],
101
+ example: 'ticker'
102
+ } as const;
103
+
104
+ export const JobStateSchema = {
105
+ type: 'object',
106
+ description: 'Information about a single job',
107
+ required: ['contextId', 'status', 'size', 'completed'],
108
+ properties: {
109
+ contextId: {
110
+ type: 'string',
111
+ description: 'Unique context ID for the job',
112
+ example: 'jctx:ticker:4a627755-7f5a-4297-b647-8dddd8aee416:binance:1rabbrpk5r4kkegs83w6qr:btc/usdt:2o8heaioicr0edvx5ybcap'
113
+ },
114
+ status: {
115
+ type: 'string',
116
+ description: 'Current status of the job',
117
+ enum: ['New', 'Started', 'Completed', 'Aborted', 'Failed'],
118
+ example: 'Completed'
119
+ },
120
+ statusDetail: {
121
+ type: ['string', 'null'],
122
+ description: 'Detailed status information, if available',
123
+ example: 'Job completed with error code 5001'
124
+ },
125
+ size: {
126
+ type: 'integer',
127
+ description: 'Total size of the data being prepared',
128
+ example: 100
129
+ },
130
+ completed: {
131
+ type: 'integer',
132
+ description: 'The amount of data processed so far',
133
+ example: 50
134
+ },
135
+ startTime: {
136
+ type: ['string', 'null'],
137
+ format: 'date-time',
138
+ description: 'Timestamp for when the preparation started',
139
+ example: '2025-01-04T14:00:00Z'
140
+ },
141
+ endTime: {
142
+ type: ['string', 'null'],
143
+ format: 'date-time',
144
+ description: 'Timestamp for when the preparation finished',
145
+ example: '2025-01-04T14:00:20Z'
146
+ }
147
+ }
148
+ } as const;
149
+
150
+ export const AcceptedJobSchema = {
151
+ type: 'object',
152
+ description: `Response returned by async endpoints (\`202 Accepted\`). The \`jobId\` is deterministic for the
153
+ same input parameters — repeated calls with identical params return the same id.
154
+ `,
155
+ required: ['jobId'],
156
+ properties: {
157
+ jobId: {
158
+ type: 'string',
159
+ description: 'Unique job identifier; use this to poll for completion.',
160
+ example: '13RBLGQlPnfDjO6wyKSX8i'
161
+ }
162
+ },
163
+ example: {
164
+ jobId: '13RBLGQlPnfDjO6wyKSX8i'
165
+ }
166
+ } as const;
167
+
168
+ export const BacktestJobResultSchema = {
169
+ type: 'object',
170
+ description: 'Backtest job result.',
171
+ required: ['results', 'state'],
172
+ properties: {
173
+ results: {
174
+ '$ref': '#/components/schemas/ResultMap'
175
+ },
176
+ state: {
177
+ '$ref': '#/components/schemas/JobState'
178
+ }
179
+ }
180
+ } as const;
181
+
182
+ export const ResultMapSchema = {
183
+ type: 'object',
184
+ description: 'Execution result map. Always includes core fields (hostName, iops, strategyId, instrument). Yield metrics (pnlTotal, totalTrades, winRate, etc.) are present when the strategy emitted at least one trade. When signal storage is enabled, includes signal fields described below.',
185
+ required: ['strategyId', 'instrument'],
186
+ properties: {
187
+ hostName: {
188
+ type: 'string',
189
+ description: 'Hostname of the worker node that executed the strategy',
190
+ example: 'backtesting-job-worker-84b569dff9-dr4lb'
191
+ },
192
+ iops: {
193
+ type: 'number',
194
+ format: 'double',
195
+ description: 'Instrument operations per second throughput during execution',
196
+ example: 123956.53
197
+ },
198
+ strategyId: {
199
+ type: 'string',
200
+ description: 'Redis key of the compiled strategy used for execution. Format: strategy:{userId}:ticker:{compilationId}',
201
+ example: 'strategy:4a627755-7f5a-4297-b647-8dddd8aee416:ticker:2iyvtenlzh9dabqtxn7nbv'
202
+ },
203
+ instrument: {
204
+ type: 'string',
205
+ description: 'The instrument (currency pair) that was backtested',
206
+ example: 'BTC/USDT'
207
+ },
208
+ pnlTotal: {
209
+ type: 'number',
210
+ format: 'double',
211
+ description: 'Total profit and loss in the output currency',
212
+ example: 42.75
213
+ },
214
+ totalTrades: {
215
+ type: 'integer',
216
+ format: 'int64',
217
+ description: 'Total number of trades executed by the strategy',
218
+ example: 156
219
+ },
220
+ winRate: {
221
+ type: 'number',
222
+ format: 'double',
223
+ description: 'Percentage of profitable trades (0-100)',
224
+ example: 58.33
225
+ },
226
+ sharpeRatio: {
227
+ type: 'number',
228
+ format: 'double',
229
+ description: 'Risk-adjusted return ratio (mean return / standard deviation of returns)',
230
+ example: 1.245
231
+ },
232
+ sortinoRatio: {
233
+ type: 'number',
234
+ format: 'double',
235
+ description: 'Downside risk-adjusted return ratio (mean return / downside deviation)',
236
+ example: 1.872
237
+ },
238
+ cagr: {
239
+ type: 'number',
240
+ format: 'double',
241
+ description: 'Compound Annual Growth Rate',
242
+ example: 0.1534
243
+ },
244
+ maxDrawdown: {
245
+ type: 'number',
246
+ format: 'double',
247
+ description: 'Maximum absolute drawdown in the output currency',
248
+ example: 12.5
249
+ },
250
+ maxDrawdownPercent: {
251
+ type: 'number',
252
+ format: 'double',
253
+ description: 'Maximum percentage drawdown from peak equity',
254
+ example: 8.75
255
+ },
256
+ signalCount: {
257
+ type: 'integer',
258
+ description: 'Number of signals emitted during strategy execution',
259
+ example: 100000
260
+ },
261
+ signalsId: {
262
+ type: 'string',
263
+ description: 'Storage key for the signal Parquet file. Format: {userId}/exec/{exchange}/{jobId}',
264
+ example: '4a627755-7f5a-4297-b647-8dddd8aee416/exec/binance/3vsndwikcuaatjmb83fjtl'
265
+ },
266
+ signalsUrl: {
267
+ type: 'string',
268
+ format: 'uri',
269
+ description: 'Public HTTPS URL to the Parquet file. Computed at setup time from publicBaseUrl + signalsId + .parquet. Available even before upload completes.',
270
+ example: 'https://storage.qtsurfer.com/4a627755-7f5a-4297-b647-8dddd8aee416/exec/binance/3vsndwikcuaatjmb83fjtl.parquet'
271
+ },
272
+ signalsUpload: {
273
+ type: 'string',
274
+ enum: ['Done', 'Failed', 'Skipped'],
275
+ description: 'Upload status. Done = file uploaded to R2. Failed = upload error (see signalsUploadReason). Skipped = no signals emitted or storage not configured.',
276
+ example: 'Done'
277
+ },
278
+ signalsUploadedAt: {
279
+ type: 'string',
280
+ format: 'date-time',
281
+ description: 'ISO 8601 timestamp of when the upload completed. Only present when signalsUpload is Done.',
282
+ example: '2026-03-18T13:21:48.170Z'
283
+ },
284
+ signalsUploadReason: {
285
+ type: 'string',
286
+ description: 'Human-readable reason when signalsUpload is Failed or Skipped.',
287
+ example: 'parquet file empty or missing after close'
288
+ }
289
+ }
290
+ } as const;
291
+
292
+ export const strategyIdSchema = {
293
+ description: 'Unique identifier for a compiled strategy',
294
+ type: 'string',
295
+ example: '6bsh31ikwkuivhtgcoa6s4'
296
+ } as const;
@@ -0,0 +1,202 @@
1
+ // This file is auto-generated by @hey-api/openapi-ts
2
+
3
+ import type { Options as ClientOptions, TDataShape, Client } from '@hey-api/client-fetch';
4
+ import type { GetExchangesData, GetExchangesResponse, GetInstrumentsData, GetInstrumentsResponse, GetInstrumentsError, PostStrategyData, PostStrategyResponse, PostStrategyError, GetStrategyStatusData, GetStrategyStatusResponse, GetStrategyStatusError, PrepareBacktestingData, PrepareBacktestingResponse, PrepareBacktestingError, GetPreparationStatusData, GetPreparationStatusResponse, GetPreparationStatusError, ExecuteBacktestingData, ExecuteBacktestingResponse, ExecuteBacktestingError, CancelExecutionData, CancelExecutionResponse, CancelExecutionError, GetExecutionResultData, GetExecutionResultResponse, GetExecutionResultError } from './types.gen';
5
+ import { client as _heyApiClient } from './client.gen';
6
+
7
+ export type Options<TData extends TDataShape = TDataShape, ThrowOnError extends boolean = boolean> = ClientOptions<TData, ThrowOnError> & {
8
+ /**
9
+ * You can provide a client instance returned by `createClient()` instead of
10
+ * individual options. This might be also useful if you want to implement a
11
+ * custom client.
12
+ */
13
+ client?: Client;
14
+ /**
15
+ * You can pass arbitrary values through the `meta` object. This can be
16
+ * used to access values that aren't defined as part of the SDK function.
17
+ */
18
+ meta?: Record<string, unknown>;
19
+ };
20
+
21
+ /**
22
+ * Get a list of available exchanges
23
+ */
24
+ export const getExchanges = <ThrowOnError extends boolean = false>(options?: Options<GetExchangesData, ThrowOnError>) => {
25
+ return (options?.client ?? _heyApiClient).get<GetExchangesResponse, unknown, ThrowOnError>({
26
+ url: '/exchanges',
27
+ ...options
28
+ });
29
+ };
30
+
31
+ /**
32
+ * Get a list of Instruments from a specific exchange
33
+ */
34
+ export const getInstruments = <ThrowOnError extends boolean = false>(options: Options<GetInstrumentsData, ThrowOnError>) => {
35
+ return (options.client ?? _heyApiClient).get<GetInstrumentsResponse, GetInstrumentsError, ThrowOnError>({
36
+ url: '/exchange/{exchangeId}/instruments',
37
+ ...options
38
+ });
39
+ };
40
+
41
+ /**
42
+ * Compile a strategy from source code
43
+ * Submits raw strategy source for compilation. By default the call is synchronous and returns
44
+ * the `strategyId` once compilation succeeds. Set the header `X-Compile-Async: true` to enqueue
45
+ * the compile task and return immediately with a `jobId` — poll
46
+ * `GET /strategy/{strategyId}` to check status.
47
+ *
48
+ * The `strategyId` is deterministic: the same source for the same user always produces the
49
+ * same id.
50
+ *
51
+ */
52
+ export const postStrategy = <ThrowOnError extends boolean = false>(options: Options<PostStrategyData, ThrowOnError>) => {
53
+ return (options.client ?? _heyApiClient).post<PostStrategyResponse, PostStrategyError, ThrowOnError>({
54
+ bodySerializer: null,
55
+ security: [
56
+ {
57
+ scheme: 'bearer',
58
+ type: 'http'
59
+ }
60
+ ],
61
+ url: '/strategy',
62
+ ...options,
63
+ headers: {
64
+ 'Content-Type': 'text/plain',
65
+ ...options?.headers
66
+ }
67
+ });
68
+ };
69
+
70
+ /**
71
+ * Get the status of an async compile task
72
+ * Polls the status of a strategy compilation. Useful when the strategy was submitted with
73
+ * `X-Compile-Async: true`. Returns the resolved `strategyId` once compilation completes.
74
+ *
75
+ */
76
+ export const getStrategyStatus = <ThrowOnError extends boolean = false>(options: Options<GetStrategyStatusData, ThrowOnError>) => {
77
+ return (options.client ?? _heyApiClient).get<GetStrategyStatusResponse, GetStrategyStatusError, ThrowOnError>({
78
+ security: [
79
+ {
80
+ scheme: 'bearer',
81
+ type: 'http'
82
+ }
83
+ ],
84
+ url: '/strategy/{strategyId}',
85
+ ...options
86
+ });
87
+ };
88
+
89
+ /**
90
+ * Prepare backtesting data
91
+ * Enqueues a prepare task over the requested date range. Returns immediately with a `jobId`;
92
+ * poll `GET /backtest/{exchangeId}/{type}/prepare/{jobId}` for completion.
93
+ *
94
+ * The same params always return the same `jobId` (idempotent). Repeated calls with identical
95
+ * params do not enqueue duplicate work — they reuse the existing job.
96
+ *
97
+ */
98
+ export const prepareBacktesting = <ThrowOnError extends boolean = false>(options: Options<PrepareBacktestingData, ThrowOnError>) => {
99
+ return (options.client ?? _heyApiClient).post<PrepareBacktestingResponse, PrepareBacktestingError, ThrowOnError>({
100
+ security: [
101
+ {
102
+ scheme: 'bearer',
103
+ type: 'http'
104
+ }
105
+ ],
106
+ url: '/backtest/{exchangeId}/{type}/prepare',
107
+ ...options,
108
+ headers: {
109
+ 'Content-Type': 'application/json',
110
+ ...options?.headers
111
+ }
112
+ });
113
+ };
114
+
115
+ /**
116
+ * Get the status of a prepare job
117
+ * Retrieves the current state of the prepare job identified by `jobId`.
118
+ * Poll until `status` is `Completed`, `Failed`, or `Aborted`.
119
+ *
120
+ */
121
+ export const getPreparationStatus = <ThrowOnError extends boolean = false>(options: Options<GetPreparationStatusData, ThrowOnError>) => {
122
+ return (options.client ?? _heyApiClient).get<GetPreparationStatusResponse, GetPreparationStatusError, ThrowOnError>({
123
+ security: [
124
+ {
125
+ scheme: 'bearer',
126
+ type: 'http'
127
+ }
128
+ ],
129
+ url: '/backtest/{exchangeId}/{type}/prepare/{jobId}',
130
+ ...options
131
+ });
132
+ };
133
+
134
+ /**
135
+ * Execute a compiled strategy against a prepared dataset
136
+ * Enqueues an execute task that runs the strategy identified by `strategyId` over the data
137
+ * prepared by the prepare job identified by `prepareJobId`. The instrument and date range are
138
+ * recovered from the prepare job — they do not need to be sent again.
139
+ *
140
+ * Returns immediately with a `jobId`; poll `GET /backtest/{exchangeId}/{type}/execute/{jobId}`
141
+ * for the result.
142
+ *
143
+ * The same params (same `prepareJobId`, `strategyId`, `storeSignals`) always return the same
144
+ * `jobId` (idempotent).
145
+ *
146
+ */
147
+ export const executeBacktesting = <ThrowOnError extends boolean = false>(options: Options<ExecuteBacktestingData, ThrowOnError>) => {
148
+ return (options.client ?? _heyApiClient).post<ExecuteBacktestingResponse, ExecuteBacktestingError, ThrowOnError>({
149
+ security: [
150
+ {
151
+ scheme: 'bearer',
152
+ type: 'http'
153
+ }
154
+ ],
155
+ url: '/backtest/{exchangeId}/{type}/execute',
156
+ ...options,
157
+ headers: {
158
+ 'Content-Type': 'application/json',
159
+ ...options?.headers
160
+ }
161
+ });
162
+ };
163
+
164
+ /**
165
+ * Cancel a running backtest execution
166
+ * Requests cancellation of the specified execution. The execution
167
+ * status will transition to `Aborted` once the cancellation is
168
+ * processed. Cancellation is asynchronous — poll the GET endpoint
169
+ * to confirm the final status.
170
+ *
171
+ */
172
+ export const cancelExecution = <ThrowOnError extends boolean = false>(options: Options<CancelExecutionData, ThrowOnError>) => {
173
+ return (options.client ?? _heyApiClient).delete<CancelExecutionResponse, CancelExecutionError, ThrowOnError>({
174
+ security: [
175
+ {
176
+ scheme: 'bearer',
177
+ type: 'http'
178
+ }
179
+ ],
180
+ url: '/backtest/{exchangeId}/{type}/execute/{jobId}',
181
+ ...options
182
+ });
183
+ };
184
+
185
+ /**
186
+ * Get the result of a backtest execution job
187
+ * Retrieves the current state and results of the execute job identified by `jobId`.
188
+ * Poll until `state.status` is `Completed`, `Failed`, or `Aborted`.
189
+ *
190
+ */
191
+ export const getExecutionResult = <ThrowOnError extends boolean = false>(options: Options<GetExecutionResultData, ThrowOnError>) => {
192
+ return (options.client ?? _heyApiClient).get<GetExecutionResultResponse, GetExecutionResultError, ThrowOnError>({
193
+ security: [
194
+ {
195
+ scheme: 'bearer',
196
+ type: 'http'
197
+ }
198
+ ],
199
+ url: '/backtest/{exchangeId}/{type}/execute/{jobId}',
200
+ ...options
201
+ });
202
+ };