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
package/src/config/propfirms.js
CHANGED
|
@@ -1,194 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* @fileoverview PropFirm API Configurations -
|
|
2
|
+
* @fileoverview PropFirm API Configurations - Rithmic Only
|
|
3
3
|
* @module config/propfirms
|
|
4
4
|
*/
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
* PropFirm configurations
|
|
8
|
-
* Synced with: /root/HQX-Dev/hqx_tg/src/propfirms/config.ts
|
|
7
|
+
* PropFirm configurations (Rithmic platform only)
|
|
9
8
|
*/
|
|
10
9
|
const PROPFIRMS = {
|
|
11
|
-
// ==================== ProjectX Platform ====================
|
|
12
|
-
topstep: {
|
|
13
|
-
id: 'topstepx',
|
|
14
|
-
name: 'TopStep',
|
|
15
|
-
displayName: 'TopStep',
|
|
16
|
-
platform: 'ProjectX',
|
|
17
|
-
userApi: 'userapi.topstepx.com',
|
|
18
|
-
gatewayApi: 'api.topstepx.com'
|
|
19
|
-
},
|
|
20
|
-
alpha_futures: {
|
|
21
|
-
id: 'alphafutures',
|
|
22
|
-
name: 'Alpha Futures',
|
|
23
|
-
displayName: 'Alpha Futures',
|
|
24
|
-
platform: 'ProjectX',
|
|
25
|
-
userApi: 'userapi.alphafutures.projectx.com',
|
|
26
|
-
gatewayApi: 'api.alphafutures.projectx.com'
|
|
27
|
-
},
|
|
28
|
-
tickticktrader: {
|
|
29
|
-
id: 'tickticktrader',
|
|
30
|
-
name: 'TickTickTrader',
|
|
31
|
-
displayName: 'TickTickTrader',
|
|
32
|
-
platform: 'ProjectX',
|
|
33
|
-
userApi: 'userapi.tickticktrader.projectx.com',
|
|
34
|
-
gatewayApi: 'api.tickticktrader.projectx.com'
|
|
35
|
-
},
|
|
36
|
-
bulenox: {
|
|
37
|
-
id: 'bulenox',
|
|
38
|
-
name: 'Bulenox',
|
|
39
|
-
displayName: 'Bulenox',
|
|
40
|
-
platform: 'ProjectX',
|
|
41
|
-
userApi: 'userapi.bulenox.projectx.com',
|
|
42
|
-
gatewayApi: 'api.bulenox.projectx.com'
|
|
43
|
-
},
|
|
44
|
-
tradeday: {
|
|
45
|
-
id: 'tradeday',
|
|
46
|
-
name: 'TradeDay',
|
|
47
|
-
displayName: 'TradeDay',
|
|
48
|
-
platform: 'ProjectX',
|
|
49
|
-
userApi: 'userapi.tradeday.projectx.com',
|
|
50
|
-
gatewayApi: 'api.tradeday.projectx.com'
|
|
51
|
-
},
|
|
52
|
-
blusky: {
|
|
53
|
-
id: 'blusky',
|
|
54
|
-
name: 'Blusky',
|
|
55
|
-
displayName: 'Blusky',
|
|
56
|
-
platform: 'ProjectX',
|
|
57
|
-
userApi: 'userapi.blusky.projectx.com',
|
|
58
|
-
gatewayApi: 'api.blusky.projectx.com'
|
|
59
|
-
},
|
|
60
|
-
goat_futures: {
|
|
61
|
-
id: 'goatfutures',
|
|
62
|
-
name: 'Goat Futures',
|
|
63
|
-
displayName: 'Goat Futures',
|
|
64
|
-
platform: 'ProjectX',
|
|
65
|
-
userApi: 'userapi.goatfutures.projectx.com',
|
|
66
|
-
gatewayApi: 'api.goatfutures.projectx.com'
|
|
67
|
-
},
|
|
68
|
-
futures_desk: {
|
|
69
|
-
id: 'thefuturesdesk',
|
|
70
|
-
name: 'The Futures Desk',
|
|
71
|
-
displayName: 'The Futures Desk',
|
|
72
|
-
platform: 'ProjectX',
|
|
73
|
-
userApi: 'userapi.thefuturesdesk.projectx.com',
|
|
74
|
-
gatewayApi: 'api.thefuturesdesk.projectx.com'
|
|
75
|
-
},
|
|
76
|
-
daytraders: {
|
|
77
|
-
id: 'daytraders',
|
|
78
|
-
name: 'DayTraders',
|
|
79
|
-
displayName: 'DayTraders',
|
|
80
|
-
platform: 'ProjectX',
|
|
81
|
-
userApi: 'userapi.daytraders.projectx.com',
|
|
82
|
-
gatewayApi: 'api.daytraders.projectx.com'
|
|
83
|
-
},
|
|
84
|
-
e8_futures: {
|
|
85
|
-
id: 'e8futures',
|
|
86
|
-
name: 'E8 Futures',
|
|
87
|
-
displayName: 'E8 Futures',
|
|
88
|
-
platform: 'ProjectX',
|
|
89
|
-
userApi: 'userapi.e8futures.projectx.com',
|
|
90
|
-
gatewayApi: 'api.e8futures.projectx.com'
|
|
91
|
-
},
|
|
92
|
-
blue_guardian: {
|
|
93
|
-
id: 'blueguardianfutures',
|
|
94
|
-
name: 'Blue Guardian Futures',
|
|
95
|
-
displayName: 'Blue Guardian Futures',
|
|
96
|
-
platform: 'ProjectX',
|
|
97
|
-
userApi: 'userapi.blueguardianfutures.projectx.com',
|
|
98
|
-
gatewayApi: 'api.blueguardianfutures.projectx.com'
|
|
99
|
-
},
|
|
100
|
-
futures_elite: {
|
|
101
|
-
id: 'futureselite',
|
|
102
|
-
name: 'FuturesElite',
|
|
103
|
-
displayName: 'FuturesElite',
|
|
104
|
-
platform: 'ProjectX',
|
|
105
|
-
userApi: 'userapi.futureselite.projectx.com',
|
|
106
|
-
gatewayApi: 'api.futureselite.projectx.com'
|
|
107
|
-
},
|
|
108
|
-
fxify: {
|
|
109
|
-
id: 'fxify',
|
|
110
|
-
name: 'FXIFY',
|
|
111
|
-
displayName: 'FXIFY',
|
|
112
|
-
platform: 'ProjectX',
|
|
113
|
-
userApi: 'userapi.fxify.projectx.com',
|
|
114
|
-
gatewayApi: 'api.fxify.projectx.com'
|
|
115
|
-
},
|
|
116
|
-
hola_prime: {
|
|
117
|
-
id: 'holaprime',
|
|
118
|
-
name: 'Hola Prime',
|
|
119
|
-
displayName: 'Hola Prime',
|
|
120
|
-
platform: 'ProjectX',
|
|
121
|
-
userApi: 'userapi.holaprime.projectx.com',
|
|
122
|
-
gatewayApi: 'api.holaprime.projectx.com'
|
|
123
|
-
},
|
|
124
|
-
top_one_futures: {
|
|
125
|
-
id: 'toponefutures',
|
|
126
|
-
name: 'Top One Futures',
|
|
127
|
-
displayName: 'Top One Futures',
|
|
128
|
-
platform: 'ProjectX',
|
|
129
|
-
userApi: 'userapi.toponefutures.projectx.com',
|
|
130
|
-
gatewayApi: 'api.toponefutures.projectx.com'
|
|
131
|
-
},
|
|
132
|
-
funding_futures: {
|
|
133
|
-
id: 'fundingfutures',
|
|
134
|
-
name: 'Funding Futures',
|
|
135
|
-
displayName: 'Funding Futures',
|
|
136
|
-
platform: 'ProjectX',
|
|
137
|
-
userApi: 'userapi.fundingfutures.projectx.com',
|
|
138
|
-
gatewayApi: 'api.fundingfutures.projectx.com'
|
|
139
|
-
},
|
|
140
|
-
tx3_funding: {
|
|
141
|
-
id: 'tx3funding',
|
|
142
|
-
name: 'TX3 Funding',
|
|
143
|
-
displayName: 'TX3 Funding',
|
|
144
|
-
platform: 'ProjectX',
|
|
145
|
-
userApi: 'userapi.tx3funding.projectx.com',
|
|
146
|
-
gatewayApi: 'api.tx3funding.projectx.com'
|
|
147
|
-
},
|
|
148
|
-
lucid_trading: {
|
|
149
|
-
id: 'lucidtrading',
|
|
150
|
-
name: 'Lucid Trading',
|
|
151
|
-
displayName: 'Lucid Trading',
|
|
152
|
-
platform: 'ProjectX',
|
|
153
|
-
userApi: 'userapi.lucidtrading.projectx.com',
|
|
154
|
-
gatewayApi: 'api.lucidtrading.projectx.com'
|
|
155
|
-
},
|
|
156
|
-
tradeify: {
|
|
157
|
-
id: 'tradeify',
|
|
158
|
-
name: 'Tradeify',
|
|
159
|
-
displayName: 'Tradeify',
|
|
160
|
-
platform: 'ProjectX',
|
|
161
|
-
userApi: 'userapi.tradeify.projectx.com',
|
|
162
|
-
gatewayApi: 'api.tradeify.projectx.com'
|
|
163
|
-
},
|
|
164
|
-
|
|
165
|
-
// ==================== Tradovate Platform ====================
|
|
166
|
-
apex_tradovate: {
|
|
167
|
-
id: 'apex',
|
|
168
|
-
name: 'Apex',
|
|
169
|
-
displayName: 'Apex (Tradovate)',
|
|
170
|
-
platform: 'Tradovate',
|
|
171
|
-
userApi: 'userapi.apex.tradovate.com',
|
|
172
|
-
gatewayApi: 'api.apex.tradovate.com'
|
|
173
|
-
},
|
|
174
|
-
takeprofittrader: {
|
|
175
|
-
id: 'takeprofittrader',
|
|
176
|
-
name: 'TakeProfitTrader',
|
|
177
|
-
displayName: 'TakeProfitTrader',
|
|
178
|
-
platform: 'Tradovate',
|
|
179
|
-
userApi: 'userapi.takeprofittrader.tradovate.com',
|
|
180
|
-
gatewayApi: 'api.takeprofittrader.tradovate.com'
|
|
181
|
-
},
|
|
182
|
-
myfundedfutures: {
|
|
183
|
-
id: 'myfundedfutures',
|
|
184
|
-
name: 'MyFundedFutures',
|
|
185
|
-
displayName: 'MyFundedFutures',
|
|
186
|
-
platform: 'Tradovate',
|
|
187
|
-
userApi: 'live.tradovateapi.com',
|
|
188
|
-
gatewayApi: 'live.tradovateapi.com'
|
|
189
|
-
},
|
|
190
|
-
|
|
191
|
-
// ==================== Rithmic Platform ====================
|
|
192
10
|
apex_rithmic: {
|
|
193
11
|
id: 'rithmic-apex',
|
|
194
12
|
name: 'Apex',
|
|
@@ -196,7 +14,6 @@ const PROPFIRMS = {
|
|
|
196
14
|
platform: 'Rithmic',
|
|
197
15
|
rithmicSystem: 'Apex',
|
|
198
16
|
wsEndpoint: 'wss://ritpa11120.11.rithmic.com:443',
|
|
199
|
-
|
|
200
17
|
},
|
|
201
18
|
topsteptrader: {
|
|
202
19
|
id: 'topsteptrader',
|
|
@@ -265,7 +82,7 @@ const PROPFIRMS = {
|
|
|
265
82
|
daytraders_rithmic: {
|
|
266
83
|
id: 'rithmic-daytraders',
|
|
267
84
|
name: 'DayTraders.com',
|
|
268
|
-
displayName: 'DayTraders.com
|
|
85
|
+
displayName: 'DayTraders.com',
|
|
269
86
|
platform: 'Rithmic',
|
|
270
87
|
rithmicSystem: 'DayTraders.com',
|
|
271
88
|
wsEndpoint: 'wss://ritpa11120.11.rithmic.com:443'
|
|
@@ -281,7 +98,7 @@ const PROPFIRMS = {
|
|
|
281
98
|
lucidtrading_rithmic: {
|
|
282
99
|
id: 'rithmic-lucidtrading',
|
|
283
100
|
name: 'LucidTrading',
|
|
284
|
-
displayName: 'LucidTrading
|
|
101
|
+
displayName: 'LucidTrading',
|
|
285
102
|
platform: 'Rithmic',
|
|
286
103
|
rithmicSystem: 'LucidTrading',
|
|
287
104
|
wsEndpoint: 'wss://ritpa11120.11.rithmic.com:443'
|
|
@@ -321,50 +138,29 @@ const PROPFIRMS = {
|
|
|
321
138
|
};
|
|
322
139
|
|
|
323
140
|
/**
|
|
324
|
-
* PropFirm choices for menus
|
|
141
|
+
* PropFirm choices for menus
|
|
325
142
|
*/
|
|
326
|
-
const PROPFIRM_CHOICES =
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
.map(([key, val]) => ({ name: val.displayName, value: key })),
|
|
330
|
-
|
|
331
|
-
tradovate: Object.entries(PROPFIRMS)
|
|
332
|
-
.filter(([_, v]) => v.platform === 'Tradovate')
|
|
333
|
-
.map(([key, val]) => ({ name: val.displayName, value: key })),
|
|
334
|
-
|
|
335
|
-
rithmic: Object.entries(PROPFIRMS)
|
|
336
|
-
.filter(([_, v]) => v.platform === 'Rithmic')
|
|
337
|
-
.map(([key, val]) => ({ name: val.displayName, value: key })),
|
|
338
|
-
|
|
339
|
-
all: Object.entries(PROPFIRMS)
|
|
340
|
-
.map(([key, val]) => ({ name: `${val.displayName} (${val.platform})`, value: key }))
|
|
341
|
-
};
|
|
143
|
+
const PROPFIRM_CHOICES = Object.entries(PROPFIRMS)
|
|
144
|
+
.map(([key, val]) => ({ name: val.displayName, value: key }))
|
|
145
|
+
.sort((a, b) => a.name.localeCompare(b.name));
|
|
342
146
|
|
|
343
147
|
/**
|
|
344
148
|
* Gets a PropFirm by key
|
|
345
|
-
* @param {string} key - PropFirm key
|
|
346
|
-
* @returns {Object|undefined} PropFirm config
|
|
347
149
|
*/
|
|
348
150
|
const getPropFirm = (key) => PROPFIRMS[key];
|
|
349
151
|
|
|
350
152
|
/**
|
|
351
|
-
* Gets PropFirm by ID
|
|
352
|
-
* @param {string} id - PropFirm ID
|
|
353
|
-
* @returns {Object|undefined} PropFirm config
|
|
153
|
+
* Gets PropFirm by ID
|
|
354
154
|
*/
|
|
355
155
|
const getPropFirmById = (id) => {
|
|
356
156
|
return Object.values(PROPFIRMS).find(pf => pf.id === id);
|
|
357
157
|
};
|
|
358
158
|
|
|
359
159
|
/**
|
|
360
|
-
* Gets all PropFirms
|
|
361
|
-
* @param {string} platform - Platform name (ProjectX, Tradovate, Rithmic)
|
|
362
|
-
* @returns {Array} PropFirm configs
|
|
160
|
+
* Gets all PropFirms
|
|
363
161
|
*/
|
|
364
|
-
const
|
|
365
|
-
return Object.entries(PROPFIRMS)
|
|
366
|
-
.filter(([_, v]) => v.platform === platform)
|
|
367
|
-
.map(([key, val]) => ({ key, ...val }));
|
|
162
|
+
const getAllPropFirms = () => {
|
|
163
|
+
return Object.entries(PROPFIRMS).map(([key, val]) => ({ key, ...val }));
|
|
368
164
|
};
|
|
369
165
|
|
|
370
166
|
module.exports = {
|
|
@@ -372,5 +168,5 @@ module.exports = {
|
|
|
372
168
|
PROPFIRM_CHOICES,
|
|
373
169
|
getPropFirm,
|
|
374
170
|
getPropFirmById,
|
|
375
|
-
|
|
171
|
+
getAllPropFirms
|
|
376
172
|
};
|
package/src/config/settings.js
CHANGED
|
@@ -136,48 +136,6 @@ const CACHE = {
|
|
|
136
136
|
STATS_TTL: 60000, // 1 minute
|
|
137
137
|
};
|
|
138
138
|
|
|
139
|
-
// ==================== FAST SCALPING (Ultra-Low Latency) ====================
|
|
140
|
-
const FAST_SCALPING = {
|
|
141
|
-
// Hold constraints (prop firm rules - NON-NEGOTIABLE)
|
|
142
|
-
MIN_HOLD_MS: 10000, // 10 seconds minimum hold
|
|
143
|
-
MAX_HOLD_MS: 60000, // 60 seconds failsafe (force exit if stuck)
|
|
144
|
-
|
|
145
|
-
// Exit targets (in ticks) - defaults, override per symbol
|
|
146
|
-
TARGET_TICKS: 16, // Take profit target (+$80 on NQ)
|
|
147
|
-
STOP_TICKS: 20, // Stop loss (-$100 on NQ)
|
|
148
|
-
|
|
149
|
-
// Breakeven (BE) - move SL to entry price after profit threshold
|
|
150
|
-
BREAKEVEN_ACTIVATION_TICKS: 6, // Activate BE after +6 ticks profit (+$30 on NQ)
|
|
151
|
-
BREAKEVEN_OFFSET_TICKS: 1, // BE at entry + 1 tick (small profit lock)
|
|
152
|
-
|
|
153
|
-
// Trailing stop (activates after MIN_HOLD + profit threshold)
|
|
154
|
-
TRAILING_ACTIVATION_TICKS: 8, // Start trailing after +8 ticks profit (+$40 on NQ)
|
|
155
|
-
TRAILING_DISTANCE_TICKS: 4, // Trail 4 ticks behind high/low
|
|
156
|
-
|
|
157
|
-
// Position monitoring
|
|
158
|
-
MONITOR_INTERVAL_MS: 100, // Check position every 100ms after hold
|
|
159
|
-
|
|
160
|
-
// Momentum thresholds (cumulative delta over 5 seconds)
|
|
161
|
-
MOMENTUM_STRONG_THRESHOLD: 50, // Delta > 50 = strong momentum, HOLD
|
|
162
|
-
MOMENTUM_WEAK_THRESHOLD: 20, // Delta < 20 = weak momentum, consider EXIT
|
|
163
|
-
MOMENTUM_WINDOW_MS: 5000, // 5 second window for momentum calc
|
|
164
|
-
|
|
165
|
-
// Latency monitoring
|
|
166
|
-
LOG_LATENCY: true,
|
|
167
|
-
LATENCY_TARGET_MS: 50, // Target entry latency
|
|
168
|
-
LATENCY_WARN_MS: 100, // Warn if entry takes > 100ms
|
|
169
|
-
|
|
170
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
171
|
-
// RECOVERY MODE - Math-based adaptive strategy when in drawdown
|
|
172
|
-
// Uses Kelly Criterion, Volatility scaling, and Win Rate adjustment
|
|
173
|
-
// ═══════════════════════════════════════════════════════════════════════════
|
|
174
|
-
RECOVERY: {
|
|
175
|
-
ENABLED: true,
|
|
176
|
-
ACTIVATION_PNL: -300, // Activate recovery at -$300 session P&L
|
|
177
|
-
DEACTIVATION_PNL: -100, // Deactivate when recovered to -$100
|
|
178
|
-
},
|
|
179
|
-
};
|
|
180
|
-
|
|
181
139
|
// ==================== DEBUG ====================
|
|
182
140
|
const DEBUG = {
|
|
183
141
|
get enabled() {
|
|
@@ -194,5 +152,4 @@ module.exports = {
|
|
|
194
152
|
HQX_SERVER,
|
|
195
153
|
CACHE,
|
|
196
154
|
DEBUG,
|
|
197
|
-
FAST_SCALPING,
|
|
198
155
|
};
|
package/src/lib/api.js
ADDED
|
@@ -0,0 +1,198 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Trading API - REAL ORDER EXECUTION
|
|
3
|
+
* Connects to ProjectX/TopstepX API for real trades
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
const https = require('https');
|
|
7
|
+
|
|
8
|
+
const PROPFIRM_APIS = {
|
|
9
|
+
topstep: 'api.topstepx.com',
|
|
10
|
+
alpha_futures: 'api.alphafutures.projectx.com',
|
|
11
|
+
tickticktrader: 'api.tickticktrader.projectx.com',
|
|
12
|
+
bulenox: 'api.bulenox.projectx.com',
|
|
13
|
+
tradeday: 'api.tradeday.projectx.com'
|
|
14
|
+
};
|
|
15
|
+
|
|
16
|
+
class TradingAPI {
|
|
17
|
+
constructor(token, propfirm = 'topstep') {
|
|
18
|
+
this.token = token;
|
|
19
|
+
this.apiHost = PROPFIRM_APIS[propfirm] || PROPFIRM_APIS.topstep;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
async _request(path, method = 'POST', data = null) {
|
|
23
|
+
return new Promise((resolve, reject) => {
|
|
24
|
+
const options = {
|
|
25
|
+
hostname: this.apiHost,
|
|
26
|
+
port: 443,
|
|
27
|
+
path: path,
|
|
28
|
+
method: method,
|
|
29
|
+
headers: {
|
|
30
|
+
'Content-Type': 'application/json',
|
|
31
|
+
'Accept': 'application/json',
|
|
32
|
+
'Authorization': `Bearer ${this.token}`
|
|
33
|
+
},
|
|
34
|
+
timeout: 10000
|
|
35
|
+
};
|
|
36
|
+
|
|
37
|
+
const req = https.request(options, (res) => {
|
|
38
|
+
let body = '';
|
|
39
|
+
res.on('data', chunk => body += chunk);
|
|
40
|
+
res.on('end', () => {
|
|
41
|
+
try {
|
|
42
|
+
resolve({ status: res.statusCode, data: JSON.parse(body) });
|
|
43
|
+
} catch (e) {
|
|
44
|
+
resolve({ status: res.statusCode, data: body });
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
req.on('error', reject);
|
|
50
|
+
req.on('timeout', () => {
|
|
51
|
+
req.destroy();
|
|
52
|
+
reject(new Error('Request timeout'));
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
if (data) req.write(JSON.stringify(data));
|
|
56
|
+
req.end();
|
|
57
|
+
});
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* Place a market order - REAL EXECUTION
|
|
62
|
+
* ProjectX API order types:
|
|
63
|
+
* 1 = Limit (requires limitPrice)
|
|
64
|
+
* 2 = Market (no price required)
|
|
65
|
+
* 3 = Stop Market (requires stopPrice)
|
|
66
|
+
* 4 = Stop Limit (requires both)
|
|
67
|
+
*/
|
|
68
|
+
async placeMarketOrder(accountId, contractId, side, quantity, currentPrice = 0) {
|
|
69
|
+
// Type 2 = Market order - tested and confirmed working
|
|
70
|
+
const orderData = {
|
|
71
|
+
accountId: parseInt(accountId),
|
|
72
|
+
contractId: contractId,
|
|
73
|
+
type: 2, // Market order
|
|
74
|
+
side: side === 'buy' ? 0 : 1, // 0=Buy, 1=Sell
|
|
75
|
+
size: quantity
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
console.log(`[TRADING] MARKET ${side.toUpperCase()} ${quantity}x ${contractId}`);
|
|
79
|
+
|
|
80
|
+
const response = await this._request('/api/Order/place', 'POST', orderData);
|
|
81
|
+
|
|
82
|
+
if (response.status === 200 && response.data.success) {
|
|
83
|
+
console.log(`[TRADING] FILLED - OrderId: ${response.data.orderId}`);
|
|
84
|
+
return { success: true, order: response.data };
|
|
85
|
+
} else {
|
|
86
|
+
console.log(`[TRADING] REJECTED: ${response.data.errorMessage || 'Unknown error'}`);
|
|
87
|
+
return { success: false, error: response.data.errorMessage || 'Order failed' };
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Place a limit order - REAL EXECUTION
|
|
93
|
+
*/
|
|
94
|
+
async placeLimitOrder(accountId, contractId, side, quantity, price) {
|
|
95
|
+
const orderData = {
|
|
96
|
+
accountId: parseInt(accountId),
|
|
97
|
+
contractId: contractId,
|
|
98
|
+
type: 0, // Limit order
|
|
99
|
+
side: side === 'buy' ? 0 : 1,
|
|
100
|
+
size: quantity,
|
|
101
|
+
limitPrice: price
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
console.log(`[TRADING] Placing LIMIT order: ${side.toUpperCase()} ${quantity}x ${contractId} @ ${price}`);
|
|
105
|
+
|
|
106
|
+
const response = await this._request('/api/Order/place', 'POST', orderData);
|
|
107
|
+
|
|
108
|
+
if (response.status === 200 && response.data.success) {
|
|
109
|
+
console.log(`[TRADING] Limit order placed: ${JSON.stringify(response.data)}`);
|
|
110
|
+
return { success: true, order: response.data };
|
|
111
|
+
} else {
|
|
112
|
+
return { success: false, error: response.data.errorMessage || 'Order failed' };
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/**
|
|
117
|
+
* Place a stop order - REAL EXECUTION
|
|
118
|
+
* ProjectX API: type 2 = Stop Market
|
|
119
|
+
*/
|
|
120
|
+
async placeStopOrder(accountId, contractId, side, quantity, stopPrice) {
|
|
121
|
+
const orderData = {
|
|
122
|
+
accountId: parseInt(accountId),
|
|
123
|
+
contractId: contractId,
|
|
124
|
+
type: 2, // Stop Market order
|
|
125
|
+
side: side === 'buy' ? 0 : 1,
|
|
126
|
+
size: quantity,
|
|
127
|
+
stopPrice: stopPrice
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
console.log(`[TRADING] Placing STOP order: ${side.toUpperCase()} ${quantity}x ${contractId} @ stop ${stopPrice}`);
|
|
131
|
+
|
|
132
|
+
const response = await this._request('/api/Order/place', 'POST', orderData);
|
|
133
|
+
|
|
134
|
+
console.log(`[TRADING] Stop response: ${JSON.stringify(response.data)}`);
|
|
135
|
+
|
|
136
|
+
if (response.status === 200 && response.data.success) {
|
|
137
|
+
console.log(`[TRADING] Stop order placed - OrderId: ${response.data.orderId}`);
|
|
138
|
+
return { success: true, order: response.data };
|
|
139
|
+
} else {
|
|
140
|
+
console.log(`[TRADING] Stop order REJECTED: ${response.data.errorMessage || 'Unknown error'}`);
|
|
141
|
+
return { success: false, error: response.data.errorMessage || 'Order failed' };
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
/**
|
|
146
|
+
* Cancel an order
|
|
147
|
+
*/
|
|
148
|
+
async cancelOrder(orderId) {
|
|
149
|
+
const response = await this._request('/api/Order/cancel', 'POST', { orderId: parseInt(orderId) });
|
|
150
|
+
return { success: response.status === 200 && response.data.success };
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Close a position - REAL EXECUTION
|
|
155
|
+
*/
|
|
156
|
+
async closePosition(accountId, contractId) {
|
|
157
|
+
console.log(`[TRADING] Closing position: ${contractId}`);
|
|
158
|
+
|
|
159
|
+
const response = await this._request('/api/Position/closeContract', 'POST', {
|
|
160
|
+
accountId: parseInt(accountId),
|
|
161
|
+
contractId: contractId
|
|
162
|
+
});
|
|
163
|
+
|
|
164
|
+
if (response.status === 200 && response.data.success) {
|
|
165
|
+
console.log(`[TRADING] Position CLOSED`);
|
|
166
|
+
return { success: true };
|
|
167
|
+
} else {
|
|
168
|
+
console.log(`[TRADING] Close FAILED: ${JSON.stringify(response.data)}`);
|
|
169
|
+
return { success: false, error: response.data.errorMessage || 'Close failed' };
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Get open positions
|
|
175
|
+
*/
|
|
176
|
+
async getPositions(accountId) {
|
|
177
|
+
const response = await this._request('/api/Position/searchOpen', 'POST', { accountId: parseInt(accountId) });
|
|
178
|
+
|
|
179
|
+
if (response.status === 200) {
|
|
180
|
+
return { success: true, positions: response.data.positions || response.data || [] };
|
|
181
|
+
}
|
|
182
|
+
return { success: false, positions: [] };
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Get open orders
|
|
187
|
+
*/
|
|
188
|
+
async getOrders(accountId) {
|
|
189
|
+
const response = await this._request('/api/Order/searchOpen', 'POST', { accountId: parseInt(accountId) });
|
|
190
|
+
|
|
191
|
+
if (response.status === 200) {
|
|
192
|
+
return { success: true, orders: response.data.orders || response.data || [] };
|
|
193
|
+
}
|
|
194
|
+
return { success: false, orders: [] };
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
module.exports = { TradingAPI };
|