aiden-shared-calculations-unified 1.0.107 → 1.0.108
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.
|
@@ -4,7 +4,9 @@
|
|
|
4
4
|
*/
|
|
5
5
|
class AssetPnlStatus {
|
|
6
6
|
constructor() {
|
|
7
|
-
this.
|
|
7
|
+
// [FIX 1] Use 'this.results' directly.
|
|
8
|
+
// The StandardExecutor monitors this property to perform Batch Flushing.
|
|
9
|
+
this.results = {};
|
|
8
10
|
}
|
|
9
11
|
|
|
10
12
|
static getMetadata() {
|
|
@@ -22,29 +24,26 @@ class AssetPnlStatus {
|
|
|
22
24
|
static getSchema() {
|
|
23
25
|
return {
|
|
24
26
|
"type": "object",
|
|
25
|
-
"
|
|
26
|
-
|
|
27
|
+
// [FIX 2] Flattened Schema (removed "by_user" wrapper)
|
|
28
|
+
"patternProperties": {
|
|
29
|
+
"^[0-9]+$": {
|
|
27
30
|
"type": "object",
|
|
28
|
-
"
|
|
29
|
-
"
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
"losers": { "type": "array", "items": { "type": "string" } }
|
|
34
|
-
},
|
|
35
|
-
"required": ["winners", "losers"]
|
|
36
|
-
}
|
|
37
|
-
}
|
|
31
|
+
"properties": {
|
|
32
|
+
"winners": { "type": "array", "items": { "type": "string" } },
|
|
33
|
+
"losers": { "type": "array", "items": { "type": "string" } }
|
|
34
|
+
},
|
|
35
|
+
"required": ["winners", "losers"]
|
|
38
36
|
}
|
|
39
37
|
}
|
|
40
38
|
};
|
|
41
39
|
}
|
|
42
40
|
|
|
43
41
|
_initUser(userId) {
|
|
44
|
-
|
|
45
|
-
|
|
42
|
+
// [FIX 3] Direct access to this.results
|
|
43
|
+
if (!this.results[userId]) {
|
|
44
|
+
this.results[userId] = { winners: [], losers: [] };
|
|
46
45
|
}
|
|
47
|
-
return this.
|
|
46
|
+
return this.results[userId];
|
|
48
47
|
}
|
|
49
48
|
|
|
50
49
|
process(context) {
|
|
@@ -55,7 +54,9 @@ class AssetPnlStatus {
|
|
|
55
54
|
const positions = extract.getPositions(user.portfolio.today, user.type);
|
|
56
55
|
if (!positions || positions.length === 0) return;
|
|
57
56
|
|
|
58
|
-
|
|
57
|
+
// Use temporary sets for processing to keep logic clean, then convert to array for storage
|
|
58
|
+
const winners = new Set();
|
|
59
|
+
const losers = new Set();
|
|
59
60
|
|
|
60
61
|
for (const pos of positions) {
|
|
61
62
|
const instId = extract.getInstrumentId(pos);
|
|
@@ -68,35 +69,26 @@ class AssetPnlStatus {
|
|
|
68
69
|
const sector = mappings.instrumentToSector[instId];
|
|
69
70
|
const isWinner = pnl > 0;
|
|
70
71
|
|
|
71
|
-
if (ticker
|
|
72
|
-
|
|
73
|
-
if (ticker) {
|
|
74
|
-
if (isWinner) stats.winners.add(ticker); else stats.losers.add(ticker);
|
|
75
|
-
}
|
|
76
|
-
if (sector) {
|
|
77
|
-
if (isWinner) stats.winners.add(sector); else stats.losers.add(sector);
|
|
78
|
-
}
|
|
79
|
-
}
|
|
72
|
+
if (ticker) { isWinner ? winners.add(ticker) : losers.add(ticker); }
|
|
73
|
+
if (sector) { isWinner ? winners.add(sector) : losers.add(sector); }
|
|
80
74
|
}
|
|
81
|
-
}
|
|
82
75
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
byUser[userId] = {
|
|
89
|
-
winners: Array.from(stats.winners),
|
|
90
|
-
losers: Array.from(stats.losers)
|
|
91
|
-
};
|
|
92
|
-
}
|
|
76
|
+
if (winners.size > 0 || losers.size > 0) {
|
|
77
|
+
this.results[userId] = {
|
|
78
|
+
winners: Array.from(winners),
|
|
79
|
+
losers: Array.from(losers)
|
|
80
|
+
};
|
|
93
81
|
}
|
|
82
|
+
}
|
|
94
83
|
|
|
95
|
-
|
|
96
|
-
|
|
84
|
+
async getResult() {
|
|
85
|
+
// [FIX 4] Return 'this.results' directly.
|
|
86
|
+
// This is a FLAT object { "user1": {...}, "user2": {...} }
|
|
87
|
+
// The ResultCommitter can now shard this into 50-user chunks if needed.
|
|
88
|
+
return this.results;
|
|
97
89
|
}
|
|
98
90
|
|
|
99
|
-
reset
|
|
91
|
+
// [FIX 5] No manual reset needed, StandardExecutor does it.
|
|
100
92
|
}
|
|
101
93
|
|
|
102
94
|
module.exports = AssetPnlStatus;
|
|
@@ -82,9 +82,7 @@ class UserHistoryReconstructor {
|
|
|
82
82
|
events.push({ time: openTime, type: 'OPEN', trade, ticker });
|
|
83
83
|
|
|
84
84
|
// Add CLOSE event (if closed)
|
|
85
|
-
if (closeTime) {
|
|
86
|
-
events.push({ time: closeTime, type: 'CLOSE', trade, ticker });
|
|
87
|
-
}
|
|
85
|
+
if (closeTime) { events.push({ time: closeTime, type: 'CLOSE', trade, ticker }); }
|
|
88
86
|
}
|
|
89
87
|
|
|
90
88
|
// Sort events by time
|
|
@@ -49,8 +49,8 @@ class SqueezePotential {
|
|
|
49
49
|
|
|
50
50
|
for (const ticker of tickers) {
|
|
51
51
|
const shortSlAvg = signals.getMetric(computed, 'speculator-stop-loss-distance-by-ticker-short-long-breakdown', ticker, 'avg_short_sl_distance_pct');
|
|
52
|
-
const userCount
|
|
53
|
-
const weight
|
|
52
|
+
const userCount = signals.getMetric(computed, 'short-position-per-stock', ticker, 'short_count');
|
|
53
|
+
const weight = signals.getMetric(computed, 'short-position-per-stock', ticker, 'total_short_exposure_weight');
|
|
54
54
|
|
|
55
55
|
if (userCount > 0) {
|
|
56
56
|
result[ticker] = {
|