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,206 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Position Momentum Calculator
|
|
3
|
-
* Calculates momentum using strategy's math models (OFI, Kalman, Z-Score)
|
|
4
|
-
*
|
|
5
|
-
* Data sources:
|
|
6
|
-
* - OFI: Strategy's computeOrderFlowImbalance()
|
|
7
|
-
* - Kalman: Strategy's kalmanStates
|
|
8
|
-
* - Z-Score: Strategy's computeZScore()
|
|
9
|
-
* - VPIN: Strategy's computeVPIN()
|
|
10
|
-
*/
|
|
11
|
-
|
|
12
|
-
const { logger } = require('../utils/logger');
|
|
13
|
-
const { WEIGHTS } = require('./position-constants');
|
|
14
|
-
|
|
15
|
-
const log = logger.scope('PositionMomentum');
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Get OFI (Order Flow Imbalance) from strategy
|
|
19
|
-
* @param {Object} strategy - Strategy instance
|
|
20
|
-
* @param {string} contractId - Contract identifier
|
|
21
|
-
* @returns {number|null} OFI value [-1, 1] or null if unavailable
|
|
22
|
-
*/
|
|
23
|
-
const getOFI = (strategy, contractId) => {
|
|
24
|
-
if (!strategy) return null;
|
|
25
|
-
|
|
26
|
-
// Try strategy's computeOrderFlowImbalance (direct calculation from bars)
|
|
27
|
-
if (typeof strategy.computeOrderFlowImbalance === 'function') {
|
|
28
|
-
const bars = strategy.getBarHistory?.(contractId);
|
|
29
|
-
if (bars && bars.length >= 20) {
|
|
30
|
-
try {
|
|
31
|
-
return strategy.computeOrderFlowImbalance(bars);
|
|
32
|
-
} catch (error) {
|
|
33
|
-
log.debug('OFI calculation failed', { error: error.message });
|
|
34
|
-
}
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
// Try getModelValues (pre-calculated values)
|
|
39
|
-
const modelValues = strategy.getModelValues?.(contractId);
|
|
40
|
-
if (modelValues && modelValues.rawOfi !== undefined) {
|
|
41
|
-
return modelValues.rawOfi;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
return null;
|
|
45
|
-
};
|
|
46
|
-
|
|
47
|
-
/**
|
|
48
|
-
* Get Kalman velocity from strategy's Kalman filter
|
|
49
|
-
* @param {Object} strategy - Strategy instance
|
|
50
|
-
* @param {string} contractId - Contract identifier
|
|
51
|
-
* @param {number} currentPrice - Latest price
|
|
52
|
-
* @returns {number|null} Velocity value or null if unavailable
|
|
53
|
-
*/
|
|
54
|
-
const getKalmanVelocity = (strategy, contractId, currentPrice) => {
|
|
55
|
-
if (!strategy) return null;
|
|
56
|
-
|
|
57
|
-
// Try to access kalmanStates from strategy
|
|
58
|
-
if (strategy.kalmanStates) {
|
|
59
|
-
const state = strategy.kalmanStates.get(contractId);
|
|
60
|
-
if (state && typeof state.estimate === 'number') {
|
|
61
|
-
if (currentPrice !== undefined && currentPrice !== null) {
|
|
62
|
-
return currentPrice - state.estimate;
|
|
63
|
-
}
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
return null;
|
|
68
|
-
};
|
|
69
|
-
|
|
70
|
-
/**
|
|
71
|
-
* Get Z-Score from strategy
|
|
72
|
-
* @param {Object} strategy - Strategy instance
|
|
73
|
-
* @param {string} contractId - Contract identifier
|
|
74
|
-
* @returns {number|null} Z-Score value or null if unavailable
|
|
75
|
-
*/
|
|
76
|
-
const getZScore = (strategy, contractId) => {
|
|
77
|
-
if (!strategy) return null;
|
|
78
|
-
|
|
79
|
-
// Try strategy's computeZScore (direct calculation from price buffer)
|
|
80
|
-
if (typeof strategy.computeZScore === 'function') {
|
|
81
|
-
const prices = strategy.priceBuffer?.get(contractId);
|
|
82
|
-
if (prices && prices.length >= 50) {
|
|
83
|
-
try {
|
|
84
|
-
return strategy.computeZScore(prices);
|
|
85
|
-
} catch (error) {
|
|
86
|
-
log.debug('Z-Score calculation failed', { error: error.message });
|
|
87
|
-
}
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
return null;
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
/**
|
|
95
|
-
* Get VPIN from strategy
|
|
96
|
-
* @param {Object} strategy - Strategy instance
|
|
97
|
-
* @param {string} contractId - Contract identifier
|
|
98
|
-
* @returns {number|null} VPIN value [0, 1] or null if unavailable
|
|
99
|
-
*/
|
|
100
|
-
const getVPIN = (strategy, contractId) => {
|
|
101
|
-
if (!strategy) return null;
|
|
102
|
-
|
|
103
|
-
// Try strategy's computeVPIN (direct calculation from volume buffer)
|
|
104
|
-
if (typeof strategy.computeVPIN === 'function') {
|
|
105
|
-
const volumes = strategy.volumeBuffer?.get(contractId);
|
|
106
|
-
if (volumes && volumes.length >= 50) {
|
|
107
|
-
try {
|
|
108
|
-
return strategy.computeVPIN(volumes);
|
|
109
|
-
} catch (error) {
|
|
110
|
-
log.debug('VPIN calculation failed', { error: error.message });
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// Try getModelValues (pre-calculated, stored as 1 - vpin for scoring)
|
|
116
|
-
const modelValues = strategy.getModelValues?.(contractId);
|
|
117
|
-
if (modelValues && typeof modelValues.vpin === 'number') {
|
|
118
|
-
return 1 - modelValues.vpin;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
return null;
|
|
122
|
-
};
|
|
123
|
-
|
|
124
|
-
/**
|
|
125
|
-
* Calculate momentum score using strategy's existing math models
|
|
126
|
-
* Weighted: OFI (50%) + Kalman Velocity (25%) + Z-Score (25%)
|
|
127
|
-
*
|
|
128
|
-
* @param {Object} params - Parameters
|
|
129
|
-
* @param {Object} params.strategy - Strategy instance
|
|
130
|
-
* @param {string} params.contractId - Contract identifier
|
|
131
|
-
* @param {number} params.side - Position side (0=Long, 1=Short)
|
|
132
|
-
* @param {number} params.currentPrice - Latest price
|
|
133
|
-
* @param {number|null} params.tickSize - Tick size from API
|
|
134
|
-
* @returns {number|null} Momentum score [-1 to 1], positive = favorable, null if insufficient data
|
|
135
|
-
*/
|
|
136
|
-
const calculateMomentum = ({ strategy, contractId, side, currentPrice, tickSize }) => {
|
|
137
|
-
if (!strategy) {
|
|
138
|
-
return null;
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
// Get individual model values (all from API/strategy, not invented)
|
|
142
|
-
const ofi = getOFI(strategy, contractId);
|
|
143
|
-
const velocity = getKalmanVelocity(strategy, contractId, currentPrice);
|
|
144
|
-
const zscore = getZScore(strategy, contractId);
|
|
145
|
-
|
|
146
|
-
// Count how many models have data
|
|
147
|
-
let availableModels = 0;
|
|
148
|
-
let totalWeight = 0;
|
|
149
|
-
let weightedSum = 0;
|
|
150
|
-
|
|
151
|
-
// 1. OFI (50%) - Order Flow Imbalance
|
|
152
|
-
if (ofi !== null) {
|
|
153
|
-
// For long: positive OFI = favorable, For short: negative OFI = favorable
|
|
154
|
-
const favorableOfi = side === 0 ? ofi : -ofi;
|
|
155
|
-
const ofiScore = Math.min(1, Math.max(-1, favorableOfi));
|
|
156
|
-
weightedSum += ofiScore * WEIGHTS.OFI;
|
|
157
|
-
totalWeight += WEIGHTS.OFI;
|
|
158
|
-
availableModels++;
|
|
159
|
-
}
|
|
160
|
-
|
|
161
|
-
// 2. Kalman Velocity (25%)
|
|
162
|
-
if (velocity !== null && tickSize !== null) {
|
|
163
|
-
// Normalize velocity: favorable direction = positive
|
|
164
|
-
const favorableVelocity = side === 0 ? velocity : -velocity;
|
|
165
|
-
// Normalize to [-1, 1]: 4 ticks of velocity = 1.0 score
|
|
166
|
-
const normalizedVelocity = favorableVelocity / (tickSize * 4);
|
|
167
|
-
const velocityScore = Math.min(1, Math.max(-1, normalizedVelocity));
|
|
168
|
-
weightedSum += velocityScore * WEIGHTS.KALMAN;
|
|
169
|
-
totalWeight += WEIGHTS.KALMAN;
|
|
170
|
-
availableModels++;
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
// 3. Z-Score (25%) - Progression toward mean
|
|
174
|
-
if (zscore !== null) {
|
|
175
|
-
let zscoreScore;
|
|
176
|
-
if (side === 0) {
|
|
177
|
-
// Long: entered when Z < -threshold, improving = Z moving toward 0
|
|
178
|
-
zscoreScore = zscore > -0.5 ? 0.5 : -0.5;
|
|
179
|
-
} else {
|
|
180
|
-
// Short: entered when Z > threshold, improving = Z moving toward 0
|
|
181
|
-
zscoreScore = zscore < 0.5 ? 0.5 : -0.5;
|
|
182
|
-
}
|
|
183
|
-
weightedSum += zscoreScore * WEIGHTS.ZSCORE;
|
|
184
|
-
totalWeight += WEIGHTS.ZSCORE;
|
|
185
|
-
availableModels++;
|
|
186
|
-
}
|
|
187
|
-
|
|
188
|
-
// Need at least 1 model with data to calculate momentum
|
|
189
|
-
if (availableModels === 0 || totalWeight === 0) {
|
|
190
|
-
return null;
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
// Normalize by actual total weight (in case some models unavailable)
|
|
194
|
-
const momentum = weightedSum / totalWeight;
|
|
195
|
-
|
|
196
|
-
// Clamp to [-1, 1]
|
|
197
|
-
return Math.min(1, Math.max(-1, momentum));
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
module.exports = {
|
|
201
|
-
getOFI,
|
|
202
|
-
getKalmanVelocity,
|
|
203
|
-
getZScore,
|
|
204
|
-
getVPIN,
|
|
205
|
-
calculateMomentum,
|
|
206
|
-
};
|
|
@@ -1,142 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* ProjectX Account Management
|
|
3
|
-
* @module services/projectx/accounts
|
|
4
|
-
*
|
|
5
|
-
* Account enrichment and P&L calculations.
|
|
6
|
-
*/
|
|
7
|
-
|
|
8
|
-
const { logger } = require('../../utils/logger');
|
|
9
|
-
|
|
10
|
-
const log = logger.scope('ProjectX');
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* Enrich account with P&L data from API
|
|
14
|
-
* @param {Function} request - Request function
|
|
15
|
-
* @param {Object} propfirm - Propfirm config
|
|
16
|
-
* @param {Object} account - Account object
|
|
17
|
-
* @param {Array} templates - Account templates
|
|
18
|
-
*/
|
|
19
|
-
async function enrichAccount(request, propfirm, account, templates) {
|
|
20
|
-
const template = templates.find(t =>
|
|
21
|
-
account.accountName && (
|
|
22
|
-
account.accountName.includes(t.title) ||
|
|
23
|
-
t.title.includes(account.accountName)
|
|
24
|
-
)
|
|
25
|
-
);
|
|
26
|
-
|
|
27
|
-
const enriched = {
|
|
28
|
-
accountId: account.accountId,
|
|
29
|
-
accountName: account.accountName,
|
|
30
|
-
balance: account.balance,
|
|
31
|
-
status: account.status,
|
|
32
|
-
type: account.type,
|
|
33
|
-
startingBalance: template?.startingBalance || null,
|
|
34
|
-
platform: 'ProjectX',
|
|
35
|
-
propfirm: propfirm.name,
|
|
36
|
-
openPnL: null,
|
|
37
|
-
todayPnL: null,
|
|
38
|
-
profitAndLoss: null,
|
|
39
|
-
};
|
|
40
|
-
|
|
41
|
-
// Only fetch P&L for active accounts
|
|
42
|
-
if (account.status !== 0) {
|
|
43
|
-
return enriched;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
// Get unrealized P&L from open positions
|
|
47
|
-
let openPnL = 0;
|
|
48
|
-
try {
|
|
49
|
-
const posRes = await request(
|
|
50
|
-
propfirm.userApi,
|
|
51
|
-
`/Position?accountId=${account.accountId}`,
|
|
52
|
-
'GET'
|
|
53
|
-
);
|
|
54
|
-
|
|
55
|
-
if (posRes.statusCode === 200 && Array.isArray(posRes.data)) {
|
|
56
|
-
for (const pos of posRes.data) {
|
|
57
|
-
if (pos.profitAndLoss != null) {
|
|
58
|
-
openPnL += pos.profitAndLoss;
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
} catch {
|
|
63
|
-
log.debug('Failed to get positions', { accountId: account.accountId });
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Get realized P&L from today's trades
|
|
67
|
-
let todayPnL = 0;
|
|
68
|
-
try {
|
|
69
|
-
const today = new Date();
|
|
70
|
-
today.setHours(0, 0, 0, 0);
|
|
71
|
-
|
|
72
|
-
const tradesRes = await request(
|
|
73
|
-
propfirm.gatewayApi,
|
|
74
|
-
'/api/Trade/search',
|
|
75
|
-
'POST',
|
|
76
|
-
{
|
|
77
|
-
accountId: account.accountId,
|
|
78
|
-
startTimestamp: today.toISOString(),
|
|
79
|
-
endTimestamp: new Date().toISOString(),
|
|
80
|
-
}
|
|
81
|
-
);
|
|
82
|
-
|
|
83
|
-
if (tradesRes.statusCode === 200) {
|
|
84
|
-
const trades = Array.isArray(tradesRes.data) ? tradesRes.data : (tradesRes.data.trades || []);
|
|
85
|
-
for (const trade of trades) {
|
|
86
|
-
if (trade.profitAndLoss != null) {
|
|
87
|
-
todayPnL += trade.profitAndLoss;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
}
|
|
91
|
-
} catch {
|
|
92
|
-
log.debug('Failed to get today trades', { accountId: account.accountId });
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
enriched.openPnL = openPnL;
|
|
96
|
-
enriched.todayPnL = todayPnL;
|
|
97
|
-
enriched.profitAndLoss = openPnL + todayPnL;
|
|
98
|
-
|
|
99
|
-
return enriched;
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
/**
|
|
103
|
-
* Get trading accounts with REAL P&L from API
|
|
104
|
-
* @param {Function} request - Request function
|
|
105
|
-
* @param {Object} propfirm - Propfirm config
|
|
106
|
-
*/
|
|
107
|
-
async function getTradingAccounts(request, propfirm) {
|
|
108
|
-
try {
|
|
109
|
-
const response = await request(propfirm.userApi, '/TradingAccount', 'GET');
|
|
110
|
-
|
|
111
|
-
if (response.statusCode !== 200) {
|
|
112
|
-
return { success: false, accounts: [], error: 'Failed to get accounts' };
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
const accounts = Array.isArray(response.data) ? response.data : [];
|
|
116
|
-
|
|
117
|
-
// Get account templates for startingBalance
|
|
118
|
-
let templates = [];
|
|
119
|
-
try {
|
|
120
|
-
const templateRes = await request(propfirm.userApi, '/AccountTemplate/userTemplates', 'GET');
|
|
121
|
-
if (templateRes.statusCode === 200 && Array.isArray(templateRes.data)) {
|
|
122
|
-
templates = templateRes.data;
|
|
123
|
-
}
|
|
124
|
-
} catch {
|
|
125
|
-
log.debug('Failed to get templates');
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
const enrichedAccounts = await Promise.all(
|
|
129
|
-
accounts.map(account => enrichAccount(request, propfirm, account, templates))
|
|
130
|
-
);
|
|
131
|
-
|
|
132
|
-
return { success: true, accounts: enrichedAccounts };
|
|
133
|
-
} catch (err) {
|
|
134
|
-
log.error('Failed to get accounts', { error: err.message });
|
|
135
|
-
return { success: false, accounts: [], error: err.message };
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
module.exports = {
|
|
140
|
-
enrichAccount,
|
|
141
|
-
getTradingAccounts,
|
|
142
|
-
};
|