hedgequantx 1.3.6 → 1.3.7
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/package.json
CHANGED
|
@@ -95,29 +95,30 @@ const getTradingAccounts = async (service) => {
|
|
|
95
95
|
let tradingAccounts = service.accounts.map((acc) => {
|
|
96
96
|
// Get P&L data from accountPnL map (populated by PNL_PLANT messages)
|
|
97
97
|
const pnlData = service.accountPnL.get(acc.accountId) || {};
|
|
98
|
-
debug(`Account ${acc.accountId} pnlData:`, pnlData);
|
|
98
|
+
debug(`Account ${acc.accountId} pnlData:`, JSON.stringify(pnlData));
|
|
99
|
+
debug(` accountPnL map size:`, service.accountPnL.size);
|
|
99
100
|
|
|
100
|
-
// Use API values if available
|
|
101
|
+
// Use API values if available
|
|
101
102
|
const accountBalance = parseFloat(pnlData.accountBalance || 0);
|
|
102
103
|
const openPnL = parseFloat(pnlData.openPositionPnl || 0);
|
|
103
104
|
const closedPnL = parseFloat(pnlData.closedPositionPnl || 0);
|
|
104
105
|
const dayPnL = parseFloat(pnlData.dayPnl || 0);
|
|
105
106
|
|
|
106
|
-
// Balance: use API value if
|
|
107
|
-
|
|
107
|
+
// Balance: use API value if > 0, otherwise default
|
|
108
|
+
// Most prop firms don't report balance via PnL stream, so we use default
|
|
108
109
|
const startingBalance = service.propfirm.defaultBalance;
|
|
110
|
+
const balance = accountBalance > 0 ? accountBalance : startingBalance;
|
|
109
111
|
|
|
110
|
-
// P&L: prefer dayPnl from API, otherwise calculate
|
|
112
|
+
// P&L: prefer dayPnl from API, otherwise calculate from open+closed
|
|
111
113
|
let profitAndLoss = 0;
|
|
112
114
|
if (dayPnL !== 0) {
|
|
113
115
|
profitAndLoss = dayPnL;
|
|
114
116
|
} else if (openPnL !== 0 || closedPnL !== 0) {
|
|
115
117
|
profitAndLoss = openPnL + closedPnL;
|
|
116
|
-
} else if (accountBalance > 0) {
|
|
117
|
-
profitAndLoss = accountBalance - startingBalance;
|
|
118
118
|
}
|
|
119
|
+
// Don't calculate P&L from balance difference - that's estimation
|
|
119
120
|
|
|
120
|
-
debug(` balance: ${balance}, P&L: ${profitAndLoss}`);
|
|
121
|
+
debug(` balance: ${balance}, startingBalance: ${startingBalance}, P&L: ${profitAndLoss}`);
|
|
121
122
|
|
|
122
123
|
return {
|
|
123
124
|
accountId: hashAccountId(acc.accountId),
|
|
@@ -6,6 +6,10 @@
|
|
|
6
6
|
const { proto, decodeAccountPnL, decodeInstrumentPnL } = require('./protobuf');
|
|
7
7
|
const { RES, STREAM } = require('./constants');
|
|
8
8
|
|
|
9
|
+
// Debug mode
|
|
10
|
+
const DEBUG = process.env.HQX_DEBUG === '1';
|
|
11
|
+
const debug = (...args) => DEBUG && console.log('[Rithmic:Handler]', ...args);
|
|
12
|
+
|
|
9
13
|
/**
|
|
10
14
|
* Create ORDER_PLANT message handler
|
|
11
15
|
* @param {RithmicService} service - The Rithmic service instance
|
|
@@ -44,18 +48,24 @@ const createOrderHandler = (service) => {
|
|
|
44
48
|
const createPnLHandler = (service) => {
|
|
45
49
|
return (msg) => {
|
|
46
50
|
const { templateId, data } = msg;
|
|
51
|
+
|
|
52
|
+
debug('PNL message received, templateId:', templateId);
|
|
47
53
|
|
|
48
54
|
switch (templateId) {
|
|
49
55
|
case RES.PNL_POSITION_SNAPSHOT:
|
|
50
56
|
case RES.PNL_POSITION_UPDATES:
|
|
51
|
-
|
|
57
|
+
debug('PNL snapshot/updates response OK');
|
|
52
58
|
break;
|
|
53
59
|
case STREAM.ACCOUNT_PNL_UPDATE:
|
|
60
|
+
debug('Account PNL update received');
|
|
54
61
|
handleAccountPnLUpdate(service, data);
|
|
55
62
|
break;
|
|
56
63
|
case STREAM.INSTRUMENT_PNL_UPDATE:
|
|
64
|
+
debug('Instrument PNL update received');
|
|
57
65
|
handleInstrumentPnLUpdate(service, data);
|
|
58
66
|
break;
|
|
67
|
+
default:
|
|
68
|
+
debug('Unknown PNL templateId:', templateId);
|
|
59
69
|
}
|
|
60
70
|
};
|
|
61
71
|
};
|
|
@@ -136,19 +146,25 @@ const handleShowOrdersResponse = (service, data) => {
|
|
|
136
146
|
const handleAccountPnLUpdate = (service, data) => {
|
|
137
147
|
try {
|
|
138
148
|
const pnl = decodeAccountPnL(data);
|
|
149
|
+
debug('Decoded Account PNL:', JSON.stringify(pnl));
|
|
150
|
+
|
|
139
151
|
if (pnl.accountId) {
|
|
140
|
-
|
|
152
|
+
const pnlData = {
|
|
141
153
|
accountBalance: parseFloat(pnl.accountBalance || 0),
|
|
142
154
|
cashOnHand: parseFloat(pnl.cashOnHand || 0),
|
|
143
155
|
marginBalance: parseFloat(pnl.marginBalance || 0),
|
|
144
156
|
openPositionPnl: parseFloat(pnl.openPositionPnl || 0),
|
|
145
157
|
closedPositionPnl: parseFloat(pnl.closedPositionPnl || 0),
|
|
146
158
|
dayPnl: parseFloat(pnl.dayPnl || 0),
|
|
147
|
-
}
|
|
159
|
+
};
|
|
160
|
+
debug('Storing PNL for account:', pnl.accountId, pnlData);
|
|
161
|
+
service.accountPnL.set(pnl.accountId, pnlData);
|
|
148
162
|
service.emit('pnlUpdate', pnl);
|
|
163
|
+
} else {
|
|
164
|
+
debug('No accountId in PNL response');
|
|
149
165
|
}
|
|
150
166
|
} catch (e) {
|
|
151
|
-
|
|
167
|
+
debug('Error decoding Account PNL:', e.message);
|
|
152
168
|
}
|
|
153
169
|
};
|
|
154
170
|
|
|
@@ -10,6 +10,10 @@ const { createOrderHandler, createPnLHandler } = require('./handlers');
|
|
|
10
10
|
const { fetchAccounts, getTradingAccounts, requestPnLSnapshot, subscribePnLUpdates, getPositions, hashAccountId } = require('./accounts');
|
|
11
11
|
const { placeOrder, cancelOrder, getOrders, getOrderHistory, closePosition } = require('./orders');
|
|
12
12
|
|
|
13
|
+
// Debug mode
|
|
14
|
+
const DEBUG = process.env.HQX_DEBUG === '1';
|
|
15
|
+
const debug = (...args) => DEBUG && console.log('[Rithmic:Service]', ...args);
|
|
16
|
+
|
|
13
17
|
// PropFirm configurations
|
|
14
18
|
const PROPFIRM_CONFIGS = {
|
|
15
19
|
'apex': { name: 'Apex Trader Funding', systemName: 'Apex', defaultBalance: 300000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
|
|
@@ -94,19 +98,28 @@ class RithmicService extends EventEmitter {
|
|
|
94
98
|
|
|
95
99
|
this.credentials = { username, password };
|
|
96
100
|
|
|
101
|
+
debug('Accounts found:', this.accounts.length);
|
|
102
|
+
debug('Account IDs:', this.accounts.map(a => a.accountId));
|
|
103
|
+
|
|
97
104
|
// Connect to PNL_PLANT for balance/P&L data
|
|
98
105
|
try {
|
|
99
|
-
|
|
106
|
+
debug('Connecting to PNL_PLANT...');
|
|
107
|
+
const pnlConnected = await this.connectPnL(username, password);
|
|
108
|
+
debug('PNL_PLANT connected:', pnlConnected, 'pnlConn:', !!this.pnlConn);
|
|
109
|
+
|
|
100
110
|
if (this.pnlConn) {
|
|
111
|
+
debug('Requesting P&L snapshot...');
|
|
101
112
|
await requestPnLSnapshot(this);
|
|
113
|
+
debug('accountPnL map size after snapshot:', this.accountPnL.size);
|
|
102
114
|
subscribePnLUpdates(this);
|
|
103
115
|
}
|
|
104
116
|
} catch (e) {
|
|
105
|
-
|
|
117
|
+
debug('PnL connection failed:', e.message);
|
|
106
118
|
}
|
|
107
119
|
|
|
108
120
|
// Get accounts with P&L data (if available)
|
|
109
121
|
const result = await getTradingAccounts(this);
|
|
122
|
+
debug('Final accounts:', result.accounts.length);
|
|
110
123
|
|
|
111
124
|
resolve({ success: true, user: this.user, accounts: result.accounts });
|
|
112
125
|
});
|