Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 65 additions & 41 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@ npm install dxtrade-api
- [x] OHLC / price bar data
- [x] PnL assessments
- [x] Multi-broker support (FTMO, Eightcap, Lark Funding)
- [x] Persistent WebSocket with `connect()`
- [x] Real-time position streaming
- [x] Full TypeScript support
- [ ] Batch orders
- [ ] Modify existing orders
Expand All @@ -46,12 +48,13 @@ const client = new DxtradeClient({
accountId: "optional_account_id",
});

// connect() = auth + persistent WebSocket (recommended)
await client.connect();

const suggestions = await client.getSymbolSuggestions("EURUSD");
const suggestions = await client.symbols.search("EURUSD");
const symbol = suggestions[0];

const order = await client.submitOrder({
const order = await client.orders.submit({
symbol: symbol.name,
side: SIDE.BUY,
quantity: 0.01,
Expand All @@ -60,6 +63,18 @@ const order = await client.submitOrder({
});

console.log(`Order ${order.orderId}: ${order.status}`);
client.disconnect();
```

## Connection Modes

```ts
// Persistent WebSocket (recommended) — reuses one WS for all data, enables streaming
await client.connect();
client.disconnect(); // when done

// Lightweight — auth only, each data call opens a temporary WebSocket
await client.auth();
```

## Configuration
Expand Down Expand Up @@ -89,42 +104,51 @@ BROKER.FTMO // "https://dxtrade.ftmo.com"

### Session

- `client.connect()` — Login, fetch CSRF, WebSocket handshake, optional account switch
- `client.connect()` — Auth + persistent WebSocket. Recommended for most use cases.
- `client.auth()` — Lightweight: login, fetch CSRF, WebSocket handshake, optional account switch. No persistent WS.
- `client.disconnect()` — Close the persistent WebSocket connection
- `client.login()` — Authenticate with broker
- `client.fetchCsrf()` — Fetch CSRF token from broker page
- `client.switchAccount(accountId)` — Switch to a specific account

### Market Data
### Positions

- `client.positions.get()` — Get all open positions
- `client.positions.close(params)` — Close a position (supports partial closes via the quantity field)
- `client.positions.closeAll()` — Close all open positions with market orders
- `client.positions.metrics()` — Get position-level P&L metrics
- `client.positions.stream(callback)` — Stream real-time position updates (requires `connect()`). Returns an unsubscribe function.

- `client.getSymbolSuggestions(text)` — Search for symbols
- `client.getSymbolInfo(symbol)` — Get instrument info (volume limits, lot size)
- `client.getSymbolLimits()` — Get order size limits and stop/limit distances for all symbols
- `client.getInstruments(params?)` — Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`)
- `client.getOHLC(params)` — Fetch OHLC price bars for a symbol (resolution, range, maxBars, priceField)
### Orders

### Trading
- `client.orders.get()` — Get all pending/open orders
- `client.orders.submit(params)` — Submit an order and wait for WebSocket confirmation
- `client.orders.cancel(orderChainId)` — Cancel a single pending order
- `client.orders.cancelAll()` — Cancel all pending orders

- `client.submitOrder(params)` — Submit an order and wait for WebSocket confirmation
- `client.getOrders()` — Get all pending/open orders via WebSocket
- `client.cancelOrder(orderChainId)` — Cancel a single pending order
- `client.cancelAllOrders()` — Cancel all pending orders
### Account

### Positions
- `client.account.metrics()` — Get account metrics (equity, balance, margin, open P&L, etc.)
- `client.account.tradeJournal({ from, to })` — Fetch trade journal entries for a date range (Unix timestamps)
- `client.account.tradeHistory({ from, to })` — Fetch trade history for a date range (Unix timestamps)

- `client.getPositions()` — Get all open positions via WebSocket
- `client.closePosition(params)` — Close a position (supports partial closes via the quantity field)
- `client.closeAllPositions()` — Close all open positions with market orders
- `client.getPositionMetrics()` — Get position-level P&L metrics via WebSocket
### Symbols

### Account
- `client.symbols.search(text)` — Search for symbols
- `client.symbols.info(symbol)` — Get instrument info (volume limits, lot size)
- `client.symbols.limits()` — Get order size limits and stop/limit distances for all symbols

### Instruments

- `client.instruments.get(params?)` — Get all available instruments, optionally filtered by partial match (e.g. `{ type: "FOREX" }`)

### OHLC

- `client.getAccountMetrics()` — Get account metrics (equity, balance, margin, open P&L, etc.)
- `client.getTradeJournal({ from, to })` — Fetch trade journal entries for a date range (Unix timestamps)
- `client.getTradeHistory({ from, to })` — Fetch trade history for a date range (Unix timestamps)
- `client.ohlc.get(params)` — Fetch OHLC price bars for a symbol (resolution, range, maxBars, priceField)

### Analytics
### Assessments

- `client.getAssessments(params)` — Fetch PnL assessments for a date range
- `client.assessments.get(params)` — Fetch PnL assessments for a date range

## Enums

Expand Down Expand Up @@ -157,23 +181,23 @@ const client = new DxtradeClient({
```bash
cp .env.example .env # fill in credentials
npm run example:connect
npm run example:order
npm run example:orders
npm run example:positions
npm run example:close-position
npm run example:close-all-positions
npm run example:position-metrics
npm run example:assessments
npm run example:assessments:btc
npm run example:account
npm run example:instruments
npm run example:ohlc
npm run example:instruments:forex
npm run example:symbol
npm run example:symbol:btc
npm run example:trade-journal
npm run example:trade-history
npm run example:debug
npm run example:positions:get
npm run example:positions:close
npm run example:positions:close-all
npm run example:positions:metrics
npm run example:positions:stream
npm run example:orders:submit
npm run example:account:metrics
npm run example:account:trade-journal
npm run example:account:trade-history
npm run example:symbols:info
npm run example:symbols:info:btc
npm run example:instruments:get
npm run example:instruments:get:forex
npm run example:ohlc:get
npm run example:assessments:get
npm run example:assessments:get:btc
```

## DXtrade API Docs
Expand Down
4 changes: 2 additions & 2 deletions examples/account-metrics.ts → examples/account.metrics.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
const metrics = await client.getAccountMetrics();
await client.auth();
const metrics = await client.account.metrics();

console.log("Account metrics:", metrics);
})().catch(console.error);
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
await client.auth();

const from = new Date(new Date().setMonth(new Date().getMonth() - 1)).getTime();
const to = Date.now();

const history = await client.getTradeHistory({ from, to });
const history = await client.account.tradeHistory({ from, to });

console.log("Trade history:", history);
})().catch(console.error);
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
await client.auth();
// convert the dates to normal dates
const from = new Date(new Date().setMonth(new Date().getMonth() - 1)).getTime();
const to = Date.now();

const journal = await client.getTradeJournal({ from, to });
const journal = await client.account.tradeJournal({ from, to });

console.log("Trade journal:", journal);
})().catch(console.error);
4 changes: 2 additions & 2 deletions examples/get-assessments.ts → examples/assessments.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
await client.auth();

