hedgequantx 2.9.249 → 2.9.251
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
|
@@ -119,30 +119,33 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
|
|
|
119
119
|
ui.addLog('system', 'Connecting to market data...');
|
|
120
120
|
|
|
121
121
|
// Listen for position updates from Rithmic (external closes, manual trades)
|
|
122
|
+
// Only if service supports events (RithmicService or DaemonProxyService)
|
|
122
123
|
const accId = account.rithmicAccountId || account.accountId;
|
|
123
|
-
service.on
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
124
|
+
if (typeof service.on === 'function') {
|
|
125
|
+
service.on('positionUpdate', (pos) => {
|
|
126
|
+
// Match by account and symbol
|
|
127
|
+
const posSymbol = pos.contractId || pos.symbol || '';
|
|
128
|
+
const matchesSymbol = posSymbol.includes(contract.name) || posSymbol.includes(contractId) ||
|
|
129
|
+
posSymbol === symbolCode || contractId.includes(posSymbol);
|
|
130
|
+
const matchesAccount = pos.accountId === accId || pos.accountId === account.accountId;
|
|
131
|
+
|
|
132
|
+
if (matchesSymbol && matchesAccount) {
|
|
133
|
+
const qty = parseInt(pos.quantity) || 0;
|
|
134
|
+
if (!isNaN(qty) && Math.abs(qty) < 1000 && qty !== currentPosition) {
|
|
135
|
+
const oldPos = currentPosition;
|
|
136
|
+
currentPosition = qty;
|
|
137
|
+
if (qty === 0 && oldPos !== 0) {
|
|
138
|
+
ui.addLog('trade', `Position closed externally (was ${oldPos})`);
|
|
139
|
+
sessionLogger.log('POSITION', `External close: ${oldPos} -> 0`);
|
|
140
|
+
pendingOrder = false; // Reset pending order flag
|
|
141
|
+
} else if (qty !== 0 && oldPos === 0) {
|
|
142
|
+
ui.addLog('trade', `Position opened externally: ${qty}`);
|
|
143
|
+
sessionLogger.log('POSITION', `External open: 0 -> ${qty}`);
|
|
144
|
+
}
|
|
142
145
|
}
|
|
143
146
|
}
|
|
144
|
-
}
|
|
145
|
-
}
|
|
147
|
+
});
|
|
148
|
+
}
|
|
146
149
|
|
|
147
150
|
strategy.on('signal', async (signal) => {
|
|
148
151
|
const dir = signal.direction?.toUpperCase() || 'UNKNOWN';
|
|
@@ -221,19 +221,31 @@ const handleNewOrderResponse = (service, data) => {
|
|
|
221
221
|
try {
|
|
222
222
|
const res = proto.decode('ResponseNewOrder', data);
|
|
223
223
|
|
|
224
|
+
// Log full response for debugging
|
|
225
|
+
console.log('[Rithmic] ResponseNewOrder:', JSON.stringify(res));
|
|
226
|
+
|
|
224
227
|
const isAccepted = res.rpCode?.[0] === '0';
|
|
225
228
|
|
|
226
229
|
// Build rejection reason from rpCode array
|
|
227
|
-
// rpCode is typically ['code', 'message'] or just ['code']
|
|
228
230
|
let rejectReason = null;
|
|
229
|
-
if (!isAccepted) {
|
|
230
|
-
//
|
|
231
|
-
|
|
232
|
-
const
|
|
233
|
-
|
|
231
|
+
if (!isAccepted && res.rpCode) {
|
|
232
|
+
// rpCode can be ['0'] for success or ['code', 'message', ...] for errors
|
|
233
|
+
// Join all parts after the code for the full message
|
|
234
|
+
const allCodes = Array.isArray(res.rpCode) ? res.rpCode : [res.rpCode];
|
|
235
|
+
const rqCodes = Array.isArray(res.rqHandlerRpCode) ? res.rqHandlerRpCode : [];
|
|
236
|
+
|
|
237
|
+
// Get message from rpCode (skip first element which is the code)
|
|
238
|
+
const rpMsg = allCodes.slice(1).join(' ').trim();
|
|
239
|
+
const rqMsg = rqCodes.slice(1).join(' ').trim();
|
|
234
240
|
|
|
235
|
-
//
|
|
236
|
-
if (
|
|
241
|
+
// Use the message if available
|
|
242
|
+
if (rpMsg) {
|
|
243
|
+
rejectReason = rpMsg;
|
|
244
|
+
} else if (rqMsg) {
|
|
245
|
+
rejectReason = rqMsg;
|
|
246
|
+
} else {
|
|
247
|
+
// Map numeric codes to messages
|
|
248
|
+
const code = allCodes[0];
|
|
237
249
|
const codeMap = {
|
|
238
250
|
'1': 'Invalid request',
|
|
239
251
|
'2': 'Invalid account',
|
|
@@ -245,17 +257,17 @@ const handleNewOrderResponse = (service, data) => {
|
|
|
245
257
|
'8': 'Position limit exceeded',
|
|
246
258
|
'9': 'Rate limit exceeded',
|
|
247
259
|
};
|
|
248
|
-
rejectReason = codeMap[
|
|
260
|
+
rejectReason = codeMap[code] || `Gateway rejected (code: ${code})`;
|
|
249
261
|
}
|
|
250
262
|
|
|
251
|
-
console.log('[Rithmic]
|
|
263
|
+
console.log('[Rithmic] Order REJECTED:', rejectReason);
|
|
252
264
|
}
|
|
253
265
|
|
|
254
266
|
const order = {
|
|
255
267
|
basketId: res.basketId || null,
|
|
256
268
|
symbol: res.symbol,
|
|
257
269
|
exchange: res.exchange || 'CME',
|
|
258
|
-
notifyType: isAccepted ? 1 : 6,
|
|
270
|
+
notifyType: isAccepted ? 1 : 6,
|
|
259
271
|
status: isAccepted ? 2 : 6,
|
|
260
272
|
text: rejectReason,
|
|
261
273
|
rpCode: res.rpCode,
|