hedgequantx 1.8.31 → 1.8.32

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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "hedgequantx",
3
- "version": "1.8.31",
3
+ "version": "1.8.32",
4
4
  "description": "Prop Futures Algo Trading CLI - Connect to Topstep, Alpha Futures, and other prop firms",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -196,7 +196,7 @@ const PROPFIRMS = {
196
196
  platform: 'Rithmic',
197
197
  rithmicSystem: 'Apex',
198
198
  wsEndpoint: 'wss://ritpa11120.11.rithmic.com:443',
199
- defaultStartingBalance: 300000
199
+
200
200
  },
201
201
  topsteptrader: {
202
202
  id: 'topsteptrader',
@@ -72,7 +72,7 @@ const copyTradingMenu = async () => {
72
72
  // Step 1: Select Lead Account
73
73
  console.log(chalk.cyan(' Step 1: Select LEAD Account'));
74
74
  const leadOptions = allAccounts.map((a, i) => ({
75
- label: `${a.propfirm} - ${a.account.accountName || a.account.accountId} ($${a.account.balance.toLocaleString()})`,
75
+ label: `${a.propfirm} - ${a.account.accountName || a.account.accountId}${a.account.balance !== null ? ` ($${a.account.balance.toLocaleString()})` : ''}`,
76
76
  value: i
77
77
  }));
78
78
  leadOptions.push({ label: '< Cancel', value: -1 });
@@ -88,7 +88,7 @@ const copyTradingMenu = async () => {
88
88
  .map((a, i) => ({ a, i }))
89
89
  .filter(x => x.i !== leadIdx)
90
90
  .map(x => ({
91
- label: `${x.a.propfirm} - ${x.a.account.accountName || x.a.account.accountId} ($${x.a.account.balance.toLocaleString()})`,
91
+ label: `${x.a.propfirm} - ${x.a.account.accountName || x.a.account.accountId}${x.a.account.balance !== null ? ` ($${x.a.account.balance.toLocaleString()})` : ''}`,
92
92
  value: x.i
93
93
  }));
94
94
  followerOptions.push({ label: '< Cancel', value: -1 });
@@ -49,7 +49,7 @@ const oneAccountMenu = async (service) => {
49
49
 
50
50
  // Select account
51
51
  const options = activeAccounts.map(acc => ({
52
- label: `${acc.accountName || acc.accountId} (${acc.propfirm || 'Unknown'}) - $${(acc.balance || 0).toLocaleString()}`,
52
+ label: `${acc.accountName || acc.accountId} (${acc.propfirm || 'Unknown'})${acc.balance !== null ? ` - $${acc.balance.toLocaleString()}` : ''}`,
53
53
  value: acc
54
54
  }));
55
55
  options.push({ label: '< Back', value: 'back' });
@@ -183,26 +183,17 @@ const launchAlgo = async (service, account, contract, config) => {
183
183
  if (!showName && account.accountName) msg = msg.replace(new RegExp(account.accountName, 'gi'), 'HQX *****');
184
184
  ui.addLog(d.type || 'info', msg);
185
185
  });
186
- hqx.on('signal', (d) => {
187
- stats.signals = (stats.signals || 0) + 1;
188
- ui.addLog('signal', `${d.side === 'long' ? 'BUY' : 'SELL'} @ ${d.entry?.toFixed(2) || 'MKT'}`);
189
- });
190
- hqx.on('trade', (d) => {
191
- stats.trades++;
192
- stats.pnl += d.pnl || 0;
193
- if (d.pnl >= 0) { stats.wins++; ui.addLog('trade', `+$${d.pnl.toFixed(2)}`); }
194
- else { stats.losses++; ui.addLog('loss', `-$${Math.abs(d.pnl).toFixed(2)}`); }
195
-
196
- if (stats.pnl >= dailyTarget) {
197
- stopReason = 'target'; running = false;
198
- ui.addLog('success', `TARGET! +$${stats.pnl.toFixed(2)}`);
199
- hqx.stopAlgo();
200
- } else if (stats.pnl <= -maxRisk) {
201
- stopReason = 'risk'; running = false;
202
- ui.addLog('error', `MAX RISK! -$${Math.abs(stats.pnl).toFixed(2)}`);
203
- hqx.stopAlgo();
186
+
187
+ // REAL P&L direct from Rithmic - no calculation
188
+ hqx.on('stats', (d) => {
189
+ if (d.realTimePnL) {
190
+ stats.pnl = d.realTimePnL.totalPnL;
204
191
  }
192
+ stats.trades = d.trades;
193
+ stats.wins = d.wins;
194
+ stats.losses = d.losses;
205
195
  });
196
+
206
197
  hqx.on('error', (d) => { ui.addLog('error', d.message || 'Error'); });
207
198
  hqx.on('disconnected', () => { stats.connected = false; ui.addLog('warning', 'Disconnected'); });
208
199
 
@@ -128,8 +128,9 @@ class AlgoUI {
128
128
  const { W } = this;
129
129
  const isCopyTrading = this.config.mode === 'copy-trading';
130
130
 
131
- const pnlColor = stats.pnl >= 0 ? chalk.green : chalk.red;
132
- const pnlStr = (stats.pnl >= 0 ? '+$' : '-$') + Math.abs(stats.pnl).toFixed(2);
131
+ const pnl = stats.pnl !== null && stats.pnl !== undefined ? stats.pnl : null;
132
+ const pnlColor = pnl === null ? chalk.gray : (pnl >= 0 ? chalk.green : chalk.red);
133
+ const pnlStr = pnl === null ? '--' : ((pnl >= 0 ? '+$' : '-$') + Math.abs(pnl).toFixed(2));
133
134
  const latencyColor = stats.latency < 100 ? chalk.green : (stats.latency < 300 ? chalk.yellow : chalk.red);
134
135
  const serverColor = stats.connected ? chalk.green : chalk.red;
135
136
 
@@ -172,8 +173,10 @@ class AlgoUI {
172
173
  this._line(chalk.cyan(GM));
173
174
 
174
175
  // Row 3: Target | Risk
175
- const r3c1 = buildCell('Target', '$' + (stats.target || 0).toFixed(2), chalk.green, colL);
176
- const r3c2 = buildCell('Risk', '$' + (stats.risk || 0).toFixed(2), chalk.red, colR);
176
+ const targetStr = stats.target !== null && stats.target !== undefined ? '$' + stats.target.toFixed(2) : '--';
177
+ const riskStr = stats.risk !== null && stats.risk !== undefined ? '$' + stats.risk.toFixed(2) : '--';
178
+ const r3c1 = buildCell('Target', targetStr, chalk.green, colL);
179
+ const r3c2 = buildCell('Risk', riskStr, chalk.red, colR);
177
180
  row(r3c1.padded, r3c2.padded);
178
181
 
179
182
  this._line(chalk.cyan(GM));
@@ -65,10 +65,9 @@ const showStats = async (service) => {
65
65
  return;
66
66
  }
67
67
 
68
- // Collect stats
69
- let totalBalance = 0;
70
- let totalStartingBalance = 0;
71
- let totalPnL = 0;
68
+ // Collect REAL stats only - no estimation
69
+ let totalBalance = null;
70
+ let totalPnL = null;
72
71
  let allTrades = [];
73
72
  let totalOpenPositions = 0;
74
73
  let totalOpenOrders = 0;
@@ -78,27 +77,15 @@ const showStats = async (service) => {
78
77
 
79
78
  for (const account of activeAccounts) {
80
79
  const svc = account.service;
81
- const currentBalance = account.balance || 0;
82
- totalBalance += currentBalance;
83
80
 
84
- // Estimate starting balance
85
- let startingBalance = account.startingBalance || account.initialBalance || 0;
86
- if (!startingBalance) {
87
- const name = (account.accountName || '').toUpperCase();
88
- if (name.includes('150K') || name.includes('150')) startingBalance = 150000;
89
- else if (name.includes('100K') || name.includes('100')) startingBalance = 100000;
90
- else if (name.includes('50K') || name.includes('50')) startingBalance = 50000;
91
- else if (currentBalance >= 140000) startingBalance = 150000;
92
- else if (currentBalance >= 90000) startingBalance = 100000;
93
- else if (currentBalance >= 45000) startingBalance = 50000;
94
- else startingBalance = currentBalance;
81
+ // Only add REAL balance from API
82
+ if (account.balance !== null && account.balance !== undefined) {
83
+ totalBalance = (totalBalance || 0) + account.balance;
95
84
  }
96
85
 
97
- totalStartingBalance += startingBalance;
98
- account.startingBalance = startingBalance;
99
-
100
- if (account.profitAndLoss !== undefined) {
101
- totalPnL += account.profitAndLoss;
86
+ // Only add REAL P&L from API
87
+ if (account.profitAndLoss !== null && account.profitAndLoss !== undefined) {
88
+ totalPnL = (totalPnL || 0) + account.profitAndLoss;
102
89
  }
103
90
 
104
91
  // Positions & Orders
@@ -138,9 +125,7 @@ const showStats = async (service) => {
138
125
  }
139
126
  }
140
127
 
141
- if (totalPnL === 0 && totalStartingBalance > 0) {
142
- totalPnL = totalBalance - totalStartingBalance;
143
- }
128
+ // NO estimation - only real data from API
144
129
 
145
130
  // Aggregate stats
146
131
  let stats = {
@@ -34,6 +34,7 @@ const hashAccountId = (str) => {
34
34
  */
35
35
  const fetchAccounts = async (service) => {
36
36
  if (!service.orderConn || !service.loginInfo) {
37
+ debug('fetchAccounts: no connection or loginInfo');
37
38
  return [];
38
39
  }
39
40
 
@@ -41,29 +42,39 @@ const fetchAccounts = async (service) => {
41
42
  const accounts = [];
42
43
 
43
44
  const timeout = setTimeout(() => {
45
+ debug('fetchAccounts: timeout, found', accounts.length, 'accounts');
44
46
  service.accounts = accounts;
45
47
  resolve(accounts);
46
- }, 2000);
48
+ }, 5000);
47
49
 
48
- service.once('accountReceived', (account) => {
50
+ // Listen for ALL accounts (not just once)
51
+ const onAccount = (account) => {
52
+ debug('fetchAccounts: received account', account.accountId);
49
53
  accounts.push(account);
50
- });
54
+ };
55
+ service.on('accountReceived', onAccount);
51
56
 
52
57
  service.once('accountListComplete', () => {
58
+ debug('fetchAccounts: complete, found', accounts.length, 'accounts');
53
59
  clearTimeout(timeout);
60
+ service.removeListener('accountReceived', onAccount);
54
61
  service.accounts = accounts;
55
62
  resolve(accounts);
56
63
  });
57
64
 
58
65
  try {
66
+ debug('fetchAccounts: sending RequestAccountList');
59
67
  service.orderConn.send('RequestAccountList', {
60
68
  templateId: REQ.ACCOUNT_LIST,
61
69
  userMsg: ['HQX'],
62
70
  fcmId: service.loginInfo.fcmId,
63
71
  ibId: service.loginInfo.ibId,
72
+ userType: 3, // USER_TYPE_TRADER - required by Rithmic API
64
73
  });
65
74
  } catch (e) {
75
+ debug('fetchAccounts: error', e.message);
66
76
  clearTimeout(timeout);
77
+ service.removeListener('accountReceived', onAccount);
67
78
  resolve([]);
68
79
  }
69
80
  });
@@ -98,36 +109,19 @@ const getTradingAccounts = async (service) => {
98
109
  debug(`Account ${acc.accountId} pnlData:`, JSON.stringify(pnlData));
99
110
  debug(` accountPnL map size:`, service.accountPnL.size);
100
111
 
101
- // Use API values if available
102
- const accountBalance = parseFloat(pnlData.accountBalance || 0);
103
- const openPnL = parseFloat(pnlData.openPositionPnl || 0);
104
- const closedPnL = parseFloat(pnlData.closedPositionPnl || 0);
105
- const dayPnL = parseFloat(pnlData.dayPnl || 0);
106
-
107
- // Balance: use API value if > 0, otherwise default
108
- // Most prop firms don't report balance via PnL stream, so we use default
109
- const startingBalance = service.propfirm.defaultBalance;
110
- const balance = accountBalance > 0 ? accountBalance : startingBalance;
111
-
112
- // P&L: prefer dayPnl from API, otherwise calculate from open+closed
113
- let profitAndLoss = 0;
114
- if (dayPnL !== 0) {
115
- profitAndLoss = dayPnL;
116
- } else if (openPnL !== 0 || closedPnL !== 0) {
117
- profitAndLoss = openPnL + closedPnL;
118
- }
119
- // Don't calculate P&L from balance difference - that's estimation
120
-
121
- debug(` balance: ${balance}, startingBalance: ${startingBalance}, P&L: ${profitAndLoss}`);
112
+ // REAL DATA FROM RITHMIC ONLY - NO DEFAULTS
113
+ const accountBalance = pnlData.accountBalance ? parseFloat(pnlData.accountBalance) : null;
114
+ const openPnL = pnlData.openPositionPnl ? parseFloat(pnlData.openPositionPnl) : null;
115
+ const closedPnL = pnlData.closedPositionPnl ? parseFloat(pnlData.closedPositionPnl) : null;
116
+ const dayPnL = pnlData.dayPnl ? parseFloat(pnlData.dayPnl) : null;
122
117
 
123
118
  return {
124
119
  accountId: hashAccountId(acc.accountId),
125
120
  rithmicAccountId: acc.accountId,
126
121
  accountName: acc.accountName || acc.accountId,
127
122
  name: acc.accountName || acc.accountId,
128
- balance: balance,
129
- startingBalance: startingBalance,
130
- profitAndLoss: profitAndLoss,
123
+ balance: accountBalance,
124
+ profitAndLoss: dayPnL !== null ? dayPnL : (openPnL !== null || closedPnL !== null ? (openPnL || 0) + (closedPnL || 0) : null),
131
125
  openPnL: openPnL,
132
126
  todayPnL: closedPnL,
133
127
  status: 0,
@@ -136,24 +130,7 @@ const getTradingAccounts = async (service) => {
136
130
  };
137
131
  });
138
132
 
139
- // Fallback if no accounts
140
- if (tradingAccounts.length === 0 && service.user) {
141
- const userName = service.user.userName || 'Unknown';
142
- tradingAccounts = [{
143
- accountId: hashAccountId(userName),
144
- rithmicAccountId: userName,
145
- accountName: userName,
146
- name: userName,
147
- balance: service.propfirm.defaultBalance,
148
- startingBalance: service.propfirm.defaultBalance,
149
- profitAndLoss: 0,
150
- openPnL: 0,
151
- todayPnL: 0,
152
- status: 0,
153
- platform: 'Rithmic',
154
- propfirm: service.propfirm.name,
155
- }];
156
- }
133
+ // No fallback - only real accounts from Rithmic
157
134
 
158
135
  return { success: true, accounts: tradingAccounts };
159
136
  };
@@ -17,12 +17,16 @@ const debug = (...args) => DEBUG && console.log('[Rithmic:Handler]', ...args);
17
17
  const createOrderHandler = (service) => {
18
18
  return (msg) => {
19
19
  const { templateId, data } = msg;
20
+
21
+ debug('ORDER_PLANT message received, templateId:', templateId);
20
22
 
21
23
  switch (templateId) {
22
24
  case RES.LOGIN_INFO:
25
+ debug('Handling LOGIN_INFO');
23
26
  handleLoginInfo(service, data);
24
27
  break;
25
28
  case RES.ACCOUNT_LIST:
29
+ debug('Handling ACCOUNT_LIST (303)');
26
30
  handleAccountList(service, data);
27
31
  break;
28
32
  case RES.TRADE_ROUTES:
@@ -93,10 +97,13 @@ const handleLoginInfo = (service, data) => {
93
97
  */
94
98
  const handleAccountList = (service, data) => {
95
99
  try {
100
+ debug('Decoding ResponseAccountList...');
96
101
  const res = proto.decode('ResponseAccountList', data);
102
+ debug('Decoded account list response:', JSON.stringify(res));
97
103
 
98
104
  if (res.rpCode?.[0] === '0') {
99
105
  // End of list
106
+ debug('Account list complete signal received');
100
107
  service.emit('accountListComplete');
101
108
  } else if (res.accountId) {
102
109
  const account = {
@@ -106,11 +113,14 @@ const handleAccountList = (service, data) => {
106
113
  accountName: res.accountName,
107
114
  accountCurrency: res.accountCurrency,
108
115
  };
116
+ debug('Account received:', account.accountId);
109
117
  service.accounts.push(account);
110
118
  service.emit('accountReceived', account);
119
+ } else {
120
+ debug('No accountId and no rpCode[0]=0, raw response:', res);
111
121
  }
112
122
  } catch (e) {
113
- // Ignore decode errors
123
+ debug('Error decoding account list:', e.message);
114
124
  }
115
125
  };
116
126
 
@@ -14,24 +14,24 @@ const { placeOrder, cancelOrder, getOrders, getOrderHistory, closePosition } = r
14
14
  const DEBUG = process.env.HQX_DEBUG === '1';
15
15
  const debug = (...args) => DEBUG && console.log('[Rithmic:Service]', ...args);
16
16
 
17
- // PropFirm configurations
17
+ // PropFirm configurations - NO FAKE DATA
18
18
  const PROPFIRM_CONFIGS = {
19
- 'apex': { name: 'Apex Trader Funding', systemName: 'Apex', defaultBalance: 300000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
20
- 'apex_rithmic': { name: 'Apex Trader Funding', systemName: 'Apex', defaultBalance: 300000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
21
- 'topstep_r': { name: 'Topstep (Rithmic)', systemName: RITHMIC_SYSTEMS.TOPSTEP, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
22
- 'bulenox_r': { name: 'Bulenox (Rithmic)', systemName: RITHMIC_SYSTEMS.BULENOX, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
23
- 'earn2trade': { name: 'Earn2Trade', systemName: RITHMIC_SYSTEMS.EARN_2_TRADE, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
24
- 'mescapital': { name: 'MES Capital', systemName: RITHMIC_SYSTEMS.MES_CAPITAL, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
25
- 'tradefundrr': { name: 'TradeFundrr', systemName: RITHMIC_SYSTEMS.TRADEFUNDRR, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
26
- 'thetradingpit': { name: 'The Trading Pit', systemName: RITHMIC_SYSTEMS.THE_TRADING_PIT, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
27
- 'fundedfutures': { name: 'Funded Futures Network', systemName: RITHMIC_SYSTEMS.FUNDED_FUTURES_NETWORK, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
28
- 'propshop': { name: 'PropShop Trader', systemName: RITHMIC_SYSTEMS.PROPSHOP_TRADER, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
29
- '4proptrader': { name: '4PropTrader', systemName: RITHMIC_SYSTEMS.FOUR_PROP_TRADER, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
30
- 'daytraders': { name: 'DayTraders.com', systemName: RITHMIC_SYSTEMS.DAY_TRADERS, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
31
- '10xfutures': { name: '10X Futures', systemName: RITHMIC_SYSTEMS.TEN_X_FUTURES, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
32
- 'lucidtrading': { name: 'Lucid Trading', systemName: RITHMIC_SYSTEMS.LUCID_TRADING, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
33
- 'thrivetrading': { name: 'Thrive Trading', systemName: RITHMIC_SYSTEMS.THRIVE_TRADING, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
34
- 'legendstrading': { name: 'Legends Trading', systemName: RITHMIC_SYSTEMS.LEGENDS_TRADING, defaultBalance: 150000, gateway: RITHMIC_ENDPOINTS.CHICAGO },
19
+ 'apex': { name: 'Apex Trader Funding', systemName: 'Apex', gateway: RITHMIC_ENDPOINTS.CHICAGO },
20
+ 'apex_rithmic': { name: 'Apex Trader Funding', systemName: 'Apex', gateway: RITHMIC_ENDPOINTS.CHICAGO },
21
+ 'topstep_r': { name: 'Topstep (Rithmic)', systemName: RITHMIC_SYSTEMS.TOPSTEP, gateway: RITHMIC_ENDPOINTS.CHICAGO },
22
+ 'bulenox_r': { name: 'Bulenox (Rithmic)', systemName: RITHMIC_SYSTEMS.BULENOX, gateway: RITHMIC_ENDPOINTS.CHICAGO },
23
+ 'earn2trade': { name: 'Earn2Trade', systemName: RITHMIC_SYSTEMS.EARN_2_TRADE, gateway: RITHMIC_ENDPOINTS.CHICAGO },
24
+ 'mescapital': { name: 'MES Capital', systemName: RITHMIC_SYSTEMS.MES_CAPITAL, gateway: RITHMIC_ENDPOINTS.CHICAGO },
25
+ 'tradefundrr': { name: 'TradeFundrr', systemName: RITHMIC_SYSTEMS.TRADEFUNDRR, gateway: RITHMIC_ENDPOINTS.CHICAGO },
26
+ 'thetradingpit': { name: 'The Trading Pit', systemName: RITHMIC_SYSTEMS.THE_TRADING_PIT, gateway: RITHMIC_ENDPOINTS.CHICAGO },
27
+ 'fundedfutures': { name: 'Funded Futures Network', systemName: RITHMIC_SYSTEMS.FUNDED_FUTURES_NETWORK, gateway: RITHMIC_ENDPOINTS.CHICAGO },
28
+ 'propshop': { name: 'PropShop Trader', systemName: RITHMIC_SYSTEMS.PROPSHOP_TRADER, gateway: RITHMIC_ENDPOINTS.CHICAGO },
29
+ '4proptrader': { name: '4PropTrader', systemName: RITHMIC_SYSTEMS.FOUR_PROP_TRADER, gateway: RITHMIC_ENDPOINTS.CHICAGO },
30
+ 'daytraders': { name: 'DayTraders.com', systemName: RITHMIC_SYSTEMS.DAY_TRADERS, gateway: RITHMIC_ENDPOINTS.CHICAGO },
31
+ '10xfutures': { name: '10X Futures', systemName: RITHMIC_SYSTEMS.TEN_X_FUTURES, gateway: RITHMIC_ENDPOINTS.CHICAGO },
32
+ 'lucidtrading': { name: 'Lucid Trading', systemName: RITHMIC_SYSTEMS.LUCID_TRADING, gateway: RITHMIC_ENDPOINTS.CHICAGO },
33
+ 'thrivetrading': { name: 'Thrive Trading', systemName: RITHMIC_SYSTEMS.THRIVE_TRADING, gateway: RITHMIC_ENDPOINTS.CHICAGO },
34
+ 'legendstrading': { name: 'Legends Trading', systemName: RITHMIC_SYSTEMS.LEGENDS_TRADING, gateway: RITHMIC_ENDPOINTS.CHICAGO },
35
35
  };
36
36
 
37
37
  class RithmicService extends EventEmitter {
@@ -41,7 +41,6 @@ class RithmicService extends EventEmitter {
41
41
  this.propfirm = PROPFIRM_CONFIGS[propfirmKey] || {
42
42
  name: propfirmKey,
43
43
  systemName: 'Rithmic Paper Trading',
44
- defaultBalance: 150000,
45
44
  gateway: RITHMIC_ENDPOINTS.PAPER
46
45
  };
47
46
  this.orderConn = null;
@@ -85,17 +84,15 @@ class RithmicService extends EventEmitter {
85
84
  this.loginInfo = data;
86
85
  this.user = { userName: username, fcmId: data.fcmId, ibId: data.ibId };
87
86
 
88
- try { await fetchAccounts(this); } catch (e) {}
89
-
90
- if (this.accounts.length === 0) {
91
- this.accounts = [{
92
- accountId: username,
93
- accountName: username,
94
- fcmId: data.fcmId,
95
- ibId: data.ibId,
96
- }];
87
+ try {
88
+ await fetchAccounts(this);
89
+ debug('Fetched accounts:', this.accounts.map(a => a.accountId));
90
+ } catch (e) {
91
+ debug('fetchAccounts error:', e.message);
97
92
  }
98
93
 
94
+ // NO FAKE ACCOUNTS - only real from Rithmic API
95
+
99
96
  this.credentials = { username, password };
100
97
 
101
98
  debug('Accounts found:', this.accounts.length);
@@ -34,11 +34,11 @@ class TradovateService extends EventEmitter {
34
34
  */
35
35
  getPropFirmConfig(key) {
36
36
  const propfirms = {
37
- 'apex_tradovate': { name: 'Apex (Tradovate)', isDemo: false, defaultBalance: 300000 },
38
- 'takeprofittrader': { name: 'TakeProfitTrader', isDemo: false, defaultBalance: 150000 },
39
- 'myfundedfutures': { name: 'MyFundedFutures', isDemo: false, defaultBalance: 150000 },
37
+ 'apex_tradovate': { name: 'Apex (Tradovate)', isDemo: false },
38
+ 'takeprofittrader': { name: 'TakeProfitTrader', isDemo: false },
39
+ 'myfundedfutures': { name: 'MyFundedFutures', isDemo: false },
40
40
  };
41
- return propfirms[key] || { name: key, isDemo: false, defaultBalance: 150000 };
41
+ return propfirms[key] || { name: key, isDemo: false };
42
42
  }
43
43
 
44
44
  /**