hedgequantx 2.9.76 → 2.9.78
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/lib/smart-logs-messages.js +369 -0
- package/src/lib/smart-logs.js +52 -333
- package/src/pages/algo/algo-executor.js +49 -49
- package/src/pages/algo/ui.js +2 -2
package/package.json
CHANGED
|
@@ -0,0 +1,369 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* =============================================================================
|
|
3
|
+
* Smart Logs Messages - HF Grade Message Pools
|
|
4
|
+
* =============================================================================
|
|
5
|
+
* Max message length: 76 chars (fits in 96-char UI width)
|
|
6
|
+
*
|
|
7
|
+
* Color placeholders:
|
|
8
|
+
* {bull:text} {bear:text} {zone:text} {action:text}
|
|
9
|
+
* {risk:text} {profit:text} {flow:text} {inst:text}
|
|
10
|
+
*/
|
|
11
|
+
|
|
12
|
+
'use strict';
|
|
13
|
+
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// MESSAGE POOLS - Market Flow (Bullish) - Max 50 chars + details
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
const LONG_BIAS_MESSAGES = [
|
|
19
|
+
'{bull:Buyers} taking control with aggressive {bull:lifting}',
|
|
20
|
+
'{bull:Bid} side absorbing sell pressure',
|
|
21
|
+
'{bull:Bullish} flow on {action:liquidity sweep}',
|
|
22
|
+
'{bull:Buy} programs {bull:lifting} through {zone:resistance}',
|
|
23
|
+
'Strong {bull:buyer} presence at {bull:bid} levels',
|
|
24
|
+
'{flow:Accumulation} with increasing {flow:volume}',
|
|
25
|
+
'{flow:Demand} exceeding supply - {bull:bid} strengthening',
|
|
26
|
+
'{bull:Buyers} stepping up with {inst:institutional} size',
|
|
27
|
+
'{bull:Long}-side {flow:momentum} with positive {flow:delta}',
|
|
28
|
+
'{bull:Bid} accumulation at key {zone:support}',
|
|
29
|
+
'{bull:Bullish} {flow:delta} divergence confirmed',
|
|
30
|
+
'{bull:Buy}-side imbalance driving price higher',
|
|
31
|
+
'{inst:Institutional} {bull:buying} on tape',
|
|
32
|
+
'Aggressive {bull:bid} through stacked offers',
|
|
33
|
+
'{bull:Bullish} microstructure with strong {flow:delta}',
|
|
34
|
+
];
|
|
35
|
+
|
|
36
|
+
// =============================================================================
|
|
37
|
+
// MESSAGE POOLS - Market Flow (Bearish)
|
|
38
|
+
// =============================================================================
|
|
39
|
+
|
|
40
|
+
const SHORT_BIAS_MESSAGES = [
|
|
41
|
+
'{bear:Sellers} taking control with aggressive {bear:hitting}',
|
|
42
|
+
'{bear:Offer} side absorbing buy pressure',
|
|
43
|
+
'{bear:Bearish} flow on {action:liquidity sweep}',
|
|
44
|
+
'{bear:Sell} programs {bear:hitting} through {zone:support}',
|
|
45
|
+
'Strong {bear:seller} presence at {bear:offer} levels',
|
|
46
|
+
'{flow:Distribution} with increasing {flow:volume}',
|
|
47
|
+
'{flow:Supply} exceeding demand - {bear:offer} strengthening',
|
|
48
|
+
'{bear:Sellers} stepping in with {inst:institutional} size',
|
|
49
|
+
'{bear:Short}-side {flow:momentum} with negative {flow:delta}',
|
|
50
|
+
'{bear:Offer} distribution at key {zone:resistance}',
|
|
51
|
+
'{bear:Bearish} {flow:delta} divergence confirmed',
|
|
52
|
+
'{bear:Sell}-side imbalance driving price lower',
|
|
53
|
+
'{inst:Institutional} {bear:selling} on tape',
|
|
54
|
+
'Aggressive {bear:offer} through stacked bids',
|
|
55
|
+
'{bear:Bearish} microstructure with weak {flow:delta}',
|
|
56
|
+
];
|
|
57
|
+
|
|
58
|
+
// =============================================================================
|
|
59
|
+
// MESSAGE POOLS - Market Flow (Neutral)
|
|
60
|
+
// =============================================================================
|
|
61
|
+
|
|
62
|
+
const FLAT_BIAS_MESSAGES = [
|
|
63
|
+
'Market balanced - two-way {inst:institutional} flow',
|
|
64
|
+
'Two-way flow - no clear directional bias',
|
|
65
|
+
'Consolidation with balanced order book',
|
|
66
|
+
'No direction - awaiting {action:breakout} catalyst',
|
|
67
|
+
'Mixed signals across timeframes',
|
|
68
|
+
'Range-bound with absorption both sides',
|
|
69
|
+
'Equilibrium - {bull:buyers}/{bear:sellers} balanced',
|
|
70
|
+
'Neutral flow with symmetric book depth',
|
|
71
|
+
'Balanced book at current price levels',
|
|
72
|
+
'Rotation between {zone:support}/{zone:resistance}',
|
|
73
|
+
'Price discovery with low conviction',
|
|
74
|
+
'Awaiting catalyst - {flow:volume} declining',
|
|
75
|
+
'Sideways chop - mean reversion behavior',
|
|
76
|
+
'Mean reversion {zone:zone} active',
|
|
77
|
+
'Liquidity absorption {bull:bid}/{bear:offer} sides',
|
|
78
|
+
];
|
|
79
|
+
|
|
80
|
+
// =============================================================================
|
|
81
|
+
// MESSAGE POOLS - Trading Signals
|
|
82
|
+
// =============================================================================
|
|
83
|
+
|
|
84
|
+
const SIGNAL_LONG_MESSAGES = [
|
|
85
|
+
'{bull:Buy} signal - high confidence',
|
|
86
|
+
'{bull:Long} opportunity at key {zone:support}',
|
|
87
|
+
'{bull:Bullish} setup with {flow:volume} confirmation',
|
|
88
|
+
'Entry: {bull:LONG} optimal risk-reward',
|
|
89
|
+
'{bull:Buy} {zone:zone} after {action:sweep} complete',
|
|
90
|
+
'{bull:Long} trigger on {zone:support} {action:rejection}',
|
|
91
|
+
'{bull:Bullish} confirmation from multiple factors',
|
|
92
|
+
'{bull:Buy} validated with {flow:momentum}',
|
|
93
|
+
'{bull:Long} setup materialized',
|
|
94
|
+
'{bull:Bullish} pattern complete - entry met',
|
|
95
|
+
];
|
|
96
|
+
|
|
97
|
+
const SIGNAL_SHORT_MESSAGES = [
|
|
98
|
+
'{bear:Sell} signal - high confidence',
|
|
99
|
+
'{bear:Short} opportunity at key {zone:resistance}',
|
|
100
|
+
'{bear:Bearish} setup with {flow:volume} confirmation',
|
|
101
|
+
'Entry: {bear:SHORT} optimal risk-reward',
|
|
102
|
+
'{bear:Sell} {zone:zone} after {action:sweep} complete',
|
|
103
|
+
'{bear:Short} trigger on {zone:resistance} {action:rejection}',
|
|
104
|
+
'{bear:Bearish} confirmation from multiple factors',
|
|
105
|
+
'{bear:Sell} validated with {flow:momentum}',
|
|
106
|
+
'{bear:Short} setup materialized',
|
|
107
|
+
'{bear:Bearish} pattern complete - entry met',
|
|
108
|
+
];
|
|
109
|
+
|
|
110
|
+
// =============================================================================
|
|
111
|
+
// MESSAGE POOLS - Trade Execution
|
|
112
|
+
// =============================================================================
|
|
113
|
+
|
|
114
|
+
const ENTRY_LONG_MESSAGES = [
|
|
115
|
+
'{bull:Long} opened at optimal entry',
|
|
116
|
+
'{bull:Buy} filled - minimal slippage',
|
|
117
|
+
'Entered {bull:long} with brackets',
|
|
118
|
+
'{bull:Long} at {zone:support} {action:rejection}',
|
|
119
|
+
'Position: {bull:LONG} - {risk:risk} defined',
|
|
120
|
+
'{bull:Long} complete - {risk:SL}/{profit:TP} set',
|
|
121
|
+
'{bull:Buy} confirmed at expected price',
|
|
122
|
+
'{bull:Long} executed - tight spread',
|
|
123
|
+
'{bull:Bought} at market - filled',
|
|
124
|
+
'{bull:Long} established - {risk:risk} active',
|
|
125
|
+
];
|
|
126
|
+
|
|
127
|
+
const ENTRY_SHORT_MESSAGES = [
|
|
128
|
+
'{bear:Short} opened at optimal entry',
|
|
129
|
+
'{bear:Sell} filled - minimal slippage',
|
|
130
|
+
'Entered {bear:short} with brackets',
|
|
131
|
+
'{bear:Short} at {zone:resistance} {action:rejection}',
|
|
132
|
+
'Position: {bear:SHORT} - {risk:risk} defined',
|
|
133
|
+
'{bear:Short} complete - {risk:SL}/{profit:TP} set',
|
|
134
|
+
'{bear:Sell} confirmed at expected price',
|
|
135
|
+
'{bear:Short} executed - tight spread',
|
|
136
|
+
'{bear:Sold} at market - filled',
|
|
137
|
+
'{bear:Short} established - {risk:risk} active',
|
|
138
|
+
];
|
|
139
|
+
|
|
140
|
+
const EXIT_PROFIT_MESSAGES = [
|
|
141
|
+
'{profit:Target} reached - locked',
|
|
142
|
+
'{profit:Profit} at target level',
|
|
143
|
+
'{profit:Winner} closed - full target',
|
|
144
|
+
'{profit:TP} hit - realized gain',
|
|
145
|
+
'{profit:Profit} locked successfully',
|
|
146
|
+
'{profit:Gain} realized - objective met',
|
|
147
|
+
'{profit:Profitable} exit optimal',
|
|
148
|
+
'{profit:Target} achieved clean',
|
|
149
|
+
'{profit:Winner} booked to P&L',
|
|
150
|
+
'{profit:Profit} at {zone:level}',
|
|
151
|
+
];
|
|
152
|
+
|
|
153
|
+
const EXIT_LOSS_MESSAGES = [
|
|
154
|
+
'{risk:Stop} triggered - contained',
|
|
155
|
+
'{risk:Loss} within parameters',
|
|
156
|
+
'{risk:Loser} closed - capital preserved',
|
|
157
|
+
'{risk:SL} hit - controlled loss',
|
|
158
|
+
'{risk:Risk} contained - SL executed',
|
|
159
|
+
'{risk:Loss} within budget',
|
|
160
|
+
'{risk:Stop} at predetermined level',
|
|
161
|
+
'{risk:Risk} managed - acceptable',
|
|
162
|
+
'{risk:Loser} booked - discipline',
|
|
163
|
+
'{risk:Loss} controlled - next setup',
|
|
164
|
+
];
|
|
165
|
+
|
|
166
|
+
// =============================================================================
|
|
167
|
+
// MESSAGE POOLS - Zone Analysis
|
|
168
|
+
// =============================================================================
|
|
169
|
+
|
|
170
|
+
const ZONE_APPROACH_MESSAGES = [
|
|
171
|
+
'Approaching {zone:liquidity zone} for {action:sweep}',
|
|
172
|
+
'{zone:Zone} test - monitoring {action:rejection}',
|
|
173
|
+
'Near decision point - watching flow',
|
|
174
|
+
'{zone:Level} approach with {flow:volume}',
|
|
175
|
+
'Key {zone:zone} in range',
|
|
176
|
+
'Price nearing {zone:structure}',
|
|
177
|
+
'{zone:Zone} proximity - {action:sweep} forming',
|
|
178
|
+
'Testing {zone:liquidity zone}',
|
|
179
|
+
'Approaching {zone:pivot} with {flow:volume}',
|
|
180
|
+
'Near {flow:volume} node - reaction expected',
|
|
181
|
+
];
|
|
182
|
+
|
|
183
|
+
const ZONE_CONFIRMED_MESSAGES = [
|
|
184
|
+
'{zone:Zone} confirmed - {action:rejection}',
|
|
185
|
+
'{zone:Level} validated - strong response',
|
|
186
|
+
'{zone:S/R} active with defense',
|
|
187
|
+
'{zone:Zone} reaction - signal possible',
|
|
188
|
+
'{zone:Level} holding - {inst:institutional}',
|
|
189
|
+
'{zone:Structure} confirmed by {action:rejection}',
|
|
190
|
+
'{zone:Zone} defense - absorption visible',
|
|
191
|
+
'{zone:Level} response on tape',
|
|
192
|
+
'{zone:Pivot} confirmed with {flow:volume}',
|
|
193
|
+
'{flow:Volume} node - {zone:zone} intact',
|
|
194
|
+
];
|
|
195
|
+
|
|
196
|
+
// =============================================================================
|
|
197
|
+
// MESSAGE POOLS - Volatility
|
|
198
|
+
// =============================================================================
|
|
199
|
+
|
|
200
|
+
const HIGH_VOLATILITY_MESSAGES = [
|
|
201
|
+
'{flow:Volatility} elevated - widen {risk:stops}',
|
|
202
|
+
'High ATR - adjust sizing',
|
|
203
|
+
'Increased range - fast moves',
|
|
204
|
+
'Market volatile - caution',
|
|
205
|
+
'Wide swings - rapid reversals',
|
|
206
|
+
'{flow:Volatility} expansion - {action:breakout}',
|
|
207
|
+
'Range expanding - {flow:momentum}',
|
|
208
|
+
'High activity {zone:zone}',
|
|
209
|
+
'{flow:Momentum} surge - directional',
|
|
210
|
+
'{action:Breakout} conditions with {flow:volume}',
|
|
211
|
+
];
|
|
212
|
+
|
|
213
|
+
const LOW_VOLATILITY_MESSAGES = [
|
|
214
|
+
'Low {flow:volatility} - tighten {risk:stops}',
|
|
215
|
+
'Tight range - {action:breakout} pending',
|
|
216
|
+
'Compressed action before expansion',
|
|
217
|
+
'Market quiet - awaiting catalyst',
|
|
218
|
+
'Narrow swings - {flow:volume} low',
|
|
219
|
+
'{flow:Volatility} contraction - coiling',
|
|
220
|
+
'Range compressing',
|
|
221
|
+
'Low activity - patience required',
|
|
222
|
+
'{flow:Momentum} cooling',
|
|
223
|
+
'Consolidation forming',
|
|
224
|
+
];
|
|
225
|
+
|
|
226
|
+
// =============================================================================
|
|
227
|
+
// MESSAGE POOLS - Risk Management
|
|
228
|
+
// =============================================================================
|
|
229
|
+
|
|
230
|
+
const RISK_PASSED_MESSAGES = [
|
|
231
|
+
'{profit:Risk passed} - within parameters',
|
|
232
|
+
'Trade {profit:approved} by {risk:risk} filters',
|
|
233
|
+
'Within {risk:risk} limits - size OK',
|
|
234
|
+
'{risk:Risk} validated - criteria met',
|
|
235
|
+
'{profit:Clear to trade} - no violations',
|
|
236
|
+
'{risk:Risk} parameters met',
|
|
237
|
+
'Size {profit:approved} within limits',
|
|
238
|
+
'{risk:Risk} budget OK',
|
|
239
|
+
'Trade {profit:authorized}',
|
|
240
|
+
'{risk:Risk} satisfied - executing',
|
|
241
|
+
];
|
|
242
|
+
|
|
243
|
+
const RISK_BLOCKED_MESSAGES = [
|
|
244
|
+
'{risk:Risk limit} - blocked',
|
|
245
|
+
'Trade {risk:blocked} - size exceeded',
|
|
246
|
+
'Exceeds {risk:threshold} - wait',
|
|
247
|
+
'{risk:Rejected} - loss limit near',
|
|
248
|
+
'{risk:Risk} too elevated',
|
|
249
|
+
'{risk:Parameters exceeded}',
|
|
250
|
+
'Size {risk:rejected} - max exceeded',
|
|
251
|
+
'{risk:Budget depleted}',
|
|
252
|
+
'Trade {risk:denied} - drawdown',
|
|
253
|
+
'{risk:Constraints violated}',
|
|
254
|
+
];
|
|
255
|
+
|
|
256
|
+
// =============================================================================
|
|
257
|
+
// MESSAGE POOLS - Status
|
|
258
|
+
// =============================================================================
|
|
259
|
+
|
|
260
|
+
const SCANNING_MESSAGES = [
|
|
261
|
+
'Scanning for {action:liquidity sweep}...',
|
|
262
|
+
'Analyzing order flow for bias...',
|
|
263
|
+
'Monitoring {zone:structure} for zones...',
|
|
264
|
+
'Watching swing point development...',
|
|
265
|
+
'Evaluating high-probability setup...',
|
|
266
|
+
'Processing through strategy filters...',
|
|
267
|
+
'Analyzing order book imbalances...',
|
|
268
|
+
'Monitoring for {inst:institutional} activity...',
|
|
269
|
+
'Scanning for alpha opportunities...',
|
|
270
|
+
'Evaluating at key {zone:levels}...',
|
|
271
|
+
'Analyzing microstructure for edge...',
|
|
272
|
+
'Monitoring {bull:bid}/{bear:ask} imbalances...',
|
|
273
|
+
'Scanning {zone:zones} for {action:sweep}...',
|
|
274
|
+
'Evaluating {flow:momentum}...',
|
|
275
|
+
'Analyzing regime alignment...',
|
|
276
|
+
];
|
|
277
|
+
|
|
278
|
+
const WAITING_MESSAGES = [
|
|
279
|
+
'Waiting for {action:sweep} confirmation...',
|
|
280
|
+
'Pending - {zone:zone} penetration needed...',
|
|
281
|
+
'Standby - conditions not met...',
|
|
282
|
+
'Awaiting signal - monitoring {zone:zone}...',
|
|
283
|
+
'Ready for {action:liquidity sweep}...',
|
|
284
|
+
'Monitoring entry trigger...',
|
|
285
|
+
'Waiting for {action:rejection}...',
|
|
286
|
+
'Confirmation pending...',
|
|
287
|
+
'Entry conditions not met...',
|
|
288
|
+
'Awaiting confluence...',
|
|
289
|
+
];
|
|
290
|
+
|
|
291
|
+
// =============================================================================
|
|
292
|
+
// MESSAGE POOLS - Data Flow
|
|
293
|
+
// =============================================================================
|
|
294
|
+
|
|
295
|
+
const TICK_FLOW_MESSAGES = [
|
|
296
|
+
'Processing tick data from Rithmic',
|
|
297
|
+
'Market data flowing - normal latency',
|
|
298
|
+
'Live feed active - systems OK',
|
|
299
|
+
'Tick stream healthy',
|
|
300
|
+
'Data from ticker plant',
|
|
301
|
+
'Feed stable - no packet loss',
|
|
302
|
+
'Real-time data synchronized',
|
|
303
|
+
'Tick processing nominal',
|
|
304
|
+
'Pipeline healthy - low latency',
|
|
305
|
+
'Market feed online',
|
|
306
|
+
'Tick ingestion active',
|
|
307
|
+
'Data flow nominal',
|
|
308
|
+
'Stream latency optimal',
|
|
309
|
+
'Feed quality excellent',
|
|
310
|
+
'Throughput normal',
|
|
311
|
+
];
|
|
312
|
+
|
|
313
|
+
const BUILDING_BARS_MESSAGES = [
|
|
314
|
+
'Building bars from ticks',
|
|
315
|
+
'Aggregating into OHLC',
|
|
316
|
+
'Forming candles',
|
|
317
|
+
'Bar construction active',
|
|
318
|
+
'Chart building',
|
|
319
|
+
'OHLC updating',
|
|
320
|
+
'Bar formation active',
|
|
321
|
+
'Candle building',
|
|
322
|
+
'Time bar processing',
|
|
323
|
+
'Bar data updating',
|
|
324
|
+
];
|
|
325
|
+
|
|
326
|
+
const MODEL_ANALYSIS_MESSAGES = [
|
|
327
|
+
'Running models on live data',
|
|
328
|
+
'Analyzing for signals',
|
|
329
|
+
'Computing multi-factor signals',
|
|
330
|
+
'Model evaluation active',
|
|
331
|
+
'Strategy analysis running',
|
|
332
|
+
'Pattern recognition scanning',
|
|
333
|
+
'Signal computation active',
|
|
334
|
+
'Model processing ticks',
|
|
335
|
+
'Algorithm evaluation',
|
|
336
|
+
'Quantitative analysis',
|
|
337
|
+
'Statistical modeling',
|
|
338
|
+
'Feature extraction',
|
|
339
|
+
'Predictive analysis',
|
|
340
|
+
'Model optimization',
|
|
341
|
+
'Multi-factor analysis',
|
|
342
|
+
];
|
|
343
|
+
|
|
344
|
+
// =============================================================================
|
|
345
|
+
// EXPORTS
|
|
346
|
+
// =============================================================================
|
|
347
|
+
|
|
348
|
+
module.exports = {
|
|
349
|
+
LONG_BIAS_MESSAGES,
|
|
350
|
+
SHORT_BIAS_MESSAGES,
|
|
351
|
+
FLAT_BIAS_MESSAGES,
|
|
352
|
+
SIGNAL_LONG_MESSAGES,
|
|
353
|
+
SIGNAL_SHORT_MESSAGES,
|
|
354
|
+
ENTRY_LONG_MESSAGES,
|
|
355
|
+
ENTRY_SHORT_MESSAGES,
|
|
356
|
+
EXIT_PROFIT_MESSAGES,
|
|
357
|
+
EXIT_LOSS_MESSAGES,
|
|
358
|
+
ZONE_APPROACH_MESSAGES,
|
|
359
|
+
ZONE_CONFIRMED_MESSAGES,
|
|
360
|
+
HIGH_VOLATILITY_MESSAGES,
|
|
361
|
+
LOW_VOLATILITY_MESSAGES,
|
|
362
|
+
RISK_PASSED_MESSAGES,
|
|
363
|
+
RISK_BLOCKED_MESSAGES,
|
|
364
|
+
SCANNING_MESSAGES,
|
|
365
|
+
WAITING_MESSAGES,
|
|
366
|
+
TICK_FLOW_MESSAGES,
|
|
367
|
+
BUILDING_BARS_MESSAGES,
|
|
368
|
+
MODEL_ANALYSIS_MESSAGES,
|
|
369
|
+
};
|
package/src/lib/smart-logs.js
CHANGED
|
@@ -3,18 +3,66 @@
|
|
|
3
3
|
* Smart Logging System - HF Grade
|
|
4
4
|
* =============================================================================
|
|
5
5
|
* Non-repetitive, contextual, varied log messages for professional HF CLI
|
|
6
|
-
* - Large message pools (
|
|
6
|
+
* - Large message pools (15 per category) to avoid repetition
|
|
7
7
|
* - Tracks recent messages to ensure variety
|
|
8
8
|
* - Professional, institutional-grade messaging
|
|
9
|
+
*
|
|
10
|
+
* Messages are in separate file: smart-logs-messages.js (RULES.md compliance)
|
|
9
11
|
*/
|
|
10
12
|
|
|
11
13
|
'use strict';
|
|
12
14
|
|
|
13
15
|
const chalk = require('chalk');
|
|
16
|
+
// Force colors to be enabled for log messages
|
|
17
|
+
chalk.level = 3;
|
|
18
|
+
const {
|
|
19
|
+
LONG_BIAS_MESSAGES,
|
|
20
|
+
SHORT_BIAS_MESSAGES,
|
|
21
|
+
FLAT_BIAS_MESSAGES,
|
|
22
|
+
SIGNAL_LONG_MESSAGES,
|
|
23
|
+
SIGNAL_SHORT_MESSAGES,
|
|
24
|
+
ENTRY_LONG_MESSAGES,
|
|
25
|
+
ENTRY_SHORT_MESSAGES,
|
|
26
|
+
EXIT_PROFIT_MESSAGES,
|
|
27
|
+
EXIT_LOSS_MESSAGES,
|
|
28
|
+
ZONE_APPROACH_MESSAGES,
|
|
29
|
+
ZONE_CONFIRMED_MESSAGES,
|
|
30
|
+
HIGH_VOLATILITY_MESSAGES,
|
|
31
|
+
LOW_VOLATILITY_MESSAGES,
|
|
32
|
+
RISK_PASSED_MESSAGES,
|
|
33
|
+
RISK_BLOCKED_MESSAGES,
|
|
34
|
+
SCANNING_MESSAGES,
|
|
35
|
+
WAITING_MESSAGES,
|
|
36
|
+
TICK_FLOW_MESSAGES,
|
|
37
|
+
BUILDING_BARS_MESSAGES,
|
|
38
|
+
MODEL_ANALYSIS_MESSAGES,
|
|
39
|
+
} = require('./smart-logs-messages');
|
|
14
40
|
|
|
15
41
|
// Track recently used messages to avoid repetition
|
|
16
42
|
const recentMessages = new Map();
|
|
17
|
-
const MAX_RECENT = 8;
|
|
43
|
+
const MAX_RECENT = 8;
|
|
44
|
+
|
|
45
|
+
// Color map for placeholders {type:text}
|
|
46
|
+
const colorMap = {
|
|
47
|
+
bull: chalk.cyan,
|
|
48
|
+
bear: chalk.magenta,
|
|
49
|
+
zone: chalk.yellow,
|
|
50
|
+
action: chalk.green,
|
|
51
|
+
risk: chalk.red,
|
|
52
|
+
profit: chalk.green.bold,
|
|
53
|
+
flow: chalk.blue,
|
|
54
|
+
inst: chalk.white.bold,
|
|
55
|
+
};
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* Apply colors to message placeholders like {bull:Buyers}
|
|
59
|
+
*/
|
|
60
|
+
function colorize(msg) {
|
|
61
|
+
return msg.replace(/\{(\w+):([^}]+)\}/g, (match, type, text) => {
|
|
62
|
+
const colorFn = colorMap[type];
|
|
63
|
+
return colorFn ? colorFn(text) : text;
|
|
64
|
+
});
|
|
65
|
+
}
|
|
18
66
|
|
|
19
67
|
/**
|
|
20
68
|
* Get a message from a pool, avoiding recent ones
|
|
@@ -33,339 +81,10 @@ function getVariedMessage(category, pool, defaultMsg) {
|
|
|
33
81
|
if (recent.length > MAX_RECENT) recent.shift();
|
|
34
82
|
recentMessages.set(category, recent);
|
|
35
83
|
|
|
36
|
-
|
|
84
|
+
// Apply colors to placeholders
|
|
85
|
+
return colorize(chosen);
|
|
37
86
|
}
|
|
38
87
|
|
|
39
|
-
// =============================================================================
|
|
40
|
-
// MESSAGE POOLS - Market Flow (Bullish)
|
|
41
|
-
// =============================================================================
|
|
42
|
-
|
|
43
|
-
const LONG_BIAS_MESSAGES = [
|
|
44
|
-
'Buyers taking control of the tape',
|
|
45
|
-
'Bid side absorbing sell pressure',
|
|
46
|
-
'Bullish order flow detected on sweep',
|
|
47
|
-
'Buy programs actively lifting offers',
|
|
48
|
-
'Strong buyer presence at current levels',
|
|
49
|
-
'Accumulation pattern forming on volume',
|
|
50
|
-
'Demand exceeding supply at bid',
|
|
51
|
-
'Buyers stepping up with size',
|
|
52
|
-
'Long-side momentum building steadily',
|
|
53
|
-
'Bid accumulation detected at support',
|
|
54
|
-
'Bullish delta divergence confirmed',
|
|
55
|
-
'Buy-side imbalance driving price higher',
|
|
56
|
-
'Institutional buying detected on tape',
|
|
57
|
-
'Aggressive bid lifting through offers',
|
|
58
|
-
'Bullish tape reading with strong delta',
|
|
59
|
-
];
|
|
60
|
-
|
|
61
|
-
// =============================================================================
|
|
62
|
-
// MESSAGE POOLS - Market Flow (Bearish)
|
|
63
|
-
// =============================================================================
|
|
64
|
-
|
|
65
|
-
const SHORT_BIAS_MESSAGES = [
|
|
66
|
-
'Sellers taking control of the tape',
|
|
67
|
-
'Offer side absorbing buy pressure',
|
|
68
|
-
'Bearish order flow detected on sweep',
|
|
69
|
-
'Sell programs actively hitting bids',
|
|
70
|
-
'Strong seller presence at current levels',
|
|
71
|
-
'Distribution pattern forming on volume',
|
|
72
|
-
'Supply exceeding demand at offer',
|
|
73
|
-
'Sellers stepping in with size',
|
|
74
|
-
'Short-side momentum building steadily',
|
|
75
|
-
'Offer distribution detected at resistance',
|
|
76
|
-
'Bearish delta divergence confirmed',
|
|
77
|
-
'Sell-side imbalance driving price lower',
|
|
78
|
-
'Institutional selling detected on tape',
|
|
79
|
-
'Aggressive offer hitting through bids',
|
|
80
|
-
'Bearish tape reading with weak delta',
|
|
81
|
-
];
|
|
82
|
-
|
|
83
|
-
// =============================================================================
|
|
84
|
-
// MESSAGE POOLS - Market Flow (Neutral)
|
|
85
|
-
// =============================================================================
|
|
86
|
-
|
|
87
|
-
const FLAT_BIAS_MESSAGES = [
|
|
88
|
-
'Market balanced',
|
|
89
|
-
'Two-way flow active',
|
|
90
|
-
'Consolidation mode',
|
|
91
|
-
'No clear direction',
|
|
92
|
-
'Mixed signals detected',
|
|
93
|
-
'Range-bound activity',
|
|
94
|
-
'Equilibrium state',
|
|
95
|
-
'Neutral order flow',
|
|
96
|
-
'Balanced book pressure',
|
|
97
|
-
'Rotation in progress',
|
|
98
|
-
'Price discovery phase',
|
|
99
|
-
'Awaiting catalyst',
|
|
100
|
-
'Sideways chop detected',
|
|
101
|
-
'Mean reversion zone',
|
|
102
|
-
'Liquidity absorption',
|
|
103
|
-
];
|
|
104
|
-
|
|
105
|
-
// =============================================================================
|
|
106
|
-
// MESSAGE POOLS - Trading Signals
|
|
107
|
-
// =============================================================================
|
|
108
|
-
|
|
109
|
-
const SIGNAL_LONG_MESSAGES = [
|
|
110
|
-
'Buy signal generated',
|
|
111
|
-
'Long opportunity detected',
|
|
112
|
-
'Bullish setup confirmed',
|
|
113
|
-
'Entry signal: LONG',
|
|
114
|
-
'Buy zone activated',
|
|
115
|
-
'Long trigger fired',
|
|
116
|
-
'Bullish confirmation received',
|
|
117
|
-
'Buy entry validated',
|
|
118
|
-
'Long setup materialized',
|
|
119
|
-
'Bullish pattern complete',
|
|
120
|
-
];
|
|
121
|
-
|
|
122
|
-
const SIGNAL_SHORT_MESSAGES = [
|
|
123
|
-
'Sell signal generated',
|
|
124
|
-
'Short opportunity detected',
|
|
125
|
-
'Bearish setup confirmed',
|
|
126
|
-
'Entry signal: SHORT',
|
|
127
|
-
'Sell zone activated',
|
|
128
|
-
'Short trigger fired',
|
|
129
|
-
'Bearish confirmation received',
|
|
130
|
-
'Sell entry validated',
|
|
131
|
-
'Short setup materialized',
|
|
132
|
-
'Bearish pattern complete',
|
|
133
|
-
];
|
|
134
|
-
|
|
135
|
-
// =============================================================================
|
|
136
|
-
// MESSAGE POOLS - Trade Execution
|
|
137
|
-
// =============================================================================
|
|
138
|
-
|
|
139
|
-
const ENTRY_LONG_MESSAGES = [
|
|
140
|
-
'Long position opened',
|
|
141
|
-
'Buy order filled',
|
|
142
|
-
'Entered long',
|
|
143
|
-
'Long initiated',
|
|
144
|
-
'Position: LONG',
|
|
145
|
-
'Long execution complete',
|
|
146
|
-
'Buy fill confirmed',
|
|
147
|
-
'Long entry executed',
|
|
148
|
-
'Bought at market',
|
|
149
|
-
'Long position established',
|
|
150
|
-
];
|
|
151
|
-
|
|
152
|
-
const ENTRY_SHORT_MESSAGES = [
|
|
153
|
-
'Short position opened',
|
|
154
|
-
'Sell order filled',
|
|
155
|
-
'Entered short',
|
|
156
|
-
'Short initiated',
|
|
157
|
-
'Position: SHORT',
|
|
158
|
-
'Short execution complete',
|
|
159
|
-
'Sell fill confirmed',
|
|
160
|
-
'Short entry executed',
|
|
161
|
-
'Sold at market',
|
|
162
|
-
'Short position established',
|
|
163
|
-
];
|
|
164
|
-
|
|
165
|
-
const EXIT_PROFIT_MESSAGES = [
|
|
166
|
-
'Target reached',
|
|
167
|
-
'Profit taken',
|
|
168
|
-
'Winner closed',
|
|
169
|
-
'TP hit',
|
|
170
|
-
'Profit locked',
|
|
171
|
-
'Gain realized',
|
|
172
|
-
'Profitable exit',
|
|
173
|
-
'Target achieved',
|
|
174
|
-
'Winner booked',
|
|
175
|
-
'Profit captured',
|
|
176
|
-
];
|
|
177
|
-
|
|
178
|
-
const EXIT_LOSS_MESSAGES = [
|
|
179
|
-
'Stop triggered',
|
|
180
|
-
'Loss taken',
|
|
181
|
-
'Loser closed',
|
|
182
|
-
'SL hit',
|
|
183
|
-
'Risk contained',
|
|
184
|
-
'Loss realized',
|
|
185
|
-
'Stop executed',
|
|
186
|
-
'Risk managed',
|
|
187
|
-
'Loser booked',
|
|
188
|
-
'Loss controlled',
|
|
189
|
-
];
|
|
190
|
-
|
|
191
|
-
// =============================================================================
|
|
192
|
-
// MESSAGE POOLS - Zone Analysis
|
|
193
|
-
// =============================================================================
|
|
194
|
-
|
|
195
|
-
const ZONE_APPROACH_MESSAGES = [
|
|
196
|
-
'Approaching key level',
|
|
197
|
-
'Zone test incoming',
|
|
198
|
-
'Near decision point',
|
|
199
|
-
'Level approach detected',
|
|
200
|
-
'Key zone in range',
|
|
201
|
-
'Price nearing structure',
|
|
202
|
-
'Zone proximity alert',
|
|
203
|
-
'Testing liquidity zone',
|
|
204
|
-
'Approaching pivot',
|
|
205
|
-
'Near high-volume node',
|
|
206
|
-
];
|
|
207
|
-
|
|
208
|
-
const ZONE_CONFIRMED_MESSAGES = [
|
|
209
|
-
'Zone confirmation',
|
|
210
|
-
'Level validated',
|
|
211
|
-
'Support/resistance active',
|
|
212
|
-
'Zone reaction detected',
|
|
213
|
-
'Level holding',
|
|
214
|
-
'Structure confirmed',
|
|
215
|
-
'Zone defense active',
|
|
216
|
-
'Level response detected',
|
|
217
|
-
'Pivot confirmed',
|
|
218
|
-
'Volume node reaction',
|
|
219
|
-
];
|
|
220
|
-
|
|
221
|
-
// =============================================================================
|
|
222
|
-
// MESSAGE POOLS - Volatility
|
|
223
|
-
// =============================================================================
|
|
224
|
-
|
|
225
|
-
const HIGH_VOLATILITY_MESSAGES = [
|
|
226
|
-
'Volatility elevated',
|
|
227
|
-
'High ATR detected',
|
|
228
|
-
'Increased price range',
|
|
229
|
-
'Market volatile',
|
|
230
|
-
'Wide swings detected',
|
|
231
|
-
'Volatility expansion',
|
|
232
|
-
'Range expanding',
|
|
233
|
-
'High activity zone',
|
|
234
|
-
'Momentum surge',
|
|
235
|
-
'Breakout conditions',
|
|
236
|
-
];
|
|
237
|
-
|
|
238
|
-
const LOW_VOLATILITY_MESSAGES = [
|
|
239
|
-
'Low volatility',
|
|
240
|
-
'Tight range detected',
|
|
241
|
-
'Compressed price action',
|
|
242
|
-
'Market quiet',
|
|
243
|
-
'Narrow swings',
|
|
244
|
-
'Volatility contraction',
|
|
245
|
-
'Range compressing',
|
|
246
|
-
'Low activity zone',
|
|
247
|
-
'Momentum cooling',
|
|
248
|
-
'Consolidation forming',
|
|
249
|
-
];
|
|
250
|
-
|
|
251
|
-
// =============================================================================
|
|
252
|
-
// MESSAGE POOLS - Risk Management
|
|
253
|
-
// =============================================================================
|
|
254
|
-
|
|
255
|
-
const RISK_PASSED_MESSAGES = [
|
|
256
|
-
'Risk check passed',
|
|
257
|
-
'Trade approved',
|
|
258
|
-
'Within risk limits',
|
|
259
|
-
'Risk validated',
|
|
260
|
-
'Clear to trade',
|
|
261
|
-
'Risk parameters met',
|
|
262
|
-
'Position size approved',
|
|
263
|
-
'Risk budget OK',
|
|
264
|
-
'Trade authorized',
|
|
265
|
-
'Risk constraints satisfied',
|
|
266
|
-
];
|
|
267
|
-
|
|
268
|
-
const RISK_BLOCKED_MESSAGES = [
|
|
269
|
-
'Risk limit reached',
|
|
270
|
-
'Trade blocked',
|
|
271
|
-
'Exceeds risk threshold',
|
|
272
|
-
'Risk rejected',
|
|
273
|
-
'Waiting for conditions',
|
|
274
|
-
'Risk parameters exceeded',
|
|
275
|
-
'Position size rejected',
|
|
276
|
-
'Risk budget depleted',
|
|
277
|
-
'Trade denied',
|
|
278
|
-
'Risk constraints violated',
|
|
279
|
-
];
|
|
280
|
-
|
|
281
|
-
// =============================================================================
|
|
282
|
-
// MESSAGE POOLS - Status
|
|
283
|
-
// =============================================================================
|
|
284
|
-
|
|
285
|
-
const SCANNING_MESSAGES = [
|
|
286
|
-
'Scanning market...',
|
|
287
|
-
'Analyzing flow...',
|
|
288
|
-
'Monitoring structure...',
|
|
289
|
-
'Watching for setups...',
|
|
290
|
-
'Evaluating conditions...',
|
|
291
|
-
'Processing market data...',
|
|
292
|
-
'Analyzing order book...',
|
|
293
|
-
'Monitoring tape...',
|
|
294
|
-
'Scanning for alpha...',
|
|
295
|
-
'Evaluating price action...',
|
|
296
|
-
'Analyzing microstructure...',
|
|
297
|
-
'Monitoring imbalances...',
|
|
298
|
-
'Scanning liquidity zones...',
|
|
299
|
-
'Evaluating momentum...',
|
|
300
|
-
'Analyzing market regime...',
|
|
301
|
-
];
|
|
302
|
-
|
|
303
|
-
const WAITING_MESSAGES = [
|
|
304
|
-
'Waiting for confirmation...',
|
|
305
|
-
'Pending trigger...',
|
|
306
|
-
'Standby mode...',
|
|
307
|
-
'Awaiting signal...',
|
|
308
|
-
'Ready to act...',
|
|
309
|
-
'Monitoring for entry...',
|
|
310
|
-
'Waiting for setup...',
|
|
311
|
-
'Confirmation pending...',
|
|
312
|
-
'Entry conditions not met...',
|
|
313
|
-
'Awaiting confluence...',
|
|
314
|
-
];
|
|
315
|
-
|
|
316
|
-
// =============================================================================
|
|
317
|
-
// MESSAGE POOLS - Data Flow
|
|
318
|
-
// =============================================================================
|
|
319
|
-
|
|
320
|
-
const TICK_FLOW_MESSAGES = [
|
|
321
|
-
'Processing tick data',
|
|
322
|
-
'Market data flowing',
|
|
323
|
-
'Live feed active',
|
|
324
|
-
'Tick stream healthy',
|
|
325
|
-
'Data streaming',
|
|
326
|
-
'Feed connection stable',
|
|
327
|
-
'Real-time data active',
|
|
328
|
-
'Tick processing nominal',
|
|
329
|
-
'Data pipeline healthy',
|
|
330
|
-
'Market feed online',
|
|
331
|
-
'Tick ingestion active',
|
|
332
|
-
'Data flow nominal',
|
|
333
|
-
'Stream latency optimal',
|
|
334
|
-
'Feed quality excellent',
|
|
335
|
-
'Data throughput normal',
|
|
336
|
-
];
|
|
337
|
-
|
|
338
|
-
const BUILDING_BARS_MESSAGES = [
|
|
339
|
-
'Building price bars',
|
|
340
|
-
'Aggregating ticks',
|
|
341
|
-
'Forming candles',
|
|
342
|
-
'Bar construction',
|
|
343
|
-
'Chart building',
|
|
344
|
-
'OHLC aggregation',
|
|
345
|
-
'Bar formation active',
|
|
346
|
-
'Candle building',
|
|
347
|
-
'Time bar processing',
|
|
348
|
-
'Bar data updating',
|
|
349
|
-
];
|
|
350
|
-
|
|
351
|
-
const MODEL_ANALYSIS_MESSAGES = [
|
|
352
|
-
'Running models',
|
|
353
|
-
'Analyzing patterns',
|
|
354
|
-
'Computing signals',
|
|
355
|
-
'Model evaluation',
|
|
356
|
-
'Strategy analysis',
|
|
357
|
-
'ML inference active',
|
|
358
|
-
'Pattern recognition',
|
|
359
|
-
'Signal computation',
|
|
360
|
-
'Model processing',
|
|
361
|
-
'Algorithm evaluation',
|
|
362
|
-
'Quantitative analysis',
|
|
363
|
-
'Statistical modeling',
|
|
364
|
-
'Feature extraction',
|
|
365
|
-
'Predictive analysis',
|
|
366
|
-
'Model optimization',
|
|
367
|
-
];
|
|
368
|
-
|
|
369
88
|
// =============================================================================
|
|
370
89
|
// SMART LOG GENERATORS
|
|
371
90
|
// =============================================================================
|
|
@@ -292,17 +292,37 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
|
|
|
292
292
|
// Combined single line for zones info
|
|
293
293
|
ui.addLog('analysis', `Zones: ${state.activeZones} | R: ${resStr} | S: ${supStr} | Swings: ${state.swingsDetected}`);
|
|
294
294
|
|
|
295
|
+
// HF-grade proximity logs with precise distance info
|
|
296
|
+
if (price && state.nearestResistance) {
|
|
297
|
+
const gapR = state.nearestResistance - price;
|
|
298
|
+
const ticksR = Math.round(gapR / tickSize);
|
|
299
|
+
const dirR = gapR > 0 ? 'below' : 'above';
|
|
300
|
+
const absTicksR = Math.abs(ticksR);
|
|
301
|
+
if (absTicksR <= 50) { // Only show if within 50 ticks
|
|
302
|
+
ui.addLog('analysis', `PROX R: ${Math.abs(gapR).toFixed(2)} pts (${absTicksR} ticks ${dirR}) | Trigger: price must sweep ABOVE then reject`);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
if (price && state.nearestSupport) {
|
|
306
|
+
const gapS = price - state.nearestSupport;
|
|
307
|
+
const ticksS = Math.round(gapS / tickSize);
|
|
308
|
+
const dirS = gapS > 0 ? 'above' : 'below';
|
|
309
|
+
const absTicksS = Math.abs(ticksS);
|
|
310
|
+
if (absTicksS <= 50) { // Only show if within 50 ticks
|
|
311
|
+
ui.addLog('analysis', `PROX S: ${Math.abs(gapS).toFixed(2)} pts (${absTicksS} ticks ${dirS}) | Trigger: price must sweep BELOW then reject`);
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
295
315
|
// Strategy status - what we're waiting for
|
|
296
316
|
if (state.activeZones === 0) {
|
|
297
|
-
ui.addLog('risk', '
|
|
317
|
+
ui.addLog('risk', 'Building liquidity map - scanning swing points for zone formation...');
|
|
298
318
|
} else if (!state.nearestSupport && !state.nearestResistance) {
|
|
299
|
-
ui.addLog('risk', 'Zones detected but
|
|
319
|
+
ui.addLog('risk', 'Zones detected but outside proximity range - waiting for price approach');
|
|
300
320
|
} else if (!state.nearestSupport) {
|
|
301
|
-
ui.addLog('analysis', '
|
|
321
|
+
ui.addLog('analysis', 'Monitoring resistance for HIGH SWEEP opportunity (SHORT entry on rejection)');
|
|
302
322
|
} else if (!state.nearestResistance) {
|
|
303
|
-
ui.addLog('analysis', '
|
|
323
|
+
ui.addLog('analysis', 'Monitoring support for LOW SWEEP opportunity (LONG entry on rejection)');
|
|
304
324
|
} else {
|
|
305
|
-
ui.addLog('ready', 'Both zones active - monitoring for liquidity sweep');
|
|
325
|
+
ui.addLog('ready', 'Both zones active - monitoring for liquidity sweep with rejection confirmation');
|
|
306
326
|
}
|
|
307
327
|
}
|
|
308
328
|
}
|
|
@@ -344,27 +364,23 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
|
|
|
344
364
|
timestamp: tick.timestamp || Date.now()
|
|
345
365
|
});
|
|
346
366
|
|
|
347
|
-
// Calculate latency
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
if (!isNaN(tickTime) && tickTime > 1000000000000) { // Valid millisecond timestamp
|
|
351
|
-
stats.latency = Math.max(0, now - tickTime);
|
|
352
|
-
}
|
|
353
|
-
} else if (tick.ssboe && tick.usecs) {
|
|
367
|
+
// Calculate latency from Rithmic ssboe/usecs (exchange timestamp)
|
|
368
|
+
// Priority: ssboe/usecs (real exchange time) > inter-tick timing (fallback)
|
|
369
|
+
if (tick.ssboe && tick.usecs !== undefined) {
|
|
354
370
|
// Rithmic sends ssboe (seconds since epoch) and usecs (microseconds)
|
|
355
|
-
const tickTimeMs = tick.ssboe * 1000 + Math.floor(tick.usecs / 1000);
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
371
|
+
const tickTimeMs = (tick.ssboe * 1000) + Math.floor(tick.usecs / 1000);
|
|
372
|
+
const latency = now - tickTimeMs;
|
|
373
|
+
// Only update if reasonable (0-5000ms) - avoids clock sync issues
|
|
374
|
+
if (latency >= 0 && latency < 5000) {
|
|
375
|
+
stats.latency = latency;
|
|
376
|
+
}
|
|
377
|
+
} else if (lastTickTime > 0) {
|
|
378
|
+
// Fallback: estimate from inter-tick timing
|
|
379
|
+
const timeSinceLastTick = now - lastTickTime;
|
|
380
|
+
if (timeSinceLastTick < 100) {
|
|
381
|
+
tickLatencies.push(timeSinceLastTick);
|
|
382
|
+
if (tickLatencies.length > 20) tickLatencies.shift();
|
|
383
|
+
stats.latency = Math.round(tickLatencies.reduce((a, b) => a + b, 0) / tickLatencies.length);
|
|
368
384
|
}
|
|
369
385
|
}
|
|
370
386
|
lastTickTime = now;
|
|
@@ -437,31 +453,20 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
|
|
|
437
453
|
const pnlInterval = setInterval(() => { if (running) pollPnL(); }, 2000);
|
|
438
454
|
pollPnL();
|
|
439
455
|
|
|
440
|
-
// Keyboard handler
|
|
456
|
+
// Keyboard handler for exit (X or Ctrl+C)
|
|
441
457
|
const setupKeyHandler = () => {
|
|
442
458
|
if (!process.stdin.isTTY) return;
|
|
443
459
|
readline.emitKeypressEvents(process.stdin);
|
|
444
460
|
process.stdin.setRawMode(true);
|
|
445
461
|
process.stdin.resume();
|
|
446
|
-
|
|
447
|
-
const onKey = (str, key) => {
|
|
448
|
-
if (key && (key.name === 'x' || key.name === 'X' || (key.ctrl && key.name === 'c'))) {
|
|
449
|
-
running = false; stopReason = 'manual';
|
|
450
|
-
}
|
|
451
|
-
};
|
|
462
|
+
const onKey = (str, key) => { if (key && (key.name === 'x' || key.name === 'X' || (key.ctrl && key.name === 'c'))) { running = false; stopReason = 'manual'; } };
|
|
452
463
|
process.stdin.on('keypress', onKey);
|
|
453
|
-
return () => {
|
|
454
|
-
process.stdin.removeListener('keypress', onKey);
|
|
455
|
-
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
456
|
-
};
|
|
464
|
+
return () => { process.stdin.removeListener('keypress', onKey); if (process.stdin.isTTY) process.stdin.setRawMode(false); };
|
|
457
465
|
};
|
|
458
|
-
|
|
459
466
|
const cleanupKeys = setupKeyHandler();
|
|
460
467
|
|
|
461
|
-
// Wait for stop
|
|
462
|
-
await new Promise(resolve => {
|
|
463
|
-
const check = setInterval(() => { if (!running) { clearInterval(check); resolve(); } }, 100);
|
|
464
|
-
});
|
|
468
|
+
// Wait for stop signal
|
|
469
|
+
await new Promise(resolve => { const check = setInterval(() => { if (!running) { clearInterval(check); resolve(); } }, 100); });
|
|
465
470
|
|
|
466
471
|
// Cleanup
|
|
467
472
|
clearInterval(refreshInterval);
|
|
@@ -469,19 +474,14 @@ const executeAlgo = async ({ service, account, contract, config, strategy: strat
|
|
|
469
474
|
await marketFeed.disconnect();
|
|
470
475
|
if (cleanupKeys) cleanupKeys();
|
|
471
476
|
ui.cleanup();
|
|
472
|
-
|
|
473
477
|
if (process.stdin.isTTY) process.stdin.setRawMode(false);
|
|
474
478
|
process.stdin.resume();
|
|
475
479
|
|
|
476
|
-
// Duration
|
|
480
|
+
// Duration and summary
|
|
477
481
|
const durationMs = Date.now() - stats.startTime;
|
|
478
|
-
const
|
|
479
|
-
|
|
480
|
-
const seconds = Math.floor((durationMs % 60000) / 1000);
|
|
481
|
-
stats.duration = hours > 0 ? `${hours}h ${minutes}m ${seconds}s` : minutes > 0 ? `${minutes}m ${seconds}s` : `${seconds}s`;
|
|
482
|
-
|
|
482
|
+
const h = Math.floor(durationMs / 3600000), m = Math.floor((durationMs % 3600000) / 60000), s = Math.floor((durationMs % 60000) / 1000);
|
|
483
|
+
stats.duration = h > 0 ? `${h}h ${m}m ${s}s` : m > 0 ? `${m}m ${s}s` : `${s}s`;
|
|
483
484
|
renderSessionSummary(stats, stopReason);
|
|
484
|
-
|
|
485
485
|
console.log('\n Returning to menu in 3 seconds...');
|
|
486
486
|
await new Promise(resolve => setTimeout(resolve, 3000));
|
|
487
487
|
};
|
package/src/pages/algo/ui.js
CHANGED
|
@@ -289,8 +289,8 @@ class AlgoUI {
|
|
|
289
289
|
|
|
290
290
|
// Activity header - HF style with animated spinner
|
|
291
291
|
if (!this.startTime) this.startTime = Date.now();
|
|
292
|
-
|
|
293
|
-
this.spinnerFrame = (this.spinnerFrame + 1) % SPINNER.length;
|
|
292
|
+
// Increment spinner frame on each render
|
|
293
|
+
this.spinnerFrame = ((this.spinnerFrame || 0) + 1) % SPINNER.length;
|
|
294
294
|
const spinner = SPINNER[this.spinnerFrame];
|
|
295
295
|
const now = new Date();
|
|
296
296
|
const timeStr = now.toLocaleTimeString('en-US', { hour12: false });
|