hedgequantx 2.9.57 → 2.9.59
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 +1 -1
- package/src/app.js +11 -2
- package/src/lib/data.js +28 -2
- package/src/pages/algo/one-account.js +10 -4
- package/src/services/rithmic/protobuf-decoders.js +375 -0
- package/src/services/rithmic/protobuf-utils.js +71 -0
- package/src/services/rithmic/protobuf.js +19 -403
- package/src/ui/menu.js +6 -1
- package/src/utils/prompts.js +302 -116
|
@@ -1,316 +1,23 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* Rithmic Protobuf Handler
|
|
3
|
-
*
|
|
3
|
+
* Main interface for encoding/decoding Rithmic protobuf messages
|
|
4
|
+
* @module services/rithmic/protobuf
|
|
4
5
|
*/
|
|
5
6
|
|
|
6
7
|
const protobuf = require('protobufjs');
|
|
7
8
|
const path = require('path');
|
|
8
9
|
const { PROTO_FILES } = require('./constants');
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
ACCOUNT_ID: 154008,
|
|
17
|
-
ACCOUNT_BALANCE: 156970,
|
|
18
|
-
CASH_ON_HAND: 156971,
|
|
19
|
-
MARGIN_BALANCE: 156977,
|
|
20
|
-
MIN_ACCOUNT_BALANCE: 156968,
|
|
21
|
-
OPEN_POSITION_PNL: 156961,
|
|
22
|
-
CLOSED_POSITION_PNL: 156963,
|
|
23
|
-
DAY_PNL: 157956,
|
|
24
|
-
DAY_OPEN_PNL: 157954,
|
|
25
|
-
DAY_CLOSED_PNL: 157955,
|
|
26
|
-
AVAILABLE_BUYING_POWER: 157015,
|
|
27
|
-
SSBOE: 150100,
|
|
28
|
-
USECS: 150101,
|
|
29
|
-
};
|
|
30
|
-
|
|
31
|
-
// Symbol/Contract field IDs (ResponseProductCodes, ResponseFrontMonthContract)
|
|
32
|
-
const SYMBOL_FIELDS = {
|
|
33
|
-
TEMPLATE_ID: 154467,
|
|
34
|
-
RP_CODE: 132766,
|
|
35
|
-
EXCHANGE: 110101,
|
|
36
|
-
PRODUCT_CODE: 110102, // Base symbol (ES, NQ, MNQ)
|
|
37
|
-
PRODUCT_NAME: 110103, // Product name
|
|
38
|
-
SYMBOL: 110100, // Full contract symbol (ESH26)
|
|
39
|
-
TRADING_SYMBOL: 157095, // Trading symbol
|
|
40
|
-
DESCRIPTION: 110114, // Contract description
|
|
41
|
-
USER_MSG: 132760,
|
|
42
|
-
};
|
|
43
|
-
|
|
44
|
-
// Instrument PnL Position Update field IDs
|
|
45
|
-
const INSTRUMENT_PNL_FIELDS = {
|
|
46
|
-
TEMPLATE_ID: 154467,
|
|
47
|
-
IS_SNAPSHOT: 110121,
|
|
48
|
-
FCM_ID: 154013,
|
|
49
|
-
IB_ID: 154014,
|
|
50
|
-
ACCOUNT_ID: 154008,
|
|
51
|
-
SYMBOL: 110100,
|
|
52
|
-
EXCHANGE: 110101,
|
|
53
|
-
PRODUCT_CODE: 100749,
|
|
54
|
-
INSTRUMENT_TYPE: 110116,
|
|
55
|
-
FILL_BUY_QTY: 154041,
|
|
56
|
-
FILL_SELL_QTY: 154042,
|
|
57
|
-
ORDER_BUY_QTY: 154037,
|
|
58
|
-
ORDER_SELL_QTY: 154038,
|
|
59
|
-
BUY_QTY: 154260,
|
|
60
|
-
SELL_QTY: 154261,
|
|
61
|
-
AVG_OPEN_FILL_PRICE: 154434,
|
|
62
|
-
DAY_OPEN_PNL: 157954,
|
|
63
|
-
DAY_CLOSED_PNL: 157955,
|
|
64
|
-
DAY_PNL: 157956,
|
|
65
|
-
OPEN_POSITION_PNL: 156961,
|
|
66
|
-
OPEN_POSITION_QUANTITY: 156962,
|
|
67
|
-
CLOSED_POSITION_PNL: 156963,
|
|
68
|
-
CLOSED_POSITION_QUANTITY: 156964,
|
|
69
|
-
NET_QUANTITY: 156967,
|
|
70
|
-
SSBOE: 150100,
|
|
71
|
-
USECS: 150101,
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Read a varint from buffer
|
|
76
|
-
*/
|
|
77
|
-
function readVarint(buffer, offset) {
|
|
78
|
-
let result = BigInt(0);
|
|
79
|
-
let shift = BigInt(0);
|
|
80
|
-
let pos = offset;
|
|
81
|
-
|
|
82
|
-
while (pos < buffer.length) {
|
|
83
|
-
const byte = buffer[pos++];
|
|
84
|
-
result |= BigInt(byte & 0x7f) << shift;
|
|
85
|
-
if ((byte & 0x80) === 0) {
|
|
86
|
-
return [Number(result), pos];
|
|
87
|
-
}
|
|
88
|
-
shift += BigInt(7);
|
|
89
|
-
if (shift > BigInt(63)) {
|
|
90
|
-
throw new Error('Varint too large');
|
|
91
|
-
}
|
|
92
|
-
}
|
|
93
|
-
throw new Error('Incomplete varint');
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Read a length-delimited field (string/bytes)
|
|
98
|
-
*/
|
|
99
|
-
function readLengthDelimited(buffer, offset) {
|
|
100
|
-
const [length, newOffset] = readVarint(buffer, offset);
|
|
101
|
-
const value = buffer.slice(newOffset, newOffset + length).toString('utf8');
|
|
102
|
-
return [value, newOffset + length];
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
/**
|
|
106
|
-
* Skip a field based on wire type
|
|
107
|
-
*/
|
|
108
|
-
function skipField(buffer, offset, wireType) {
|
|
109
|
-
switch (wireType) {
|
|
110
|
-
case 0: // Varint
|
|
111
|
-
const [, newOffset] = readVarint(buffer, offset);
|
|
112
|
-
return newOffset;
|
|
113
|
-
case 1: // 64-bit
|
|
114
|
-
return offset + 8;
|
|
115
|
-
case 2: // Length-delimited
|
|
116
|
-
const [length, lenOffset] = readVarint(buffer, offset);
|
|
117
|
-
return lenOffset + length;
|
|
118
|
-
case 5: // 32-bit
|
|
119
|
-
return offset + 4;
|
|
120
|
-
default:
|
|
121
|
-
throw new Error(`Unknown wire type: ${wireType}`);
|
|
122
|
-
}
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
/**
|
|
126
|
-
* Manually decode AccountPnL from raw bytes
|
|
127
|
-
* Skips 4-byte length prefix if present
|
|
128
|
-
*/
|
|
129
|
-
function decodeAccountPnL(buffer) {
|
|
130
|
-
// Skip 4-byte length prefix
|
|
131
|
-
const data = buffer.length > 4 ? buffer.slice(4) : buffer;
|
|
132
|
-
|
|
133
|
-
const result = {};
|
|
134
|
-
let offset = 0;
|
|
135
|
-
|
|
136
|
-
while (offset < data.length) {
|
|
137
|
-
try {
|
|
138
|
-
const [tag, tagOffset] = readVarint(data, offset);
|
|
139
|
-
const wireType = tag & 0x7;
|
|
140
|
-
const fieldNumber = tag >>> 3;
|
|
141
|
-
offset = tagOffset;
|
|
142
|
-
|
|
143
|
-
switch (fieldNumber) {
|
|
144
|
-
case PNL_FIELDS.TEMPLATE_ID:
|
|
145
|
-
[result.templateId, offset] = readVarint(data, offset);
|
|
146
|
-
break;
|
|
147
|
-
case PNL_FIELDS.IS_SNAPSHOT:
|
|
148
|
-
const [isSnap, snapOffset] = readVarint(data, offset);
|
|
149
|
-
result.isSnapshot = isSnap !== 0;
|
|
150
|
-
offset = snapOffset;
|
|
151
|
-
break;
|
|
152
|
-
case PNL_FIELDS.FCM_ID:
|
|
153
|
-
[result.fcmId, offset] = readLengthDelimited(data, offset);
|
|
154
|
-
break;
|
|
155
|
-
case PNL_FIELDS.IB_ID:
|
|
156
|
-
[result.ibId, offset] = readLengthDelimited(data, offset);
|
|
157
|
-
break;
|
|
158
|
-
case PNL_FIELDS.ACCOUNT_ID:
|
|
159
|
-
[result.accountId, offset] = readLengthDelimited(data, offset);
|
|
160
|
-
break;
|
|
161
|
-
case PNL_FIELDS.ACCOUNT_BALANCE:
|
|
162
|
-
[result.accountBalance, offset] = readLengthDelimited(data, offset);
|
|
163
|
-
break;
|
|
164
|
-
case PNL_FIELDS.CASH_ON_HAND:
|
|
165
|
-
[result.cashOnHand, offset] = readLengthDelimited(data, offset);
|
|
166
|
-
break;
|
|
167
|
-
case PNL_FIELDS.MARGIN_BALANCE:
|
|
168
|
-
[result.marginBalance, offset] = readLengthDelimited(data, offset);
|
|
169
|
-
break;
|
|
170
|
-
case PNL_FIELDS.MIN_ACCOUNT_BALANCE:
|
|
171
|
-
[result.minAccountBalance, offset] = readLengthDelimited(data, offset);
|
|
172
|
-
break;
|
|
173
|
-
case PNL_FIELDS.OPEN_POSITION_PNL:
|
|
174
|
-
[result.openPositionPnl, offset] = readLengthDelimited(data, offset);
|
|
175
|
-
break;
|
|
176
|
-
case PNL_FIELDS.CLOSED_POSITION_PNL:
|
|
177
|
-
[result.closedPositionPnl, offset] = readLengthDelimited(data, offset);
|
|
178
|
-
break;
|
|
179
|
-
case PNL_FIELDS.DAY_PNL:
|
|
180
|
-
[result.dayPnl, offset] = readLengthDelimited(data, offset);
|
|
181
|
-
break;
|
|
182
|
-
case PNL_FIELDS.DAY_OPEN_PNL:
|
|
183
|
-
[result.dayOpenPnl, offset] = readLengthDelimited(data, offset);
|
|
184
|
-
break;
|
|
185
|
-
case PNL_FIELDS.DAY_CLOSED_PNL:
|
|
186
|
-
[result.dayClosedPnl, offset] = readLengthDelimited(data, offset);
|
|
187
|
-
break;
|
|
188
|
-
case PNL_FIELDS.AVAILABLE_BUYING_POWER:
|
|
189
|
-
[result.availableBuyingPower, offset] = readLengthDelimited(data, offset);
|
|
190
|
-
break;
|
|
191
|
-
case PNL_FIELDS.SSBOE:
|
|
192
|
-
[result.ssboe, offset] = readVarint(data, offset);
|
|
193
|
-
break;
|
|
194
|
-
case PNL_FIELDS.USECS:
|
|
195
|
-
[result.usecs, offset] = readVarint(data, offset);
|
|
196
|
-
break;
|
|
197
|
-
default:
|
|
198
|
-
offset = skipField(data, offset, wireType);
|
|
199
|
-
}
|
|
200
|
-
} catch (error) {
|
|
201
|
-
break;
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
return result;
|
|
206
|
-
}
|
|
207
|
-
|
|
208
|
-
/**
|
|
209
|
-
* Manually decode InstrumentPnLPositionUpdate from raw bytes
|
|
210
|
-
* Skips 4-byte length prefix if present
|
|
211
|
-
*/
|
|
212
|
-
function decodeInstrumentPnL(buffer) {
|
|
213
|
-
// Skip 4-byte length prefix
|
|
214
|
-
const data = buffer.length > 4 ? buffer.slice(4) : buffer;
|
|
215
|
-
|
|
216
|
-
const result = {};
|
|
217
|
-
let offset = 0;
|
|
218
|
-
|
|
219
|
-
while (offset < data.length) {
|
|
220
|
-
try {
|
|
221
|
-
const [tag, tagOffset] = readVarint(data, offset);
|
|
222
|
-
const wireType = tag & 0x7;
|
|
223
|
-
const fieldNumber = tag >>> 3;
|
|
224
|
-
offset = tagOffset;
|
|
225
|
-
|
|
226
|
-
switch (fieldNumber) {
|
|
227
|
-
case INSTRUMENT_PNL_FIELDS.TEMPLATE_ID:
|
|
228
|
-
[result.templateId, offset] = readVarint(data, offset);
|
|
229
|
-
break;
|
|
230
|
-
case INSTRUMENT_PNL_FIELDS.IS_SNAPSHOT:
|
|
231
|
-
const [isSnap, snapOffset] = readVarint(data, offset);
|
|
232
|
-
result.isSnapshot = isSnap !== 0;
|
|
233
|
-
offset = snapOffset;
|
|
234
|
-
break;
|
|
235
|
-
case INSTRUMENT_PNL_FIELDS.FCM_ID:
|
|
236
|
-
[result.fcmId, offset] = readLengthDelimited(data, offset);
|
|
237
|
-
break;
|
|
238
|
-
case INSTRUMENT_PNL_FIELDS.IB_ID:
|
|
239
|
-
[result.ibId, offset] = readLengthDelimited(data, offset);
|
|
240
|
-
break;
|
|
241
|
-
case INSTRUMENT_PNL_FIELDS.ACCOUNT_ID:
|
|
242
|
-
[result.accountId, offset] = readLengthDelimited(data, offset);
|
|
243
|
-
break;
|
|
244
|
-
case INSTRUMENT_PNL_FIELDS.SYMBOL:
|
|
245
|
-
[result.symbol, offset] = readLengthDelimited(data, offset);
|
|
246
|
-
break;
|
|
247
|
-
case INSTRUMENT_PNL_FIELDS.EXCHANGE:
|
|
248
|
-
[result.exchange, offset] = readLengthDelimited(data, offset);
|
|
249
|
-
break;
|
|
250
|
-
case INSTRUMENT_PNL_FIELDS.PRODUCT_CODE:
|
|
251
|
-
[result.productCode, offset] = readLengthDelimited(data, offset);
|
|
252
|
-
break;
|
|
253
|
-
case INSTRUMENT_PNL_FIELDS.BUY_QTY:
|
|
254
|
-
[result.buyQty, offset] = readVarint(data, offset);
|
|
255
|
-
break;
|
|
256
|
-
case INSTRUMENT_PNL_FIELDS.SELL_QTY:
|
|
257
|
-
[result.sellQty, offset] = readVarint(data, offset);
|
|
258
|
-
break;
|
|
259
|
-
case INSTRUMENT_PNL_FIELDS.FILL_BUY_QTY:
|
|
260
|
-
[result.fillBuyQty, offset] = readVarint(data, offset);
|
|
261
|
-
break;
|
|
262
|
-
case INSTRUMENT_PNL_FIELDS.FILL_SELL_QTY:
|
|
263
|
-
[result.fillSellQty, offset] = readVarint(data, offset);
|
|
264
|
-
break;
|
|
265
|
-
case INSTRUMENT_PNL_FIELDS.NET_QUANTITY:
|
|
266
|
-
[result.netQuantity, offset] = readVarint(data, offset);
|
|
267
|
-
break;
|
|
268
|
-
case INSTRUMENT_PNL_FIELDS.OPEN_POSITION_QUANTITY:
|
|
269
|
-
[result.openPositionQuantity, offset] = readVarint(data, offset);
|
|
270
|
-
break;
|
|
271
|
-
case INSTRUMENT_PNL_FIELDS.AVG_OPEN_FILL_PRICE:
|
|
272
|
-
// Double is 64-bit fixed
|
|
273
|
-
if (wireType === 1) {
|
|
274
|
-
result.avgOpenFillPrice = data.readDoubleLE(offset);
|
|
275
|
-
offset += 8;
|
|
276
|
-
} else {
|
|
277
|
-
offset = skipField(data, offset, wireType);
|
|
278
|
-
}
|
|
279
|
-
break;
|
|
280
|
-
case INSTRUMENT_PNL_FIELDS.OPEN_POSITION_PNL:
|
|
281
|
-
[result.openPositionPnl, offset] = readLengthDelimited(data, offset);
|
|
282
|
-
break;
|
|
283
|
-
case INSTRUMENT_PNL_FIELDS.CLOSED_POSITION_PNL:
|
|
284
|
-
[result.closedPositionPnl, offset] = readLengthDelimited(data, offset);
|
|
285
|
-
break;
|
|
286
|
-
case INSTRUMENT_PNL_FIELDS.DAY_PNL:
|
|
287
|
-
[result.dayPnl, offset] = readLengthDelimited(data, offset);
|
|
288
|
-
break;
|
|
289
|
-
case INSTRUMENT_PNL_FIELDS.DAY_OPEN_PNL:
|
|
290
|
-
[result.dayOpenPnl, offset] = readLengthDelimited(data, offset);
|
|
291
|
-
break;
|
|
292
|
-
case INSTRUMENT_PNL_FIELDS.DAY_CLOSED_PNL:
|
|
293
|
-
[result.dayClosedPnl, offset] = readLengthDelimited(data, offset);
|
|
294
|
-
break;
|
|
295
|
-
case INSTRUMENT_PNL_FIELDS.SSBOE:
|
|
296
|
-
[result.ssboe, offset] = readVarint(data, offset);
|
|
297
|
-
break;
|
|
298
|
-
case INSTRUMENT_PNL_FIELDS.USECS:
|
|
299
|
-
[result.usecs, offset] = readVarint(data, offset);
|
|
300
|
-
break;
|
|
301
|
-
default:
|
|
302
|
-
offset = skipField(data, offset, wireType);
|
|
303
|
-
}
|
|
304
|
-
} catch (error) {
|
|
305
|
-
break;
|
|
306
|
-
}
|
|
307
|
-
}
|
|
308
|
-
|
|
309
|
-
return result;
|
|
310
|
-
}
|
|
10
|
+
const { readVarint, readLengthDelimited, skipField } = require('./protobuf-utils');
|
|
11
|
+
const {
|
|
12
|
+
decodeAccountPnL,
|
|
13
|
+
decodeInstrumentPnL,
|
|
14
|
+
decodeProductCodes,
|
|
15
|
+
decodeFrontMonthContract,
|
|
16
|
+
} = require('./protobuf-decoders');
|
|
311
17
|
|
|
312
18
|
/**
|
|
313
19
|
* Protobuf Handler class
|
|
20
|
+
* Handles loading proto files and encoding/decoding messages
|
|
314
21
|
*/
|
|
315
22
|
class ProtobufHandler {
|
|
316
23
|
constructor() {
|
|
@@ -340,6 +47,9 @@ class ProtobufHandler {
|
|
|
340
47
|
|
|
341
48
|
/**
|
|
342
49
|
* Encode a message to Buffer with 4-byte length prefix
|
|
50
|
+
* @param {string} typeName - Protobuf type name
|
|
51
|
+
* @param {Object} data - Data to encode
|
|
52
|
+
* @returns {Buffer} Encoded buffer with length prefix
|
|
343
53
|
*/
|
|
344
54
|
encode(typeName, data) {
|
|
345
55
|
if (!this.root) throw new Error('Proto not loaded');
|
|
@@ -357,6 +67,9 @@ class ProtobufHandler {
|
|
|
357
67
|
|
|
358
68
|
/**
|
|
359
69
|
* Decode a Buffer to object (skip 4-byte length prefix)
|
|
70
|
+
* @param {string} typeName - Protobuf type name
|
|
71
|
+
* @param {Buffer} buffer - Buffer to decode
|
|
72
|
+
* @returns {Object} Decoded message
|
|
360
73
|
*/
|
|
361
74
|
decode(typeName, buffer) {
|
|
362
75
|
if (!this.root) throw new Error('Proto not loaded');
|
|
@@ -371,6 +84,8 @@ class ProtobufHandler {
|
|
|
371
84
|
/**
|
|
372
85
|
* Get template ID from buffer (manual decode for large field IDs)
|
|
373
86
|
* Skips 4-byte length prefix if present
|
|
87
|
+
* @param {Buffer} buffer - Buffer to parse
|
|
88
|
+
* @returns {number} Template ID or -1 if not found
|
|
374
89
|
*/
|
|
375
90
|
getTemplateId(buffer) {
|
|
376
91
|
const TEMPLATE_ID_FIELD = 154467;
|
|
@@ -411,106 +126,7 @@ class ProtobufHandler {
|
|
|
411
126
|
}
|
|
412
127
|
}
|
|
413
128
|
|
|
414
|
-
|
|
415
|
-
* Decode ResponseProductCodes (template 112) - list of available symbols
|
|
416
|
-
*/
|
|
417
|
-
function decodeProductCodes(buffer) {
|
|
418
|
-
const result = { rpCode: [] };
|
|
419
|
-
let offset = 0;
|
|
420
|
-
|
|
421
|
-
while (offset < buffer.length) {
|
|
422
|
-
try {
|
|
423
|
-
const [tag, tagOffset] = readVarint(buffer, offset);
|
|
424
|
-
const wireType = tag & 0x7;
|
|
425
|
-
const fieldNumber = tag >>> 3;
|
|
426
|
-
offset = tagOffset;
|
|
427
|
-
|
|
428
|
-
switch (fieldNumber) {
|
|
429
|
-
case SYMBOL_FIELDS.TEMPLATE_ID:
|
|
430
|
-
[result.templateId, offset] = readVarint(buffer, offset);
|
|
431
|
-
break;
|
|
432
|
-
case SYMBOL_FIELDS.RP_CODE:
|
|
433
|
-
let rpCode;
|
|
434
|
-
[rpCode, offset] = readLengthDelimited(buffer, offset);
|
|
435
|
-
result.rpCode.push(rpCode);
|
|
436
|
-
break;
|
|
437
|
-
case SYMBOL_FIELDS.EXCHANGE:
|
|
438
|
-
[result.exchange, offset] = readLengthDelimited(buffer, offset);
|
|
439
|
-
break;
|
|
440
|
-
case SYMBOL_FIELDS.PRODUCT_CODE:
|
|
441
|
-
[result.productCode, offset] = readLengthDelimited(buffer, offset);
|
|
442
|
-
break;
|
|
443
|
-
case SYMBOL_FIELDS.PRODUCT_NAME:
|
|
444
|
-
[result.productName, offset] = readLengthDelimited(buffer, offset);
|
|
445
|
-
break;
|
|
446
|
-
case SYMBOL_FIELDS.USER_MSG:
|
|
447
|
-
[result.userMsg, offset] = readLengthDelimited(buffer, offset);
|
|
448
|
-
break;
|
|
449
|
-
default:
|
|
450
|
-
offset = skipField(buffer, offset, wireType);
|
|
451
|
-
}
|
|
452
|
-
} catch (error) {
|
|
453
|
-
break;
|
|
454
|
-
}
|
|
455
|
-
}
|
|
456
|
-
|
|
457
|
-
return result;
|
|
458
|
-
}
|
|
459
|
-
|
|
460
|
-
/**
|
|
461
|
-
* Decode ResponseFrontMonthContract (template 114) - current tradeable contract
|
|
462
|
-
* Skips 4-byte length prefix if present
|
|
463
|
-
*/
|
|
464
|
-
function decodeFrontMonthContract(buffer) {
|
|
465
|
-
// Skip 4-byte length prefix
|
|
466
|
-
const data = buffer.length > 4 ? buffer.slice(4) : buffer;
|
|
467
|
-
|
|
468
|
-
const result = { rpCode: [] };
|
|
469
|
-
let offset = 0;
|
|
470
|
-
|
|
471
|
-
while (offset < data.length) {
|
|
472
|
-
try {
|
|
473
|
-
const [tag, tagOffset] = readVarint(data, offset);
|
|
474
|
-
const wireType = tag & 0x7;
|
|
475
|
-
const fieldNumber = tag >>> 3;
|
|
476
|
-
offset = tagOffset;
|
|
477
|
-
|
|
478
|
-
switch (fieldNumber) {
|
|
479
|
-
case SYMBOL_FIELDS.TEMPLATE_ID:
|
|
480
|
-
[result.templateId, offset] = readVarint(data, offset);
|
|
481
|
-
break;
|
|
482
|
-
case SYMBOL_FIELDS.RP_CODE:
|
|
483
|
-
let rpCode;
|
|
484
|
-
[rpCode, offset] = readLengthDelimited(data, offset);
|
|
485
|
-
result.rpCode.push(rpCode);
|
|
486
|
-
break;
|
|
487
|
-
case SYMBOL_FIELDS.SYMBOL:
|
|
488
|
-
[result.symbol, offset] = readLengthDelimited(data, offset);
|
|
489
|
-
break;
|
|
490
|
-
case SYMBOL_FIELDS.EXCHANGE:
|
|
491
|
-
[result.exchange, offset] = readLengthDelimited(data, offset);
|
|
492
|
-
break;
|
|
493
|
-
case SYMBOL_FIELDS.TRADING_SYMBOL:
|
|
494
|
-
[result.tradingSymbol, offset] = readLengthDelimited(data, offset);
|
|
495
|
-
break;
|
|
496
|
-
case SYMBOL_FIELDS.DESCRIPTION:
|
|
497
|
-
[result.description, offset] = readLengthDelimited(data, offset);
|
|
498
|
-
break;
|
|
499
|
-
case SYMBOL_FIELDS.USER_MSG:
|
|
500
|
-
[result.userMsg, offset] = readLengthDelimited(data, offset);
|
|
501
|
-
break;
|
|
502
|
-
default:
|
|
503
|
-
offset = skipField(data, offset, wireType);
|
|
504
|
-
}
|
|
505
|
-
} catch (error) {
|
|
506
|
-
break;
|
|
507
|
-
}
|
|
508
|
-
}
|
|
509
|
-
|
|
510
|
-
return result;
|
|
511
|
-
}
|
|
512
|
-
|
|
513
|
-
// Singleton
|
|
129
|
+
// Singleton instance
|
|
514
130
|
const proto = new ProtobufHandler();
|
|
515
131
|
|
|
516
132
|
module.exports = {
|
package/src/ui/menu.js
CHANGED
|
@@ -48,7 +48,12 @@ const createBoxMenu = async (title, items, options = {}) => {
|
|
|
48
48
|
});
|
|
49
49
|
|
|
50
50
|
console.log(chalk.cyan('╠' + '═'.repeat(innerWidth) + '╣'));
|
|
51
|
-
|
|
51
|
+
const taglineBase = 'PROP FUTURES ALGO TRADING ';
|
|
52
|
+
const taglineVersion = `V${version}`;
|
|
53
|
+
const totalLen = taglineBase.length + taglineVersion.length;
|
|
54
|
+
const padLeft = Math.floor((innerWidth - totalLen) / 2);
|
|
55
|
+
const padRight = innerWidth - totalLen - padLeft;
|
|
56
|
+
console.log(chalk.cyan('║') + ' '.repeat(padLeft) + chalk.yellow(taglineBase) + chalk.magenta(taglineVersion) + ' '.repeat(padRight) + chalk.cyan('║'));
|
|
52
57
|
|
|
53
58
|
// Stats bar if provided
|
|
54
59
|
if (options.statsLine) {
|