@tradejs/cli 2.0.2 → 2.0.4
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/dist/cli.js +43 -20
- package/dist/lib/aiPocketSearch.js +18 -0
- package/dist/lib/runtimeTradeSync.js +22 -15
- package/dist/scripts/aiExport.js +2 -1
- package/dist/scripts/aiExportSelect.js +2 -1
- package/dist/scripts/aiPocketSearch.js +18 -0
- package/dist/scripts/mlExport.js +2 -1
- package/dist/scripts/mlExportSelect.js +2 -1
- package/dist/scripts/mlTrainLatestSelect.js +2 -1
- package/dist/scripts/replay.js +20 -15
- package/dist/scripts/replayRunner.js +20 -15
- package/dist/scripts/resolveExportStrategy.js +2 -1
- package/dist/scripts/selectStrategy.js +2 -1
- package/dist/scripts/signalsSummary.js +21 -17
- package/package.json +9 -9
package/dist/cli.js
CHANGED
|
@@ -2755,7 +2755,8 @@ var init_selectStrategy = __esm({
|
|
|
2755
2755
|
"MaStrategy",
|
|
2756
2756
|
"AdaptiveMomentumRibbon",
|
|
2757
2757
|
"TrendLine",
|
|
2758
|
-
"VolumeDivergence"
|
|
2758
|
+
"VolumeDivergence",
|
|
2759
|
+
"Grid"
|
|
2759
2760
|
];
|
|
2760
2761
|
};
|
|
2761
2762
|
selectStrategy = async (promptLabel = "Select strategy", options) => {
|
|
@@ -3435,7 +3436,7 @@ var init_aiTrainOptions = __esm({
|
|
|
3435
3436
|
});
|
|
3436
3437
|
|
|
3437
3438
|
// src/lib/aiPocketSearch.ts
|
|
3438
|
-
var DAY_MS2, DAYS_PER_WEEK2, DAYS_PER_MONTH2, OUTCOME_SEGMENTS, isPlainRecord, isFiniteNumber, isFeaturePrimitive, normalizeFeaturePrimitive, isOutcomePath, isFeaturePathPrefix, isCompactFeaturePathSkipped, addFlattenedFeatures, findFeatureNumber, findFeatureString, addDirectionalDerivedFeatures, collectAiPocketFeatures, formatNumber, formatPredicateValue, roundThreshold, quantileAt, getPeriodDays, createSummaryAccumulator, addSummaryRow, emptyAiPocketSummary, finalizeAiPocketSummary, summarizeSelectedRows, summarizeMask, summarizeRowIndexes, summarizeAiPocketRows, matchesPredicate, buildMask, intersectMasks, buildPredicateListMask, toPublicPredicate, buildAiPocketPredicateResult, scorePositivePocket, scoreNegativePocket, comparePositivePockets, compareNegativePockets, createPocketResult, hashMask, isBetterRepresentativePocket, estimateCombinationCount, searchAiPockets, formatMdNumber, formatMdPercent, escapeMarkdownCell, markdownTable, summaryMetricRows, pocketRows, buildAiPocketMarkdownReport;
|
|
3439
|
+
var DAY_MS2, DAYS_PER_WEEK2, DAYS_PER_MONTH2, OUTCOME_SEGMENTS, isPlainRecord, isFiniteNumber, isFeaturePrimitive, normalizeFeaturePrimitive, isOutcomePath, isFeaturePathPrefix, isCompactFeaturePathSkipped, addFlattenedFeatures, findFeatureNumber, findFeatureString, addDirectionalDerivedFeatures, addSignalRiskDistanceFeatures, collectAiPocketFeatures, formatNumber, formatPredicateValue, roundThreshold, quantileAt, getPeriodDays, createSummaryAccumulator, addSummaryRow, emptyAiPocketSummary, finalizeAiPocketSummary, summarizeSelectedRows, summarizeMask, summarizeRowIndexes, summarizeAiPocketRows, matchesPredicate, buildMask, intersectMasks, buildPredicateListMask, toPublicPredicate, buildAiPocketPredicateResult, scorePositivePocket, scoreNegativePocket, comparePositivePockets, compareNegativePockets, createPocketResult, hashMask, isBetterRepresentativePocket, estimateCombinationCount, searchAiPockets, formatMdNumber, formatMdPercent, escapeMarkdownCell, markdownTable, summaryMetricRows, pocketRows, buildAiPocketMarkdownReport;
|
|
3439
3440
|
var init_aiPocketSearch = __esm({
|
|
3440
3441
|
"src/lib/aiPocketSearch.ts"() {
|
|
3441
3442
|
"use strict";
|
|
@@ -3739,6 +3740,23 @@ var init_aiPocketSearch = __esm({
|
|
|
3739
3740
|
}
|
|
3740
3741
|
features["derived.directIndicatorSupportCount"] = supportCount;
|
|
3741
3742
|
};
|
|
3743
|
+
addSignalRiskDistanceFeatures = ({
|
|
3744
|
+
features,
|
|
3745
|
+
signal
|
|
3746
|
+
}) => {
|
|
3747
|
+
const currentPrice = isFiniteNumber(signal.prices?.currentPrice) ? signal.prices.currentPrice : null;
|
|
3748
|
+
const stopLossPrice = isFiniteNumber(signal.prices?.stopLossPrice) ? signal.prices.stopLossPrice : null;
|
|
3749
|
+
const takeProfitPrice = isFiniteNumber(signal.prices?.takeProfitPrice) ? signal.prices.takeProfitPrice : null;
|
|
3750
|
+
if (currentPrice == null || currentPrice === 0) {
|
|
3751
|
+
return;
|
|
3752
|
+
}
|
|
3753
|
+
if (stopLossPrice != null) {
|
|
3754
|
+
features["derived.stopDistanceBps"] = Math.abs(currentPrice - stopLossPrice) / Math.abs(currentPrice) * 1e4;
|
|
3755
|
+
}
|
|
3756
|
+
if (takeProfitPrice != null) {
|
|
3757
|
+
features["derived.takeProfitDistanceBps"] = Math.abs(takeProfitPrice - currentPrice) / Math.abs(currentPrice) * 1e4;
|
|
3758
|
+
}
|
|
3759
|
+
};
|
|
3742
3760
|
collectAiPocketFeatures = ({
|
|
3743
3761
|
payload,
|
|
3744
3762
|
gateContext,
|
|
@@ -3766,6 +3784,7 @@ var init_aiPocketSearch = __esm({
|
|
|
3766
3784
|
maxDepth: 8,
|
|
3767
3785
|
shouldSkipPath: featureProfile === "compact" ? isCompactFeaturePathSkipped : void 0
|
|
3768
3786
|
});
|
|
3787
|
+
addSignalRiskDistanceFeatures({ features, signal });
|
|
3769
3788
|
addDirectionalDerivedFeatures(features);
|
|
3770
3789
|
return features;
|
|
3771
3790
|
};
|
|
@@ -30291,7 +30310,7 @@ var init_resultsReporting = __esm({
|
|
|
30291
30310
|
});
|
|
30292
30311
|
|
|
30293
30312
|
// src/lib/runtimeTradeSync.ts
|
|
30294
|
-
var import_constants18, import_time10, import_redis21, CLOSED_PNL_LIMIT, EXCHANGE_HISTORY_MAX_RANGE_MS, splitExchangeHistoryTimeRange, formatRuntimeTradeSyncError, loadClosedPnlRows, consumeClosedPnlMatch, syncRuntimeTrades;
|
|
30313
|
+
var import_constants18, import_time10, import_redis21, CLOSED_PNL_LIMIT, CLOSED_PNL_RECONCILIATION_LOOKBACK_MS, EXCHANGE_HISTORY_MAX_RANGE_MS, isRuntimeTradeSyncFallbackClose, splitExchangeHistoryTimeRange, formatRuntimeTradeSyncError, loadClosedPnlRows, consumeClosedPnlMatch, syncRuntimeTrades;
|
|
30295
30314
|
var init_runtimeTradeSync = __esm({
|
|
30296
30315
|
"src/lib/runtimeTradeSync.ts"() {
|
|
30297
30316
|
"use strict";
|
|
@@ -30299,7 +30318,9 @@ var init_runtimeTradeSync = __esm({
|
|
|
30299
30318
|
import_time10 = require("@tradejs/core/time");
|
|
30300
30319
|
import_redis21 = require("@tradejs/infra/redis");
|
|
30301
30320
|
CLOSED_PNL_LIMIT = 100;
|
|
30321
|
+
CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
30302
30322
|
EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
30323
|
+
isRuntimeTradeSyncFallbackClose = (trade) => trade.status === "closed" && trade.exitTimestamp === trade.lastSyncedAt && trade.exitPrice == null && trade.actualExitPrice == null && trade.closeFee == null && trade.fundingFee == null;
|
|
30303
30324
|
splitExchangeHistoryTimeRange = ({
|
|
30304
30325
|
startTime,
|
|
30305
30326
|
endTime,
|
|
@@ -30428,7 +30449,7 @@ var init_runtimeTradeSync = __esm({
|
|
|
30428
30449
|
);
|
|
30429
30450
|
const closedPnlRows = await loadClosedPnlRows({
|
|
30430
30451
|
connector,
|
|
30431
|
-
startTime,
|
|
30452
|
+
startTime: Math.max(0, startTime - CLOSED_PNL_RECONCILIATION_LOOKBACK_MS),
|
|
30432
30453
|
endTime,
|
|
30433
30454
|
callbacks: closedPnlCallbacks
|
|
30434
30455
|
});
|
|
@@ -30440,14 +30461,14 @@ var init_runtimeTradeSync = __esm({
|
|
|
30440
30461
|
}
|
|
30441
30462
|
const syncedTrades = [];
|
|
30442
30463
|
for (const trade of trades) {
|
|
30443
|
-
if (trade.status !== "active") {
|
|
30464
|
+
if (trade.status !== "active" && !isRuntimeTradeSyncFallbackClose(trade)) {
|
|
30444
30465
|
syncedTrades.push(trade);
|
|
30445
30466
|
continue;
|
|
30446
30467
|
}
|
|
30447
30468
|
const openPosition = openPositionsBySymbol.get(trade.symbol);
|
|
30448
30469
|
const activeOrderId = activeOrderIdBySymbol.get(trade.symbol);
|
|
30449
30470
|
const isCurrentActiveTrade = activeOrderId === trade.orderId;
|
|
30450
|
-
if (!openPositionsReliable) {
|
|
30471
|
+
if (trade.status === "active" && !openPositionsReliable) {
|
|
30451
30472
|
syncedTrades.push({
|
|
30452
30473
|
...trade,
|
|
30453
30474
|
status: "active",
|
|
@@ -30455,7 +30476,7 @@ var init_runtimeTradeSync = __esm({
|
|
|
30455
30476
|
});
|
|
30456
30477
|
continue;
|
|
30457
30478
|
}
|
|
30458
|
-
if (isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
30479
|
+
if (trade.status === "active" && isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
30459
30480
|
const nextTrade2 = {
|
|
30460
30481
|
...trade,
|
|
30461
30482
|
status: "active",
|
|
@@ -30483,21 +30504,24 @@ var init_runtimeTradeSync = __esm({
|
|
|
30483
30504
|
continue;
|
|
30484
30505
|
}
|
|
30485
30506
|
const matchedClosedPnl = consumeClosedPnlMatch(closedPnlBuckets, trade);
|
|
30507
|
+
if (!matchedClosedPnl) {
|
|
30508
|
+
continue;
|
|
30509
|
+
}
|
|
30486
30510
|
const nextTrade = {
|
|
30487
30511
|
...trade,
|
|
30488
30512
|
status: "closed",
|
|
30489
|
-
currentPrice: matchedClosedPnl
|
|
30490
|
-
currentPnl: matchedClosedPnl
|
|
30491
|
-
closedPnl: matchedClosedPnl
|
|
30492
|
-
actualEntryPrice: matchedClosedPnl
|
|
30493
|
-
exitPrice: matchedClosedPnl
|
|
30494
|
-
actualExitPrice: matchedClosedPnl
|
|
30495
|
-
exitTimestamp: matchedClosedPnl
|
|
30513
|
+
currentPrice: matchedClosedPnl.exitPrice ?? trade.currentPrice ?? null,
|
|
30514
|
+
currentPnl: matchedClosedPnl.closedPnl,
|
|
30515
|
+
closedPnl: matchedClosedPnl.closedPnl,
|
|
30516
|
+
actualEntryPrice: matchedClosedPnl.entryPrice ?? trade.actualEntryPrice ?? null,
|
|
30517
|
+
exitPrice: matchedClosedPnl.exitPrice ?? trade.exitPrice ?? null,
|
|
30518
|
+
actualExitPrice: matchedClosedPnl.exitPrice ?? trade.actualExitPrice ?? null,
|
|
30519
|
+
exitTimestamp: matchedClosedPnl.closedAt,
|
|
30496
30520
|
exitType: trade.exitType ?? null,
|
|
30497
|
-
openFee: matchedClosedPnl
|
|
30498
|
-
closeFee: matchedClosedPnl
|
|
30499
|
-
fundingFee: matchedClosedPnl
|
|
30500
|
-
totalFee: matchedClosedPnl
|
|
30521
|
+
openFee: matchedClosedPnl.openFee ?? trade.openFee ?? null,
|
|
30522
|
+
closeFee: matchedClosedPnl.closeFee ?? trade.closeFee ?? null,
|
|
30523
|
+
fundingFee: matchedClosedPnl.fundingFee ?? trade.fundingFee ?? null,
|
|
30524
|
+
totalFee: matchedClosedPnl.totalFee ?? trade.totalFee ?? null,
|
|
30501
30525
|
lastSyncedAt: endTime
|
|
30502
30526
|
};
|
|
30503
30527
|
await Promise.all([
|
|
@@ -32655,8 +32679,7 @@ var init_signalsSummary = __esm({
|
|
|
32655
32679
|
if (trade.status !== "closed" || !isTimestampInWindow(trade.exitTimestamp, startTime, endTime)) {
|
|
32656
32680
|
return false;
|
|
32657
32681
|
}
|
|
32658
|
-
|
|
32659
|
-
return !looksLikeSyncFallbackClose;
|
|
32682
|
+
return !isRuntimeTradeSyncFallbackClose(trade);
|
|
32660
32683
|
};
|
|
32661
32684
|
buildSummaryMessages = ({
|
|
32662
32685
|
hours,
|
|
@@ -327,6 +327,23 @@ var addDirectionalDerivedFeatures = (features) => {
|
|
|
327
327
|
}
|
|
328
328
|
features["derived.directIndicatorSupportCount"] = supportCount;
|
|
329
329
|
};
|
|
330
|
+
var addSignalRiskDistanceFeatures = ({
|
|
331
|
+
features,
|
|
332
|
+
signal
|
|
333
|
+
}) => {
|
|
334
|
+
const currentPrice = isFiniteNumber(signal.prices?.currentPrice) ? signal.prices.currentPrice : null;
|
|
335
|
+
const stopLossPrice = isFiniteNumber(signal.prices?.stopLossPrice) ? signal.prices.stopLossPrice : null;
|
|
336
|
+
const takeProfitPrice = isFiniteNumber(signal.prices?.takeProfitPrice) ? signal.prices.takeProfitPrice : null;
|
|
337
|
+
if (currentPrice == null || currentPrice === 0) {
|
|
338
|
+
return;
|
|
339
|
+
}
|
|
340
|
+
if (stopLossPrice != null) {
|
|
341
|
+
features["derived.stopDistanceBps"] = Math.abs(currentPrice - stopLossPrice) / Math.abs(currentPrice) * 1e4;
|
|
342
|
+
}
|
|
343
|
+
if (takeProfitPrice != null) {
|
|
344
|
+
features["derived.takeProfitDistanceBps"] = Math.abs(takeProfitPrice - currentPrice) / Math.abs(currentPrice) * 1e4;
|
|
345
|
+
}
|
|
346
|
+
};
|
|
330
347
|
var collectAiPocketFeatures = ({
|
|
331
348
|
payload,
|
|
332
349
|
gateContext,
|
|
@@ -354,6 +371,7 @@ var collectAiPocketFeatures = ({
|
|
|
354
371
|
maxDepth: 8,
|
|
355
372
|
shouldSkipPath: featureProfile === "compact" ? isCompactFeaturePathSkipped : void 0
|
|
356
373
|
});
|
|
374
|
+
addSignalRiskDistanceFeatures({ features, signal });
|
|
357
375
|
addDirectionalDerivedFeatures(features);
|
|
358
376
|
return features;
|
|
359
377
|
};
|
|
@@ -23,6 +23,7 @@ __export(runtimeTradeSync_exports, {
|
|
|
23
23
|
EXCHANGE_HISTORY_MAX_RANGE_MS: () => EXCHANGE_HISTORY_MAX_RANGE_MS,
|
|
24
24
|
consumeClosedPnlMatch: () => consumeClosedPnlMatch,
|
|
25
25
|
formatRuntimeTradeSyncError: () => formatRuntimeTradeSyncError,
|
|
26
|
+
isRuntimeTradeSyncFallbackClose: () => isRuntimeTradeSyncFallbackClose,
|
|
26
27
|
loadClosedPnlRows: () => loadClosedPnlRows,
|
|
27
28
|
splitExchangeHistoryTimeRange: () => splitExchangeHistoryTimeRange,
|
|
28
29
|
syncRuntimeTrades: () => syncRuntimeTrades
|
|
@@ -32,7 +33,9 @@ var import_constants = require("@tradejs/core/constants");
|
|
|
32
33
|
var import_time = require("@tradejs/core/time");
|
|
33
34
|
var import_redis = require("@tradejs/infra/redis");
|
|
34
35
|
var CLOSED_PNL_LIMIT = 100;
|
|
36
|
+
var CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
35
37
|
var EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
38
|
+
var isRuntimeTradeSyncFallbackClose = (trade) => trade.status === "closed" && trade.exitTimestamp === trade.lastSyncedAt && trade.exitPrice == null && trade.actualExitPrice == null && trade.closeFee == null && trade.fundingFee == null;
|
|
36
39
|
var splitExchangeHistoryTimeRange = ({
|
|
37
40
|
startTime,
|
|
38
41
|
endTime,
|
|
@@ -161,7 +164,7 @@ var syncRuntimeTrades = async ({
|
|
|
161
164
|
);
|
|
162
165
|
const closedPnlRows = await loadClosedPnlRows({
|
|
163
166
|
connector,
|
|
164
|
-
startTime,
|
|
167
|
+
startTime: Math.max(0, startTime - CLOSED_PNL_RECONCILIATION_LOOKBACK_MS),
|
|
165
168
|
endTime,
|
|
166
169
|
callbacks: closedPnlCallbacks
|
|
167
170
|
});
|
|
@@ -173,14 +176,14 @@ var syncRuntimeTrades = async ({
|
|
|
173
176
|
}
|
|
174
177
|
const syncedTrades = [];
|
|
175
178
|
for (const trade of trades) {
|
|
176
|
-
if (trade.status !== "active") {
|
|
179
|
+
if (trade.status !== "active" && !isRuntimeTradeSyncFallbackClose(trade)) {
|
|
177
180
|
syncedTrades.push(trade);
|
|
178
181
|
continue;
|
|
179
182
|
}
|
|
180
183
|
const openPosition = openPositionsBySymbol.get(trade.symbol);
|
|
181
184
|
const activeOrderId = activeOrderIdBySymbol.get(trade.symbol);
|
|
182
185
|
const isCurrentActiveTrade = activeOrderId === trade.orderId;
|
|
183
|
-
if (!openPositionsReliable) {
|
|
186
|
+
if (trade.status === "active" && !openPositionsReliable) {
|
|
184
187
|
syncedTrades.push({
|
|
185
188
|
...trade,
|
|
186
189
|
status: "active",
|
|
@@ -188,7 +191,7 @@ var syncRuntimeTrades = async ({
|
|
|
188
191
|
});
|
|
189
192
|
continue;
|
|
190
193
|
}
|
|
191
|
-
if (isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
194
|
+
if (trade.status === "active" && isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
192
195
|
const nextTrade2 = {
|
|
193
196
|
...trade,
|
|
194
197
|
status: "active",
|
|
@@ -216,21 +219,24 @@ var syncRuntimeTrades = async ({
|
|
|
216
219
|
continue;
|
|
217
220
|
}
|
|
218
221
|
const matchedClosedPnl = consumeClosedPnlMatch(closedPnlBuckets, trade);
|
|
222
|
+
if (!matchedClosedPnl) {
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
219
225
|
const nextTrade = {
|
|
220
226
|
...trade,
|
|
221
227
|
status: "closed",
|
|
222
|
-
currentPrice: matchedClosedPnl
|
|
223
|
-
currentPnl: matchedClosedPnl
|
|
224
|
-
closedPnl: matchedClosedPnl
|
|
225
|
-
actualEntryPrice: matchedClosedPnl
|
|
226
|
-
exitPrice: matchedClosedPnl
|
|
227
|
-
actualExitPrice: matchedClosedPnl
|
|
228
|
-
exitTimestamp: matchedClosedPnl
|
|
228
|
+
currentPrice: matchedClosedPnl.exitPrice ?? trade.currentPrice ?? null,
|
|
229
|
+
currentPnl: matchedClosedPnl.closedPnl,
|
|
230
|
+
closedPnl: matchedClosedPnl.closedPnl,
|
|
231
|
+
actualEntryPrice: matchedClosedPnl.entryPrice ?? trade.actualEntryPrice ?? null,
|
|
232
|
+
exitPrice: matchedClosedPnl.exitPrice ?? trade.exitPrice ?? null,
|
|
233
|
+
actualExitPrice: matchedClosedPnl.exitPrice ?? trade.actualExitPrice ?? null,
|
|
234
|
+
exitTimestamp: matchedClosedPnl.closedAt,
|
|
229
235
|
exitType: trade.exitType ?? null,
|
|
230
|
-
openFee: matchedClosedPnl
|
|
231
|
-
closeFee: matchedClosedPnl
|
|
232
|
-
fundingFee: matchedClosedPnl
|
|
233
|
-
totalFee: matchedClosedPnl
|
|
236
|
+
openFee: matchedClosedPnl.openFee ?? trade.openFee ?? null,
|
|
237
|
+
closeFee: matchedClosedPnl.closeFee ?? trade.closeFee ?? null,
|
|
238
|
+
fundingFee: matchedClosedPnl.fundingFee ?? trade.fundingFee ?? null,
|
|
239
|
+
totalFee: matchedClosedPnl.totalFee ?? trade.totalFee ?? null,
|
|
234
240
|
lastSyncedAt: endTime
|
|
235
241
|
};
|
|
236
242
|
await Promise.all([
|
|
@@ -257,6 +263,7 @@ var syncRuntimeTrades = async ({
|
|
|
257
263
|
EXCHANGE_HISTORY_MAX_RANGE_MS,
|
|
258
264
|
consumeClosedPnlMatch,
|
|
259
265
|
formatRuntimeTradeSyncError,
|
|
266
|
+
isRuntimeTradeSyncFallbackClose,
|
|
260
267
|
loadClosedPnlRows,
|
|
261
268
|
splitExchangeHistoryTimeRange,
|
|
262
269
|
syncRuntimeTrades
|
package/dist/scripts/aiExport.js
CHANGED
|
@@ -1697,7 +1697,8 @@ var getStrategyChoices = async () => {
|
|
|
1697
1697
|
"MaStrategy",
|
|
1698
1698
|
"AdaptiveMomentumRibbon",
|
|
1699
1699
|
"TrendLine",
|
|
1700
|
-
"VolumeDivergence"
|
|
1700
|
+
"VolumeDivergence",
|
|
1701
|
+
"Grid"
|
|
1701
1702
|
];
|
|
1702
1703
|
};
|
|
1703
1704
|
var selectStrategy = async (promptLabel = "Select strategy", options) => {
|
|
@@ -2310,6 +2310,23 @@ var addDirectionalDerivedFeatures = (features) => {
|
|
|
2310
2310
|
}
|
|
2311
2311
|
features["derived.directIndicatorSupportCount"] = supportCount;
|
|
2312
2312
|
};
|
|
2313
|
+
var addSignalRiskDistanceFeatures = ({
|
|
2314
|
+
features,
|
|
2315
|
+
signal
|
|
2316
|
+
}) => {
|
|
2317
|
+
const currentPrice = isFiniteNumber(signal.prices?.currentPrice) ? signal.prices.currentPrice : null;
|
|
2318
|
+
const stopLossPrice = isFiniteNumber(signal.prices?.stopLossPrice) ? signal.prices.stopLossPrice : null;
|
|
2319
|
+
const takeProfitPrice = isFiniteNumber(signal.prices?.takeProfitPrice) ? signal.prices.takeProfitPrice : null;
|
|
2320
|
+
if (currentPrice == null || currentPrice === 0) {
|
|
2321
|
+
return;
|
|
2322
|
+
}
|
|
2323
|
+
if (stopLossPrice != null) {
|
|
2324
|
+
features["derived.stopDistanceBps"] = Math.abs(currentPrice - stopLossPrice) / Math.abs(currentPrice) * 1e4;
|
|
2325
|
+
}
|
|
2326
|
+
if (takeProfitPrice != null) {
|
|
2327
|
+
features["derived.takeProfitDistanceBps"] = Math.abs(takeProfitPrice - currentPrice) / Math.abs(currentPrice) * 1e4;
|
|
2328
|
+
}
|
|
2329
|
+
};
|
|
2313
2330
|
var collectAiPocketFeatures = ({
|
|
2314
2331
|
payload,
|
|
2315
2332
|
gateContext,
|
|
@@ -2337,6 +2354,7 @@ var collectAiPocketFeatures = ({
|
|
|
2337
2354
|
maxDepth: 8,
|
|
2338
2355
|
shouldSkipPath: featureProfile === "compact" ? isCompactFeaturePathSkipped : void 0
|
|
2339
2356
|
});
|
|
2357
|
+
addSignalRiskDistanceFeatures({ features, signal });
|
|
2340
2358
|
addDirectionalDerivedFeatures(features);
|
|
2341
2359
|
return features;
|
|
2342
2360
|
};
|
package/dist/scripts/mlExport.js
CHANGED
|
@@ -1697,7 +1697,8 @@ var getStrategyChoices = async () => {
|
|
|
1697
1697
|
"MaStrategy",
|
|
1698
1698
|
"AdaptiveMomentumRibbon",
|
|
1699
1699
|
"TrendLine",
|
|
1700
|
-
"VolumeDivergence"
|
|
1700
|
+
"VolumeDivergence",
|
|
1701
|
+
"Grid"
|
|
1701
1702
|
];
|
|
1702
1703
|
};
|
|
1703
1704
|
var selectStrategy = async (promptLabel = "Select strategy", options) => {
|
package/dist/scripts/replay.js
CHANGED
|
@@ -6909,7 +6909,9 @@ var import_constants5 = require("@tradejs/core/constants");
|
|
|
6909
6909
|
var import_time5 = require("@tradejs/core/time");
|
|
6910
6910
|
var import_redis4 = require("@tradejs/infra/redis");
|
|
6911
6911
|
var CLOSED_PNL_LIMIT = 100;
|
|
6912
|
+
var CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
6912
6913
|
var EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
6914
|
+
var isRuntimeTradeSyncFallbackClose = (trade) => trade.status === "closed" && trade.exitTimestamp === trade.lastSyncedAt && trade.exitPrice == null && trade.actualExitPrice == null && trade.closeFee == null && trade.fundingFee == null;
|
|
6913
6915
|
var splitExchangeHistoryTimeRange = ({
|
|
6914
6916
|
startTime,
|
|
6915
6917
|
endTime,
|
|
@@ -7038,7 +7040,7 @@ var syncRuntimeTrades = async ({
|
|
|
7038
7040
|
);
|
|
7039
7041
|
const closedPnlRows = await loadClosedPnlRows({
|
|
7040
7042
|
connector,
|
|
7041
|
-
startTime,
|
|
7043
|
+
startTime: Math.max(0, startTime - CLOSED_PNL_RECONCILIATION_LOOKBACK_MS),
|
|
7042
7044
|
endTime,
|
|
7043
7045
|
callbacks: closedPnlCallbacks
|
|
7044
7046
|
});
|
|
@@ -7050,14 +7052,14 @@ var syncRuntimeTrades = async ({
|
|
|
7050
7052
|
}
|
|
7051
7053
|
const syncedTrades = [];
|
|
7052
7054
|
for (const trade of trades) {
|
|
7053
|
-
if (trade.status !== "active") {
|
|
7055
|
+
if (trade.status !== "active" && !isRuntimeTradeSyncFallbackClose(trade)) {
|
|
7054
7056
|
syncedTrades.push(trade);
|
|
7055
7057
|
continue;
|
|
7056
7058
|
}
|
|
7057
7059
|
const openPosition = openPositionsBySymbol.get(trade.symbol);
|
|
7058
7060
|
const activeOrderId = activeOrderIdBySymbol.get(trade.symbol);
|
|
7059
7061
|
const isCurrentActiveTrade = activeOrderId === trade.orderId;
|
|
7060
|
-
if (!openPositionsReliable) {
|
|
7062
|
+
if (trade.status === "active" && !openPositionsReliable) {
|
|
7061
7063
|
syncedTrades.push({
|
|
7062
7064
|
...trade,
|
|
7063
7065
|
status: "active",
|
|
@@ -7065,7 +7067,7 @@ var syncRuntimeTrades = async ({
|
|
|
7065
7067
|
});
|
|
7066
7068
|
continue;
|
|
7067
7069
|
}
|
|
7068
|
-
if (isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
7070
|
+
if (trade.status === "active" && isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
7069
7071
|
const nextTrade2 = {
|
|
7070
7072
|
...trade,
|
|
7071
7073
|
status: "active",
|
|
@@ -7093,21 +7095,24 @@ var syncRuntimeTrades = async ({
|
|
|
7093
7095
|
continue;
|
|
7094
7096
|
}
|
|
7095
7097
|
const matchedClosedPnl = consumeClosedPnlMatch(closedPnlBuckets, trade);
|
|
7098
|
+
if (!matchedClosedPnl) {
|
|
7099
|
+
continue;
|
|
7100
|
+
}
|
|
7096
7101
|
const nextTrade = {
|
|
7097
7102
|
...trade,
|
|
7098
7103
|
status: "closed",
|
|
7099
|
-
currentPrice: matchedClosedPnl
|
|
7100
|
-
currentPnl: matchedClosedPnl
|
|
7101
|
-
closedPnl: matchedClosedPnl
|
|
7102
|
-
actualEntryPrice: matchedClosedPnl
|
|
7103
|
-
exitPrice: matchedClosedPnl
|
|
7104
|
-
actualExitPrice: matchedClosedPnl
|
|
7105
|
-
exitTimestamp: matchedClosedPnl
|
|
7104
|
+
currentPrice: matchedClosedPnl.exitPrice ?? trade.currentPrice ?? null,
|
|
7105
|
+
currentPnl: matchedClosedPnl.closedPnl,
|
|
7106
|
+
closedPnl: matchedClosedPnl.closedPnl,
|
|
7107
|
+
actualEntryPrice: matchedClosedPnl.entryPrice ?? trade.actualEntryPrice ?? null,
|
|
7108
|
+
exitPrice: matchedClosedPnl.exitPrice ?? trade.exitPrice ?? null,
|
|
7109
|
+
actualExitPrice: matchedClosedPnl.exitPrice ?? trade.actualExitPrice ?? null,
|
|
7110
|
+
exitTimestamp: matchedClosedPnl.closedAt,
|
|
7106
7111
|
exitType: trade.exitType ?? null,
|
|
7107
|
-
openFee: matchedClosedPnl
|
|
7108
|
-
closeFee: matchedClosedPnl
|
|
7109
|
-
fundingFee: matchedClosedPnl
|
|
7110
|
-
totalFee: matchedClosedPnl
|
|
7112
|
+
openFee: matchedClosedPnl.openFee ?? trade.openFee ?? null,
|
|
7113
|
+
closeFee: matchedClosedPnl.closeFee ?? trade.closeFee ?? null,
|
|
7114
|
+
fundingFee: matchedClosedPnl.fundingFee ?? trade.fundingFee ?? null,
|
|
7115
|
+
totalFee: matchedClosedPnl.totalFee ?? trade.totalFee ?? null,
|
|
7111
7116
|
lastSyncedAt: endTime
|
|
7112
7117
|
};
|
|
7113
7118
|
await Promise.all([
|
|
@@ -6912,7 +6912,9 @@ var import_constants5 = require("@tradejs/core/constants");
|
|
|
6912
6912
|
var import_time5 = require("@tradejs/core/time");
|
|
6913
6913
|
var import_redis4 = require("@tradejs/infra/redis");
|
|
6914
6914
|
var CLOSED_PNL_LIMIT = 100;
|
|
6915
|
+
var CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
6915
6916
|
var EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
6917
|
+
var isRuntimeTradeSyncFallbackClose = (trade) => trade.status === "closed" && trade.exitTimestamp === trade.lastSyncedAt && trade.exitPrice == null && trade.actualExitPrice == null && trade.closeFee == null && trade.fundingFee == null;
|
|
6916
6918
|
var splitExchangeHistoryTimeRange = ({
|
|
6917
6919
|
startTime,
|
|
6918
6920
|
endTime,
|
|
@@ -7041,7 +7043,7 @@ var syncRuntimeTrades = async ({
|
|
|
7041
7043
|
);
|
|
7042
7044
|
const closedPnlRows = await loadClosedPnlRows({
|
|
7043
7045
|
connector,
|
|
7044
|
-
startTime,
|
|
7046
|
+
startTime: Math.max(0, startTime - CLOSED_PNL_RECONCILIATION_LOOKBACK_MS),
|
|
7045
7047
|
endTime,
|
|
7046
7048
|
callbacks: closedPnlCallbacks
|
|
7047
7049
|
});
|
|
@@ -7053,14 +7055,14 @@ var syncRuntimeTrades = async ({
|
|
|
7053
7055
|
}
|
|
7054
7056
|
const syncedTrades = [];
|
|
7055
7057
|
for (const trade of trades) {
|
|
7056
|
-
if (trade.status !== "active") {
|
|
7058
|
+
if (trade.status !== "active" && !isRuntimeTradeSyncFallbackClose(trade)) {
|
|
7057
7059
|
syncedTrades.push(trade);
|
|
7058
7060
|
continue;
|
|
7059
7061
|
}
|
|
7060
7062
|
const openPosition = openPositionsBySymbol.get(trade.symbol);
|
|
7061
7063
|
const activeOrderId = activeOrderIdBySymbol.get(trade.symbol);
|
|
7062
7064
|
const isCurrentActiveTrade = activeOrderId === trade.orderId;
|
|
7063
|
-
if (!openPositionsReliable) {
|
|
7065
|
+
if (trade.status === "active" && !openPositionsReliable) {
|
|
7064
7066
|
syncedTrades.push({
|
|
7065
7067
|
...trade,
|
|
7066
7068
|
status: "active",
|
|
@@ -7068,7 +7070,7 @@ var syncRuntimeTrades = async ({
|
|
|
7068
7070
|
});
|
|
7069
7071
|
continue;
|
|
7070
7072
|
}
|
|
7071
|
-
if (isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
7073
|
+
if (trade.status === "active" && isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
7072
7074
|
const nextTrade2 = {
|
|
7073
7075
|
...trade,
|
|
7074
7076
|
status: "active",
|
|
@@ -7096,21 +7098,24 @@ var syncRuntimeTrades = async ({
|
|
|
7096
7098
|
continue;
|
|
7097
7099
|
}
|
|
7098
7100
|
const matchedClosedPnl = consumeClosedPnlMatch(closedPnlBuckets, trade);
|
|
7101
|
+
if (!matchedClosedPnl) {
|
|
7102
|
+
continue;
|
|
7103
|
+
}
|
|
7099
7104
|
const nextTrade = {
|
|
7100
7105
|
...trade,
|
|
7101
7106
|
status: "closed",
|
|
7102
|
-
currentPrice: matchedClosedPnl
|
|
7103
|
-
currentPnl: matchedClosedPnl
|
|
7104
|
-
closedPnl: matchedClosedPnl
|
|
7105
|
-
actualEntryPrice: matchedClosedPnl
|
|
7106
|
-
exitPrice: matchedClosedPnl
|
|
7107
|
-
actualExitPrice: matchedClosedPnl
|
|
7108
|
-
exitTimestamp: matchedClosedPnl
|
|
7107
|
+
currentPrice: matchedClosedPnl.exitPrice ?? trade.currentPrice ?? null,
|
|
7108
|
+
currentPnl: matchedClosedPnl.closedPnl,
|
|
7109
|
+
closedPnl: matchedClosedPnl.closedPnl,
|
|
7110
|
+
actualEntryPrice: matchedClosedPnl.entryPrice ?? trade.actualEntryPrice ?? null,
|
|
7111
|
+
exitPrice: matchedClosedPnl.exitPrice ?? trade.exitPrice ?? null,
|
|
7112
|
+
actualExitPrice: matchedClosedPnl.exitPrice ?? trade.actualExitPrice ?? null,
|
|
7113
|
+
exitTimestamp: matchedClosedPnl.closedAt,
|
|
7109
7114
|
exitType: trade.exitType ?? null,
|
|
7110
|
-
openFee: matchedClosedPnl
|
|
7111
|
-
closeFee: matchedClosedPnl
|
|
7112
|
-
fundingFee: matchedClosedPnl
|
|
7113
|
-
totalFee: matchedClosedPnl
|
|
7115
|
+
openFee: matchedClosedPnl.openFee ?? trade.openFee ?? null,
|
|
7116
|
+
closeFee: matchedClosedPnl.closeFee ?? trade.closeFee ?? null,
|
|
7117
|
+
fundingFee: matchedClosedPnl.fundingFee ?? trade.fundingFee ?? null,
|
|
7118
|
+
totalFee: matchedClosedPnl.totalFee ?? trade.totalFee ?? null,
|
|
7114
7119
|
lastSyncedAt: endTime
|
|
7115
7120
|
};
|
|
7116
7121
|
await Promise.all([
|
|
@@ -113,7 +113,9 @@ var import_constants = require("@tradejs/core/constants");
|
|
|
113
113
|
var import_time2 = require("@tradejs/core/time");
|
|
114
114
|
var import_redis2 = require("@tradejs/infra/redis");
|
|
115
115
|
var CLOSED_PNL_LIMIT = 100;
|
|
116
|
+
var CLOSED_PNL_RECONCILIATION_LOOKBACK_MS = 24 * 60 * 60 * 1e3;
|
|
116
117
|
var EXCHANGE_HISTORY_MAX_RANGE_MS = 7 * 24 * 60 * 60 * 1e3;
|
|
118
|
+
var isRuntimeTradeSyncFallbackClose = (trade) => trade.status === "closed" && trade.exitTimestamp === trade.lastSyncedAt && trade.exitPrice == null && trade.actualExitPrice == null && trade.closeFee == null && trade.fundingFee == null;
|
|
117
119
|
var splitExchangeHistoryTimeRange = ({
|
|
118
120
|
startTime,
|
|
119
121
|
endTime,
|
|
@@ -242,7 +244,7 @@ var syncRuntimeTrades = async ({
|
|
|
242
244
|
);
|
|
243
245
|
const closedPnlRows = await loadClosedPnlRows({
|
|
244
246
|
connector,
|
|
245
|
-
startTime,
|
|
247
|
+
startTime: Math.max(0, startTime - CLOSED_PNL_RECONCILIATION_LOOKBACK_MS),
|
|
246
248
|
endTime,
|
|
247
249
|
callbacks: closedPnlCallbacks
|
|
248
250
|
});
|
|
@@ -254,14 +256,14 @@ var syncRuntimeTrades = async ({
|
|
|
254
256
|
}
|
|
255
257
|
const syncedTrades = [];
|
|
256
258
|
for (const trade of trades) {
|
|
257
|
-
if (trade.status !== "active") {
|
|
259
|
+
if (trade.status !== "active" && !isRuntimeTradeSyncFallbackClose(trade)) {
|
|
258
260
|
syncedTrades.push(trade);
|
|
259
261
|
continue;
|
|
260
262
|
}
|
|
261
263
|
const openPosition = openPositionsBySymbol.get(trade.symbol);
|
|
262
264
|
const activeOrderId = activeOrderIdBySymbol.get(trade.symbol);
|
|
263
265
|
const isCurrentActiveTrade = activeOrderId === trade.orderId;
|
|
264
|
-
if (!openPositionsReliable) {
|
|
266
|
+
if (trade.status === "active" && !openPositionsReliable) {
|
|
265
267
|
syncedTrades.push({
|
|
266
268
|
...trade,
|
|
267
269
|
status: "active",
|
|
@@ -269,7 +271,7 @@ var syncRuntimeTrades = async ({
|
|
|
269
271
|
});
|
|
270
272
|
continue;
|
|
271
273
|
}
|
|
272
|
-
if (isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
274
|
+
if (trade.status === "active" && isCurrentActiveTrade && openPosition && openPosition.direction === trade.direction) {
|
|
273
275
|
const nextTrade2 = {
|
|
274
276
|
...trade,
|
|
275
277
|
status: "active",
|
|
@@ -297,21 +299,24 @@ var syncRuntimeTrades = async ({
|
|
|
297
299
|
continue;
|
|
298
300
|
}
|
|
299
301
|
const matchedClosedPnl = consumeClosedPnlMatch(closedPnlBuckets, trade);
|
|
302
|
+
if (!matchedClosedPnl) {
|
|
303
|
+
continue;
|
|
304
|
+
}
|
|
300
305
|
const nextTrade = {
|
|
301
306
|
...trade,
|
|
302
307
|
status: "closed",
|
|
303
|
-
currentPrice: matchedClosedPnl
|
|
304
|
-
currentPnl: matchedClosedPnl
|
|
305
|
-
closedPnl: matchedClosedPnl
|
|
306
|
-
actualEntryPrice: matchedClosedPnl
|
|
307
|
-
exitPrice: matchedClosedPnl
|
|
308
|
-
actualExitPrice: matchedClosedPnl
|
|
309
|
-
exitTimestamp: matchedClosedPnl
|
|
308
|
+
currentPrice: matchedClosedPnl.exitPrice ?? trade.currentPrice ?? null,
|
|
309
|
+
currentPnl: matchedClosedPnl.closedPnl,
|
|
310
|
+
closedPnl: matchedClosedPnl.closedPnl,
|
|
311
|
+
actualEntryPrice: matchedClosedPnl.entryPrice ?? trade.actualEntryPrice ?? null,
|
|
312
|
+
exitPrice: matchedClosedPnl.exitPrice ?? trade.exitPrice ?? null,
|
|
313
|
+
actualExitPrice: matchedClosedPnl.exitPrice ?? trade.actualExitPrice ?? null,
|
|
314
|
+
exitTimestamp: matchedClosedPnl.closedAt,
|
|
310
315
|
exitType: trade.exitType ?? null,
|
|
311
|
-
openFee: matchedClosedPnl
|
|
312
|
-
closeFee: matchedClosedPnl
|
|
313
|
-
fundingFee: matchedClosedPnl
|
|
314
|
-
totalFee: matchedClosedPnl
|
|
316
|
+
openFee: matchedClosedPnl.openFee ?? trade.openFee ?? null,
|
|
317
|
+
closeFee: matchedClosedPnl.closeFee ?? trade.closeFee ?? null,
|
|
318
|
+
fundingFee: matchedClosedPnl.fundingFee ?? trade.fundingFee ?? null,
|
|
319
|
+
totalFee: matchedClosedPnl.totalFee ?? trade.totalFee ?? null,
|
|
315
320
|
lastSyncedAt: endTime
|
|
316
321
|
};
|
|
317
322
|
await Promise.all([
|
|
@@ -904,8 +909,7 @@ var isRuntimeTradeClosedInWindow = (trade, startTime, endTime) => {
|
|
|
904
909
|
if (trade.status !== "closed" || !isTimestampInWindow(trade.exitTimestamp, startTime, endTime)) {
|
|
905
910
|
return false;
|
|
906
911
|
}
|
|
907
|
-
|
|
908
|
-
return !looksLikeSyncFallbackClose;
|
|
912
|
+
return !isRuntimeTradeSyncFallbackClose(trade);
|
|
909
913
|
};
|
|
910
914
|
var buildSummaryMessages = ({
|
|
911
915
|
hours,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@tradejs/cli",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.4",
|
|
4
4
|
"description": "Official CLI for the TradeJS TypeScript framework: infra setup, backtests, signals, bots, and ML workflows.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"tradejs",
|
|
@@ -29,14 +29,14 @@
|
|
|
29
29
|
"tradejs": "dist/cli.js"
|
|
30
30
|
},
|
|
31
31
|
"dependencies": {
|
|
32
|
-
"@tradejs/base": "^2.0.
|
|
33
|
-
"@tradejs/connectors": "^2.0.
|
|
34
|
-
"@tradejs/core": "^2.0.
|
|
35
|
-
"@tradejs/indicators": "^2.0.
|
|
36
|
-
"@tradejs/infra": "^2.0.
|
|
37
|
-
"@tradejs/node": "^2.0.
|
|
38
|
-
"@tradejs/strategies": "^2.0.
|
|
39
|
-
"@tradejs/types": "^2.0.
|
|
32
|
+
"@tradejs/base": "^2.0.4",
|
|
33
|
+
"@tradejs/connectors": "^2.0.4",
|
|
34
|
+
"@tradejs/core": "^2.0.4",
|
|
35
|
+
"@tradejs/indicators": "^2.0.4",
|
|
36
|
+
"@tradejs/infra": "^2.0.4",
|
|
37
|
+
"@tradejs/node": "^2.0.4",
|
|
38
|
+
"@tradejs/strategies": "^2.0.4",
|
|
39
|
+
"@tradejs/types": "^2.0.4",
|
|
40
40
|
"args": "^5.0.3",
|
|
41
41
|
"bcryptjs": "^2.4.3",
|
|
42
42
|
"chalk": "4.1.2",
|