@danielgroen/dxtrade-api 1.0.23 → 1.0.25

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -26,13 +26,15 @@ npm install dxtrade-api
26
26
  - [x] Position metrics (per-position P&L)
27
27
  - [x] Account metrics, trade journal & trade history
28
28
  - [x] Symbol search & instrument info
29
- - [x] OHLC / price bar data
29
+ - [x] OHLC / price bar data (one-shot & streaming)
30
30
  - [x] PnL assessments
31
31
  - [x] Multi-broker support (FTMO, Eightcap, Lark Funding)
32
+ - [x] Persistent WebSocket with `connect()`
33
+ - [x] Real-time position streaming
32
34
  - [x] Full TypeScript support
33
35
  - [ ] Batch orders
34
36
  - [ ] Modify existing orders
35
- - [ ] Real-time price streaming
37
+ - [x] Real-time OHLC streaming
36
38
 
37
39
  ## Quick Start
38
40
 
@@ -46,12 +48,13 @@ const client = new DxtradeClient({
46
48
  accountId: "optional_account_id",
47
49
  });
48
50
 
49
- await client.connect();
51
+ // await client.auth(); // Auth only
52
+ await client.connect(); // Auth + persistent WebSocket (recommended)
50
53
 
51
- const suggestions = await client.getSymbolSuggestions("EURUSD");
54
+ const suggestions = await client.symbols.search("EURUSD");
52
55
  const symbol = suggestions[0];
53
56
 