const now = Date.now();
const oneWeekAgo = now - 7 * 24 * 60 * 60 * 1000;

const assessments = await client.getAssessments({
const assessments = await client.assessments.get({
from: oneWeekAgo,
to: now,
instrument: "EURUSD",
Expand Down
3 changes: 2 additions & 1 deletion examples/connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,6 @@ const client = new DxtradeClient({

(async () => {
await client.connect();
console.log("Connected successfully");
console.log("Connected successfully (persistent WS open)");
client.disconnect();
})().catch(console.error);
14 changes: 0 additions & 14 deletions examples/debug.ts

This file was deleted.

10 changes: 5 additions & 5 deletions examples/instruments.ts → examples/instruments.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,16 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
console.log("Connected — fetching instruments\n");
await client.auth();
console.log("Authenticated — fetching instruments\n");

// Get all instruments
const instruments = await client.getInstruments();
console.log("instruments", "[\n", instruments[0], `\n...and ${instruments.length - 1} more`, "\n]");
const instruments = await client.instruments.get();
console.log("instruments: ", "[\n", instruments[0], `\n...and ${instruments.length - 1} more`, "\n]");

console.log("\n===================================\n");

// Get filtered instruments
const instrumentFiltered = await client.getInstruments({ symbol: "BTCUSD" });
const instrumentFiltered = await client.instruments.get({ symbol: "BTCUSD" });
console.log("instrumentFiltered: ", instrumentFiltered);
})().catch(console.error);
4 changes: 2 additions & 2 deletions examples/ohlc.ts → examples/ohlc.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@ const client = new DxtradeClient({
const symbol = process.argv[2] ?? "EURUSD";

(async () => {
await client.connect();
await client.auth();

const bars = await client.getOHLC({ symbol });
const bars = await client.ohlc.get({ symbol });

console.log("Last 5 bars:", "[\n", ...bars.slice(-5), `\n...and ${bars.length - 5} more`, "\n]");
console.log(`Fetched ${bars.length} bars for ${symbol}`);
Expand Down
14 changes: 7 additions & 7 deletions examples/orders.ts → examples/orders.submit.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,17 @@ const client = new DxtradeClient({
const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));

(async () => {
await client.connect();
await client.auth();

const suggestions = await client.getSymbolSuggestions("EURUSD");
const suggestions = await client.symbols.search("EURUSD");
const symbol = suggestions[0];
console.log(`Found symbol: ${symbol.name} (id: ${symbol.id})`);

const info = await client.getSymbolInfo(symbol.name);
const info = await client.symbols.info(symbol.name);
console.log(`Min volume: ${info.minVolume}, Lot size: ${info.lotSize}`);

// 1. Submit a market order
const order = await client.submitOrder({
const order = await client.orders.submit({
symbol: symbol.name,
side: SIDE.BUY,
quantity: info.minVolume,
Expand All @@ -34,13 +34,13 @@ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
// 2. Wait 2 seconds, then close the position
await sleep(2000);
console.log("\nClosing position...");
await client.closeAllPositions();
await client.positions.closeAll();
console.log("All positions closed");

// 3. Wait 2 seconds, then submit a limit order and immediately cancel it
await sleep(2000);
console.log("\nPlacing limit order...");
const limitOrder = await client.submitOrder({
const limitOrder = await client.orders.submit({
symbol: symbol.name,
side: SIDE.BUY,
quantity: info.minVolume,
Expand All @@ -51,6 +51,6 @@ const sleep = (ms: number) => new Promise((resolve) => setTimeout(resolve, ms));
console.log(`Limit order placed: ${limitOrder.orderId} — status: ${limitOrder.status}`);

console.log("Cancelling order...");
await client.cancelAllOrders();
await client.orders.cancelAll();
console.log("All orders cancelled");
})().catch(console.error);
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
await client.auth();

const positions = await client.getPositions();
const positions = await client.positions.get();
console.log(`Closing ${positions.length} position(s)...`);

await client.closeAllPositions();
await client.positions.closeAll();

console.log("All positions closed");
})().catch(console.error);
4 changes: 2 additions & 2 deletions examples/close-position.ts → examples/positions.close.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
await client.auth();
// TODO:: improve parameters! maybe even have a "closeWholePosition" function

const positions = await client.closePosition({
const positions = await client.positions.close({
legs: [
{
instrumentId: 3438,
Expand Down
4 changes: 2 additions & 2 deletions examples/positions.ts → examples/positions.get.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
const positions = await client.getPositions();
await client.auth();
const positions = await client.positions.get();

console.log("Positions: ", positions);
})().catch(console.error);
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,8 @@ const client = new DxtradeClient({
});

(async () => {
await client.connect();
const metrics = await client.getPositionMetrics();
await client.auth();
const metrics = await client.positions.metrics();

console.log("Position metrics:", metrics);
})().catch(console.error);
27 changes: 27 additions & 0 deletions examples/positions.stream.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
import "dotenv/config";
import { DxtradeClient, BROKER } from "../src";

const client = new DxtradeClient({
username: process.env.DXTRADE_USERNAME!,
password: process.env.DXTRADE_PASSWORD!,
broker: process.env.DXTRADE_BROKER! || BROKER.FTMO,
accountId: process.env.DXTRADE_ACCOUNT_ID,
debug: process.env.DXTRADE_DEBUG || false,
});

(async () => {
await client.connect();
console.log("Connected — streaming positions...\n");

const unsubscribe = client.positions.stream((positions) => {
console.log("Positions: ", positions);
console.log();
});

// Stream for 60 seconds then clean up
setTimeout(() => {
console.log("Unsubscribing and disconnecting...");
unsubscribe();
client.disconnect();
}, 60_000);
})().catch(console.error);
Loading