hedgequantx 2.9.180 → 2.9.182

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": "2.9.180",
3
+ "version": "2.9.182",
4
4
  "description": "HedgeQuantX - Prop Futures Trading CLI",
5
5
  "main": "src/app.js",
6
6
  "bin": {
@@ -251,9 +251,23 @@ const fetchAllFrontMonths = (service) => {
251
251
 
252
252
  let sentCount = 0;
253
253
  let sendErrors = [];
254
- // Only send for first 5 products to test
254
+
255
+ // Prioritize CME products (ES, NQ, MNQ, MES, etc.) - most used by traders
255
256
  const productsArray = Array.from(productsToCheck.values());
256
- const testProducts = productsArray.slice(0, 60); // Limit to 60 for testing
257
+ const prioritySymbols = ['ES', 'NQ', 'MNQ', 'MES', 'RTY', 'M2K', 'YM', 'MYM', 'CL', 'MCL', 'GC', 'MGC', 'SI', 'HG', 'NG', 'ZB', 'ZN', 'ZF', 'ZT', '6E', '6J', '6B', '6A', '6C', '6S', 'ZC', 'ZS', 'ZW', 'ZM', 'ZL', 'HE', 'LE', 'GF'];
258
+
259
+ // Sort: priority symbols first (CME), then others
260
+ productsArray.sort((a, b) => {
261
+ const aPriority = prioritySymbols.includes(a.productCode) ? 0 : 1;
262
+ const bPriority = prioritySymbols.includes(b.productCode) ? 0 : 1;
263
+ if (aPriority !== bPriority) return aPriority - bPriority;
264
+ // Within same priority, prefer CME/CBOT
265
+ const aExchange = (a.exchange === 'CME' || a.exchange === 'CBOT') ? 0 : 1;
266
+ const bExchange = (b.exchange === 'CME' || b.exchange === 'CBOT') ? 0 : 1;
267
+ return aExchange - bExchange;
268
+ });
269
+
270
+ const testProducts = productsArray.slice(0, 60); // Limit to 60
257
271
 
258
272
  for (const product of testProducts) {
259
273
  try {
@@ -85,13 +85,19 @@ const storage = {
85
85
  };
86
86
 
87
87
  // Lazy load services to avoid circular dependencies
88
- let RithmicBrokerClient, brokerManager;
88
+ let RithmicBrokerClient, brokerManager, RithmicService;
89
89
  const loadServices = () => {
90
90
  if (!RithmicBrokerClient) {
91
91
  ({ RithmicBrokerClient, manager: brokerManager } = require('./rithmic-broker'));
92
92
  }
93
+ if (!RithmicService) {
94
+ ({ RithmicService } = require('./rithmic'));
95
+ }
93
96
  };
94
97
 
98
+ // Direct mode flag - bypass daemon completely
99
+ const DIRECT_MODE = process.env.HQX_DIRECT === '1' || true; // Default to direct for now
100
+
95
101
  /**
96
102
  * Multi-connection manager (Rithmic only)
97
103
  */
@@ -152,6 +158,28 @@ const connections = {
152
158
  async restoreFromStorage() {
153
159
  loadServices();
154
160
 
161
+ // DIRECT MODE: Bypass daemon, connect directly to Rithmic
162
+ if (DIRECT_MODE) {
163
+ log.info('Direct mode enabled - bypassing daemon');
164
+
165
+ const sessions = storage.load();
166
+ const rithmicSessions = sessions.filter(s => s.type === 'rithmic');
167
+
168
+ if (!rithmicSessions.length) {
169
+ return false;
170
+ }
171
+
172
+ for (const session of rithmicSessions) {
173
+ try {
174
+ await this._restoreSessionDirect(session);
175
+ } catch (err) {
176
+ log.warn('Failed to restore session direct', { error: err.message });
177
+ }
178
+ }
179
+
180
+ return this.services.length > 0;
181
+ }
182
+
155
183
  // Check if daemon is already running with active connections
156
184
  const daemonStatus = await brokerManager.getStatus();
157
185
 
@@ -211,6 +239,41 @@ const connections = {
211
239
 
212
240
  return this.services.length > 0;
213
241
  },
242
+
243
+ /**
244
+ * Restore session using direct RithmicService (no daemon)
245
+ */
246
+ async _restoreSessionDirect(session) {
247
+ const { type, propfirm, propfirmKey } = session;
248
+
249
+ if (type === 'rithmic' && session.credentials) {
250
+ const service = new RithmicService(propfirmKey || 'apex_rithmic');
251
+
252
+ // Validate cached accounts
253
+ let validAccounts = null;
254
+ if (session.accounts && Array.isArray(session.accounts)) {
255
+ validAccounts = session.accounts
256
+ .map(a => this._sanitizeAccount(a))
257
+ .filter(Boolean);
258
+ if (validAccounts.length === 0) validAccounts = null;
259
+ }
260
+
261
+ // Login with cached accounts to avoid API limit
262
+ const loginOptions = validAccounts ? { skipFetchAccounts: true, cachedAccounts: validAccounts } : {};
263
+ const result = await service.login(session.credentials.username, session.credentials.password, loginOptions);
264
+
265
+ if (result.success) {
266
+ this.services.push({
267
+ type,
268
+ service,
269
+ propfirm,
270
+ propfirmKey,
271
+ connectedAt: new Date(),
272
+ });
273
+ log.info('Direct session restored', { propfirm, accounts: service.accounts?.length || 0 });
274
+ }
275
+ }
276
+ },
214
277
 
215
278
  async _restoreSession(session) {
216
279
  const { type, propfirm, propfirmKey } = session;