@kkkermit/trading212.js 0.1.0 → 0.1.2
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/CHANGELOG.md +12 -0
- package/README.md +5 -0
- package/dist/chunk-AVOYEH6N.js +2661 -0
- package/dist/chunk-K766TWIM.cjs +2700 -0
- package/dist/cli.js +2804 -0
- package/dist/client-BSQXqdxj.d.cts +1684 -0
- package/dist/client-BSQXqdxj.d.ts +1684 -0
- package/dist/csv.cjs +54 -0
- package/dist/csv.d.cts +21 -0
- package/dist/csv.d.ts +21 -0
- package/dist/csv.js +50 -0
- package/dist/index.cjs +154 -0
- package/dist/index.d.cts +35 -0
- package/dist/index.d.ts +35 -0
- package/dist/index.js +1 -0
- package/dist/testing.cjs +651 -0
- package/dist/testing.d.cts +159 -0
- package/dist/testing.d.ts +159 -0
- package/dist/testing.js +642 -0
- package/package.json +4 -4
|
@@ -0,0 +1,1684 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Where the client keeps the instrument and exchange lists. Implement it over a file, Redis or anything else to share
|
|
3
|
+
* them between processes; each method may return a promise, and values are plain JSON.
|
|
4
|
+
*/
|
|
5
|
+
interface CacheStore {
|
|
6
|
+
/** `undefined` or `null` means a miss. */
|
|
7
|
+
get(key: string): unknown;
|
|
8
|
+
set(key: string, value: unknown, ttlMs: number): unknown;
|
|
9
|
+
delete?(key: string): unknown;
|
|
10
|
+
}
|
|
11
|
+
interface LoadOptions<T> {
|
|
12
|
+
readonly ttlMs: number;
|
|
13
|
+
/** Skip the cache and load afresh. */
|
|
14
|
+
readonly refresh?: boolean;
|
|
15
|
+
/** Stops this caller waiting; a load other callers share carries on. */
|
|
16
|
+
readonly signal?: AbortSignal | undefined;
|
|
17
|
+
/** Rejects a cached value of the wrong shape, which is then reported and loaded afresh. */
|
|
18
|
+
readonly accept?: (value: unknown) => value is T;
|
|
19
|
+
}
|
|
20
|
+
/** The default store: a `Map` with expiry, private to one client. */
|
|
21
|
+
declare class MemoryCache implements CacheStore {
|
|
22
|
+
#private;
|
|
23
|
+
get(key: string): unknown;
|
|
24
|
+
set(key: string, value: unknown, ttlMs: number): void;
|
|
25
|
+
delete(key: string): void;
|
|
26
|
+
clear(): void;
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* Loads a value through the cache, sharing one in-flight load between concurrent callers. A cache store that fails is
|
|
30
|
+
* reported and bypassed, so a broken cache costs a download rather than the call.
|
|
31
|
+
*/
|
|
32
|
+
declare class CachedLoader {
|
|
33
|
+
#private;
|
|
34
|
+
constructor(store: CacheStore, onError?: (error: unknown, key: string) => void);
|
|
35
|
+
/**
|
|
36
|
+
* The shared load is started without any caller's signal, so one caller giving up never fails the others; each
|
|
37
|
+
* caller stops waiting when its own `signal` aborts.
|
|
38
|
+
*/
|
|
39
|
+
load<T>(key: string, options: LoadOptions<T>, loader: () => Promise<T>): Promise<T>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/** `demo` is paper trading; `live` is real money. A key works in exactly one of them. */
|
|
43
|
+
type Environment = "demo" | "live";
|
|
44
|
+
declare const BASE_URLS: Readonly<Record<Environment, string>>;
|
|
45
|
+
|
|
46
|
+
type HttpMethod = "GET" | "POST" | "DELETE";
|
|
47
|
+
/**
|
|
48
|
+
* How an endpoint may be treated. `read` is safe to retry; `write` changes something harmless such as requesting a
|
|
49
|
+
* report; `trade` moves money or holdings and is never retried and refused on live unless trading is enabled.
|
|
50
|
+
*/
|
|
51
|
+
type EndpointKind = "read" | "write" | "trade";
|
|
52
|
+
interface EndpointRateLimit {
|
|
53
|
+
readonly requests: number;
|
|
54
|
+
readonly periodMs: number;
|
|
55
|
+
}
|
|
56
|
+
interface EndpointDefinition {
|
|
57
|
+
readonly id: string;
|
|
58
|
+
readonly method: HttpMethod;
|
|
59
|
+
readonly path: string;
|
|
60
|
+
/** The API key permission the endpoint needs, or `null` where the spec does not name one. */
|
|
61
|
+
readonly scope: string | null;
|
|
62
|
+
readonly rateLimit: EndpointRateLimit;
|
|
63
|
+
readonly kind: EndpointKind;
|
|
64
|
+
readonly deprecated: boolean;
|
|
65
|
+
readonly summary: string;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
/** What the `x-ratelimit-*` headers said about an endpoint's budget. Absent headers leave fields undefined. */
|
|
69
|
+
interface RateLimitInfo {
|
|
70
|
+
/** Requests allowed per period. */
|
|
71
|
+
readonly limit?: number;
|
|
72
|
+
/** Length of the period, in milliseconds. */
|
|
73
|
+
readonly periodMs?: number;
|
|
74
|
+
/** Requests left in this period. */
|
|
75
|
+
readonly remaining?: number;
|
|
76
|
+
/** Requests already made in this period. */
|
|
77
|
+
readonly used?: number;
|
|
78
|
+
/** When the budget fully resets, as epoch milliseconds. */
|
|
79
|
+
readonly resetAt?: number;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* - `pace` (default) spreads calls evenly over each period, as Trading 212 recommends, so 429s should not happen.
|
|
84
|
+
* - `burst` spends a period's whole allowance at once, then waits for the reset.
|
|
85
|
+
* - `off` sends immediately; a read that meets a 429 is still retried after the reset.
|
|
86
|
+
*/
|
|
87
|
+
type RateLimitMode = "pace" | "burst" | "off";
|
|
88
|
+
/** What is known about one endpoint's budget right now. */
|
|
89
|
+
interface EndpointBudget {
|
|
90
|
+
readonly limit: number;
|
|
91
|
+
readonly periodMs: number;
|
|
92
|
+
/** From the last response's headers; undefined until the endpoint has been called. */
|
|
93
|
+
readonly remaining: number | undefined;
|
|
94
|
+
readonly resetAt: Date | undefined;
|
|
95
|
+
}
|
|
96
|
+
/** How long a call must wait for its slot, and whether the slot was taken. */
|
|
97
|
+
interface Reservation {
|
|
98
|
+
readonly waitMs: number;
|
|
99
|
+
readonly booked: boolean;
|
|
100
|
+
}
|
|
101
|
+
declare class RateLimiter {
|
|
102
|
+
#private;
|
|
103
|
+
constructor(accountKey: string, mode: RateLimitMode);
|
|
104
|
+
/**
|
|
105
|
+
* Books the next slot for a call. When the wait would be longer than `maxWaitMs`, nothing is booked, so a refused
|
|
106
|
+
* call never delays the ones after it.
|
|
107
|
+
*/
|
|
108
|
+
reserve(endpoint: EndpointDefinition, now: number, maxWaitMs?: number): Reservation;
|
|
109
|
+
/** Corrects the budget from what Trading 212's headers said, which beats the documented figures. */
|
|
110
|
+
update(endpoint: EndpointDefinition, info: RateLimitInfo, now: number): void;
|
|
111
|
+
/** How long the endpoint is closed for after a 429 or an empty budget, in milliseconds. */
|
|
112
|
+
blockedFor(endpoint: EndpointDefinition, now: number): number;
|
|
113
|
+
/** Records a 429: nothing more is sent to the endpoint until the reset. */
|
|
114
|
+
markLimited(endpoint: EndpointDefinition, resetAt: number | undefined, now: number): void;
|
|
115
|
+
snapshot(endpoints: readonly EndpointDefinition[]): Record<string, EndpointBudget>;
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
/** Retries apply to reads only. Orders, cancellations and pie changes are never retried. */
|
|
119
|
+
interface RetryOptions {
|
|
120
|
+
/** Total tries, including the first. Default 3. */
|
|
121
|
+
maxAttempts?: number;
|
|
122
|
+
/** The first backoff, doubled on each retry, with full jitter. Default 500 ms. */
|
|
123
|
+
baseDelayMs?: number;
|
|
124
|
+
/** The longest backoff. Default 10 s. */
|
|
125
|
+
maxDelayMs?: number;
|
|
126
|
+
}
|
|
127
|
+
interface ResolvedRetry {
|
|
128
|
+
readonly maxAttempts: number;
|
|
129
|
+
readonly baseDelayMs: number;
|
|
130
|
+
readonly maxDelayMs: number;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/** A stable, machine-readable name for what went wrong. */
|
|
134
|
+
type ErrorCode = "configuration" | "authentication" | "missing_scope" | "not_available_in_demo" | "permission" | "validation" | "order_rejected" | "not_found" | "instrument_not_found" | "rate_limited" | "timeout" | "outcome_unknown" | "trading_disabled" | "network" | "server" | "http_error" | "unexpected_response";
|
|
135
|
+
/** The request an error came from. Never holds headers or credentials. */
|
|
136
|
+
interface RequestDescription {
|
|
137
|
+
readonly method: string;
|
|
138
|
+
readonly path: string;
|
|
139
|
+
/** The library's name for the endpoint, such as `placeLimitOrder`. */
|
|
140
|
+
readonly endpoint?: string;
|
|
141
|
+
}
|
|
142
|
+
interface ErrorDetails {
|
|
143
|
+
hint?: string;
|
|
144
|
+
status?: number;
|
|
145
|
+
request?: RequestDescription;
|
|
146
|
+
rateLimit?: RateLimitInfo;
|
|
147
|
+
/** The response body, parsed when it was JSON and always redacted. */
|
|
148
|
+
body?: unknown;
|
|
149
|
+
/** The error code Trading 212 put in the body, such as `min-quantity-exceeded`. */
|
|
150
|
+
apiCode?: string;
|
|
151
|
+
/** Trading 212's reference for the failed request, worth quoting if you contact its support. */
|
|
152
|
+
traceId?: string;
|
|
153
|
+
cause?: unknown;
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* The base of every error this library throws. `instanceof` works on it and on every subclass even when two copies
|
|
157
|
+
* of the package are loaded (ESM beside CJS), because the check reads a brand rather than the prototype chain.
|
|
158
|
+
*/
|
|
159
|
+
declare class Trading212Error extends Error {
|
|
160
|
+
static readonly kind: string;
|
|
161
|
+
readonly code: ErrorCode;
|
|
162
|
+
/** What to do about it, in plain English. */
|
|
163
|
+
readonly hint: string | undefined;
|
|
164
|
+
readonly status: number | undefined;
|
|
165
|
+
readonly request: RequestDescription | undefined;
|
|
166
|
+
readonly rateLimit: RateLimitInfo | undefined;
|
|
167
|
+
readonly body: unknown;
|
|
168
|
+
readonly apiCode: string | undefined;
|
|
169
|
+
/** Trading 212's reference for the failed request, worth quoting if you contact its support. */
|
|
170
|
+
readonly traceId: string | undefined;
|
|
171
|
+
/** Set when a paginated read failed part-way: pass it as `cursor` to carry on from where it stopped. */
|
|
172
|
+
resumeCursor: string | undefined;
|
|
173
|
+
constructor(message: string, code: ErrorCode, details?: ErrorDetails);
|
|
174
|
+
static [Symbol.hasInstance](value: unknown): boolean;
|
|
175
|
+
/** A plain, redacted object for structured logs: every field that has a value, plus the cause's message. */
|
|
176
|
+
toLog(): Record<string, unknown>;
|
|
177
|
+
toJSON(): Record<string, unknown>;
|
|
178
|
+
}
|
|
179
|
+
/** True for any error this library threw, from any copy of the package. */
|
|
180
|
+
declare function isTrading212Error(value: unknown): value is Trading212Error;
|
|
181
|
+
/** The options passed to the client, or the environment variables behind them, are wrong. No request was made. */
|
|
182
|
+
declare class ConfigurationError extends Trading212Error {
|
|
183
|
+
static readonly kind = "ConfigurationError";
|
|
184
|
+
/** The option at fault, such as `apiKey`. */
|
|
185
|
+
readonly field: string | undefined;
|
|
186
|
+
constructor(message: string, details?: ErrorDetails & {
|
|
187
|
+
field?: string;
|
|
188
|
+
});
|
|
189
|
+
}
|
|
190
|
+
/** 401: Trading 212 did not accept the key and secret. */
|
|
191
|
+
declare class AuthenticationError extends Trading212Error {
|
|
192
|
+
static readonly kind = "AuthenticationError";
|
|
193
|
+
readonly environment: Environment;
|
|
194
|
+
constructor(message: string, details: ErrorDetails & {
|
|
195
|
+
environment: Environment;
|
|
196
|
+
});
|
|
197
|
+
}
|
|
198
|
+
/** 403 with a missing permission: the key exists but was not given this scope. */
|
|
199
|
+
declare class MissingScopeError extends Trading212Error {
|
|
200
|
+
static readonly kind = "MissingScopeError";
|
|
201
|
+
/** The permission the key lacks, such as `orders:execute`. */
|
|
202
|
+
readonly scope: string;
|
|
203
|
+
constructor(message: string, details: ErrorDetails & {
|
|
204
|
+
scope: string;
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
/** 403 for a feature that only exists on live, such as CSV exports. */
|
|
208
|
+
declare class NotAvailableInDemoError extends Trading212Error {
|
|
209
|
+
static readonly kind = "NotAvailableInDemoError";
|
|
210
|
+
constructor(message: string, details?: ErrorDetails);
|
|
211
|
+
}
|
|
212
|
+
/** Any other 403, for example a key restricted to IP addresses this machine is not on. */
|
|
213
|
+
declare class PermissionError extends Trading212Error {
|
|
214
|
+
static readonly kind = "PermissionError";
|
|
215
|
+
constructor(message: string, details?: ErrorDetails);
|
|
216
|
+
}
|
|
217
|
+
interface ValidationIssue {
|
|
218
|
+
readonly field: string;
|
|
219
|
+
readonly message: string;
|
|
220
|
+
}
|
|
221
|
+
/** The request was invalid: caught here before sending, or refused by Trading 212 with a 400. */
|
|
222
|
+
declare class ValidationError extends Trading212Error {
|
|
223
|
+
static readonly kind: string;
|
|
224
|
+
readonly issues: readonly ValidationIssue[];
|
|
225
|
+
constructor(message: string, details?: ErrorDetails & {
|
|
226
|
+
issues?: readonly ValidationIssue[];
|
|
227
|
+
}, code?: ErrorCode);
|
|
228
|
+
}
|
|
229
|
+
/** Why Trading 212 refused an order, spelt as its error bodies spell it; an unknown reason arrives as its raw code. */
|
|
230
|
+
type OrderRejectionReason = "min-quantity-exceeded" | "max-quantity-exceeded" | "insufficient-free-for-stocks-buy" | "selling-equity-not-owned" | "market-closed" | "quantity-precision-mismatch" | (string & {});
|
|
231
|
+
/** Trading 212 refused an order for a business reason, such as not enough cash. Nothing was traded. */
|
|
232
|
+
declare class OrderRejectedError extends ValidationError {
|
|
233
|
+
static readonly kind = "OrderRejectedError";
|
|
234
|
+
readonly reason: OrderRejectionReason;
|
|
235
|
+
/** The smallest quantity Trading 212 accepts for this order, read from a `min-quantity-exceeded` refusal. */
|
|
236
|
+
readonly minQuantity: number | undefined;
|
|
237
|
+
/** The largest quantity it accepts in one order, read from a `max-quantity-exceeded` refusal. */
|
|
238
|
+
readonly maxQuantity: number | undefined;
|
|
239
|
+
/** The most decimal places a quantity may have, read from a `quantity-precision-mismatch` refusal. */
|
|
240
|
+
readonly maxDecimals: number | undefined;
|
|
241
|
+
/** How many shares Trading 212 says the account owns, read from a `selling-equity-not-owned` refusal. */
|
|
242
|
+
readonly ownedQuantity: number | undefined;
|
|
243
|
+
constructor(message: string, details: ErrorDetails & {
|
|
244
|
+
reason: OrderRejectionReason;
|
|
245
|
+
minQuantity?: number;
|
|
246
|
+
maxQuantity?: number;
|
|
247
|
+
maxDecimals?: number;
|
|
248
|
+
ownedQuantity?: number;
|
|
249
|
+
});
|
|
250
|
+
}
|
|
251
|
+
/** 404: the order, pie or other resource does not exist (any more). */
|
|
252
|
+
declare class NotFoundError extends Trading212Error {
|
|
253
|
+
static readonly kind: string;
|
|
254
|
+
constructor(message: string, details?: ErrorDetails, code?: ErrorCode);
|
|
255
|
+
}
|
|
256
|
+
interface InstrumentSuggestion {
|
|
257
|
+
readonly ticker: string;
|
|
258
|
+
readonly name: string | undefined;
|
|
259
|
+
}
|
|
260
|
+
/** No instrument matched, or several did equally well. `suggestions` lists the closest. */
|
|
261
|
+
declare class InstrumentNotFoundError extends NotFoundError {
|
|
262
|
+
static readonly kind = "InstrumentNotFoundError";
|
|
263
|
+
readonly query: string;
|
|
264
|
+
readonly suggestions: readonly InstrumentSuggestion[];
|
|
265
|
+
constructor(message: string, details: ErrorDetails & {
|
|
266
|
+
query: string;
|
|
267
|
+
suggestions: readonly InstrumentSuggestion[];
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
/** 429, or a client-side wait for budget that would have been longer than allowed. */
|
|
271
|
+
declare class RateLimitError extends Trading212Error {
|
|
272
|
+
static readonly kind = "RateLimitError";
|
|
273
|
+
/** How long to wait before the next try. */
|
|
274
|
+
readonly retryAfterMs: number | undefined;
|
|
275
|
+
/** When the budget resets. */
|
|
276
|
+
readonly resetAt: Date | undefined;
|
|
277
|
+
constructor(message: string, details: ErrorDetails & {
|
|
278
|
+
retryAfterMs?: number;
|
|
279
|
+
resetAt?: number;
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/** The request took too long: a 408 from Trading 212, or the client's own `timeoutMs`. */
|
|
283
|
+
declare class TimeoutError extends Trading212Error {
|
|
284
|
+
static readonly kind = "TimeoutError";
|
|
285
|
+
constructor(message: string, details?: ErrorDetails);
|
|
286
|
+
}
|
|
287
|
+
/** An order, cancellation or pie change may or may not have happened. Check `orders.list()` before resending. */
|
|
288
|
+
declare class OrderOutcomeUnknownError extends Trading212Error {
|
|
289
|
+
static readonly kind = "OrderOutcomeUnknownError";
|
|
290
|
+
/** What was sent, so it can be looked for. */
|
|
291
|
+
readonly sent: unknown;
|
|
292
|
+
constructor(message: string, details: ErrorDetails & {
|
|
293
|
+
sent?: unknown;
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
/** A trade was refused before sending because trading is off for this client, the default on live. */
|
|
297
|
+
declare class TradingDisabledError extends Trading212Error {
|
|
298
|
+
static readonly kind = "TradingDisabledError";
|
|
299
|
+
constructor(message: string, details?: ErrorDetails);
|
|
300
|
+
}
|
|
301
|
+
/** The connection failed. `sent` is false when it failed before reaching Trading 212, such as a DNS failure. */
|
|
302
|
+
declare class NetworkError extends Trading212Error {
|
|
303
|
+
static readonly kind = "NetworkError";
|
|
304
|
+
readonly sent: boolean;
|
|
305
|
+
constructor(message: string, details: ErrorDetails & {
|
|
306
|
+
sent: boolean;
|
|
307
|
+
});
|
|
308
|
+
}
|
|
309
|
+
/** 5xx: Trading 212 had a problem of its own. */
|
|
310
|
+
declare class ServerError extends Trading212Error {
|
|
311
|
+
static readonly kind = "ServerError";
|
|
312
|
+
constructor(message: string, details?: ErrorDetails);
|
|
313
|
+
}
|
|
314
|
+
/** Any other non-success status. */
|
|
315
|
+
declare class HttpError extends Trading212Error {
|
|
316
|
+
static readonly kind = "HttpError";
|
|
317
|
+
constructor(message: string, details?: ErrorDetails);
|
|
318
|
+
}
|
|
319
|
+
/** A success response this library could not read, or a redirect it refused to follow with your credentials. */
|
|
320
|
+
declare class UnexpectedResponseError extends Trading212Error {
|
|
321
|
+
static readonly kind = "UnexpectedResponseError";
|
|
322
|
+
constructor(message: string, details?: ErrorDetails);
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
type LogLevel = "debug" | "info" | "warn" | "error";
|
|
326
|
+
type LogFields = Record<string, unknown>;
|
|
327
|
+
/**
|
|
328
|
+
* Anything with these four methods. `console` fits as it is; for pino or bunyan, whose methods take the fields
|
|
329
|
+
* first, wrap them with {@link fieldsFirst}.
|
|
330
|
+
*/
|
|
331
|
+
interface Logger {
|
|
332
|
+
debug(message: string, fields?: LogFields): void;
|
|
333
|
+
info(message: string, fields?: LogFields): void;
|
|
334
|
+
warn(message: string, fields?: LogFields): void;
|
|
335
|
+
error(message: string, fields?: LogFields): void;
|
|
336
|
+
}
|
|
337
|
+
/** The default: says nothing. */
|
|
338
|
+
declare const silentLogger: Logger;
|
|
339
|
+
/** The console methods `consoleLogger` writes to. */
|
|
340
|
+
interface ConsoleLike {
|
|
341
|
+
debug(...args: unknown[]): void;
|
|
342
|
+
info(...args: unknown[]): void;
|
|
343
|
+
warn(...args: unknown[]): void;
|
|
344
|
+
error(...args: unknown[]): void;
|
|
345
|
+
}
|
|
346
|
+
/**
|
|
347
|
+
* Writes one line per event, such as `[trading212] WARN Retrying GET … in 500 ms. endpoint=getAccountSummary`, and
|
|
348
|
+
* drops anything below `level` (default `info`).
|
|
349
|
+
*/
|
|
350
|
+
declare function consoleLogger(options?: {
|
|
351
|
+
level?: LogLevel;
|
|
352
|
+
console?: ConsoleLike;
|
|
353
|
+
}): Logger;
|
|
354
|
+
/** A pino- or bunyan-style log method. */
|
|
355
|
+
type FieldsFirstMethod = (fields: LogFields, message: string) => void;
|
|
356
|
+
/** Adapts a pino- or bunyan-style logger, whose methods take `(fields, message)`. */
|
|
357
|
+
declare function fieldsFirst(target: {
|
|
358
|
+
debug: FieldsFirstMethod;
|
|
359
|
+
info: FieldsFirstMethod;
|
|
360
|
+
warn: FieldsFirstMethod;
|
|
361
|
+
error: FieldsFirstMethod;
|
|
362
|
+
}): Logger;
|
|
363
|
+
|
|
364
|
+
type Redactor = (value: unknown) => unknown;
|
|
365
|
+
|
|
366
|
+
interface RequestEvent {
|
|
367
|
+
readonly endpoint: string;
|
|
368
|
+
readonly method: string;
|
|
369
|
+
readonly path: string;
|
|
370
|
+
readonly attempt: number;
|
|
371
|
+
}
|
|
372
|
+
interface ResponseEvent extends RequestEvent {
|
|
373
|
+
readonly status: number;
|
|
374
|
+
readonly durationMs: number;
|
|
375
|
+
readonly rateLimit: RateLimitInfo | undefined;
|
|
376
|
+
}
|
|
377
|
+
interface RetryEvent extends RequestEvent {
|
|
378
|
+
readonly delayMs: number;
|
|
379
|
+
readonly error: Trading212Error;
|
|
380
|
+
}
|
|
381
|
+
interface RateLimitWaitEvent {
|
|
382
|
+
readonly endpoint: string;
|
|
383
|
+
readonly waitMs: number;
|
|
384
|
+
}
|
|
385
|
+
/** Callbacks for metrics and tracing. They receive no credentials, and an exception in one is ignored. */
|
|
386
|
+
interface Hooks {
|
|
387
|
+
onRequest?(event: RequestEvent): void;
|
|
388
|
+
onResponse?(event: ResponseEvent): void;
|
|
389
|
+
onRetry?(event: RetryEvent): void;
|
|
390
|
+
onRateLimitWait?(event: RateLimitWaitEvent): void;
|
|
391
|
+
}
|
|
392
|
+
type FetchLike = (input: string, init: RequestInit) => Promise<Response>;
|
|
393
|
+
interface TransportConfig {
|
|
394
|
+
readonly environment: Environment;
|
|
395
|
+
readonly origin: string;
|
|
396
|
+
readonly authorization: string;
|
|
397
|
+
readonly fetch: FetchLike;
|
|
398
|
+
readonly timeoutMs: number;
|
|
399
|
+
readonly retry: ResolvedRetry | null;
|
|
400
|
+
readonly rateLimiter: RateLimiter;
|
|
401
|
+
readonly maxRateLimitWaitMs: number;
|
|
402
|
+
readonly logger: Logger;
|
|
403
|
+
readonly hooks: Hooks;
|
|
404
|
+
readonly redact: Redactor;
|
|
405
|
+
/** For success bodies: removes the credentials without touching text that only looks like one. */
|
|
406
|
+
readonly removeSecrets: (text: string) => string;
|
|
407
|
+
readonly userAgent: string;
|
|
408
|
+
readonly trading: "enabled" | "disabled";
|
|
409
|
+
}
|
|
410
|
+
interface CallOptions {
|
|
411
|
+
/** Cancels the call. A trade aborted after it was sent throws `OrderOutcomeUnknownError`. */
|
|
412
|
+
signal?: AbortSignal;
|
|
413
|
+
/** Overrides the client's `timeoutMs` for this call. */
|
|
414
|
+
timeoutMs?: number;
|
|
415
|
+
}
|
|
416
|
+
interface RequestOptions extends CallOptions {
|
|
417
|
+
params?: Record<string, string | number>;
|
|
418
|
+
query?: Record<string, string | number | boolean | undefined>;
|
|
419
|
+
/** An already-validated query string, used to follow pagination. */
|
|
420
|
+
rawQuery?: string;
|
|
421
|
+
body?: unknown;
|
|
422
|
+
/** The endpoint always answers with a body, so an empty success is an error. */
|
|
423
|
+
expectBody?: boolean;
|
|
424
|
+
}
|
|
425
|
+
interface TransportResponse<T> {
|
|
426
|
+
readonly data: T;
|
|
427
|
+
readonly status: number;
|
|
428
|
+
readonly rateLimit: RateLimitInfo | undefined;
|
|
429
|
+
}
|
|
430
|
+
/** Sends every request the client makes: authentication, budget, timeouts, retries, logging and errors. */
|
|
431
|
+
declare class Transport {
|
|
432
|
+
#private;
|
|
433
|
+
constructor(config: TransportConfig);
|
|
434
|
+
get origin(): string;
|
|
435
|
+
get tradingEnabled(): boolean;
|
|
436
|
+
rateLimitSnapshot(): Record<string, EndpointBudget>;
|
|
437
|
+
/** Builds a request's URL and description without sending it. */
|
|
438
|
+
describe(endpoint: EndpointDefinition, options?: RequestOptions): RequestDescription & {
|
|
439
|
+
url: string;
|
|
440
|
+
};
|
|
441
|
+
request<T>(endpoint: EndpointDefinition, given?: RequestOptions): Promise<TransportResponse<T>>;
|
|
442
|
+
}
|
|
443
|
+
|
|
444
|
+
interface Trading212Options {
|
|
445
|
+
/** Required, with no default: `demo` for paper trading or `live` for real money. */
|
|
446
|
+
environment: Environment;
|
|
447
|
+
/** The API key from the Trading 212 app, under Settings > API (Beta). */
|
|
448
|
+
apiKey: string;
|
|
449
|
+
/** The secret shown once when the key was made. */
|
|
450
|
+
apiSecret: string;
|
|
451
|
+
/**
|
|
452
|
+
* Whether this client may place or cancel orders and change pies. Defaults to `enabled` on Trading 212's demo host and
|
|
453
|
+
* `disabled` everywhere else, so a live client, or one behind a custom `baseUrl`, only reads until you say otherwise.
|
|
454
|
+
* `disabled` is honoured on demo too.
|
|
455
|
+
*/
|
|
456
|
+
trading?: "enabled" | "disabled";
|
|
457
|
+
/** Per-request timeout. Default 15 s. */
|
|
458
|
+
timeoutMs?: number;
|
|
459
|
+
/** How reads are retried, or `false` for never. Trades are never retried. */
|
|
460
|
+
retry?: RetryOptions | false;
|
|
461
|
+
/** How to stay within Trading 212's per-endpoint limits. Default `pace`. */
|
|
462
|
+
rateLimit?: RateLimitMode;
|
|
463
|
+
/** The longest the client will wait for rate-limit budget before throwing `RateLimitError`. Default 60 s. */
|
|
464
|
+
maxRateLimitWaitMs?: number;
|
|
465
|
+
/** Where to send log lines. Default: nowhere. Every field is redacted first. */
|
|
466
|
+
logger?: Logger;
|
|
467
|
+
/** Callbacks for metrics and tracing. */
|
|
468
|
+
hooks?: Hooks;
|
|
469
|
+
/** Where to keep the instrument and exchange lists. Default: in memory, per client. */
|
|
470
|
+
cache?: CacheStore;
|
|
471
|
+
/** How long the instrument and exchange lists are kept. Default 1 hour; Trading 212 refreshes them every 10 minutes. */
|
|
472
|
+
metadataTtlMs?: number;
|
|
473
|
+
/** A `fetch` to use instead of the global one, for proxies and tests. */
|
|
474
|
+
fetch?: FetchLike;
|
|
475
|
+
/** Only for tests and proxies: must be `https://`, or `http://localhost`. */
|
|
476
|
+
baseUrl?: string;
|
|
477
|
+
/** Appended to the `User-Agent` this client sends. */
|
|
478
|
+
userAgent?: string;
|
|
479
|
+
/**
|
|
480
|
+
* The client refuses to start in a browser, because Trading 212 rejects browser requests and a key in a page is
|
|
481
|
+
* public. Set this only if you understand both.
|
|
482
|
+
*/
|
|
483
|
+
dangerouslyAllowBrowser?: boolean;
|
|
484
|
+
}
|
|
485
|
+
type EnvSource = Record<string, string | undefined>;
|
|
486
|
+
|
|
487
|
+
declare const SPEC_VERSION = "v0";
|
|
488
|
+
declare const DEFINITIONS: {
|
|
489
|
+
readonly cancelOrder: {
|
|
490
|
+
readonly id: "cancelOrder";
|
|
491
|
+
readonly method: "DELETE";
|
|
492
|
+
readonly path: "/api/v0/equity/orders/{id}";
|
|
493
|
+
readonly scope: "orders:execute";
|
|
494
|
+
readonly rateLimit: {
|
|
495
|
+
readonly requests: 50;
|
|
496
|
+
readonly periodMs: 60000;
|
|
497
|
+
};
|
|
498
|
+
readonly kind: "trade";
|
|
499
|
+
readonly deprecated: false;
|
|
500
|
+
readonly summary: "Cancel a pending order";
|
|
501
|
+
};
|
|
502
|
+
readonly createPie: {
|
|
503
|
+
readonly id: "createPie";
|
|
504
|
+
readonly method: "POST";
|
|
505
|
+
readonly path: "/api/v0/equity/pies";
|
|
506
|
+
readonly scope: "pies:write";
|
|
507
|
+
readonly rateLimit: {
|
|
508
|
+
readonly requests: 1;
|
|
509
|
+
readonly periodMs: 5000;
|
|
510
|
+
};
|
|
511
|
+
readonly kind: "trade";
|
|
512
|
+
readonly deprecated: true;
|
|
513
|
+
readonly summary: "Create pie";
|
|
514
|
+
};
|
|
515
|
+
readonly deletePie: {
|
|
516
|
+
readonly id: "deletePie";
|
|
517
|
+
readonly method: "DELETE";
|
|
518
|
+
readonly path: "/api/v0/equity/pies/{id}";
|
|
519
|
+
readonly scope: "pies:write";
|
|
520
|
+
readonly rateLimit: {
|
|
521
|
+
readonly requests: 1;
|
|
522
|
+
readonly periodMs: 5000;
|
|
523
|
+
};
|
|
524
|
+
readonly kind: "trade";
|
|
525
|
+
readonly deprecated: true;
|
|
526
|
+
readonly summary: "Delete pie";
|
|
527
|
+
};
|
|
528
|
+
readonly duplicatePie: {
|
|
529
|
+
readonly id: "duplicatePie";
|
|
530
|
+
readonly method: "POST";
|
|
531
|
+
readonly path: "/api/v0/equity/pies/{id}/duplicate";
|
|
532
|
+
readonly scope: "pies:write";
|
|
533
|
+
readonly rateLimit: {
|
|
534
|
+
readonly requests: 1;
|
|
535
|
+
readonly periodMs: 5000;
|
|
536
|
+
};
|
|
537
|
+
readonly kind: "trade";
|
|
538
|
+
readonly deprecated: true;
|
|
539
|
+
readonly summary: "Duplicate pie";
|
|
540
|
+
};
|
|
541
|
+
readonly getAccountSummary: {
|
|
542
|
+
readonly id: "getAccountSummary";
|
|
543
|
+
readonly method: "GET";
|
|
544
|
+
readonly path: "/api/v0/equity/account/summary";
|
|
545
|
+
readonly scope: "account";
|
|
546
|
+
readonly rateLimit: {
|
|
547
|
+
readonly requests: 1;
|
|
548
|
+
readonly periodMs: 5000;
|
|
549
|
+
};
|
|
550
|
+
readonly kind: "read";
|
|
551
|
+
readonly deprecated: false;
|
|
552
|
+
readonly summary: "Get account summary";
|
|
553
|
+
};
|
|
554
|
+
readonly getOrder: {
|
|
555
|
+
readonly id: "getOrder";
|
|
556
|
+
readonly method: "GET";
|
|
557
|
+
readonly path: "/api/v0/equity/orders/{id}";
|
|
558
|
+
readonly scope: "orders:read";
|
|
559
|
+
readonly rateLimit: {
|
|
560
|
+
readonly requests: 1;
|
|
561
|
+
readonly periodMs: 1000;
|
|
562
|
+
};
|
|
563
|
+
readonly kind: "read";
|
|
564
|
+
readonly deprecated: false;
|
|
565
|
+
readonly summary: "Get a pending order by ID";
|
|
566
|
+
};
|
|
567
|
+
readonly getPie: {
|
|
568
|
+
readonly id: "getPie";
|
|
569
|
+
readonly method: "GET";
|
|
570
|
+
readonly path: "/api/v0/equity/pies/{id}";
|
|
571
|
+
readonly scope: "pies:read";
|
|
572
|
+
readonly rateLimit: {
|
|
573
|
+
readonly requests: 1;
|
|
574
|
+
readonly periodMs: 5000;
|
|
575
|
+
};
|
|
576
|
+
readonly kind: "read";
|
|
577
|
+
readonly deprecated: true;
|
|
578
|
+
readonly summary: "Fetch a pie";
|
|
579
|
+
};
|
|
580
|
+
readonly listDividends: {
|
|
581
|
+
readonly id: "listDividends";
|
|
582
|
+
readonly method: "GET";
|
|
583
|
+
readonly path: "/api/v0/equity/history/dividends";
|
|
584
|
+
readonly scope: "history:dividends";
|
|
585
|
+
readonly rateLimit: {
|
|
586
|
+
readonly requests: 20;
|
|
587
|
+
readonly periodMs: 60000;
|
|
588
|
+
};
|
|
589
|
+
readonly kind: "read";
|
|
590
|
+
readonly deprecated: false;
|
|
591
|
+
readonly summary: "Get paid out dividends";
|
|
592
|
+
};
|
|
593
|
+
readonly listExchanges: {
|
|
594
|
+
readonly id: "listExchanges";
|
|
595
|
+
readonly method: "GET";
|
|
596
|
+
readonly path: "/api/v0/equity/metadata/exchanges";
|
|
597
|
+
readonly scope: "metadata";
|
|
598
|
+
readonly rateLimit: {
|
|
599
|
+
readonly requests: 1;
|
|
600
|
+
readonly periodMs: 30000;
|
|
601
|
+
};
|
|
602
|
+
readonly kind: "read";
|
|
603
|
+
readonly deprecated: false;
|
|
604
|
+
readonly summary: "Get exchanges metadata";
|
|
605
|
+
};
|
|
606
|
+
readonly listHistoricalOrders: {
|
|
607
|
+
readonly id: "listHistoricalOrders";
|
|
608
|
+
readonly method: "GET";
|
|
609
|
+
readonly path: "/api/v0/equity/history/orders";
|
|
610
|
+
readonly scope: "history:orders";
|
|
611
|
+
readonly rateLimit: {
|
|
612
|
+
readonly requests: 20;
|
|
613
|
+
readonly periodMs: 60000;
|
|
614
|
+
};
|
|
615
|
+
readonly kind: "read";
|
|
616
|
+
readonly deprecated: false;
|
|
617
|
+
readonly summary: "Get historical orders data";
|
|
618
|
+
};
|
|
619
|
+
readonly listInstruments: {
|
|
620
|
+
readonly id: "listInstruments";
|
|
621
|
+
readonly method: "GET";
|
|
622
|
+
readonly path: "/api/v0/equity/metadata/instruments";
|
|
623
|
+
readonly scope: "metadata";
|
|
624
|
+
readonly rateLimit: {
|
|
625
|
+
readonly requests: 1;
|
|
626
|
+
readonly periodMs: 50000;
|
|
627
|
+
};
|
|
628
|
+
readonly kind: "read";
|
|
629
|
+
readonly deprecated: false;
|
|
630
|
+
readonly summary: "Get all available instruments";
|
|
631
|
+
};
|
|
632
|
+
readonly listOrders: {
|
|
633
|
+
readonly id: "listOrders";
|
|
634
|
+
readonly method: "GET";
|
|
635
|
+
readonly path: "/api/v0/equity/orders";
|
|
636
|
+
readonly scope: "orders:read";
|
|
637
|
+
readonly rateLimit: {
|
|
638
|
+
readonly requests: 1;
|
|
639
|
+
readonly periodMs: 5000;
|
|
640
|
+
};
|
|
641
|
+
readonly kind: "read";
|
|
642
|
+
readonly deprecated: false;
|
|
643
|
+
readonly summary: "Get all pending orders";
|
|
644
|
+
};
|
|
645
|
+
readonly listPies: {
|
|
646
|
+
readonly id: "listPies";
|
|
647
|
+
readonly method: "GET";
|
|
648
|
+
readonly path: "/api/v0/equity/pies";
|
|
649
|
+
readonly scope: "pies:read";
|
|
650
|
+
readonly rateLimit: {
|
|
651
|
+
readonly requests: 1;
|
|
652
|
+
readonly periodMs: 30000;
|
|
653
|
+
};
|
|
654
|
+
readonly kind: "read";
|
|
655
|
+
readonly deprecated: true;
|
|
656
|
+
readonly summary: "Fetch all pies";
|
|
657
|
+
};
|
|
658
|
+
readonly listPositions: {
|
|
659
|
+
readonly id: "listPositions";
|
|
660
|
+
readonly method: "GET";
|
|
661
|
+
readonly path: "/api/v0/equity/positions";
|
|
662
|
+
readonly scope: "portfolio";
|
|
663
|
+
readonly rateLimit: {
|
|
664
|
+
readonly requests: 1;
|
|
665
|
+
readonly periodMs: 1000;
|
|
666
|
+
};
|
|
667
|
+
readonly kind: "read";
|
|
668
|
+
readonly deprecated: false;
|
|
669
|
+
readonly summary: "Fetch all open positions";
|
|
670
|
+
};
|
|
671
|
+
readonly listReports: {
|
|
672
|
+
readonly id: "listReports";
|
|
673
|
+
readonly method: "GET";
|
|
674
|
+
readonly path: "/api/v0/equity/history/exports";
|
|
675
|
+
readonly scope: null;
|
|
676
|
+
readonly rateLimit: {
|
|
677
|
+
readonly requests: 1;
|
|
678
|
+
readonly periodMs: 60000;
|
|
679
|
+
};
|
|
680
|
+
readonly kind: "read";
|
|
681
|
+
readonly deprecated: false;
|
|
682
|
+
readonly summary: "List generated reports";
|
|
683
|
+
};
|
|
684
|
+
readonly listTransactions: {
|
|
685
|
+
readonly id: "listTransactions";
|
|
686
|
+
readonly method: "GET";
|
|
687
|
+
readonly path: "/api/v0/equity/history/transactions";
|
|
688
|
+
readonly scope: "history:transactions";
|
|
689
|
+
readonly rateLimit: {
|
|
690
|
+
readonly requests: 20;
|
|
691
|
+
readonly periodMs: 60000;
|
|
692
|
+
};
|
|
693
|
+
readonly kind: "read";
|
|
694
|
+
readonly deprecated: false;
|
|
695
|
+
readonly summary: "Get transactions";
|
|
696
|
+
};
|
|
697
|
+
readonly placeLimitOrder: {
|
|
698
|
+
readonly id: "placeLimitOrder";
|
|
699
|
+
readonly method: "POST";
|
|
700
|
+
readonly path: "/api/v0/equity/orders/limit";
|
|
701
|
+
readonly scope: "orders:execute";
|
|
702
|
+
readonly rateLimit: {
|
|
703
|
+
readonly requests: 1;
|
|
704
|
+
readonly periodMs: 2000;
|
|
705
|
+
};
|
|
706
|
+
readonly kind: "trade";
|
|
707
|
+
readonly deprecated: false;
|
|
708
|
+
readonly summary: "Place a Limit order";
|
|
709
|
+
};
|
|
710
|
+
readonly placeMarketOrder: {
|
|
711
|
+
readonly id: "placeMarketOrder";
|
|
712
|
+
readonly method: "POST";
|
|
713
|
+
readonly path: "/api/v0/equity/orders/market";
|
|
714
|
+
readonly scope: "orders:execute";
|
|
715
|
+
readonly rateLimit: {
|
|
716
|
+
readonly requests: 50;
|
|
717
|
+
readonly periodMs: 60000;
|
|
718
|
+
};
|
|
719
|
+
readonly kind: "trade";
|
|
720
|
+
readonly deprecated: false;
|
|
721
|
+
readonly summary: "Place a Market order";
|
|
722
|
+
};
|
|
723
|
+
readonly placeStopLimitOrder: {
|
|
724
|
+
readonly id: "placeStopLimitOrder";
|
|
725
|
+
readonly method: "POST";
|
|
726
|
+
readonly path: "/api/v0/equity/orders/stop_limit";
|
|
727
|
+
readonly scope: "orders:execute";
|
|
728
|
+
readonly rateLimit: {
|
|
729
|
+
readonly requests: 1;
|
|
730
|
+
readonly periodMs: 2000;
|
|
731
|
+
};
|
|
732
|
+
readonly kind: "trade";
|
|
733
|
+
readonly deprecated: false;
|
|
734
|
+
readonly summary: "Place a StopLimit order";
|
|
735
|
+
};
|
|
736
|
+
readonly placeStopOrder: {
|
|
737
|
+
readonly id: "placeStopOrder";
|
|
738
|
+
readonly method: "POST";
|
|
739
|
+
readonly path: "/api/v0/equity/orders/stop";
|
|
740
|
+
readonly scope: "orders:execute";
|
|
741
|
+
readonly rateLimit: {
|
|
742
|
+
readonly requests: 1;
|
|
743
|
+
readonly periodMs: 2000;
|
|
744
|
+
};
|
|
745
|
+
readonly kind: "trade";
|
|
746
|
+
readonly deprecated: false;
|
|
747
|
+
readonly summary: "Place a Stop order";
|
|
748
|
+
};
|
|
749
|
+
readonly requestReport: {
|
|
750
|
+
readonly id: "requestReport";
|
|
751
|
+
readonly method: "POST";
|
|
752
|
+
readonly path: "/api/v0/equity/history/exports";
|
|
753
|
+
readonly scope: null;
|
|
754
|
+
readonly rateLimit: {
|
|
755
|
+
readonly requests: 1;
|
|
756
|
+
readonly periodMs: 30000;
|
|
757
|
+
};
|
|
758
|
+
readonly kind: "write";
|
|
759
|
+
readonly deprecated: false;
|
|
760
|
+
readonly summary: "Request a CSV report";
|
|
761
|
+
};
|
|
762
|
+
readonly updatePie: {
|
|
763
|
+
readonly id: "updatePie";
|
|
764
|
+
readonly method: "POST";
|
|
765
|
+
readonly path: "/api/v0/equity/pies/{id}";
|
|
766
|
+
readonly scope: "pies:write";
|
|
767
|
+
readonly rateLimit: {
|
|
768
|
+
readonly requests: 1;
|
|
769
|
+
readonly periodMs: 5000;
|
|
770
|
+
};
|
|
771
|
+
readonly kind: "trade";
|
|
772
|
+
readonly deprecated: true;
|
|
773
|
+
readonly summary: "Update pie";
|
|
774
|
+
};
|
|
775
|
+
};
|
|
776
|
+
/** Every endpoint in the spec, frozen so nothing at run time can turn a trade into a read. */
|
|
777
|
+
declare const ENDPOINTS: typeof DEFINITIONS;
|
|
778
|
+
type EndpointId = keyof typeof ENDPOINTS;
|
|
779
|
+
|
|
780
|
+
interface AccountBucketDetailedResponse {
|
|
781
|
+
/** ISO 8601 date and time. */
|
|
782
|
+
creationDate?: string | null;
|
|
783
|
+
dividendCashAction?: "REINVEST" | "TO_ACCOUNT_CASH" | (string & {}) | null;
|
|
784
|
+
/** ISO 8601 date and time. */
|
|
785
|
+
endDate?: string | null;
|
|
786
|
+
goal?: number | null;
|
|
787
|
+
icon?: string | null;
|
|
788
|
+
/** 64-bit integer. */
|
|
789
|
+
id?: number | null;
|
|
790
|
+
initialInvestment?: number | null;
|
|
791
|
+
instrumentShares?: Record<string, number> | null;
|
|
792
|
+
name?: string | null;
|
|
793
|
+
publicUrl?: string | null;
|
|
794
|
+
}
|
|
795
|
+
interface AccountBucketInstrumentResult {
|
|
796
|
+
currentShare?: number | null;
|
|
797
|
+
expectedShare?: number | null;
|
|
798
|
+
issues?: InstrumentIssue[] | null;
|
|
799
|
+
ownedQuantity?: number | null;
|
|
800
|
+
result?: InvestmentResult | null;
|
|
801
|
+
ticker?: string | null;
|
|
802
|
+
}
|
|
803
|
+
interface AccountBucketInstrumentsDetailedResponse {
|
|
804
|
+
instruments?: AccountBucketInstrumentResult[] | null;
|
|
805
|
+
settings?: AccountBucketDetailedResponse | null;
|
|
806
|
+
}
|
|
807
|
+
interface AccountBucketResultResponse {
|
|
808
|
+
/** Amount of money put into the pie in account currency */
|
|
809
|
+
cash?: number | null;
|
|
810
|
+
dividendDetails?: DividendDetails | null;
|
|
811
|
+
/** 64-bit integer. */
|
|
812
|
+
id?: number | null;
|
|
813
|
+
/** Progress of the pie based on the set goal */
|
|
814
|
+
progress?: number | null;
|
|
815
|
+
result?: InvestmentResult | null;
|
|
816
|
+
/** Status of the pie based on the set goal */
|
|
817
|
+
status?: "AHEAD" | "ON_TRACK" | "BEHIND" | (string & {}) | null;
|
|
818
|
+
}
|
|
819
|
+
interface AccountSummary {
|
|
820
|
+
cash?: Cash | null;
|
|
821
|
+
/** Primary account currency in ISO 4217 format. */
|
|
822
|
+
currency?: string | null;
|
|
823
|
+
/** Primary trading account number. This is the same account ID you would see in the Trading 212 web or mobile application. */
|
|
824
|
+
id?: number | null;
|
|
825
|
+
investments?: Investments | null;
|
|
826
|
+
/** Investments value in your account's primary currency. */
|
|
827
|
+
totalValue?: number | null;
|
|
828
|
+
}
|
|
829
|
+
interface Cash {
|
|
830
|
+
/** Funds available for investing. */
|
|
831
|
+
availableToTrade?: number | null;
|
|
832
|
+
/** It’s the sum of the cash inside of all pies that is not yet invested. */
|
|
833
|
+
inPies?: number | null;
|
|
834
|
+
/** The amount of cash reserved for pending orders. This cash is not available for placing new trades. */
|
|
835
|
+
reservedForOrders?: number | null;
|
|
836
|
+
}
|
|
837
|
+
interface DividendDetails {
|
|
838
|
+
gained?: number | null;
|
|
839
|
+
inCash?: number | null;
|
|
840
|
+
reinvested?: number | null;
|
|
841
|
+
}
|
|
842
|
+
interface DuplicateBucketRequest {
|
|
843
|
+
icon?: string | null;
|
|
844
|
+
name?: string | null;
|
|
845
|
+
}
|
|
846
|
+
interface EnqueuedReportResponse {
|
|
847
|
+
/** 64-bit integer. */
|
|
848
|
+
reportId?: number | null;
|
|
849
|
+
}
|
|
850
|
+
interface Exchange {
|
|
851
|
+
/** 64-bit integer. */
|
|
852
|
+
id?: number | null;
|
|
853
|
+
name?: string | null;
|
|
854
|
+
workingSchedules?: WorkingSchedule[] | null;
|
|
855
|
+
}
|
|
856
|
+
interface Fill {
|
|
857
|
+
/** ISO 8601 date and time. */
|
|
858
|
+
filledAt?: string | null;
|
|
859
|
+
/** 64-bit integer. */
|
|
860
|
+
id?: number | null;
|
|
861
|
+
price?: number | null;
|
|
862
|
+
quantity?: number | null;
|
|
863
|
+
tradingMethod?: "TOTV" | "OTC" | (string & {}) | null;
|
|
864
|
+
type?: "TRADE" | "STOCK_SPLIT" | "STOCK_DISTRIBUTION" | "FOP" | "FOP_CORRECTION" | "CUSTOM_STOCK_DISTRIBUTION" | "EQUITY_RIGHTS" | "SCRIP_STOCK_DIVIDENDS" | "STOCK_DIVIDENDS" | "STOCK_ACQUISITION" | "CASH_AND_STOCK_ACQUISITION" | "SPIN_OFF" | (string & {}) | null;
|
|
865
|
+
walletImpact?: FillWalletImpact | null;
|
|
866
|
+
}
|
|
867
|
+
interface FillWalletImpact {
|
|
868
|
+
currency?: string | null;
|
|
869
|
+
fxRate?: number | null;
|
|
870
|
+
netValue?: number | null;
|
|
871
|
+
realisedProfitLoss?: number | null;
|
|
872
|
+
taxes?: Tax[] | null;
|
|
873
|
+
}
|
|
874
|
+
interface HistoricalOrder {
|
|
875
|
+
fill?: Fill | null;
|
|
876
|
+
order?: Order | null;
|
|
877
|
+
}
|
|
878
|
+
interface HistoryDividendItem {
|
|
879
|
+
/** In account's primary currency. */
|
|
880
|
+
amount?: number | null;
|
|
881
|
+
amountInEuro?: number | null;
|
|
882
|
+
/** The account's primary currency. */
|
|
883
|
+
currency?: string | null;
|
|
884
|
+
/** In instrument currency */
|
|
885
|
+
grossAmountPerShare?: number | null;
|
|
886
|
+
instrument?: Instrument$1 | null;
|
|
887
|
+
/** ISO 8601 date and time. */
|
|
888
|
+
paidOn?: string | null;
|
|
889
|
+
quantity?: number | null;
|
|
890
|
+
reference?: string | null;
|
|
891
|
+
ticker?: string | null;
|
|
892
|
+
tickerCurrency?: string | null;
|
|
893
|
+
type?: "ORDINARY" | "BONUS" | "PROPERTY_INCOME" | "RETURN_OF_CAPITAL_NON_US" | "DEMERGER" | "INTEREST" | "CAPITAL_GAINS_DISTRIBUTION_NON_US" | "INTERIM_LIQUIDATION" | "ORDINARY_MANUFACTURED_PAYMENT" | "BONUS_MANUFACTURED_PAYMENT" | "PROPERTY_INCOME_MANUFACTURED_PAYMENT" | "RETURN_OF_CAPITAL_NON_US_MANUFACTURED_PAYMENT" | "DEMERGER_MANUFACTURED_PAYMENT" | "INTEREST_MANUFACTURED_PAYMENT" | "CAPITAL_GAINS_DISTRIBUTION_NON_US_MANUFACTURED_PAYMENT" | "INTERIM_LIQUIDATION_MANUFACTURED_PAYMENT" | "INTEREST_PAID_BY_US_OBLIGORS" | "INTEREST_PAID_BY_FOREIGN_CORPORATIONS" | "DIVIDENDS_PAID_BY_US_CORPORATIONS" | "DIVIDENDS_PAID_BY_FOREIGN_CORPORATIONS" | "CAPITAL_GAINS" | "REAL_PROPERTY_INCOME_AND_NATURAL_RESOURCES_ROYALTIES" | "OTHER_INCOME" | "QUALIFIED_INVESTMENT_ENTITY" | "TRUST_DISTRIBUTION" | "PUBLICLY_TRADED_PARTNERSHIP_DISTRIBUTION" | "CAPITAL_GAINS_DISTRIBUTION" | "RETURN_OF_CAPITAL" | "OTHER_DIVIDEND_EQUIVALENT" | "TAX_EVENT_1446F_FOR_PUBLICLY_TRADED_SECURITIES" | "PTP_UNCHARACTERISED_INCOME" | "MULTIPLE_1042S_TAX_COMPONENTS" | "DIVIDEND" | "SHORT_TERM_CAPITAL_GAINS" | "LONG_TERM_CAPITAL_GAINS" | "PROPERTY_INCOME_DISTRIBUTION" | "TAX_EXEMPTED" | "INTEREST_PAID_BY_US_OBLIGORS_MANUFACTURED_PAYMENT" | "INTEREST_PAID_BY_FOREIGN_CORPORATIONS_MANUFACTURED_PAYMENT" | "DIVIDENDS_PAID_BY_US_CORPORATIONS_MANUFACTURED_PAYMENT" | "DIVIDENDS_PAID_BY_FOREIGN_CORPORATIONS_MANUFACTURED_PAYMENT" | "CAPITAL_GAINS_MANUFACTURED_PAYMENT" | "REAL_PROPERTY_INCOME_AND_NATURAL_RESOURCES_ROYALTIES_MANUFACTURED_PAYMENT" | "OTHER_INCOME_MANUFACTURED_PAYMENT" | "QUALIFIED_INVESTMENT_ENTITY_MANUFACTURED_PAYMENT" | "TRUST_DISTRIBUTION_MANUFACTURED_PAYMENT" | "PUBLICLY_TRADED_PARTNERSHIP_DISTRIBUTION_MANUFACTURED_PAYMENT" | "CAPITAL_GAINS_DISTRIBUTION_MANUFACTURED_PAYMENT" | "RETURN_OF_CAPITAL_MANUFACTURED_PAYMENT" | "OTHER_DIVIDEND_EQUIVALENT_MANUFACTURED_PAYMENT" | "TAX_EVENT_1446F_FOR_PUBLICLY_TRADED_SECURITIES_MANUFACTURED_PAYMENT" | "PTP_UNCHARACTERISED_INCOME_MANUFACTURED_PAYMENT" | "MULTIPLE_1042S_TAX_COMPONENTS_MANUFACTURED_PAYMENT" | "DIVIDEND_MANUFACTURED_PAYMENT" | "SHORT_TERM_CAPITAL_GAINS_MANUFACTURED_PAYMENT" | "LONG_TERM_CAPITAL_GAINS_MANUFACTURED_PAYMENT" | "PROPERTY_INCOME_DISTRIBUTION_MANUFACTURED_PAYMENT" | "TAX_EXEMPTED_MANUFACTURED_PAYMENT" | (string & {}) | null;
|
|
894
|
+
}
|
|
895
|
+
interface HistoryTransactionItem {
|
|
896
|
+
/** Amount in the currency of the transaction */
|
|
897
|
+
amount?: number | null;
|
|
898
|
+
/** Currency of the transaction */
|
|
899
|
+
currency?: string | null;
|
|
900
|
+
/** ISO 8601 date and time. */
|
|
901
|
+
dateTime?: string | null;
|
|
902
|
+
/** ID */
|
|
903
|
+
reference?: string | null;
|
|
904
|
+
type?: "WITHDRAW" | "DEPOSIT" | "FEE" | "TRANSFER" | "INTEREST_ON_FREE_CASH" | "LENDING_INTEREST" | (string & {}) | null;
|
|
905
|
+
}
|
|
906
|
+
/** Instrument information as given by /instruments endpoint. */
|
|
907
|
+
interface Instrument$1 {
|
|
908
|
+
/** Instrument currency in ISO 4217 format. */
|
|
909
|
+
currency?: string | null;
|
|
910
|
+
/** ISIN of the instrument. */
|
|
911
|
+
isin?: string | null;
|
|
912
|
+
/** Name of the instrument. */
|
|
913
|
+
name?: string | null;
|
|
914
|
+
/** Unique instrument identifier. */
|
|
915
|
+
ticker?: string | null;
|
|
916
|
+
}
|
|
917
|
+
interface InstrumentIssue {
|
|
918
|
+
name?: "DELISTED" | "SUSPENDED" | "NO_LONGER_TRADABLE" | "MAX_POSITION_SIZE_REACHED" | "APPROACHING_MAX_POSITION_SIZE" | "COMPLEX_INSTRUMENT_APP_TEST_REQUIRED" | "PRICE_TOO_LOW" | (string & {}) | null;
|
|
919
|
+
severity?: "IRREVERSIBLE" | "REVERSIBLE" | "INFORMATIVE" | (string & {}) | null;
|
|
920
|
+
}
|
|
921
|
+
interface InvestmentResult {
|
|
922
|
+
priceAvgInvestedValue?: number | null;
|
|
923
|
+
priceAvgResult?: number | null;
|
|
924
|
+
priceAvgResultCoef?: number | null;
|
|
925
|
+
priceAvgValue?: number | null;
|
|
926
|
+
}
|
|
927
|
+
interface Investments {
|
|
928
|
+
/** Current value of all the investments. */
|
|
929
|
+
currentValue?: number | null;
|
|
930
|
+
/** The all-time realised profit loss from all of the trades executed. */
|
|
931
|
+
realizedProfitLoss?: number | null;
|
|
932
|
+
/** The cost basis of your current investments. The total amount of funds you've invested in the shares you currently own. */
|
|
933
|
+
totalCost?: number | null;
|
|
934
|
+
/** The potential profit/loss of your current investments, showing how much you could gain or lose if you were to sell them now. */
|
|
935
|
+
unrealizedProfitLoss?: number | null;
|
|
936
|
+
}
|
|
937
|
+
interface LimitRequest {
|
|
938
|
+
limitPrice?: number | null;
|
|
939
|
+
quantity?: number | null;
|
|
940
|
+
ticker?: string | null;
|
|
941
|
+
/** Expiration */
|
|
942
|
+
timeValidity?: TimeValidity | null;
|
|
943
|
+
}
|
|
944
|
+
interface MarketRequest {
|
|
945
|
+
extendedHours?: boolean | null;
|
|
946
|
+
quantity?: number | null;
|
|
947
|
+
ticker?: string | null;
|
|
948
|
+
}
|
|
949
|
+
interface Order {
|
|
950
|
+
/**
|
|
951
|
+
* The ISO 8601 formatted date of when the order was created.
|
|
952
|
+
*
|
|
953
|
+
* ISO 8601 date and time.
|
|
954
|
+
*/
|
|
955
|
+
createdAt?: string | null;
|
|
956
|
+
/** The currency used for the order in ISO 4217 format. */
|
|
957
|
+
currency?: string | null;
|
|
958
|
+
/** If true, the order is eligible for execution outside regular trading hours. */
|
|
959
|
+
extendedHours?: boolean | null;
|
|
960
|
+
/** The number of shares that have been successfully executed. Applicable to quantity orders. */
|
|
961
|
+
filledQuantity?: number | null;
|
|
962
|
+
/** The total monetary value of the executed portion of the order. Applicable to orders placed by value.Note: Placing orders by value is not currently supported via the API but can be done through other Trading 212 platforms. */
|
|
963
|
+
filledValue?: number | null;
|
|
964
|
+
/** A unique, system-generated identifier for the order. */
|
|
965
|
+
id?: number | null;
|
|
966
|
+
/** How the order was initiated. */
|
|
967
|
+
initiatedFrom?: "API" | "IOS" | "ANDROID" | "WEB" | "SYSTEM" | "AUTOINVEST" | "INSTRUMENT_AUTOINVEST" | (string & {}) | null;
|
|
968
|
+
instrument?: Instrument$1 | null;
|
|
969
|
+
/** Applicable to LIMIT and STOP_LIMIT orders. */
|
|
970
|
+
limitPrice?: number | null;
|
|
971
|
+
/** The total number of shares requested. Applicable to quantity orders. */
|
|
972
|
+
quantity?: number | null;
|
|
973
|
+
/** Indicates whether the order is BUY or SELL. */
|
|
974
|
+
side?: "BUY" | "SELL" | (string & {}) | null;
|
|
975
|
+
/** The current state of the order in its lifecycle. */
|
|
976
|
+
status?: "LOCAL" | "UNCONFIRMED" | "CONFIRMED" | "NEW" | "CANCELLING" | "CANCELLED" | "PARTIALLY_FILLED" | "FILLED" | "REJECTED" | "REPLACING" | "REPLACED" | (string & {}) | null;
|
|
977
|
+
/** Applicable to STOP and STOP_LIMIT orders. */
|
|
978
|
+
stopPrice?: number | null;
|
|
979
|
+
/** The strategy used to place the order, either by QUANTITY or VALUE. The API currently only supports placing orders by QUANTITY. */
|
|
980
|
+
strategy?: "QUANTITY" | "VALUE" | (string & {}) | null;
|
|
981
|
+
/** Unique instrument identifier. Get from the /instruments endpoint */
|
|
982
|
+
ticker?: string | null;
|
|
983
|
+
timeInForce?: TimeValidity | null;
|
|
984
|
+
type?: "LIMIT" | "STOP" | "MARKET" | "STOP_LIMIT" | (string & {}) | null;
|
|
985
|
+
/** The total monetary value of the order. Applicable to value orders. */
|
|
986
|
+
value?: number | null;
|
|
987
|
+
}
|
|
988
|
+
interface PaginatedResponseHistoricalOrder {
|
|
989
|
+
items?: HistoricalOrder[] | null;
|
|
990
|
+
nextPagePath?: string | null;
|
|
991
|
+
}
|
|
992
|
+
interface PaginatedResponseHistoryDividendItem {
|
|
993
|
+
items?: HistoryDividendItem[] | null;
|
|
994
|
+
nextPagePath?: string | null;
|
|
995
|
+
}
|
|
996
|
+
interface PaginatedResponseHistoryTransactionItem {
|
|
997
|
+
items?: HistoryTransactionItem[] | null;
|
|
998
|
+
nextPagePath?: string | null;
|
|
999
|
+
}
|
|
1000
|
+
interface PieRequest {
|
|
1001
|
+
dividendCashAction?: "REINVEST" | "TO_ACCOUNT_CASH" | (string & {}) | null;
|
|
1002
|
+
/** ISO 8601 date and time. */
|
|
1003
|
+
endDate?: string | null;
|
|
1004
|
+
/** Total desired value of the pie in account currency */
|
|
1005
|
+
goal?: number | null;
|
|
1006
|
+
icon?: string | null;
|
|
1007
|
+
instrumentShares?: Record<string, number> | null;
|
|
1008
|
+
name?: string | null;
|
|
1009
|
+
}
|
|
1010
|
+
interface Position {
|
|
1011
|
+
/** Average price paid, in instrument currency, per share. */
|
|
1012
|
+
averagePricePaid?: number | null;
|
|
1013
|
+
/**
|
|
1014
|
+
* The ISO 8601 formatted date of when the position was opened.
|
|
1015
|
+
*
|
|
1016
|
+
* ISO 8601 date and time.
|
|
1017
|
+
*/
|
|
1018
|
+
createdAt?: string | null;
|
|
1019
|
+
/** Current price, in instrument currency, of a single share. */
|
|
1020
|
+
currentPrice?: number | null;
|
|
1021
|
+
instrument?: Instrument$1 | null;
|
|
1022
|
+
/** Total quantity of shares owned. */
|
|
1023
|
+
quantity?: number | null;
|
|
1024
|
+
/** Quantity of shares available for trading. */
|
|
1025
|
+
quantityAvailableForTrading?: number | null;
|
|
1026
|
+
/** Quantity of shares currently used in pie. */
|
|
1027
|
+
quantityInPies?: number | null;
|
|
1028
|
+
/** Collects the financial impact of the position on the user's wallet. */
|
|
1029
|
+
walletImpact?: PositionWalletImpact | null;
|
|
1030
|
+
}
|
|
1031
|
+
interface PositionWalletImpact {
|
|
1032
|
+
/** The currency code used to represent all the wallet impact information. */
|
|
1033
|
+
currency?: string | null;
|
|
1034
|
+
/** The current market value of the position. */
|
|
1035
|
+
currentValue?: number | null;
|
|
1036
|
+
/** The positive or negative impact on the position's value due to currency rate changes. Only applies to positions with instrument currency that differs from the accounts. */
|
|
1037
|
+
fxImpact?: number | null;
|
|
1038
|
+
/** The total cost paid for the position. */
|
|
1039
|
+
totalCost?: number | null;
|
|
1040
|
+
/** The unrealized profit & loss for the position. Calculated as currentValue - totalCost. */
|
|
1041
|
+
unrealizedProfitLoss?: number | null;
|
|
1042
|
+
}
|
|
1043
|
+
interface PublicReportRequest {
|
|
1044
|
+
dataIncluded?: ReportDataIncluded | null;
|
|
1045
|
+
/** ISO 8601 date and time. */
|
|
1046
|
+
timeFrom?: string | null;
|
|
1047
|
+
/** ISO 8601 date and time. */
|
|
1048
|
+
timeTo?: string | null;
|
|
1049
|
+
}
|
|
1050
|
+
interface ReportDataIncluded {
|
|
1051
|
+
includeDividends?: boolean | null;
|
|
1052
|
+
includeInterest?: boolean | null;
|
|
1053
|
+
includeOrders?: boolean | null;
|
|
1054
|
+
includeTransactions?: boolean | null;
|
|
1055
|
+
}
|
|
1056
|
+
interface ReportResponse {
|
|
1057
|
+
dataIncluded?: ReportDataIncluded | null;
|
|
1058
|
+
downloadLink?: string | null;
|
|
1059
|
+
/** 64-bit integer. */
|
|
1060
|
+
reportId?: number | null;
|
|
1061
|
+
status?: "Queued" | "Processing" | "Running" | "Canceled" | "Failed" | "Finished" | (string & {}) | null;
|
|
1062
|
+
/** ISO 8601 date and time. */
|
|
1063
|
+
timeFrom?: string | null;
|
|
1064
|
+
/** ISO 8601 date and time. */
|
|
1065
|
+
timeTo?: string | null;
|
|
1066
|
+
}
|
|
1067
|
+
interface StopLimitRequest {
|
|
1068
|
+
limitPrice?: number | null;
|
|
1069
|
+
quantity?: number | null;
|
|
1070
|
+
stopPrice?: number | null;
|
|
1071
|
+
ticker?: string | null;
|
|
1072
|
+
/** Expiration */
|
|
1073
|
+
timeValidity?: TimeValidity | null;
|
|
1074
|
+
}
|
|
1075
|
+
interface StopRequest {
|
|
1076
|
+
quantity?: number | null;
|
|
1077
|
+
stopPrice?: number | null;
|
|
1078
|
+
ticker?: string | null;
|
|
1079
|
+
/** Expiration */
|
|
1080
|
+
timeValidity?: TimeValidity | null;
|
|
1081
|
+
}
|
|
1082
|
+
interface Tax {
|
|
1083
|
+
/** ISO 8601 date and time. */
|
|
1084
|
+
chargedAt?: string | null;
|
|
1085
|
+
currency?: string | null;
|
|
1086
|
+
name?: "COMMISSION_TURNOVER" | "CURRENCY_CONVERSION_FEE" | "FINRA_FEE" | "FRENCH_TRANSACTION_TAX" | "PTM_LEVY" | "STAMP_DUTY" | "STAMP_DUTY_RESERVE_TAX" | "TRANSACTION_FEE" | (string & {}) | null;
|
|
1087
|
+
quantity?: number | null;
|
|
1088
|
+
}
|
|
1089
|
+
interface TimeEvent {
|
|
1090
|
+
/** ISO 8601 date and time. */
|
|
1091
|
+
date?: string | null;
|
|
1092
|
+
type?: "OPEN" | "CLOSE" | "BREAK_START" | "BREAK_END" | "PRE_MARKET_OPEN" | "AFTER_HOURS_OPEN" | "AFTER_HOURS_CLOSE" | "OVERNIGHT_OPEN" | (string & {}) | null;
|
|
1093
|
+
}
|
|
1094
|
+
/**
|
|
1095
|
+
* Specifies how long the order remains active:
|
|
1096
|
+
* * DAY: The order will automatically expire if not executed by midnight in the time zone of the instrument's exchange.
|
|
1097
|
+
* * GOOD_TILL_CANCEL: The order remains active indefinitely until it is either filled or explicitly cancelled by you.
|
|
1098
|
+
*/
|
|
1099
|
+
type TimeValidity = "DAY" | "GOOD_TILL_CANCEL" | (string & {});
|
|
1100
|
+
interface TradableInstrument {
|
|
1101
|
+
/**
|
|
1102
|
+
* On the platform since
|
|
1103
|
+
*
|
|
1104
|
+
* ISO 8601 date and time.
|
|
1105
|
+
*/
|
|
1106
|
+
addedOn?: string | null;
|
|
1107
|
+
/** ISO 4217 */
|
|
1108
|
+
currencyCode?: string | null;
|
|
1109
|
+
extendedHours?: boolean | null;
|
|
1110
|
+
isin?: string | null;
|
|
1111
|
+
maxOpenQuantity?: number | null;
|
|
1112
|
+
name?: string | null;
|
|
1113
|
+
shortName?: string | null;
|
|
1114
|
+
/** Unique identifier */
|
|
1115
|
+
ticker?: string | null;
|
|
1116
|
+
type?: "CRYPTOCURRENCY" | "ETF" | "FOREX" | "FUTURES" | "INDEX" | "STOCK" | "WARRANT" | "CRYPTO" | "CVR" | "CORPACT" | (string & {}) | null;
|
|
1117
|
+
/** Get items in the /exchanges endpoint */
|
|
1118
|
+
workingScheduleId?: number | null;
|
|
1119
|
+
}
|
|
1120
|
+
interface WorkingSchedule {
|
|
1121
|
+
/** 64-bit integer. */
|
|
1122
|
+
id?: number | null;
|
|
1123
|
+
timeEvents?: TimeEvent[] | null;
|
|
1124
|
+
}
|
|
1125
|
+
|
|
1126
|
+
/** What every resource shares with the client that created it. */
|
|
1127
|
+
interface ResourceContext {
|
|
1128
|
+
readonly transport: Transport;
|
|
1129
|
+
readonly cache: CachedLoader;
|
|
1130
|
+
/** Prefixes cache keys so different accounts and environments never share entries. */
|
|
1131
|
+
readonly cacheNamespace: string;
|
|
1132
|
+
readonly metadataTtlMs: number;
|
|
1133
|
+
/** For downloads that must not carry credentials, such as signed report links. */
|
|
1134
|
+
readonly fetch: FetchLike;
|
|
1135
|
+
readonly timeoutMs: number;
|
|
1136
|
+
}
|
|
1137
|
+
|
|
1138
|
+
declare class AccountResource {
|
|
1139
|
+
#private;
|
|
1140
|
+
constructor(context: ResourceContext);
|
|
1141
|
+
/**
|
|
1142
|
+
* Cash, invested capital, profit and loss, and total value, in the account's primary currency.
|
|
1143
|
+
*
|
|
1144
|
+
* Scope `account` · 1 request / 5 s.
|
|
1145
|
+
*
|
|
1146
|
+
* @example
|
|
1147
|
+
* const { totalValue, currency } = await t212.account.summary();
|
|
1148
|
+
*/
|
|
1149
|
+
summary(options?: CallOptions): Promise<AccountSummary>;
|
|
1150
|
+
}
|
|
1151
|
+
|
|
1152
|
+
/** An instrument the account can trade, from `instruments.list()`, `search()`, `find()` and `resolve()`. */
|
|
1153
|
+
type Instrument = TradableInstrument & {
|
|
1154
|
+
ticker: string;
|
|
1155
|
+
};
|
|
1156
|
+
/** A dividend payment, from `history.dividends`. */
|
|
1157
|
+
type Dividend = HistoryDividendItem;
|
|
1158
|
+
/** A deposit, withdrawal, fee or interest payment, from `history.transactions`. */
|
|
1159
|
+
type Transaction = HistoryTransactionItem;
|
|
1160
|
+
/** A requested CSV export and its status. */
|
|
1161
|
+
type Report = ReportResponse;
|
|
1162
|
+
/** A pie as listed by `pies.list()`. */
|
|
1163
|
+
type Pie = AccountBucketResultResponse;
|
|
1164
|
+
/** A pie with its instruments and settings, from `pies.get()`. */
|
|
1165
|
+
type PieDetails = AccountBucketInstrumentsDetailedResponse;
|
|
1166
|
+
/** What `pies.create()` and `pies.update()` take. */
|
|
1167
|
+
type PieInput = PieRequest;
|
|
1168
|
+
|
|
1169
|
+
/** The list is shared between callers, so it is fetched with the client's own timeout rather than a per-call one. */
|
|
1170
|
+
interface ListOptions {
|
|
1171
|
+
/** Ignore the cache and fetch afresh. */
|
|
1172
|
+
refresh?: boolean;
|
|
1173
|
+
/** Stops this caller waiting; a download other callers share carries on. */
|
|
1174
|
+
signal?: AbortSignal;
|
|
1175
|
+
}
|
|
1176
|
+
interface SearchOptions extends ListOptions {
|
|
1177
|
+
/** Most results to return. Default 10. */
|
|
1178
|
+
limit?: number;
|
|
1179
|
+
/** Only this instrument type, such as `STOCK` or `ETF`. */
|
|
1180
|
+
type?: string;
|
|
1181
|
+
/** Only instruments traded in this currency, such as `USD` or `GBX`. */
|
|
1182
|
+
currency?: string;
|
|
1183
|
+
}
|
|
1184
|
+
interface ResolveOptions extends ListOptions {
|
|
1185
|
+
type?: string;
|
|
1186
|
+
currency?: string;
|
|
1187
|
+
}
|
|
1188
|
+
declare class InstrumentsResource {
|
|
1189
|
+
#private;
|
|
1190
|
+
constructor(context: ResourceContext);
|
|
1191
|
+
/**
|
|
1192
|
+
* Every instrument the account can trade: about 5 MB, so it is cached (one hour by default) and concurrent callers
|
|
1193
|
+
* share one download.
|
|
1194
|
+
*
|
|
1195
|
+
* Scope `metadata` · 1 request / 50 s.
|
|
1196
|
+
*/
|
|
1197
|
+
list(options?: ListOptions): Promise<Instrument[]>;
|
|
1198
|
+
/**
|
|
1199
|
+
* Finds instruments by ticker, ISIN, short name or name, best match first. Searches the cached list, so it costs
|
|
1200
|
+
* no request after the first.
|
|
1201
|
+
*
|
|
1202
|
+
* @example
|
|
1203
|
+
* const [apple] = await t212.instruments.search("Apple", { currency: "USD" });
|
|
1204
|
+
*/
|
|
1205
|
+
search(query: string, options?: SearchOptions): Promise<Instrument[]>;
|
|
1206
|
+
/** The instrument with exactly this Trading 212 ticker, or `undefined`. */
|
|
1207
|
+
find(ticker: string, options?: ListOptions): Promise<Instrument | undefined>;
|
|
1208
|
+
/**
|
|
1209
|
+
* Turns what a person would type (`AAPL`, `Apple`, an ISIN) into exactly one instrument, or throws
|
|
1210
|
+
* `InstrumentNotFoundError` listing the closest matches when none or several fit.
|
|
1211
|
+
*
|
|
1212
|
+
* @example
|
|
1213
|
+
* const apple = await t212.instruments.resolve("AAPL", { currency: "USD" }); // AAPL_US_EQ
|
|
1214
|
+
*/
|
|
1215
|
+
resolve(query: string, options?: ResolveOptions): Promise<Instrument>;
|
|
1216
|
+
}
|
|
1217
|
+
|
|
1218
|
+
/** Where an instrument's market is in its day. Pre-market, after-hours and overnight are extended-hours sessions. */
|
|
1219
|
+
type MarketSession = "regular" | "preMarket" | "afterHours" | "overnight" | "closed" | "unknown";
|
|
1220
|
+
interface MarketStatus {
|
|
1221
|
+
readonly ticker: string;
|
|
1222
|
+
/** The exchange's name, when Trading 212 listed it. */
|
|
1223
|
+
readonly exchange: string | undefined;
|
|
1224
|
+
readonly session: MarketSession;
|
|
1225
|
+
/** True during regular trading hours. */
|
|
1226
|
+
readonly open: boolean;
|
|
1227
|
+
/** True during a pre-market, after-hours or overnight session. */
|
|
1228
|
+
readonly extendedHours: boolean;
|
|
1229
|
+
/** When the current session began. */
|
|
1230
|
+
readonly since: Date | undefined;
|
|
1231
|
+
/** The next scheduled change, such as the close. */
|
|
1232
|
+
readonly next: {
|
|
1233
|
+
readonly event: string;
|
|
1234
|
+
readonly at: Date;
|
|
1235
|
+
} | undefined;
|
|
1236
|
+
/** When regular trading next starts, including the end of a break, if the schedule reaches that far. */
|
|
1237
|
+
readonly nextOpen: Date | undefined;
|
|
1238
|
+
}
|
|
1239
|
+
/** Works out the session at `at` from a working schedule. Pure, so it can be tested and reused offline. */
|
|
1240
|
+
declare function sessionAt(events: readonly TimeEvent[], at: Date): Pick<MarketStatus, "session" | "since" | "next" | "nextOpen">;
|
|
1241
|
+
declare class ExchangesResource {
|
|
1242
|
+
#private;
|
|
1243
|
+
constructor(context: ResourceContext, instruments: InstrumentsResource);
|
|
1244
|
+
/**
|
|
1245
|
+
* Every exchange and its working schedules, cached like the instrument list.
|
|
1246
|
+
*
|
|
1247
|
+
* Scope `metadata` · 1 request / 30 s.
|
|
1248
|
+
*/
|
|
1249
|
+
list(options?: ListOptions): Promise<Exchange[]>;
|
|
1250
|
+
/**
|
|
1251
|
+
* Whether an instrument's market is open, read from Trading 212's working schedules, so you can check before an
|
|
1252
|
+
* order is refused with `market-closed`. The schedules cover a limited window ahead, so `nextOpen` can be undefined.
|
|
1253
|
+
*
|
|
1254
|
+
* @example
|
|
1255
|
+
* const { open, next } = await t212.exchanges.status("AAPL_US_EQ");
|
|
1256
|
+
*/
|
|
1257
|
+
status(ticker: string | TradableInstrument, at?: Date, options?: ListOptions): Promise<MarketStatus>;
|
|
1258
|
+
}
|
|
1259
|
+
|
|
1260
|
+
/** One page of a history list. */
|
|
1261
|
+
interface Page<T> {
|
|
1262
|
+
readonly items: T[];
|
|
1263
|
+
/** Pass as `cursor` to fetch the next page later, or `null` on the last page. */
|
|
1264
|
+
readonly nextCursor: string | null;
|
|
1265
|
+
readonly hasMore: boolean;
|
|
1266
|
+
/** Fetches the next page, or resolves to `null` on the last one. */
|
|
1267
|
+
next(options?: CallOptions): Promise<Page<T> | null>;
|
|
1268
|
+
}
|
|
1269
|
+
interface PageOptions extends CallOptions {
|
|
1270
|
+
/** Items per page, 1 to 50. Default 20. */
|
|
1271
|
+
limit?: number;
|
|
1272
|
+
/** A `nextCursor` from an earlier page, to carry on from there. */
|
|
1273
|
+
cursor?: string;
|
|
1274
|
+
}
|
|
1275
|
+
interface IterateOptions extends Omit<PageOptions, "limit"> {
|
|
1276
|
+
/** Items per request, 1 to 50. Default 50, the fewest requests. */
|
|
1277
|
+
pageSize?: number;
|
|
1278
|
+
/** Stop after this many pages. */
|
|
1279
|
+
maxPages?: number;
|
|
1280
|
+
/** Stop after this many items. */
|
|
1281
|
+
maxItems?: number;
|
|
1282
|
+
}
|
|
1283
|
+
/** A history list: one page at a time, or every item with `for await`. */
|
|
1284
|
+
declare class PagedList<T, F extends object = object> {
|
|
1285
|
+
#private;
|
|
1286
|
+
constructor(transport: Transport, endpoint: EndpointDefinition);
|
|
1287
|
+
list(options?: PageOptions & F): Promise<Page<T>>;
|
|
1288
|
+
/**
|
|
1289
|
+
* Every item, newest first, fetching pages as the loop asks for them. If a request fails part-way, the error's
|
|
1290
|
+
* `resumeCursor` says where to carry on.
|
|
1291
|
+
*/
|
|
1292
|
+
all(options?: IterateOptions & F): AsyncGenerator<T, void, undefined>;
|
|
1293
|
+
}
|
|
1294
|
+
|
|
1295
|
+
/** Your account's past: filled and cancelled orders, dividends, and cash movements. Newest first. */
|
|
1296
|
+
declare class HistoryResource {
|
|
1297
|
+
/**
|
|
1298
|
+
* Orders that have finished, with their fills.
|
|
1299
|
+
*
|
|
1300
|
+
* Scope `history:orders` · 20 requests / minute.
|
|
1301
|
+
*
|
|
1302
|
+
* @example
|
|
1303
|
+
* for await (const { order, fill } of t212.history.orders.all({ ticker: "AAPL_US_EQ" })) console.log(order?.status, fill?.price);
|
|
1304
|
+
*/
|
|
1305
|
+
readonly orders: PagedList<HistoricalOrder, {
|
|
1306
|
+
ticker?: string;
|
|
1307
|
+
}>;
|
|
1308
|
+
/**
|
|
1309
|
+
* Dividends paid out.
|
|
1310
|
+
*
|
|
1311
|
+
* Scope `history:dividends` · 20 requests / minute.
|
|
1312
|
+
*/
|
|
1313
|
+
readonly dividends: PagedList<HistoryDividendItem, {
|
|
1314
|
+
ticker?: string;
|
|
1315
|
+
}>;
|
|
1316
|
+
/**
|
|
1317
|
+
* Deposits, withdrawals, fees, transfers and interest. `time` starts the list from that moment.
|
|
1318
|
+
*
|
|
1319
|
+
* Scope `history:transactions` · 20 requests / minute.
|
|
1320
|
+
*/
|
|
1321
|
+
readonly transactions: PagedList<HistoryTransactionItem, {
|
|
1322
|
+
time?: Date | string;
|
|
1323
|
+
}>;
|
|
1324
|
+
constructor(context: ResourceContext);
|
|
1325
|
+
}
|
|
1326
|
+
|
|
1327
|
+
declare const TIME_VALIDITIES: readonly ["DAY", "GOOD_TILL_CANCEL"];
|
|
1328
|
+
/** `DAY` expires at midnight in the exchange's time zone; `GOOD_TILL_CANCEL` stays until it fills or you cancel it. */
|
|
1329
|
+
type OrderTimeValidity = (typeof TIME_VALIDITIES)[number];
|
|
1330
|
+
type OrderType = "market" | "limit" | "stop" | "stopLimit";
|
|
1331
|
+
|
|
1332
|
+
declare class PositionsResource {
|
|
1333
|
+
#private;
|
|
1334
|
+
constructor(context: ResourceContext);
|
|
1335
|
+
/**
|
|
1336
|
+
* Every open position, or just one ticker's.
|
|
1337
|
+
*
|
|
1338
|
+
* Scope `portfolio` · 1 request / 1 s.
|
|
1339
|
+
*/
|
|
1340
|
+
list(options?: CallOptions & {
|
|
1341
|
+
ticker?: string;
|
|
1342
|
+
}): Promise<Position[]>;
|
|
1343
|
+
/** One ticker's position, or `undefined` when you hold none. */
|
|
1344
|
+
get(ticker: string, options?: CallOptions): Promise<Position | undefined>;
|
|
1345
|
+
}
|
|
1346
|
+
|
|
1347
|
+
interface MarketOrderRequest {
|
|
1348
|
+
/** The Trading 212 ticker, such as `AAPL_US_EQ`. */
|
|
1349
|
+
ticker: string;
|
|
1350
|
+
/** Shares to trade, at most 4 decimal places. Positive buys, negative sells. */
|
|
1351
|
+
quantity: number;
|
|
1352
|
+
/** Allow the order to fill outside regular hours. Market orders only. */
|
|
1353
|
+
extendedHours?: boolean;
|
|
1354
|
+
}
|
|
1355
|
+
interface LimitOrderRequest {
|
|
1356
|
+
ticker: string;
|
|
1357
|
+
quantity: number;
|
|
1358
|
+
/** Buys fill at this price or lower; sells at this price or higher. */
|
|
1359
|
+
limitPrice: number;
|
|
1360
|
+
timeValidity: OrderTimeValidity;
|
|
1361
|
+
}
|
|
1362
|
+
interface StopOrderRequest {
|
|
1363
|
+
ticker: string;
|
|
1364
|
+
quantity: number;
|
|
1365
|
+
/** When the price reaches this, a market order is placed. */
|
|
1366
|
+
stopPrice: number;
|
|
1367
|
+
timeValidity: OrderTimeValidity;
|
|
1368
|
+
}
|
|
1369
|
+
interface StopLimitOrderRequest {
|
|
1370
|
+
ticker: string;
|
|
1371
|
+
quantity: number;
|
|
1372
|
+
stopPrice: number;
|
|
1373
|
+
/** The limit order placed once `stopPrice` is reached. */
|
|
1374
|
+
limitPrice: number;
|
|
1375
|
+
timeValidity: OrderTimeValidity;
|
|
1376
|
+
}
|
|
1377
|
+
/** An order for `buy()` or `sell()`: the quantity is always positive and the method sets the direction. */
|
|
1378
|
+
type OrderInput = ({
|
|
1379
|
+
type?: "market";
|
|
1380
|
+
} & MarketOrderRequest) | ({
|
|
1381
|
+
type: "limit";
|
|
1382
|
+
} & LimitOrderRequest) | ({
|
|
1383
|
+
type: "stop";
|
|
1384
|
+
} & StopOrderRequest) | ({
|
|
1385
|
+
type: "stopLimit";
|
|
1386
|
+
} & StopLimitOrderRequest);
|
|
1387
|
+
interface PlaceOptions extends CallOptions {
|
|
1388
|
+
/** Validate the order and return the request it would send, without sending it. */
|
|
1389
|
+
dryRun?: boolean;
|
|
1390
|
+
}
|
|
1391
|
+
/** What `dryRun` returns instead of an order. */
|
|
1392
|
+
interface DryRunResult {
|
|
1393
|
+
readonly dryRun: true;
|
|
1394
|
+
readonly method: "POST";
|
|
1395
|
+
readonly url: string;
|
|
1396
|
+
readonly endpoint: string;
|
|
1397
|
+
readonly body: Readonly<Record<string, unknown>>;
|
|
1398
|
+
/** False when trading is off for this client, so a real call would be refused before sending. */
|
|
1399
|
+
readonly wouldSend: boolean;
|
|
1400
|
+
}
|
|
1401
|
+
/** An `Order`, a `DryRunResult` for `{ dryRun: true }`, or either when `dryRun` is only known at run time. */
|
|
1402
|
+
type Placed<O extends PlaceOptions | undefined> = O extends {
|
|
1403
|
+
dryRun: true;
|
|
1404
|
+
} ? DryRunResult : O extends undefined ? Order : "dryRun" extends keyof O ? true extends NonNullable<O["dryRun"]> ? Order | DryRunResult : Order : Order;
|
|
1405
|
+
interface NoDryRun {
|
|
1406
|
+
dryRun?: false;
|
|
1407
|
+
}
|
|
1408
|
+
interface WaitOptions extends CallOptions {
|
|
1409
|
+
/** Give up after this long. Default 60 s. */
|
|
1410
|
+
timeoutMs?: number;
|
|
1411
|
+
/** Time between checks. Default 1 s, the endpoint's limit. */
|
|
1412
|
+
intervalMs?: number;
|
|
1413
|
+
}
|
|
1414
|
+
interface SellAllOptions extends PlaceOptions {
|
|
1415
|
+
extendedHours?: boolean;
|
|
1416
|
+
}
|
|
1417
|
+
/** The statuses an order does not leave. */
|
|
1418
|
+
declare const FINAL_ORDER_STATUSES: ReadonlySet<string>;
|
|
1419
|
+
declare class OrdersResource {
|
|
1420
|
+
#private;
|
|
1421
|
+
constructor(context: ResourceContext, positions: PositionsResource, history: PagedList<HistoricalOrder, {
|
|
1422
|
+
ticker?: string;
|
|
1423
|
+
}>);
|
|
1424
|
+
/**
|
|
1425
|
+
* Orders that are still working: not yet filled, cancelled or expired.
|
|
1426
|
+
*
|
|
1427
|
+
* Scope `orders:read` · 1 request / 5 s.
|
|
1428
|
+
*/
|
|
1429
|
+
list(options?: CallOptions): Promise<Order[]>;
|
|
1430
|
+
/**
|
|
1431
|
+
* One pending order. Throws `NotFoundError` once it has filled or been cancelled.
|
|
1432
|
+
*
|
|
1433
|
+
* Scope `orders:read` · 1 request / 1 s.
|
|
1434
|
+
*/
|
|
1435
|
+
get(id: number, options?: CallOptions): Promise<Order>;
|
|
1436
|
+
/**
|
|
1437
|
+
* Asks Trading 212 to cancel a pending order. Success means the request was accepted; the order may still fill
|
|
1438
|
+
* first. Never retried.
|
|
1439
|
+
*
|
|
1440
|
+
* Scope `orders:execute` · 50 requests / minute.
|
|
1441
|
+
*/
|
|
1442
|
+
cancel(id: number, options?: CallOptions): Promise<void>;
|
|
1443
|
+
/**
|
|
1444
|
+
* Trades at the next available price. A negative quantity sells. Never retried.
|
|
1445
|
+
*
|
|
1446
|
+
* Scope `orders:execute` · 50 requests / minute.
|
|
1447
|
+
*/
|
|
1448
|
+
market<O extends PlaceOptions = NoDryRun>(request: MarketOrderRequest, options?: O): Promise<Placed<O>>;
|
|
1449
|
+
/**
|
|
1450
|
+
* Trades at `limitPrice` or better. A negative quantity sells. Never retried.
|
|
1451
|
+
*
|
|
1452
|
+
* Scope `orders:execute` · 1 request / 2 s.
|
|
1453
|
+
*/
|
|
1454
|
+
limit<O extends PlaceOptions = NoDryRun>(request: LimitOrderRequest, options?: O): Promise<Placed<O>>;
|
|
1455
|
+
/**
|
|
1456
|
+
* Places a market order once the price reaches `stopPrice`: a negative quantity makes a stop-loss. Never retried.
|
|
1457
|
+
*
|
|
1458
|
+
* Scope `orders:execute` · 1 request / 2 s.
|
|
1459
|
+
*/
|
|
1460
|
+
stop<O extends PlaceOptions = NoDryRun>(request: StopOrderRequest, options?: O): Promise<Placed<O>>;
|
|
1461
|
+
/**
|
|
1462
|
+
* Places a limit order at `limitPrice` once the price reaches `stopPrice`. Never retried.
|
|
1463
|
+
*
|
|
1464
|
+
* Scope `orders:execute` · 1 request / 2 s.
|
|
1465
|
+
*/
|
|
1466
|
+
stopLimit<O extends PlaceOptions = NoDryRun>(request: StopLimitOrderRequest, options?: O): Promise<Placed<O>>;
|
|
1467
|
+
/**
|
|
1468
|
+
* Buys. The quantity is positive; `type` defaults to `market`.
|
|
1469
|
+
*
|
|
1470
|
+
* @example
|
|
1471
|
+
* await t212.orders.buy({ ticker: "AAPL_US_EQ", quantity: 0.5 });
|
|
1472
|
+
* await t212.orders.buy({ type: "limit", ticker: "AAPL_US_EQ", quantity: 1, limitPrice: 180, timeValidity: "DAY" });
|
|
1473
|
+
*/
|
|
1474
|
+
buy<O extends PlaceOptions = NoDryRun>(input: OrderInput, options?: O): Promise<Placed<O>>;
|
|
1475
|
+
/**
|
|
1476
|
+
* Sells. The quantity is positive and the sign is set for you, so a slip cannot turn a sale into a purchase.
|
|
1477
|
+
*
|
|
1478
|
+
* @example
|
|
1479
|
+
* await t212.orders.sell({ type: "stop", ticker: "AAPL_US_EQ", quantity: 1, stopPrice: 150, timeValidity: "GOOD_TILL_CANCEL" });
|
|
1480
|
+
*/
|
|
1481
|
+
sell<O extends PlaceOptions = NoDryRun>(input: OrderInput, options?: O): Promise<Placed<O>>;
|
|
1482
|
+
/**
|
|
1483
|
+
* Sells everything you can of one holding at market: `quantityAvailableForTrading`, cut to 4 decimal places so it
|
|
1484
|
+
* never exceeds what you own. Shares held in pies or reserved by pending orders are left alone.
|
|
1485
|
+
*/
|
|
1486
|
+
sellAll<O extends SellAllOptions = NoDryRun>(ticker: string, options?: O): Promise<Placed<O>>;
|
|
1487
|
+
/**
|
|
1488
|
+
* Waits until an order is filled, cancelled or rejected, and returns it in its final state. It polls the pending
|
|
1489
|
+
* order, and once that is gone looks the order up in the history, so the key needs `history:orders` as well.
|
|
1490
|
+
* `timeoutMs` bounds the whole wait, including any wait for rate-limit budget.
|
|
1491
|
+
*/
|
|
1492
|
+
waitFor(order: Order | number, options?: WaitOptions): Promise<Order>;
|
|
1493
|
+
}
|
|
1494
|
+
|
|
1495
|
+
/**
|
|
1496
|
+
* Pies. Trading 212 has deprecated these endpoints: they still work but will not be updated, and may be removed. The
|
|
1497
|
+
* first call logs a warning. Changes count as trades, so a live client needs `trading: "enabled"`.
|
|
1498
|
+
*/
|
|
1499
|
+
declare class PiesResource {
|
|
1500
|
+
#private;
|
|
1501
|
+
constructor(context: ResourceContext);
|
|
1502
|
+
/** Every pie, with its progress. Scope `pies:read` · 1 request / 30 s. */
|
|
1503
|
+
list(options?: CallOptions): Promise<AccountBucketResultResponse[]>;
|
|
1504
|
+
/** One pie with its instruments and settings. Scope `pies:read` · 1 request / 5 s. */
|
|
1505
|
+
get(id: number, options?: CallOptions): Promise<AccountBucketInstrumentsDetailedResponse>;
|
|
1506
|
+
/** Creates a pie. Scope `pies:write` · 1 request / 5 s. */
|
|
1507
|
+
create(pie: PieRequest, options?: CallOptions): Promise<AccountBucketInstrumentsDetailedResponse>;
|
|
1508
|
+
/** Changes a pie's settings or instruments. Scope `pies:write` · 1 request / 5 s. */
|
|
1509
|
+
update(id: number, pie: PieRequest, options?: CallOptions): Promise<AccountBucketInstrumentsDetailedResponse>;
|
|
1510
|
+
/** Deletes a pie. Scope `pies:write` · 1 request / 5 s. */
|
|
1511
|
+
delete(id: number, options?: CallOptions): Promise<void>;
|
|
1512
|
+
/** Copies a pie under a new name. Scope `pies:write` · 1 request / 5 s. */
|
|
1513
|
+
duplicate(id: number, copy?: {
|
|
1514
|
+
name?: string;
|
|
1515
|
+
icon?: string;
|
|
1516
|
+
}, options?: CallOptions): Promise<AccountBucketInstrumentsDetailedResponse>;
|
|
1517
|
+
}
|
|
1518
|
+
|
|
1519
|
+
interface HoldingSnapshot {
|
|
1520
|
+
readonly ticker: string;
|
|
1521
|
+
readonly name: string | undefined;
|
|
1522
|
+
readonly quantity: number;
|
|
1523
|
+
/** Current value in the account's currency. */
|
|
1524
|
+
readonly value: number;
|
|
1525
|
+
/** What it cost, in the account's currency. */
|
|
1526
|
+
readonly cost: number;
|
|
1527
|
+
readonly profitLoss: number;
|
|
1528
|
+
/** Profit or loss as a fraction of cost: 0.1 is 10%. */
|
|
1529
|
+
readonly profitLossRatio: number | undefined;
|
|
1530
|
+
/** Share of the invested total: 0.25 is a quarter. */
|
|
1531
|
+
readonly weight: number;
|
|
1532
|
+
}
|
|
1533
|
+
interface PortfolioSnapshot {
|
|
1534
|
+
readonly currency: string | undefined;
|
|
1535
|
+
readonly totalValue: number;
|
|
1536
|
+
readonly cash: number;
|
|
1537
|
+
readonly invested: number;
|
|
1538
|
+
readonly unrealisedProfitLoss: number;
|
|
1539
|
+
readonly realisedProfitLoss: number;
|
|
1540
|
+
/** Largest holding first. */
|
|
1541
|
+
readonly holdings: readonly HoldingSnapshot[];
|
|
1542
|
+
readonly takenAt: Date;
|
|
1543
|
+
}
|
|
1544
|
+
/**
|
|
1545
|
+
* Combines an account summary and its positions: the totals, and each holding's value, profit and
|
|
1546
|
+
* share of the portfolio. Pure, so you can call it on data you already have.
|
|
1547
|
+
*/
|
|
1548
|
+
declare function buildPortfolioSnapshot(summary: AccountSummary, positions: readonly Position[], takenAt?: Date): PortfolioSnapshot;
|
|
1549
|
+
declare class PortfolioResource {
|
|
1550
|
+
#private;
|
|
1551
|
+
constructor(account: AccountResource, positions: PositionsResource);
|
|
1552
|
+
/**
|
|
1553
|
+
* The account's totals and every holding's value, profit and weight, from two requests.
|
|
1554
|
+
*
|
|
1555
|
+
* @example
|
|
1556
|
+
* const { totalValue, holdings } = await t212.portfolio.snapshot();
|
|
1557
|
+
*/
|
|
1558
|
+
snapshot(options?: CallOptions): Promise<PortfolioSnapshot>;
|
|
1559
|
+
}
|
|
1560
|
+
|
|
1561
|
+
interface ReportRequest {
|
|
1562
|
+
/** Start of the period. */
|
|
1563
|
+
from: Date | string;
|
|
1564
|
+
/** End of the period. */
|
|
1565
|
+
to: Date | string;
|
|
1566
|
+
/** What to include. Everything, unless you say otherwise. */
|
|
1567
|
+
include?: {
|
|
1568
|
+
dividends?: boolean;
|
|
1569
|
+
interest?: boolean;
|
|
1570
|
+
orders?: boolean;
|
|
1571
|
+
transactions?: boolean;
|
|
1572
|
+
};
|
|
1573
|
+
}
|
|
1574
|
+
interface ReportWaitOptions extends CallOptions {
|
|
1575
|
+
/** Give up after this long. Default 10 minutes. */
|
|
1576
|
+
timeoutMs?: number;
|
|
1577
|
+
/** Time between checks. Default 60 s, the endpoint's limit. */
|
|
1578
|
+
intervalMs?: number;
|
|
1579
|
+
/** Called each time the status is checked. */
|
|
1580
|
+
onStatus?: (report: ReportResponse) => void;
|
|
1581
|
+
}
|
|
1582
|
+
interface ExportResult {
|
|
1583
|
+
readonly report: ReportResponse;
|
|
1584
|
+
readonly csv: string;
|
|
1585
|
+
}
|
|
1586
|
+
/** CSV exports of your history. Trading 212 offers them on live only. */
|
|
1587
|
+
declare class ReportsResource {
|
|
1588
|
+
#private;
|
|
1589
|
+
constructor(context: ResourceContext);
|
|
1590
|
+
/**
|
|
1591
|
+
* Every report you have asked for, with its status and, once finished, its download link.
|
|
1592
|
+
*
|
|
1593
|
+
* 1 request / minute.
|
|
1594
|
+
*/
|
|
1595
|
+
list(options?: CallOptions): Promise<ReportResponse[]>;
|
|
1596
|
+
/**
|
|
1597
|
+
* Asks Trading 212 to build a CSV report, and returns its ID.
|
|
1598
|
+
*
|
|
1599
|
+
* 1 request / 30 s.
|
|
1600
|
+
*/
|
|
1601
|
+
request(request: ReportRequest, options?: CallOptions): Promise<number>;
|
|
1602
|
+
/** Checks a report until it is finished, and returns it. Throws if it failed or was cancelled. */
|
|
1603
|
+
waitFor(reportId: number, options?: ReportWaitOptions): Promise<ReportResponse>;
|
|
1604
|
+
/**
|
|
1605
|
+
* Downloads a finished report's CSV. The link is signed, so your API credentials are never sent with it.
|
|
1606
|
+
*/
|
|
1607
|
+
download(report: ReportResponse | string, options?: CallOptions): Promise<string>;
|
|
1608
|
+
/**
|
|
1609
|
+
* Requests a report, waits for it and downloads it, in one call. Waiting respects the one-request-a-minute limit,
|
|
1610
|
+
* so expect at least a minute.
|
|
1611
|
+
*
|
|
1612
|
+
* @example
|
|
1613
|
+
* const { csv } = await t212.reports.export({ from: "2026-01-01", to: "2026-06-30" });
|
|
1614
|
+
*/
|
|
1615
|
+
export(request: ReportRequest, options?: ReportWaitOptions): Promise<ExportResult>;
|
|
1616
|
+
}
|
|
1617
|
+
|
|
1618
|
+
/** What `verify()` learnt about the key. */
|
|
1619
|
+
interface VerifyResult {
|
|
1620
|
+
readonly environment: Environment;
|
|
1621
|
+
/** The account number shown in the Trading 212 app. */
|
|
1622
|
+
readonly accountId: number | undefined;
|
|
1623
|
+
/** The account's primary currency, such as `GBP`. */
|
|
1624
|
+
readonly currency: string | undefined;
|
|
1625
|
+
/** Whether this client may place orders. */
|
|
1626
|
+
readonly trading: "enabled" | "disabled";
|
|
1627
|
+
}
|
|
1628
|
+
declare const INSPECT: unique symbol;
|
|
1629
|
+
/**
|
|
1630
|
+
* A client for one Trading 212 account in one environment.
|
|
1631
|
+
*
|
|
1632
|
+
* @example
|
|
1633
|
+
* const t212 = new Trading212({ environment: "demo", apiKey, apiSecret });
|
|
1634
|
+
* const { totalValue } = await t212.account.summary();
|
|
1635
|
+
*/
|
|
1636
|
+
declare class Trading212 {
|
|
1637
|
+
#private;
|
|
1638
|
+
readonly environment: Environment;
|
|
1639
|
+
/** Cash and totals. */
|
|
1640
|
+
readonly account: AccountResource;
|
|
1641
|
+
/** Open positions. */
|
|
1642
|
+
readonly positions: PositionsResource;
|
|
1643
|
+
/** Everything you can trade, cached, with search and ticker lookup. */
|
|
1644
|
+
readonly instruments: InstrumentsResource;
|
|
1645
|
+
/** Exchanges, their schedules, and whether a market is open. */
|
|
1646
|
+
readonly exchanges: ExchangesResource;
|
|
1647
|
+
/** Place, inspect, cancel and wait for orders. */
|
|
1648
|
+
readonly orders: OrdersResource;
|
|
1649
|
+
/** Past orders, dividends and transactions, paginated. */
|
|
1650
|
+
readonly history: HistoryResource;
|
|
1651
|
+
/** CSV exports. */
|
|
1652
|
+
readonly reports: ReportsResource;
|
|
1653
|
+
/** The account summary and positions combined. */
|
|
1654
|
+
readonly portfolio: PortfolioResource;
|
|
1655
|
+
/**
|
|
1656
|
+
* Pies.
|
|
1657
|
+
*
|
|
1658
|
+
* @deprecated Trading 212 has deprecated the pies endpoints; they may be removed.
|
|
1659
|
+
*/
|
|
1660
|
+
readonly pies: PiesResource;
|
|
1661
|
+
constructor(options: Trading212Options);
|
|
1662
|
+
/**
|
|
1663
|
+
* Builds a client from `T212_ENV`, `T212_API_KEY` and `T212_API_SECRET` (or `T212_DEMO_*` / `T212_LIVE_*`).
|
|
1664
|
+
* `overrides` sets any other option.
|
|
1665
|
+
*
|
|
1666
|
+
* @example
|
|
1667
|
+
* const t212 = Trading212.fromEnv({ logger: consoleLogger() });
|
|
1668
|
+
*/
|
|
1669
|
+
static fromEnv(overrides?: Partial<Trading212Options>, env?: EnvSource): Trading212;
|
|
1670
|
+
/** Whether this client may place or cancel orders and change pies. */
|
|
1671
|
+
get trading(): "enabled" | "disabled";
|
|
1672
|
+
/**
|
|
1673
|
+
* Checks the key works, with one request, and says which account it belongs to. A wrong key or environment fails
|
|
1674
|
+
* here with an `AuthenticationError` that explains which.
|
|
1675
|
+
*/
|
|
1676
|
+
verify(options?: CallOptions): Promise<VerifyResult>;
|
|
1677
|
+
/** What is known about every endpoint's rate-limit budget, shared by every client using this key. */
|
|
1678
|
+
rateLimits(): Record<EndpointId, EndpointBudget>;
|
|
1679
|
+
toJSON(): Record<string, unknown>;
|
|
1680
|
+
[INSPECT](): string;
|
|
1681
|
+
}
|
|
1682
|
+
|
|
1683
|
+
export { BASE_URLS as B, ENDPOINTS as E, FINAL_ORDER_STATUSES as F, HistoryResource as M, HttpError as Q, InstrumentNotFoundError as U, InstrumentsResource as W, MemoryCache as a8, MissingScopeError as a9, PositionsResource as aD, RateLimitError as aF, ReportsResource as aO, SPEC_VERSION as aV, ServerError as aY, NetworkError as aa, NotAvailableInDemoError as ab, NotFoundError as ac, OrderOutcomeUnknownError as af, OrderRejectedError as ag, OrdersResource as ak, PagedList as an, PermissionError as ar, PiesResource as aw, PortfolioResource as az, TIME_VALIDITIES as b1, TimeoutError as b5, Trading212 as b7, Trading212Error as b8, TradingDisabledError as ba, UnexpectedResponseError as bc, ValidationError as bd, buildPortfolioSnapshot as bi, consoleLogger as bj, fieldsFirst as bk, isTrading212Error as bl, sessionAt as bm, silentLogger as bn, AccountResource as d, AuthenticationError as f, ConfigurationError as i, ExchangesResource as y };
|
|
1684
|
+
export type { LimitRequest as $, AccountBucketDetailedResponse as A, CacheStore as C, Dividend as D, FetchLike as G, FieldsFirstMethod as H, Fill as I, FillWalletImpact as J, HistoricalOrder as K, HistoryDividendItem as L, HistoryTransactionItem as N, HoldingSnapshot as O, Hooks as P, HttpMethod as R, Instrument as S, InstrumentIssue as T, InstrumentSuggestion as V, InvestmentResult as X, Investments as Y, IterateOptions as Z, LimitOrderRequest as _, AccountBucketInstrumentResult as a, StopOrderRequest as a$, ListOptions as a0, LogFields as a1, LogLevel as a2, Logger as a3, MarketOrderRequest as a4, MarketRequest as a5, MarketSession as a6, MarketStatus as a7, PortfolioSnapshot as aA, Position as aB, PositionWalletImpact as aC, PublicReportRequest as aE, RateLimitInfo as aG, RateLimitMode as aH, RateLimitWaitEvent as aI, Report as aJ, ReportDataIncluded as aK, ReportRequest as aL, ReportResponse as aM, ReportWaitOptions as aN, RequestDescription as aP, RequestEvent as aQ, ResolveOptions as aR, ResponseEvent as aS, RetryEvent as aT, RetryOptions as aU, SearchOptions as aW, SellAllOptions as aX, StopLimitOrderRequest as aZ, StopLimitRequest as a_, Order as ad, OrderInput as ae, OrderRejectionReason as ah, OrderTimeValidity as ai, OrderType as aj, Page as al, PageOptions as am, PaginatedResponseHistoricalOrder as ao, PaginatedResponseHistoryDividendItem as ap, PaginatedResponseHistoryTransactionItem as aq, Pie as as, PieDetails as at, PieInput as au, PieRequest as av, PlaceOptions as ax, Placed as ay, AccountBucketInstrumentsDetailedResponse as b, StopRequest as b0, Tax as b2, TimeEvent as b3, TimeValidity as b4, TradableInstrument as b6, Trading212Options as b9, Transaction as bb, ValidationIssue as be, VerifyResult as bf, WaitOptions as bg, WorkingSchedule as bh, AccountBucketResultResponse as c, AccountSummary as e, CallOptions as g, Cash as h, ConsoleLike as j, DividendDetails as k, DryRunResult as l, DuplicateBucketRequest as m, EndpointBudget as n, EndpointDefinition as o, EndpointId as p, EndpointKind as q, EndpointRateLimit as r, EnqueuedReportResponse as s, EnvSource as t, Environment as u, ErrorCode as v, ErrorDetails as w, Exchange as x, ExportResult as z };
|