hedgequantx 1.2.147 → 1.3.1

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.
@@ -0,0 +1,192 @@
1
+ /**
2
+ * Rithmic Orders Module
3
+ * Order placement, cancellation, and history
4
+ */
5
+
6
+ const { REQ } = require('./constants');
7
+
8
+ /**
9
+ * Place order via ORDER_PLANT
10
+ * @param {RithmicService} service - The Rithmic service instance
11
+ * @param {Object} orderData - Order parameters
12
+ */
13
+ const placeOrder = async (service, orderData) => {
14
+ if (!service.orderConn || !service.loginInfo) {
15
+ return { success: false, error: 'Not connected' };
16
+ }
17
+
18
+ try {
19
+ service.orderConn.send('RequestNewOrder', {
20
+ templateId: REQ.NEW_ORDER,
21
+ userMsg: ['HQX'],
22
+ fcmId: service.loginInfo.fcmId,
23
+ ibId: service.loginInfo.ibId,
24
+ accountId: orderData.accountId,
25
+ symbol: orderData.symbol,
26
+ exchange: orderData.exchange || 'CME',
27
+ quantity: orderData.size,
28
+ transactionType: orderData.side === 0 ? 1 : 2, // 1=Buy, 2=Sell
29
+ duration: 1, // DAY
30
+ orderType: orderData.type === 2 ? 1 : 2, // 1=Market, 2=Limit
31
+ price: orderData.price || 0,
32
+ });
33
+
34
+ return { success: true, message: 'Order submitted' };
35
+ } catch (error) {
36
+ return { success: false, error: error.message };
37
+ }
38
+ };
39
+
40
+ /**
41
+ * Cancel order
42
+ * @param {RithmicService} service - The Rithmic service instance
43
+ * @param {string} orderId - Order ID to cancel
44
+ */
45
+ const cancelOrder = async (service, orderId) => {
46
+ if (!service.orderConn || !service.loginInfo) {
47
+ return { success: false, error: 'Not connected' };
48
+ }
49
+
50
+ try {
51
+ service.orderConn.send('RequestCancelOrder', {
52
+ templateId: REQ.CANCEL_ORDER,
53
+ userMsg: ['HQX'],
54
+ fcmId: service.loginInfo.fcmId,
55
+ ibId: service.loginInfo.ibId,
56
+ orderId: orderId,
57
+ });
58
+
59
+ return { success: true };
60
+ } catch (error) {
61
+ return { success: false, error: error.message };
62
+ }
63
+ };
64
+
65
+ /**
66
+ * Get active orders
67
+ * @param {RithmicService} service - The Rithmic service instance
68
+ */
69
+ const getOrders = async (service) => {
70
+ if (!service.orderConn || !service.loginInfo) {
71
+ return { success: true, orders: [] };
72
+ }
73
+
74
+ return new Promise((resolve) => {
75
+ const orders = [];
76
+ const timeout = setTimeout(() => {
77
+ resolve({ success: true, orders });
78
+ }, 3000);
79
+
80
+ const orderHandler = (notification) => {
81
+ if (notification.orderId) {
82
+ orders.push({
83
+ orderId: notification.orderId,
84
+ symbol: notification.symbol,
85
+ exchange: notification.exchange,
86
+ side: notification.transactionType === 1 ? 'BUY' : 'SELL',
87
+ quantity: notification.quantity,
88
+ filledQuantity: notification.filledQuantity || 0,
89
+ price: notification.price,
90
+ orderType: notification.orderType,
91
+ status: notification.status,
92
+ });
93
+ }
94
+ };
95
+
96
+ service.once('ordersReceived', () => {
97
+ clearTimeout(timeout);
98
+ service.removeListener('orderNotification', orderHandler);
99
+ resolve({ success: true, orders });
100
+ });
101
+
102
+ service.on('orderNotification', orderHandler);
103
+
104
+ try {
105
+ for (const acc of service.accounts) {
106
+ service.orderConn.send('RequestShowOrders', {
107
+ templateId: REQ.SHOW_ORDERS,
108
+ userMsg: ['HQX'],
109
+ fcmId: acc.fcmId || service.loginInfo.fcmId,
110
+ ibId: acc.ibId || service.loginInfo.ibId,
111
+ accountId: acc.accountId,
112
+ });
113
+ }
114
+ } catch (e) {
115
+ clearTimeout(timeout);
116
+ resolve({ success: false, error: e.message, orders: [] });
117
+ }
118
+ });
119
+ };
120
+
121
+ /**
122
+ * Get order history
123
+ * @param {RithmicService} service - The Rithmic service instance
124
+ * @param {string} date - Date in YYYYMMDD format
125
+ */
126
+ const getOrderHistory = async (service, date) => {
127
+ if (!service.orderConn || !service.loginInfo) {
128
+ return { success: true, orders: [] };
129
+ }
130
+
131
+ const dateStr = date || new Date().toISOString().slice(0, 10).replace(/-/g, '');
132
+
133
+ return new Promise((resolve) => {
134
+ const orders = [];
135
+ const timeout = setTimeout(() => {
136
+ resolve({ success: true, orders });
137
+ }, 3000);
138
+
139
+ try {
140
+ for (const acc of service.accounts) {
141
+ service.orderConn.send('RequestShowOrderHistorySummary', {
142
+ templateId: REQ.SHOW_ORDER_HISTORY,
143
+ userMsg: ['HQX'],
144
+ fcmId: acc.fcmId || service.loginInfo.fcmId,
145
+ ibId: acc.ibId || service.loginInfo.ibId,
146
+ accountId: acc.accountId,
147
+ date: dateStr,
148
+ });
149
+ }
150
+
151
+ setTimeout(() => {
152
+ clearTimeout(timeout);
153
+ resolve({ success: true, orders });
154
+ }, 2000);
155
+ } catch (e) {
156
+ clearTimeout(timeout);
157
+ resolve({ success: false, error: e.message, orders: [] });
158
+ }
159
+ });
160
+ };
161
+
162
+ /**
163
+ * Close position (market order to flatten)
164
+ * @param {RithmicService} service - The Rithmic service instance
165
+ * @param {string} accountId - Account ID
166
+ * @param {string} symbol - Symbol to close
167
+ */
168
+ const closePosition = async (service, accountId, symbol) => {
169
+ const positions = Array.from(service.positions.values());
170
+ const position = positions.find(p => p.accountId === accountId && p.symbol === symbol);
171
+
172
+ if (!position) {
173
+ return { success: false, error: 'Position not found' };
174
+ }
175
+
176
+ return placeOrder(service, {
177
+ accountId,
178
+ symbol,
179
+ exchange: position.exchange,
180
+ size: Math.abs(position.quantity),
181
+ side: position.quantity > 0 ? 1 : 0, // Sell if long, Buy if short
182
+ type: 2, // Market
183
+ });
184
+ };
185
+
186
+ module.exports = {
187
+ placeOrder,
188
+ cancelOrder,
189
+ getOrders,
190
+ getOrderHistory,
191
+ closePosition
192
+ };
package/src/ui/index.js CHANGED
@@ -24,6 +24,26 @@ const {
24
24
  } = require('./table');
25
25
  const { createBoxMenu } = require('./menu');
26
26
 
27
+ /**
28
+ * Ensure stdin is ready for inquirer prompts
29
+ * This fixes input leaking to bash after session restore or algo trading
30
+ */
31
+ const prepareStdin = () => {
32
+ try {
33
+ // Remove any raw mode that might be left from previous operations
34
+ if (process.stdin.isTTY && process.stdin.isRaw) {
35
+ process.stdin.setRawMode(false);
36
+ }
37
+ // Remove any lingering keypress listeners
38
+ process.stdin.removeAllListeners('keypress');
39
+ process.stdin.removeAllListeners('data');
40
+ // Pause stdin so inquirer can take control
41
+ process.stdin.pause();
42
+ } catch (e) {
43
+ // Ignore errors
44
+ }
45
+ };
46
+
27
47
  module.exports = {
28
48
  // Device
29
49
  detectDevice,
@@ -47,5 +67,7 @@ module.exports = {
47
67
  draw2ColSeparator,
48
68
  fmtRow,
49
69
  // Menu
50
- createBoxMenu
70
+ createBoxMenu,
71
+ // Stdin
72
+ prepareStdin
51
73
  };