hedgequantx 2.6.162 → 2.7.0
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/README.md +15 -88
- package/bin/cli.js +0 -11
- package/dist/lib/api.jsc +0 -0
- package/dist/lib/api2.jsc +0 -0
- package/dist/lib/core.jsc +0 -0
- package/dist/lib/core2.jsc +0 -0
- package/dist/lib/data.js +1 -1
- package/dist/lib/data.jsc +0 -0
- package/dist/lib/data2.jsc +0 -0
- package/dist/lib/decoder.jsc +0 -0
- package/dist/lib/m/mod1.jsc +0 -0
- package/dist/lib/m/mod2.jsc +0 -0
- package/dist/lib/n/r1.jsc +0 -0
- package/dist/lib/n/r2.jsc +0 -0
- package/dist/lib/n/r3.jsc +0 -0
- package/dist/lib/n/r4.jsc +0 -0
- package/dist/lib/n/r5.jsc +0 -0
- package/dist/lib/n/r6.jsc +0 -0
- package/dist/lib/n/r7.jsc +0 -0
- package/dist/lib/o/util1.jsc +0 -0
- package/dist/lib/o/util2.jsc +0 -0
- package/package.json +6 -3
- package/src/app.js +40 -162
- package/src/config/constants.js +31 -33
- package/src/config/propfirms.js +13 -217
- package/src/config/settings.js +0 -43
- package/src/lib/api.js +198 -0
- package/src/lib/api2.js +353 -0
- package/src/lib/core.js +539 -0
- package/src/lib/core2.js +341 -0
- package/src/lib/data.js +555 -0
- package/src/lib/data2.js +492 -0
- package/src/lib/decoder.js +599 -0
- package/src/lib/m/s1.js +804 -0
- package/src/lib/m/s2.js +34 -0
- package/src/lib/n/r1.js +454 -0
- package/src/lib/n/r2.js +514 -0
- package/src/lib/n/r3.js +631 -0
- package/src/lib/n/r4.js +401 -0
- package/src/lib/n/r5.js +335 -0
- package/src/lib/n/r6.js +425 -0
- package/src/lib/n/r7.js +530 -0
- package/src/lib/o/l1.js +44 -0
- package/src/lib/o/l2.js +427 -0
- package/src/lib/python-bridge.js +206 -0
- package/src/menus/connect.js +14 -176
- package/src/menus/dashboard.js +65 -110
- package/src/pages/accounts.js +18 -18
- package/src/pages/algo/copy-trading.js +210 -240
- package/src/pages/algo/index.js +41 -104
- package/src/pages/algo/one-account.js +386 -33
- package/src/pages/algo/ui.js +312 -151
- package/src/pages/orders.js +3 -3
- package/src/pages/positions.js +3 -3
- package/src/pages/stats/chart.js +74 -0
- package/src/pages/stats/display.js +228 -0
- package/src/pages/stats/index.js +236 -0
- package/src/pages/stats/metrics.js +213 -0
- package/src/pages/user.js +6 -6
- package/src/services/hqx-server/constants.js +55 -0
- package/src/services/hqx-server/index.js +401 -0
- package/src/services/hqx-server/latency.js +81 -0
- package/src/services/index.js +12 -3
- package/src/services/rithmic/accounts.js +7 -32
- package/src/services/rithmic/connection.js +1 -204
- package/src/services/rithmic/contracts.js +235 -0
- package/src/services/rithmic/handlers.js +21 -196
- package/src/services/rithmic/index.js +60 -291
- package/src/services/rithmic/market.js +31 -0
- package/src/services/rithmic/orders.js +5 -361
- package/src/services/rithmic/protobuf.js +5 -195
- package/src/services/session.js +22 -173
- package/src/ui/box.js +10 -18
- package/src/ui/index.js +1 -3
- package/src/ui/menu.js +1 -1
- package/src/utils/prompts.js +2 -2
- package/dist/lib/m/s1.js +0 -1
- package/src/menus/ai-agent-connect.js +0 -181
- package/src/menus/ai-agent-models.js +0 -219
- package/src/menus/ai-agent-oauth.js +0 -292
- package/src/menus/ai-agent-ui.js +0 -141
- package/src/menus/ai-agent.js +0 -484
- package/src/pages/algo/algo-config.js +0 -195
- package/src/pages/algo/algo-multi.js +0 -801
- package/src/pages/algo/algo-utils.js +0 -58
- package/src/pages/algo/copy-engine.js +0 -449
- package/src/pages/algo/custom-strategy.js +0 -459
- package/src/pages/algo/logger.js +0 -245
- package/src/pages/algo/smart-logs-data.js +0 -218
- package/src/pages/algo/smart-logs.js +0 -387
- package/src/pages/algo/ui-constants.js +0 -144
- package/src/pages/algo/ui-summary.js +0 -184
- package/src/pages/stats-calculations.js +0 -191
- package/src/pages/stats-ui.js +0 -381
- package/src/pages/stats.js +0 -339
- package/src/services/ai/client-analysis.js +0 -194
- package/src/services/ai/client-models.js +0 -333
- package/src/services/ai/client.js +0 -343
- package/src/services/ai/index.js +0 -384
- package/src/services/ai/oauth-anthropic.js +0 -265
- package/src/services/ai/oauth-gemini.js +0 -223
- package/src/services/ai/oauth-iflow.js +0 -269
- package/src/services/ai/oauth-openai.js +0 -233
- package/src/services/ai/oauth-qwen.js +0 -279
- package/src/services/ai/providers/index.js +0 -526
- package/src/services/ai/proxy-install.js +0 -249
- package/src/services/ai/proxy-manager.js +0 -494
- package/src/services/ai/proxy-remote.js +0 -161
- package/src/services/ai/strategy-supervisor.js +0 -1312
- package/src/services/ai/supervisor-data.js +0 -195
- package/src/services/ai/supervisor-optimize.js +0 -215
- package/src/services/ai/supervisor-sync.js +0 -178
- package/src/services/ai/supervisor-utils.js +0 -158
- package/src/services/ai/supervisor.js +0 -484
- package/src/services/ai/validation.js +0 -250
- package/src/services/hqx-server-events.js +0 -110
- package/src/services/hqx-server-handlers.js +0 -217
- package/src/services/hqx-server-latency.js +0 -136
- package/src/services/hqx-server.js +0 -403
- package/src/services/position-constants.js +0 -28
- package/src/services/position-manager.js +0 -528
- package/src/services/position-momentum.js +0 -206
- package/src/services/projectx/accounts.js +0 -142
- package/src/services/projectx/index.js +0 -443
- package/src/services/projectx/market.js +0 -172
- package/src/services/projectx/stats.js +0 -110
- package/src/services/projectx/trading.js +0 -180
- package/src/services/rithmic/latency-tracker.js +0 -182
- package/src/services/rithmic/market-data.js +0 -549
- package/src/services/rithmic/specs.js +0 -146
- package/src/services/rithmic/trade-history.js +0 -254
- package/src/services/session-history.js +0 -475
- package/src/services/strategy/hft-tick.js +0 -507
- package/src/services/strategy/recovery-math.js +0 -402
- package/src/services/tradovate/constants.js +0 -109
- package/src/services/tradovate/index.js +0 -505
- package/src/services/tradovate/market.js +0 -47
- package/src/services/tradovate/websocket.js +0 -97
|
@@ -1,402 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* =============================================================================
|
|
3
|
-
* Recovery Mode - Mathematical Models for Drawdown Recovery
|
|
4
|
-
* =============================================================================
|
|
5
|
-
*
|
|
6
|
-
* Uses pure math models to adapt strategy during drawdown:
|
|
7
|
-
*
|
|
8
|
-
* 1. KELLY CRITERION - Optimal position sizing based on win rate & payoff
|
|
9
|
-
* f* = (bp - q) / b
|
|
10
|
-
* where: b = win/loss ratio, p = win probability, q = 1-p
|
|
11
|
-
*
|
|
12
|
-
* 2. VOLATILITY SCALING - Adjust size inversely to recent volatility
|
|
13
|
-
* size_adj = base_size * (target_vol / current_vol)
|
|
14
|
-
*
|
|
15
|
-
* 3. ADAPTIVE THRESHOLDS - Dynamic TP/SL based on ATR
|
|
16
|
-
* TP = entry ± (ATR * tp_multiplier)
|
|
17
|
-
* SL = entry ± (ATR * sl_multiplier)
|
|
18
|
-
*
|
|
19
|
-
* 4. EXPECTED VALUE FILTER - Only take trades with positive EV
|
|
20
|
-
* EV = (win_prob * avg_win) - (loss_prob * avg_loss)
|
|
21
|
-
*
|
|
22
|
-
* 5. DRAWDOWN-ADJUSTED KELLY - Reduce risk as drawdown deepens
|
|
23
|
-
* kelly_adj = kelly * (1 - drawdown_pct / max_drawdown)
|
|
24
|
-
*/
|
|
25
|
-
|
|
26
|
-
'use strict';
|
|
27
|
-
|
|
28
|
-
const { logger } = require('../../utils/logger');
|
|
29
|
-
const log = logger.scope('RecoveryMath');
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Recovery Math Engine
|
|
33
|
-
* Calculates optimal parameters during drawdown using mathematical models
|
|
34
|
-
*/
|
|
35
|
-
class RecoveryMath {
|
|
36
|
-
constructor() {
|
|
37
|
-
// Trade history for calculations
|
|
38
|
-
this.trades = [];
|
|
39
|
-
this.maxTrades = 100; // Rolling window
|
|
40
|
-
|
|
41
|
-
// Volatility tracking
|
|
42
|
-
this.priceReturns = [];
|
|
43
|
-
this.maxReturns = 200;
|
|
44
|
-
|
|
45
|
-
// Session state
|
|
46
|
-
this.sessionPnL = 0;
|
|
47
|
-
this.peakPnL = 0;
|
|
48
|
-
this.drawdown = 0;
|
|
49
|
-
this.recoveryActive = false;
|
|
50
|
-
|
|
51
|
-
// Default parameters (will be adjusted dynamically)
|
|
52
|
-
this.baseParams = {
|
|
53
|
-
targetTicks: 16,
|
|
54
|
-
stopTicks: 20,
|
|
55
|
-
kellyFraction: 0.25, // Use 25% of full Kelly (conservative)
|
|
56
|
-
};
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* Update session P&L and check recovery activation
|
|
61
|
-
* @param {number} pnl - Current session P&L
|
|
62
|
-
* @param {number} activationThreshold - e.g., -300
|
|
63
|
-
* @param {number} deactivationThreshold - e.g., -100
|
|
64
|
-
*/
|
|
65
|
-
updateSessionPnL(pnl, activationThreshold = -300, deactivationThreshold = -100) {
|
|
66
|
-
this.sessionPnL = pnl;
|
|
67
|
-
|
|
68
|
-
// Track peak for drawdown calculation
|
|
69
|
-
if (pnl > this.peakPnL) {
|
|
70
|
-
this.peakPnL = pnl;
|
|
71
|
-
}
|
|
72
|
-
|
|
73
|
-
// Calculate current drawdown
|
|
74
|
-
this.drawdown = this.peakPnL - pnl;
|
|
75
|
-
|
|
76
|
-
// Check recovery activation
|
|
77
|
-
const wasActive = this.recoveryActive;
|
|
78
|
-
|
|
79
|
-
if (pnl <= activationThreshold && !this.recoveryActive) {
|
|
80
|
-
this.recoveryActive = true;
|
|
81
|
-
log.info('RECOVERY MODE ACTIVATED', { pnl, threshold: activationThreshold });
|
|
82
|
-
} else if (pnl >= deactivationThreshold && this.recoveryActive) {
|
|
83
|
-
this.recoveryActive = false;
|
|
84
|
-
log.info('RECOVERY MODE DEACTIVATED', { pnl, threshold: deactivationThreshold });
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
return {
|
|
88
|
-
active: this.recoveryActive,
|
|
89
|
-
justActivated: this.recoveryActive && !wasActive,
|
|
90
|
-
justDeactivated: !this.recoveryActive && wasActive,
|
|
91
|
-
drawdown: this.drawdown,
|
|
92
|
-
};
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
/**
|
|
96
|
-
* Record a completed trade for statistics
|
|
97
|
-
* @param {Object} trade - { pnl, ticks, side, duration }
|
|
98
|
-
*/
|
|
99
|
-
recordTrade(trade) {
|
|
100
|
-
this.trades.push({
|
|
101
|
-
pnl: trade.pnl,
|
|
102
|
-
ticks: trade.ticks,
|
|
103
|
-
side: trade.side,
|
|
104
|
-
duration: trade.duration,
|
|
105
|
-
timestamp: Date.now(),
|
|
106
|
-
});
|
|
107
|
-
|
|
108
|
-
// Keep rolling window
|
|
109
|
-
if (this.trades.length > this.maxTrades) {
|
|
110
|
-
this.trades.shift();
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
/**
|
|
115
|
-
* Record price return for volatility calculation
|
|
116
|
-
* @param {number} price - Current price
|
|
117
|
-
* @param {number} prevPrice - Previous price
|
|
118
|
-
*/
|
|
119
|
-
recordPriceReturn(price, prevPrice) {
|
|
120
|
-
if (prevPrice > 0) {
|
|
121
|
-
const ret = (price - prevPrice) / prevPrice;
|
|
122
|
-
this.priceReturns.push(ret);
|
|
123
|
-
|
|
124
|
-
if (this.priceReturns.length > this.maxReturns) {
|
|
125
|
-
this.priceReturns.shift();
|
|
126
|
-
}
|
|
127
|
-
}
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
/**
|
|
131
|
-
* Calculate win rate from recent trades
|
|
132
|
-
* @returns {number} Win rate [0, 1]
|
|
133
|
-
*/
|
|
134
|
-
calcWinRate() {
|
|
135
|
-
if (this.trades.length < 5) return 0.5; // Default 50% if insufficient data
|
|
136
|
-
|
|
137
|
-
const wins = this.trades.filter(t => t.pnl > 0).length;
|
|
138
|
-
return wins / this.trades.length;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
/**
|
|
142
|
-
* Calculate average win and loss
|
|
143
|
-
* @returns {{ avgWin: number, avgLoss: number, payoffRatio: number }}
|
|
144
|
-
*/
|
|
145
|
-
calcPayoff() {
|
|
146
|
-
const wins = this.trades.filter(t => t.pnl > 0);
|
|
147
|
-
const losses = this.trades.filter(t => t.pnl < 0);
|
|
148
|
-
|
|
149
|
-
const avgWin = wins.length > 0
|
|
150
|
-
? wins.reduce((s, t) => s + t.pnl, 0) / wins.length
|
|
151
|
-
: 80; // Default $80 (16 ticks on NQ)
|
|
152
|
-
|
|
153
|
-
const avgLoss = losses.length > 0
|
|
154
|
-
? Math.abs(losses.reduce((s, t) => s + t.pnl, 0) / losses.length)
|
|
155
|
-
: 100; // Default $100 (20 ticks on NQ)
|
|
156
|
-
|
|
157
|
-
return {
|
|
158
|
-
avgWin,
|
|
159
|
-
avgLoss,
|
|
160
|
-
payoffRatio: avgWin / avgLoss,
|
|
161
|
-
};
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
/**
|
|
165
|
-
* Calculate Kelly Criterion for optimal bet sizing
|
|
166
|
-
* f* = (bp - q) / b
|
|
167
|
-
* where: b = win/loss ratio, p = win probability, q = 1-p
|
|
168
|
-
*
|
|
169
|
-
* @returns {number} Kelly fraction [0, 1]
|
|
170
|
-
*/
|
|
171
|
-
calcKelly() {
|
|
172
|
-
const winRate = this.calcWinRate();
|
|
173
|
-
const { payoffRatio } = this.calcPayoff();
|
|
174
|
-
|
|
175
|
-
const p = winRate;
|
|
176
|
-
const q = 1 - p;
|
|
177
|
-
const b = payoffRatio;
|
|
178
|
-
|
|
179
|
-
// Kelly formula
|
|
180
|
-
let kelly = (b * p - q) / b;
|
|
181
|
-
|
|
182
|
-
// Clamp to reasonable range
|
|
183
|
-
kelly = Math.max(0, Math.min(1, kelly));
|
|
184
|
-
|
|
185
|
-
return kelly;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
/**
|
|
189
|
-
* Calculate drawdown-adjusted Kelly
|
|
190
|
-
* Reduces risk as drawdown deepens
|
|
191
|
-
*
|
|
192
|
-
* @param {number} maxDrawdown - Maximum allowed drawdown (e.g., 500)
|
|
193
|
-
* @returns {number} Adjusted Kelly fraction
|
|
194
|
-
*/
|
|
195
|
-
calcDrawdownAdjustedKelly(maxDrawdown = 500) {
|
|
196
|
-
const kelly = this.calcKelly();
|
|
197
|
-
|
|
198
|
-
// Reduce Kelly based on current drawdown
|
|
199
|
-
// At 0% drawdown: use full Kelly
|
|
200
|
-
// At 100% max drawdown: use 0% Kelly
|
|
201
|
-
const drawdownPct = Math.min(1, this.drawdown / maxDrawdown);
|
|
202
|
-
const adjustment = 1 - (drawdownPct * 0.5); // Max 50% reduction
|
|
203
|
-
|
|
204
|
-
return kelly * adjustment;
|
|
205
|
-
}
|
|
206
|
-
|
|
207
|
-
/**
|
|
208
|
-
* Calculate current volatility (standard deviation of returns)
|
|
209
|
-
* @returns {number} Volatility (annualized)
|
|
210
|
-
*/
|
|
211
|
-
calcVolatility() {
|
|
212
|
-
if (this.priceReturns.length < 20) return 0.02; // Default 2%
|
|
213
|
-
|
|
214
|
-
const mean = this.priceReturns.reduce((s, r) => s + r, 0) / this.priceReturns.length;
|
|
215
|
-
const variance = this.priceReturns.reduce((s, r) => s + Math.pow(r - mean, 2), 0) / this.priceReturns.length;
|
|
216
|
-
const stdDev = Math.sqrt(variance);
|
|
217
|
-
|
|
218
|
-
return stdDev;
|
|
219
|
-
}
|
|
220
|
-
|
|
221
|
-
/**
|
|
222
|
-
* Calculate ATR-based thresholds
|
|
223
|
-
* @param {number} atr - Average True Range in ticks
|
|
224
|
-
* @returns {{ targetTicks: number, stopTicks: number }}
|
|
225
|
-
*/
|
|
226
|
-
calcATRThresholds(atr) {
|
|
227
|
-
if (!atr || atr < 1) {
|
|
228
|
-
return {
|
|
229
|
-
targetTicks: this.baseParams.targetTicks,
|
|
230
|
-
stopTicks: this.baseParams.stopTicks,
|
|
231
|
-
};
|
|
232
|
-
}
|
|
233
|
-
|
|
234
|
-
// Target = 1.5 * ATR (capture 1.5 average moves)
|
|
235
|
-
// Stop = 2 * ATR (allow 2 average moves against)
|
|
236
|
-
const targetTicks = Math.round(atr * 1.5);
|
|
237
|
-
const stopTicks = Math.round(atr * 2);
|
|
238
|
-
|
|
239
|
-
// Clamp to reasonable range
|
|
240
|
-
return {
|
|
241
|
-
targetTicks: Math.max(8, Math.min(32, targetTicks)),
|
|
242
|
-
stopTicks: Math.max(10, Math.min(40, stopTicks)),
|
|
243
|
-
};
|
|
244
|
-
}
|
|
245
|
-
|
|
246
|
-
/**
|
|
247
|
-
* Calculate Expected Value of a trade setup
|
|
248
|
-
* EV = (win_prob * avg_win) - (loss_prob * avg_loss)
|
|
249
|
-
*
|
|
250
|
-
* @param {number} confidence - Signal confidence [0, 1]
|
|
251
|
-
* @returns {number} Expected value in dollars
|
|
252
|
-
*/
|
|
253
|
-
calcExpectedValue(confidence = 0.5) {
|
|
254
|
-
const baseWinRate = this.calcWinRate();
|
|
255
|
-
const { avgWin, avgLoss } = this.calcPayoff();
|
|
256
|
-
|
|
257
|
-
// Adjust win rate by signal confidence
|
|
258
|
-
// Higher confidence = higher expected win rate
|
|
259
|
-
const adjustedWinRate = baseWinRate * (0.5 + confidence * 0.5);
|
|
260
|
-
|
|
261
|
-
const ev = (adjustedWinRate * avgWin) - ((1 - adjustedWinRate) * avgLoss);
|
|
262
|
-
|
|
263
|
-
return ev;
|
|
264
|
-
}
|
|
265
|
-
|
|
266
|
-
/**
|
|
267
|
-
* Get optimal position size using Kelly and volatility scaling
|
|
268
|
-
* @param {number} baseSize - Normal position size
|
|
269
|
-
* @param {number} maxSize - Maximum allowed size
|
|
270
|
-
* @param {number} targetVol - Target volatility (e.g., 0.02)
|
|
271
|
-
* @returns {number} Optimal position size
|
|
272
|
-
*/
|
|
273
|
-
calcOptimalSize(baseSize, maxSize, targetVol = 0.02) {
|
|
274
|
-
// Get drawdown-adjusted Kelly
|
|
275
|
-
const kelly = this.calcDrawdownAdjustedKelly();
|
|
276
|
-
|
|
277
|
-
// Get current volatility
|
|
278
|
-
const currentVol = this.calcVolatility();
|
|
279
|
-
|
|
280
|
-
// Volatility scaling: reduce size when vol is high
|
|
281
|
-
const volScale = currentVol > 0 ? targetVol / currentVol : 1;
|
|
282
|
-
const volAdjusted = Math.min(2, Math.max(0.5, volScale)); // Clamp 0.5x - 2x
|
|
283
|
-
|
|
284
|
-
// In recovery mode: use half Kelly (more conservative despite "aggressive")
|
|
285
|
-
// This is counter-intuitive but mathematically sound:
|
|
286
|
-
// - We want to recover, but not blow up
|
|
287
|
-
// - Half Kelly gives ~75% of optimal growth with much less variance
|
|
288
|
-
const kellyMultiplier = this.recoveryActive
|
|
289
|
-
? this.baseParams.kellyFraction * 0.75 // More conservative in recovery
|
|
290
|
-
: this.baseParams.kellyFraction;
|
|
291
|
-
|
|
292
|
-
// Calculate optimal size
|
|
293
|
-
let optimalSize = baseSize * kelly * volAdjusted * kellyMultiplier * 4; // 4x because kelly is small
|
|
294
|
-
|
|
295
|
-
// Clamp to max
|
|
296
|
-
optimalSize = Math.max(1, Math.min(maxSize, Math.round(optimalSize)));
|
|
297
|
-
|
|
298
|
-
return optimalSize;
|
|
299
|
-
}
|
|
300
|
-
|
|
301
|
-
/**
|
|
302
|
-
* Get recovery parameters (thresholds, size, filter)
|
|
303
|
-
* All based on mathematical models
|
|
304
|
-
*
|
|
305
|
-
* @param {Object} context - { baseSize, maxSize, atr, confidence, tickValue }
|
|
306
|
-
* @returns {Object} Recovery parameters
|
|
307
|
-
*/
|
|
308
|
-
getRecoveryParams(context) {
|
|
309
|
-
const { baseSize = 1, maxSize = 5, atr = 12, confidence = 0.5, tickValue = 5 } = context;
|
|
310
|
-
|
|
311
|
-
// Calculate all math-based values
|
|
312
|
-
const winRate = this.calcWinRate();
|
|
313
|
-
const { avgWin, avgLoss, payoffRatio } = this.calcPayoff();
|
|
314
|
-
const kelly = this.calcKelly();
|
|
315
|
-
const drawdownKelly = this.calcDrawdownAdjustedKelly();
|
|
316
|
-
const volatility = this.calcVolatility();
|
|
317
|
-
const ev = this.calcExpectedValue(confidence);
|
|
318
|
-
const { targetTicks, stopTicks } = this.calcATRThresholds(atr);
|
|
319
|
-
const optimalSize = this.calcOptimalSize(baseSize, maxSize);
|
|
320
|
-
|
|
321
|
-
// Should we take this trade?
|
|
322
|
-
// In recovery: only take positive EV trades with high confidence
|
|
323
|
-
const minEV = this.recoveryActive ? 10 : 0; // Require $10 EV in recovery
|
|
324
|
-
const shouldTrade = ev >= minEV;
|
|
325
|
-
|
|
326
|
-
return {
|
|
327
|
-
// Mode status
|
|
328
|
-
recoveryActive: this.recoveryActive,
|
|
329
|
-
sessionPnL: this.sessionPnL,
|
|
330
|
-
drawdown: this.drawdown,
|
|
331
|
-
|
|
332
|
-
// Statistics
|
|
333
|
-
winRate,
|
|
334
|
-
avgWin,
|
|
335
|
-
avgLoss,
|
|
336
|
-
payoffRatio,
|
|
337
|
-
|
|
338
|
-
// Kelly
|
|
339
|
-
kelly,
|
|
340
|
-
drawdownKelly,
|
|
341
|
-
|
|
342
|
-
// Volatility
|
|
343
|
-
volatility,
|
|
344
|
-
|
|
345
|
-
// Expected Value
|
|
346
|
-
expectedValue: ev,
|
|
347
|
-
shouldTrade,
|
|
348
|
-
|
|
349
|
-
// Optimal parameters
|
|
350
|
-
optimalSize,
|
|
351
|
-
targetTicks,
|
|
352
|
-
stopTicks,
|
|
353
|
-
|
|
354
|
-
// Breakeven (based on payoff ratio)
|
|
355
|
-
// If payoff > 1: early BE (lock small profit)
|
|
356
|
-
// If payoff < 1: late BE (need bigger moves)
|
|
357
|
-
breakevenTicks: payoffRatio >= 1
|
|
358
|
-
? Math.max(3, Math.round(targetTicks * 0.3))
|
|
359
|
-
: Math.max(4, Math.round(targetTicks * 0.4)),
|
|
360
|
-
|
|
361
|
-
// Trailing (based on volatility)
|
|
362
|
-
// High vol: wider trail
|
|
363
|
-
// Low vol: tighter trail
|
|
364
|
-
trailingActivation: Math.round(targetTicks * 0.5),
|
|
365
|
-
trailingDistance: Math.max(2, Math.round(atr * 0.5)),
|
|
366
|
-
};
|
|
367
|
-
}
|
|
368
|
-
|
|
369
|
-
/**
|
|
370
|
-
* Get summary for logging
|
|
371
|
-
*/
|
|
372
|
-
getSummary() {
|
|
373
|
-
return {
|
|
374
|
-
active: this.recoveryActive,
|
|
375
|
-
sessionPnL: this.sessionPnL,
|
|
376
|
-
drawdown: this.drawdown,
|
|
377
|
-
trades: this.trades.length,
|
|
378
|
-
winRate: (this.calcWinRate() * 100).toFixed(1) + '%',
|
|
379
|
-
kelly: (this.calcKelly() * 100).toFixed(1) + '%',
|
|
380
|
-
ev: '$' + this.calcExpectedValue().toFixed(2),
|
|
381
|
-
};
|
|
382
|
-
}
|
|
383
|
-
|
|
384
|
-
/**
|
|
385
|
-
* Reset state (new session)
|
|
386
|
-
*/
|
|
387
|
-
reset() {
|
|
388
|
-
this.sessionPnL = 0;
|
|
389
|
-
this.peakPnL = 0;
|
|
390
|
-
this.drawdown = 0;
|
|
391
|
-
this.recoveryActive = false;
|
|
392
|
-
// Keep trade history for learning
|
|
393
|
-
}
|
|
394
|
-
}
|
|
395
|
-
|
|
396
|
-
// Singleton instance
|
|
397
|
-
const recoveryMath = new RecoveryMath();
|
|
398
|
-
|
|
399
|
-
module.exports = {
|
|
400
|
-
RecoveryMath,
|
|
401
|
-
recoveryMath,
|
|
402
|
-
};
|
|
@@ -1,109 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Tradovate Constants
|
|
3
|
-
*/
|
|
4
|
-
|
|
5
|
-
// Base URLs
|
|
6
|
-
const TRADOVATE_URLS = {
|
|
7
|
-
// Live Trading
|
|
8
|
-
LIVE_API: 'https://live.tradovateapi.com/v1',
|
|
9
|
-
LIVE_MD_WS: 'wss://md.tradovateapi.com/v1/websocket',
|
|
10
|
-
LIVE_TRADING_WS: 'wss://live.tradovateapi.com/v1/websocket',
|
|
11
|
-
|
|
12
|
-
// Demo/Simulation Trading
|
|
13
|
-
DEMO_API: 'https://demo.tradovateapi.com/v1',
|
|
14
|
-
DEMO_MD_WS: 'wss://md-demo.tradovateapi.com/v1/websocket',
|
|
15
|
-
DEMO_TRADING_WS: 'wss://demo.tradovateapi.com/v1/websocket',
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
// API Paths
|
|
19
|
-
const API_PATHS = {
|
|
20
|
-
// Authentication
|
|
21
|
-
AUTH_TOKEN_REQUEST: '/auth/accesstokenrequest',
|
|
22
|
-
AUTH_RENEW_TOKEN: '/auth/renewaccesstoken',
|
|
23
|
-
AUTH_ME: '/auth/me',
|
|
24
|
-
|
|
25
|
-
// Account
|
|
26
|
-
ACCOUNT_LIST: '/account/list',
|
|
27
|
-
ACCOUNT_FIND: '/account/find',
|
|
28
|
-
ACCOUNT_ITEM: '/account/item',
|
|
29
|
-
|
|
30
|
-
// Cash Balance
|
|
31
|
-
CASH_BALANCE_LIST: '/cashBalance/list',
|
|
32
|
-
CASH_BALANCE_SNAPSHOT: '/cashBalance/getcashbalancesnapshot',
|
|
33
|
-
|
|
34
|
-
// Contract
|
|
35
|
-
CONTRACT_FIND: '/contract/find',
|
|
36
|
-
CONTRACT_ITEM: '/contract/item',
|
|
37
|
-
CONTRACT_SUGGEST: '/contract/suggest',
|
|
38
|
-
|
|
39
|
-
// Product
|
|
40
|
-
PRODUCT_LIST: '/product/list',
|
|
41
|
-
PRODUCT_FIND: '/product/find',
|
|
42
|
-
|
|
43
|
-
// Order
|
|
44
|
-
ORDER_LIST: '/order/list',
|
|
45
|
-
ORDER_PLACE: '/order/placeorder',
|
|
46
|
-
ORDER_MODIFY: '/order/modifyorder',
|
|
47
|
-
ORDER_CANCEL: '/order/cancelorder',
|
|
48
|
-
ORDER_LIQUIDATE_POSITION: '/order/liquidateposition',
|
|
49
|
-
|
|
50
|
-
// Position
|
|
51
|
-
POSITION_LIST: '/position/list',
|
|
52
|
-
POSITION_DEPS: '/position/deps',
|
|
53
|
-
|
|
54
|
-
// Fill
|
|
55
|
-
FILL_LIST: '/fill/list',
|
|
56
|
-
FILL_DEPS: '/fill/deps',
|
|
57
|
-
};
|
|
58
|
-
|
|
59
|
-
// WebSocket Events
|
|
60
|
-
const WS_EVENTS = {
|
|
61
|
-
CONNECTED: 'connected',
|
|
62
|
-
DISCONNECTED: 'disconnected',
|
|
63
|
-
ERROR: 'error',
|
|
64
|
-
QUOTE: 'md/quote',
|
|
65
|
-
DOM: 'md/dom',
|
|
66
|
-
ORDER: 'order',
|
|
67
|
-
FILL: 'fill',
|
|
68
|
-
POSITION: 'position',
|
|
69
|
-
ACCOUNT: 'account',
|
|
70
|
-
CASH_BALANCE: 'cashBalance',
|
|
71
|
-
HEARTBEAT: 'heartbeat',
|
|
72
|
-
};
|
|
73
|
-
|
|
74
|
-
// Token config
|
|
75
|
-
const TOKEN_CONFIG = {
|
|
76
|
-
EXPIRATION_MINUTES: 90,
|
|
77
|
-
RENEW_BEFORE_MINUTES: 15,
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
/**
|
|
81
|
-
* Get base URL for Tradovate API
|
|
82
|
-
*/
|
|
83
|
-
function getBaseUrl(isDemo = true) {
|
|
84
|
-
return isDemo ? TRADOVATE_URLS.DEMO_API : TRADOVATE_URLS.LIVE_API;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
/**
|
|
88
|
-
* Get WebSocket URL for trading
|
|
89
|
-
*/
|
|
90
|
-
function getTradingWebSocketUrl(isDemo = true) {
|
|
91
|
-
return isDemo ? TRADOVATE_URLS.DEMO_TRADING_WS : TRADOVATE_URLS.LIVE_TRADING_WS;
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Get WebSocket URL for market data
|
|
96
|
-
*/
|
|
97
|
-
function getMdWebSocketUrl(isDemo = true) {
|
|
98
|
-
return isDemo ? TRADOVATE_URLS.DEMO_MD_WS : TRADOVATE_URLS.LIVE_MD_WS;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
module.exports = {
|
|
102
|
-
TRADOVATE_URLS,
|
|
103
|
-
API_PATHS,
|
|
104
|
-
WS_EVENTS,
|
|
105
|
-
TOKEN_CONFIG,
|
|
106
|
-
getBaseUrl,
|
|
107
|
-
getTradingWebSocketUrl,
|
|
108
|
-
getMdWebSocketUrl,
|
|
109
|
-
};
|