@mfxhub/sdk 0.2.3 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +66 -0
- package/dist/accounts.d.ts +5 -1
- package/dist/accounts.js +17 -9
- package/dist/client.d.ts +3 -0
- package/dist/client.js +7 -1
- package/dist/execution.d.ts +7 -1
- package/dist/execution.js +15 -5
- package/dist/generated/api.d.ts +9523 -3748
- package/dist/index.d.ts +5 -3
- package/dist/index.js +1 -0
- package/dist/results.d.ts +27 -1
- package/dist/results.js +27 -0
- package/dist/terminals.d.ts +48 -1
- package/dist/terminals.js +106 -1
- package/dist/trading-accounts.d.ts +130 -0
- package/dist/trading-accounts.js +228 -0
- package/dist/version.d.ts +2 -2
- package/dist/version.js +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,72 @@ Every release of `@mfxhub/sdk`, newest first. The format follows
|
|
|
4
4
|
[Keep a Changelog](https://keepachangelog.com/en/1.1.0/), and versions follow
|
|
5
5
|
[Semantic Versioning](https://semver.org/).
|
|
6
6
|
|
|
7
|
+
## 0.4.0
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- Trade a trading account on any venue: `client.tradingAccounts.placeOrder`, `cancelOrder`,
|
|
12
|
+
`modifyOrder`, `modifyPosition`, `closePosition`, `closePositionBy`, `closePositionPartial`,
|
|
13
|
+
`setTrailingStop` and `clearTrailingStop` take the account's id and send to
|
|
14
|
+
`/v1/accounts/{id}/...` (scope `exec:write`). Same bodies and rules as `client.execution`: a
|
|
15
|
+
required `idempotencyKey`, a result resolved and never rejected, nothing retried. Read the
|
|
16
|
+
outcome with `client.execution.waitFor`.
|
|
17
|
+
- Read a trading account on any venue: `funds`, `positions`, `pendingOrders`, `dealsPage` and
|
|
18
|
+
`deals` (with `position` to read one position's deals) and `symbols` (scope `acct:read`).
|
|
19
|
+
`symbols` gives a cTrader account's volume rules in lots and its leverage.
|
|
20
|
+
- Connect cTrader accounts: `startCtraderGrant({ environment, scope, returnUrl })` resolves to the
|
|
21
|
+
consent link to send the trader to; `ctraderGrant(id)` lists the accounts they shared;
|
|
22
|
+
`connectCtraderAccounts(id, [...])` makes the chosen ones trading accounts of yours;
|
|
23
|
+
`revokeCtraderGrant(id)` moves them to `REAUTH_NEEDED`.
|
|
24
|
+
- `ExecutionResult` reads what a venue adds: `venue`, `venueCode` (the venue's own refusal code
|
|
25
|
+
beside `reason`), `deals` (each a `VenueDeal` with `volumeUnits` and `price`), `volumeUnits`,
|
|
26
|
+
`closeByEmulated` and `protectionNotSet`.
|
|
27
|
+
- The reasons `venue_unavailable` (retryable) and `not_on_this_venue`.
|
|
28
|
+
- `new Execution(client, "accounts")` sends to a trading account's routes; the default is a
|
|
29
|
+
terminal's, as before.
|
|
30
|
+
|
|
31
|
+
## 0.3.0
|
|
32
|
+
|
|
33
|
+
### Added
|
|
34
|
+
|
|
35
|
+
- A terminal can be `QUEUED`: placed on a cell and waiting for its turn to start. A cell starts
|
|
36
|
+
terminals a few at a time so the ones already running are not slowed. `terminal.queue` says its
|
|
37
|
+
place, when it is expected to start (`expected_start_at`) and why it waits (a coarse `reason`).
|
|
38
|
+
`isUsable` is false for it, as for every state but ACTIVE.
|
|
39
|
+
- `terminals.waitUntilActive(id, { timeoutMs })`: reads the terminal until it is no longer on its
|
|
40
|
+
way to ACTIVE. A QUEUED terminal is read again at its expected start (2 s to 1 min away), not on
|
|
41
|
+
a fixed beat.
|
|
42
|
+
- `terminals.bulkRestart` and `terminals.bulkRetire` (`POST /v1/terminals:restart`,
|
|
43
|
+
`POST /v1/terminals:retire`): many terminals by farm, broker or ids, answered at once with the
|
|
44
|
+
action, what was refused and the expected finish. `getBulkAction` and `cancelBulkAction` follow
|
|
45
|
+
and cancel it.
|
|
46
|
+
|
|
47
|
+
### Changed
|
|
48
|
+
|
|
49
|
+
- The vendored API description is the platform's current public contract, with the queued state,
|
|
50
|
+
the queue fields and the bulk routes; the generated types follow it.
|
|
51
|
+
|
|
52
|
+
### Fixed
|
|
53
|
+
|
|
54
|
+
- A request path whose first segment holds a colon (`/terminals:restart`) is sent to the API. The
|
|
55
|
+
URL parser read `terminals:` as a scheme.
|
|
56
|
+
|
|
57
|
+
## 0.2.4
|
|
58
|
+
|
|
59
|
+
### Added
|
|
60
|
+
|
|
61
|
+
- `client.tradingAccounts`: the trading accounts over every venue (`GET /v1/accounts`,
|
|
62
|
+
`GET /v1/accounts/{id}`, scope `acct:read`). `page()` and `list()` narrow by `venue`,
|
|
63
|
+
`environment` and `state` on the platform; `get(id)` takes the account's id or one of its
|
|
64
|
+
terminals' ids. An MT5 account's id is its terminal's id. The state is the venue-neutral word
|
|
65
|
+
(`CONNECTED`, `DEGRADED`, `REAUTH_NEEDED`, ...). `client.accounts` is unchanged: it is still the
|
|
66
|
+
balance, positions and deals of a terminal's account.
|
|
67
|
+
|
|
68
|
+
### Changed
|
|
69
|
+
|
|
70
|
+
- The vendored API description is the platform's current public contract, and the generated types
|
|
71
|
+
follow it.
|
|
72
|
+
|
|
7
73
|
## 0.2.3
|
|
8
74
|
|
|
9
75
|
### Added
|
package/dist/accounts.d.ts
CHANGED
|
@@ -30,7 +30,11 @@ export interface DealPageOptions extends DealWindow {
|
|
|
30
30
|
/** Read the trading account behind a terminal: figures, positions, pending orders and deals. */
|
|
31
31
|
export declare class Accounts {
|
|
32
32
|
#private;
|
|
33
|
-
|
|
33
|
+
/**
|
|
34
|
+
* `resource` is whose account is read: a terminal's (`client.accounts`) or a trading
|
|
35
|
+
* account's on any venue (`client.tradingAccounts`), which answer the same shapes.
|
|
36
|
+
*/
|
|
37
|
+
constructor(client: MfxClient, resource?: "terminals" | "accounts");
|
|
34
38
|
/** The account's figures. Another tenant's terminal is not found. */
|
|
35
39
|
account(terminalId: string): Promise<Account>;
|
|
36
40
|
/** Every open position, as one snapshot with its `as_of`. */
|
package/dist/accounts.js
CHANGED
|
@@ -18,27 +18,35 @@ function instant(name, value) {
|
|
|
18
18
|
/** Read the trading account behind a terminal: figures, positions, pending orders and deals. */
|
|
19
19
|
export class Accounts {
|
|
20
20
|
#client;
|
|
21
|
-
|
|
21
|
+
#resource;
|
|
22
|
+
#idName;
|
|
23
|
+
/**
|
|
24
|
+
* `resource` is whose account is read: a terminal's (`client.accounts`) or a trading
|
|
25
|
+
* account's on any venue (`client.tradingAccounts`), which answer the same shapes.
|
|
26
|
+
*/
|
|
27
|
+
constructor(client, resource = "terminals") {
|
|
22
28
|
this.#client = client;
|
|
29
|
+
this.#resource = resource;
|
|
30
|
+
this.#idName = resource === "accounts" ? "accountId" : "terminalId";
|
|
23
31
|
}
|
|
24
32
|
/** The account's figures. Another tenant's terminal is not found. */
|
|
25
33
|
async account(terminalId) {
|
|
26
|
-
const id = uuid(
|
|
34
|
+
const id = uuid(this.#idName, terminalId);
|
|
27
35
|
return (await this.#client.read({
|
|
28
36
|
method: "GET",
|
|
29
|
-
path:
|
|
37
|
+
path: `/${this.#resource}/${id}/account`,
|
|
30
38
|
}));
|
|
31
39
|
}
|
|
32
40
|
/** Every open position, as one snapshot with its `as_of`. */
|
|
33
41
|
async positions(terminalId) {
|
|
34
|
-
const id = uuid(
|
|
35
|
-
const path =
|
|
42
|
+
const id = uuid(this.#idName, terminalId);
|
|
43
|
+
const path = `/${this.#resource}/${id}/positions`;
|
|
36
44
|
return (await this.#client.read({ method: "GET", path }));
|
|
37
45
|
}
|
|
38
46
|
/** Every pending order, as one snapshot with its `as_of`. */
|
|
39
47
|
async pendingOrders(terminalId) {
|
|
40
|
-
const id = uuid(
|
|
41
|
-
const path =
|
|
48
|
+
const id = uuid(this.#idName, terminalId);
|
|
49
|
+
const path = `/${this.#resource}/${id}/orders/pending`;
|
|
42
50
|
return (await this.#client.read({ method: "GET", path }));
|
|
43
51
|
}
|
|
44
52
|
/**
|
|
@@ -46,7 +54,7 @@ export class Accounts {
|
|
|
46
54
|
* and so by this: an unbounded history read is the query that takes a database down.
|
|
47
55
|
*/
|
|
48
56
|
async dealsPage(terminalId, options) {
|
|
49
|
-
const id = uuid(
|
|
57
|
+
const id = uuid(this.#idName, terminalId);
|
|
50
58
|
const from = instant("from", options.from);
|
|
51
59
|
const to = instant("to", options.to);
|
|
52
60
|
if (options.to.getTime() < options.from.getTime()) {
|
|
@@ -61,7 +69,7 @@ export class Accounts {
|
|
|
61
69
|
}
|
|
62
70
|
const body = await this.#client.read({
|
|
63
71
|
method: "GET",
|
|
64
|
-
path:
|
|
72
|
+
path: `/${this.#resource}/${id}/history/deals`,
|
|
65
73
|
query: {
|
|
66
74
|
from,
|
|
67
75
|
to,
|
package/dist/client.d.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { Catalog } from "./catalog.js";
|
|
|
5
5
|
import { Execution } from "./execution.js";
|
|
6
6
|
import { MfxStream, type StreamOptions } from "./stream.js";
|
|
7
7
|
import { Terminals } from "./terminals.js";
|
|
8
|
+
import { TradingAccounts } from "./trading-accounts.js";
|
|
8
9
|
/** Default time a single request may take. */
|
|
9
10
|
export declare const DEFAULT_TIMEOUT_MS = 30000;
|
|
10
11
|
/** How many times a rate-limited read is tried again. */
|
|
@@ -73,6 +74,8 @@ export declare class MfxClient {
|
|
|
73
74
|
readonly catalog: Catalog;
|
|
74
75
|
/** The trading account behind a terminal: figures, positions, pending orders and deals. */
|
|
75
76
|
readonly accounts: Accounts;
|
|
77
|
+
/** The trading accounts over every venue: an MT5 account, and later a cTrader one. */
|
|
78
|
+
readonly tradingAccounts: TradingAccounts;
|
|
76
79
|
/**
|
|
77
80
|
* @param baseUrl the API's base, including the version: `https://api.mfxhub.com/v1`, or
|
|
78
81
|
* `https://api.dev.mfxhub.com/v1` for development
|
package/dist/client.js
CHANGED
|
@@ -13,6 +13,7 @@ import { Catalog } from "./catalog.js";
|
|
|
13
13
|
import { Execution } from "./execution.js";
|
|
14
14
|
import { MfxStream } from "./stream.js";
|
|
15
15
|
import { Terminals } from "./terminals.js";
|
|
16
|
+
import { TradingAccounts } from "./trading-accounts.js";
|
|
16
17
|
import { USER_AGENT } from "./version.js";
|
|
17
18
|
/** Default time a single request may take. */
|
|
18
19
|
export const DEFAULT_TIMEOUT_MS = 30_000;
|
|
@@ -55,6 +56,8 @@ export class MfxClient {
|
|
|
55
56
|
catalog;
|
|
56
57
|
/** The trading account behind a terminal: figures, positions, pending orders and deals. */
|
|
57
58
|
accounts;
|
|
59
|
+
/** The trading accounts over every venue: an MT5 account, and later a cTrader one. */
|
|
60
|
+
tradingAccounts;
|
|
58
61
|
/**
|
|
59
62
|
* @param baseUrl the API's base, including the version: `https://api.mfxhub.com/v1`, or
|
|
60
63
|
* `https://api.dev.mfxhub.com/v1` for development
|
|
@@ -76,6 +79,7 @@ export class MfxClient {
|
|
|
76
79
|
this.execution = new Execution(this);
|
|
77
80
|
this.catalog = new Catalog(this);
|
|
78
81
|
this.accounts = new Accounts(this);
|
|
82
|
+
this.tradingAccounts = new TradingAccounts(this);
|
|
79
83
|
}
|
|
80
84
|
/** The id of the key this client signs with. Safe to log, unlike the private key. */
|
|
81
85
|
get keyId() {
|
|
@@ -133,7 +137,9 @@ export class MfxClient {
|
|
|
133
137
|
}
|
|
134
138
|
/** One attempt, signed afresh. Transport faults become MfxTransportError or MfxTimeout. */
|
|
135
139
|
async send(spec) {
|
|
136
|
-
|
|
140
|
+
// "./" keeps a path with a colon in its first segment (`/terminals:restart`) relative: without
|
|
141
|
+
// it the URL parser reads `terminals:` as a scheme and the request leaves the API.
|
|
142
|
+
const url = new URL("./" + spec.path.replace(/^\/+/, ""), this.#base);
|
|
137
143
|
for (const [name, value] of Object.entries(spec.query ?? {})) {
|
|
138
144
|
if (value === null || value === undefined)
|
|
139
145
|
continue;
|
package/dist/execution.d.ts
CHANGED
|
@@ -84,10 +84,16 @@ export interface WaitFor {
|
|
|
84
84
|
export declare const POLL_FROM_MS = 200;
|
|
85
85
|
/** The longest pause between two reads of a command. */
|
|
86
86
|
export declare const POLL_CAP_MS = 2000;
|
|
87
|
+
/** Where a command goes: a terminal's routes, or a trading account's on any venue. */
|
|
88
|
+
export type Resource = "terminals" | "accounts";
|
|
87
89
|
/** Order entry for one tenant. Every method resolves to a result; none rejects. */
|
|
88
90
|
export declare class Execution {
|
|
89
91
|
#private;
|
|
90
|
-
|
|
92
|
+
/**
|
|
93
|
+
* `resource` is where the commands go: a terminal's routes (`client.execution`) or a trading
|
|
94
|
+
* account's (`client.tradingAccounts`), which take the same bodies under the same rules.
|
|
95
|
+
*/
|
|
96
|
+
constructor(client: MfxClient, resource?: Resource);
|
|
91
97
|
/**
|
|
92
98
|
* Place a market or pending order. Resolves once the platform has persisted the command
|
|
93
99
|
* (state ACCEPTED, with its `commandId`); the outcome follows on the stream.
|
package/dist/execution.js
CHANGED
|
@@ -93,8 +93,14 @@ function closing(options) {
|
|
|
93
93
|
/** Order entry for one tenant. Every method resolves to a result; none rejects. */
|
|
94
94
|
export class Execution {
|
|
95
95
|
#client;
|
|
96
|
-
|
|
96
|
+
#resource;
|
|
97
|
+
/**
|
|
98
|
+
* `resource` is where the commands go: a terminal's routes (`client.execution`) or a trading
|
|
99
|
+
* account's (`client.tradingAccounts`), which take the same bodies under the same rules.
|
|
100
|
+
*/
|
|
101
|
+
constructor(client, resource = "terminals") {
|
|
97
102
|
this.#client = client;
|
|
103
|
+
this.#resource = resource;
|
|
98
104
|
}
|
|
99
105
|
/**
|
|
100
106
|
* Place a market or pending order. Resolves once the platform has persisted the command
|
|
@@ -104,10 +110,10 @@ export class Execution {
|
|
|
104
110
|
* belongs, a missing idempotency key, a comment over 31 characters.
|
|
105
111
|
*/
|
|
106
112
|
async placeOrder(terminalId, order) {
|
|
107
|
-
const id = uuid(
|
|
113
|
+
const id = uuid(this.#idName, terminalId);
|
|
108
114
|
const key = idempotencyKey(order.idempotencyKey);
|
|
109
115
|
const body = orderBody(order);
|
|
110
|
-
return this.#command({ method: "POST", path:
|
|
116
|
+
return this.#command({ method: "POST", path: `/${this.#resource}/${id}/orders`, body, idempotencyKey: key }, key);
|
|
111
117
|
}
|
|
112
118
|
/**
|
|
113
119
|
* Amend a pending order's price, stops or expiry; at least one must change. Its volume, side,
|
|
@@ -196,12 +202,16 @@ export class Execution {
|
|
|
196
202
|
}
|
|
197
203
|
return result;
|
|
198
204
|
}
|
|
205
|
+
/** The name a wrong id is reported under. */
|
|
206
|
+
get #idName() {
|
|
207
|
+
return this.#resource === "accounts" ? "accountId" : "terminalId";
|
|
208
|
+
}
|
|
199
209
|
/** One command on an existing order or position: checked, then sent once. */
|
|
200
210
|
async #on(terminalId, ticket, kind, action, options, body, method = "POST") {
|
|
201
|
-
const id = uuid(
|
|
211
|
+
const id = uuid(this.#idName, terminalId);
|
|
202
212
|
const number = ticketOf("ticket", ticket);
|
|
203
213
|
const key = idempotencyKey(options?.idempotencyKey);
|
|
204
|
-
const path =
|
|
214
|
+
const path = `/${this.#resource}/${id}/${kind}/${String(number)}/${action}`;
|
|
205
215
|
return this.#command({ method, path, ...(body === undefined ? {} : { body }), idempotencyKey: key }, key);
|
|
206
216
|
}
|
|
207
217
|
/**
|