54
- const order = await client.submitOrder({
57
+ const order = await client.orders.submit({
55
58
  symbol: symbol.name,
56
59
  side: SIDE.BUY,
57
60
  quantity: 0.01,
@@ -60,6 +63,18 @@ const order = await client.submitOrder({
60
63
  });
61
64
 
62
65
  console.log(`Order ${order.orderId}: ${order.status}`);
66
+ client.disconnect(); // disconnect stream -- only needed if client.connect()
67
+ ```
68
+
69
+ ## Connection Modes
70
+
71
+ ```ts
72
+ // 1. Persistent WebSocket (recommended) — reuses one WS for all data, enables streaming
73
+ await client.connect();
74
+ client.disconnect(); // when done
75
+
76
+ // 2. Lightweight — auth only, each data call opens a temporary WebSocket
77
+ await client.auth();
63
78
  ```
64
79
 
65
80
  ## Configuration
@@ -89,42 +104,51 @@ BROKER.FTMO // "https://dxtrade.ftmo.com"
89
104
 
90
105
  ### Session
91
106
 
92
- - `client.connect()` — Login, fetch CSRF, WebSocket handshake, optional account switch
107
+ - `client.connect()` — Auth + persistent WebSocket. Recommended for most use cases.
108
+ - `client.auth()` — Lightweight: login, fetch CSRF, WebSocket handshake, optional account switch. No persistent WS.
109
+ - `client.disconnect()` — Close the persistent WebSocket connection
93
110
  - `client.login()` — Authenticate with broker
94
111
  - `client.fetchCsrf()` — Fetch CSRF token from broker page
95
112
  - `client.switchAccount(accountId)` — Switch to a specific account
96
113
 
97
- ### Market Data
114
+ ### Positions
98
115
 
99
- - `client.getSymbolSuggestions(text)` — Search for symbols
100
- - `client.getSymbolInfo(symbol)` — Get instrument info (volume limits, lot size)
101
- - `client.getSymbolLimits()` — Get order size limits and stop/limit distances for all symbols
102
- - `client.getInstruments(params?)` — Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`)
103
- - `client.getOHLC(params)` — Fetch OHLC price bars for a symbol (resolution, range, maxBars, priceField)
116
+ - `client.positions.get()` — Get all open positions with P&L metrics merged (margin, plOpen, marketValue, etc.)
117
+ - `client.positions.close(params)` — Close a position (supports partial closes via the quantity field)
118
+ - `client.positions.closeAll()` — Close all open positions with market orders
119
+ - `client.positions.stream(callback)` — Stream real-time position updates with live P&L (requires `connect()`). Returns an unsubscribe function.
104
120
 
105
- ### Trading
121
+ ### Orders
106
122
 
107
- - `client.submitOrder(params)` — Submit an order and wait for WebSocket confirmation
108
- - `client.getOrders()` — Get all pending/open orders via WebSocket
109
- - `client.cancelOrder(orderChainId)` — Cancel a single pending order
110
- - `client.cancelAllOrders()` — Cancel all pending orders
123
+ - `client.orders.get()` — Get all pending/open orders
124
+ - `client.orders.submit(params)` — Submit an order and wait for WebSocket confirmation
125
+ - `client.orders.cancel(orderChainId)` — Cancel a single pending order
126
+ - `client.orders.cancelAll()` — Cancel all pending orders
111
127
 
112
- ### Positions
128
+ ### Account
113
129
 
114
- - `client.getPositions()` — Get all open positions via WebSocket
115
- - `client.closePosition(params)` — Close a position (supports partial closes via the quantity field)
116
- - `client.closeAllPositions()` — Close all open positions with market orders
117
- - `client.getPositionMetrics()` — Get position-level P&L metrics via WebSocket
130
+ - `client.account.metrics()` — Get account metrics (equity, balance, margin, open P&L, etc.)
131
+ - `client.account.tradeJournal({ from, to })` — Fetch trade journal entries for a date range (Unix timestamps)
132
+ - `client.account.tradeHistory({ from, to })` — Fetch trade history for a date range (Unix timestamps)
118
133
 
119
- ### Account
134
+ ### Symbols
135
+
136
+ - `client.symbols.search(text)` — Search for symbols
137
+ - `client.symbols.info(symbol)` — Get instrument info (volume limits, lot size)
138
+ - `client.symbols.limits()` — Get order size limits and stop/limit distances for all symbols
139
+
140
+ ### Instruments
141
+
142
+ - `client.instruments.get(params?)` — Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`)
143
+
144
+ ### OHLC
120
145
 
121
- - `client.getAccountMetrics()` — Get account metrics (equity, balance, margin, open P&L, etc.)
122
- - `client.getTradeJournal({ from, to })` — Fetch trade journal entries for a date range (Unix timestamps)
123
- - `client.getTradeHistory({ from, to })` — Fetch trade history for a date range (Unix timestamps)
146
+ - `client.ohlc.get(params)` — Fetch OHLC price bars for a symbol (resolution, range, maxBars, priceField)
147
+ - `client.ohlc.stream(params, callback)` — Stream real-time OHLC bar updates (requires `connect()`). Returns a promise that resolves with an unsubscribe function after the snapshot is received.
124
148
 
125
- ### Analytics
149
+ ### Assessments
126
150
 
127
- - `client.getAssessments(params)` — Fetch PnL assessments for a date range
151
+ - `client.assessments.get(params)` — Fetch PnL assessments for a date range
128
152
 
129
153
  ## Enums
130
154
 
@@ -157,23 +181,25 @@ const client = new DxtradeClient({
157
181
  ```bash
158
182
  cp .env.example .env # fill in credentials
159
183
  npm run example:connect
160
- npm run example:order
161
- npm run example:orders
162
- npm run example:positions
163
- npm run example:close-position
164
- npm run example:close-all-positions
165
- npm run example:position-metrics
166
- npm run example:assessments
167
- npm run example:assessments:btc
168
- npm run example:account
169
- npm run example:instruments
170
- npm run example:ohlc
171
- npm run example:instruments:forex
172
- npm run example:symbol
173
- npm run example:symbol:btc
174
- npm run example:trade-journal
175
- npm run example:trade-history
176
184
  npm run example:debug
185
+ npm run example:positions:get
186
+ npm run example:positions:close
187
+ npm run example:positions:close-all
188
+ npm run example:positions:metrics
189
+ npm run example:positions:stream
190
+ npm run example:orders:submit
191
+ npm run example:account:metrics
192
+ npm run example:account:trade-journal
193
+ npm run example:account:trade-history
194
+ npm run example:symbols:info
195
+ npm run example:symbols:info:btc
196
+ npm run example:instruments:get
197
+ npm run example:instruments:get:forex
198
+ npm run example:ohlc:get
199
+ npm run example:ohlc:stream
200
+ npm run example:ohlc:stream:btc
201
+ npm run example:assessments:get
202
+ npm run example:assessments:get:btc
177
203
  ```
178
204
 
179
205
  ## DXtrade API Docs
package/dist/index.d.mts CHANGED
@@ -1,3 +1,5 @@
1
+ import { EventEmitter } from 'events';
2
+
1
3
  declare const BROKER: {
2
4
  readonly LARKFUNDING: "https://trade.gooeytrade.com";
3
5
  readonly EIGHTCAP: "https://trader.dx-eightcap.com";
@@ -74,7 +76,10 @@ declare enum ERROR {
74
76
  ACCOUNT_POSITIONS_ERROR = "ACCOUNT_POSITIONS_ERROR",
75
77
  TRADE_JOURNAL_ERROR = "TRADE_JOURNAL_ERROR",
76
78
  TRADE_HISTORY_ERROR = "TRADE_HISTORY_ERROR",
77
- ASSESSMENTS_ERROR = "ASSESSMENTS_ERROR"
79
+ ASSESSMENTS_ERROR = "ASSESSMENTS_ERROR",
80
+ RATE_LIMITED = "RATE_LIMITED",
81
+ WS_MANAGER_ERROR = "WS_MANAGER_ERROR",
82
+ STREAM_REQUIRES_CONNECT = "STREAM_REQUIRES_CONNECT"
78
83
  }
79
84
  declare enum WS_MESSAGE {
80
85
  ACCOUNT_METRICS = "ACCOUNT_METRICS",
@@ -95,7 +100,8 @@ declare enum WS_MESSAGE {
95
100
  }
96
101
  declare namespace WS_MESSAGE {
97
102
  enum SUBTOPIC {
98
- BIG_CHART_COMPONENT = "BigChartComponentPresenter-4"
103
+ BIG_CHART_COMPONENT = "BigChartComponentPresenter-4",
104
+ OHLC_STREAM = "OHLCStreamPresenter-0"
99
105
  }
100
106
  }
101
107
 
@@ -209,6 +215,16 @@ declare namespace Order {
209
215
  }
210
216
  }
211
217
 
218
+ declare class WsManager extends EventEmitter {
219
+ private _ws;
220
+ private _cache;
221
+ connect(wsUrl: string, cookieStr: string, debug?: boolean | string): Promise<void>;
222
+ waitFor<T>(type: string, timeout?: number): Promise<T>;
223
+ getCached<T>(type: string): T | undefined;
224
+ close(): void;
225
+ get isConnected(): boolean;
226
+ }
227
+
212
228
  interface DxtradeConfig {
213
229
  username: string;
214
230
  password: string;
@@ -226,6 +242,20 @@ interface DxtradeCallbacks {
226
242
  onOrderPlaced?: (order: Order.Response) => void;
227
243
  onOrderUpdate?: (order: Order.Update) => void;
228
244
  }
245
+ interface ClientContext {
246
+ config: DxtradeConfig;
247
+ callbacks: DxtradeCallbacks;
248
+ cookies: Record<string, string>;
249
+ csrf: string | null;
250
+ accountId: string | null;
251
+ atmosphereId: string | null;
252
+ wsManager: WsManager | null;
253
+ broker: keyof typeof BROKER;
254
+ retries: number;
255
+ debug: boolean | string;
256
+ ensureSession(): void;
257
+ throwError(code: string, message: string): never;
258
+ }
229
259
 
230
260
  interface WsPayload {
231
261
  accountId: string | null;
@@ -360,13 +390,28 @@ declare namespace Position {
360
390
  stopLoss: number | null;
361
391
  }
362
392
  interface Metrics {
363
- positionCode: string;
364
- openPl: number;
365
- openPlPerLot: number;
366
- currentPrice: number;
367
- convertedOpenPl: number;
393
+ uid: string;
394
+ accountId: string;
395
+ margin: number;
396
+ plOpen: number;
397
+ plClosed: number;
398
+ totalCommissions: number;
399
+ totalFinancing: number;
400
+ plRate: number;
401
+ averagePrice: number;
402
+ marketValue: number;
368
403
  [key: string]: unknown;
369
404
  }
405
+ interface Full extends Get {
406
+ margin: number;
407
+ plOpen: number;
408
+ plClosed: number;
409
+ totalCommissions: number;
410
+ totalFinancing: number;
411
+ plRate: number;
412
+ averagePrice: number;
413
+ marketValue: number;
414
+ }
370
415
  interface Close {
371
416
  legs: {
372
417
  instrumentId: number;
@@ -409,68 +454,44 @@ declare namespace Symbol {
409
454
  }
410
455
  }
411
456
 
412
- /**
413
- * Client for interacting with the DXtrade trading API.
414
- *
415
- * @example
416
- * ```ts
417
- * import { DxtradeClient, ORDER_TYPE, SIDE, BROKER } from "dxtrade-api";
418
- *
419
- * const client = new DxtradeClient({
420
- * username: "your_username",
421
- * password: "your_password",
422
- * broker: BROKER.FTMO,
423
- * });
424
- *
425
- * await client.connect();
426
- * ```
427
- */
428
- declare class DxtradeClient {
457
+ declare class PositionsDomain {
429
458
  private _ctx;
430
- constructor(config: DxtradeConfig);
431
- /** Authenticate with the broker using username and password. */
432
- login(): Promise<void>;
433
- /** Fetch the CSRF token required for authenticated requests. */
434
- fetchCsrf(): Promise<void>;
435
- /** Switch to a specific trading account by ID. */
436
- switchAccount(accountId: string): Promise<void>;
437
- /** Connect to the broker: login, fetch CSRF, WebSocket handshake, and optional account switch. */
438
- connect(): Promise<void>;
439
- /** Search for symbols matching the given text (e.g. "EURUSD", "BTC"). */
440
- getSymbolSuggestions(text: string): Promise<Symbol.Suggestion[]>;
441
- /** Get detailed instrument info for a symbol, including volume limits and lot size. */
442
- getSymbolInfo(symbol: string): Promise<Symbol.Info>;
443
- /** Get order size limits and stop/limit distances for all symbols. */
444
- getSymbolLimits(): Promise<Symbol.Limits[]>;
459
+ constructor(_ctx: ClientContext);
460
+ /** Get all open positions with P&L metrics merged. */
461
+ get(): Promise<Position.Full[]>;
462
+ /** Close a position. Supports partial closes by specifying a quantity smaller than the full position size. */
463
+ close(params: Position.Close): Promise<void>;
464
+ /** Close all open positions with market orders. */
465
+ closeAll(): Promise<void>;
466
+ /** Stream real-time position updates with P&L metrics. Requires connect(). Returns unsubscribe function. */
467
+ stream(callback: (positions: Position.Full[]) => void): () => void;
468
+ }
469
+ declare class OrdersDomain {
470
+ private _ctx;
471
+ constructor(_ctx: ClientContext);
472
+ /** Get all pending/open orders via WebSocket. */
473
+ get(): Promise<Order.Get[]>;
445
474
  /**
446
475
  * Submit a trading order and wait for WebSocket confirmation.
447
476
  * Supports market, limit, and stop orders with optional stop loss and take profit.
448
477
  */
449
- submitOrder(params: Order.SubmitParams): Promise<Order.Update>;
450
- /** Get all pending/open orders via WebSocket. */
451
- getOrders(): Promise<Order.Get[]>;
478
+ submit(params: Order.SubmitParams): Promise<Order.Update>;
452
479
  /** Cancel a single pending order by its order chain ID. */
453
- cancelOrder(orderChainId: number): Promise<void>;
480
+ cancel(orderChainId: number): Promise<void>;
454
481
  /** Cancel all pending orders. */
455
- cancelAllOrders(): Promise<void>;
482
+ cancelAll(): Promise<void>;
483
+ }
484
+ declare class AccountDomain {
485
+ private _ctx;
486
+ constructor(_ctx: ClientContext);
456
487
  /** Get account metrics including equity, balance, margin, and open P&L. */
457
- getAccountMetrics(): Promise<Account.Metrics>;
458
- /** Get all open positions via WebSocket. */
459
- getPositions(): Promise<Position.Get[]>;
460
- /**
461
- * Close a position. Supports partial closes by specifying a quantity smaller than the full position size.
462
- */
463
- closePosition(position: Position.Close): Promise<void>;
464
- /** Close all open positions with market orders. */
465
- closeAllPositions(): Promise<void>;
466
- /** Get position-level P&L metrics via WebSocket. */
467
- getPositionMetrics(): Promise<Position.Metrics[]>;
488
+ metrics(): Promise<Account.Metrics>;
468
489
  /**
469
490
  * Fetch trade journal entries for a date range.
470
491
  * @param params.from - Start timestamp (Unix ms)
471
492
  * @param params.to - End timestamp (Unix ms)
472
493
  */
473
- getTradeJournal(params: {
494
+ tradeJournal(params: {
474
495
  from: number;
475
496
  to: number;
476
497
  }): Promise<any>;
@@ -479,14 +500,30 @@ declare class DxtradeClient {
479
500
  * @param params.from - Start timestamp (Unix ms)
480
501
  * @param params.to - End timestamp (Unix ms)
481
502
  */
482
- getTradeHistory(params: {
503
+ tradeHistory(params: {
483
504
  from: number;
484
505
  to: number;
485
506
  }): Promise<Account.TradeHistory[]>;
507
+ }
508
+ declare class SymbolsDomain {
509
+ private _ctx;
510
+ constructor(_ctx: ClientContext);
511
+ /** Search for symbols matching the given text (e.g. "EURUSD", "BTC"). */
512
+ search(text: string): Promise<Symbol.Suggestion[]>;
513
+ /** Get detailed instrument info for a symbol, including volume limits and lot size. */
514
+ info(symbol: string): Promise<Symbol.Info>;
515
+ /** Get order size limits and stop/limit distances for all symbols. */
516
+ limits(): Promise<Symbol.Limits[]>;
517
+ }
518
+ declare class InstrumentsDomain {
519
+ private _ctx;
520
+ constructor(_ctx: ClientContext);
486
521
  /** Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`). */
487
- getInstruments(params?: Partial<Instrument.Info>): Promise<Instrument.Info[]>;
488
- /** Fetch PnL assessments for an instrument within a date range. */
489
- getAssessments(params: Assessments.Params): Promise<Assessments.Response>;
522
+ get(params?: Partial<Instrument.Info>): Promise<Instrument.Info[]>;
523
+ }
524
+ declare class OhlcDomain {
525
+ private _ctx;
526
+ constructor(_ctx: ClientContext);
490
527
  /**
491
528
  * Fetch OHLC price bars for a symbol.
492
529
  * @param params.symbol - Instrument symbol (e.g. "EURUSD")
@@ -495,7 +532,61 @@ declare class DxtradeClient {
495
532
  * @param params.maxBars - Maximum bars to return (default: 3500)
496
533
  * @param params.priceField - "bid" or "ask" (default: "bid")
497
534
  */
498
- getOHLC(params: OHLC.Params): Promise<OHLC.Bar[]>;
535
+ get(params: OHLC.Params): Promise<OHLC.Bar[]>;
536
+ /** Stream real-time OHLC bar updates. Requires connect(). Returns unsubscribe function. */
537
+ stream(params: OHLC.Params, callback: (bars: OHLC.Bar[]) => void): Promise<() => void>;
538
+ }
539
+ declare class AssessmentsDomain {
540
+ private _ctx;
541
+ constructor(_ctx: ClientContext);
542
+ /** Fetch PnL assessments for an instrument within a date range. */
543
+ get(params: Assessments.Params): Promise<Assessments.Response>;
544
+ }
545
+ /**
546
+ * Client for interacting with the DXtrade trading API.
547
+ *
548
+ * @example
549
+ * ```ts
550
+ * import { DxtradeClient, ORDER_TYPE, SIDE, BROKER } from "dxtrade-api";
551
+ *
552
+ * const client = new DxtradeClient({
553
+ * username: "your_username",
554
+ * password: "your_password",
555
+ * broker: BROKER.FTMO,
556
+ * });
557
+ *
558
+ * await client.connect();
559
+ * ```
560
+ */
561
+ declare class DxtradeClient {
562
+ private _ctx;
563
+ /** Position operations: get, close, metrics, streaming. */
564
+ readonly positions: PositionsDomain;
565
+ /** Order operations: get, submit, cancel. */
566
+ readonly orders: OrdersDomain;
567
+ /** Account operations: metrics, trade journal, trade history. */
568
+ readonly account: AccountDomain;
569
+ /** Symbol operations: search, info, limits. */
570
+ readonly symbols: SymbolsDomain;
571
+ /** Instrument operations: get (with optional filtering). */
572
+ readonly instruments: InstrumentsDomain;
573
+ /** OHLC price bar operations: get, stream. */
574
+ readonly ohlc: OhlcDomain;
575
+ /** PnL assessment operations: get. */
576
+ readonly assessments: AssessmentsDomain;
577
+ constructor(config: DxtradeConfig);
578
+ /** Authenticate with the broker using username and password. */
579
+ login(): Promise<void>;
580
+ /** Fetch the CSRF token required for authenticated requests. */
581
+ fetchCsrf(): Promise<void>;
582
+ /** Switch to a specific trading account by ID. */
583
+ switchAccount(accountId: string): Promise<void>;
584
+ /** Authenticate and establish a session: login, fetch CSRF, WebSocket handshake, and optional account switch. */
585
+ auth(): Promise<void>;
586
+ /** Connect to the broker with a persistent WebSocket: auth + persistent WS for data reuse and streaming. */
587
+ connect(): Promise<void>;
588
+ /** Close the persistent WebSocket connection. */
589
+ disconnect(): void;
499
590
  }
500
591
 
501
592
  export { ACTION, BROKER, type DxtradeCallbacks, DxtradeClient, type DxtradeConfig, DxtradeError, ERROR, ORDER_TYPE, SIDE, TIF, WS_MESSAGE, type WsPayload, endpoints };