aiden-shared-calculations-unified 1.0.39 → 1.0.40
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.
|
@@ -1,5 +1,12 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* @fileoverview Tracks the investment flow of "smart money".
|
|
3
|
+
*
|
|
4
|
+
* --- FIX ---
|
|
5
|
+
* The core logic (identifySmartMoney) has been moved from process() to
|
|
6
|
+
* getResult(). This is critical to prevent a race condition where
|
|
7
|
+
* this calculation tries to *read* the profitability shards
|
|
8
|
+
* before user_profitability_tracker has *written* them.
|
|
9
|
+
* --- END FIX ---
|
|
3
10
|
*/
|
|
4
11
|
|
|
5
12
|
const { Firestore } = require('@google-cloud/firestore');
|
|
@@ -8,20 +15,20 @@ const firestore = new Firestore();
|
|
|
8
15
|
const { getInstrumentSectorMap } = require('../../../utils/sector_mapping_provider');
|
|
9
16
|
|
|
10
17
|
class SmartMoneyFlow {
|
|
11
|
-
// ... (rest of the code is unchanged) ...
|
|
12
18
|
constructor() {
|
|
13
19
|
this.smartMoneyUsers = new Set();
|
|
14
|
-
this.sectorFlow = {};
|
|
15
20
|
this.sectorMap = null; // Cache for the sector map
|
|
21
|
+
|
|
22
|
+
// --- NEW ---
|
|
23
|
+
// We now store the portfolio data during process()
|
|
24
|
+
this.todayPortfolios = {};
|
|
25
|
+
this.yesterdayPortfolios = {};
|
|
26
|
+
// --- END NEW ---
|
|
16
27
|
}
|
|
17
28
|
|
|
18
29
|
async process(todayPortfolio, yesterdayPortfolio, userId) {
|
|
19
|
-
//
|
|
20
|
-
|
|
21
|
-
await this.identifySmartMoney();
|
|
22
|
-
// Log after identification attempt
|
|
23
|
-
console.log(`Identified ${this.smartMoneyUsers.size} smart money users.`);
|
|
24
|
-
}
|
|
30
|
+
// --- FIX: process() NO LONGER calls identifySmartMoney ---
|
|
31
|
+
// It just caches the portfolios we need for getResult()
|
|
25
32
|
|
|
26
33
|
// Load sector map if not already loaded
|
|
27
34
|
if (!this.sectorMap) {
|
|
@@ -29,8 +36,6 @@ class SmartMoneyFlow {
|
|
|
29
36
|
this.sectorMap = await getInstrumentSectorMap();
|
|
30
37
|
if (!this.sectorMap || Object.keys(this.sectorMap).length === 0) {
|
|
31
38
|
console.warn('Sector map loaded but is empty.');
|
|
32
|
-
} else {
|
|
33
|
-
// console.log('Sector map loaded successfully.'); // Optional: remove if too verbose
|
|
34
39
|
}
|
|
35
40
|
} catch (error) {
|
|
36
41
|
console.error('Failed to load sector map:', error);
|
|
@@ -38,36 +43,11 @@ class SmartMoneyFlow {
|
|
|
38
43
|
}
|
|
39
44
|
}
|
|
40
45
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return;
|
|
47
|
-
}
|
|
48
|
-
const todaySectorInvestment = this.calculateSectorInvestment(todayPortfolio);
|
|
49
|
-
const yesterdaySectorInvestment = this.calculateSectorInvestment(yesterdayPortfolio);
|
|
50
|
-
|
|
51
|
-
// Calculate change in investment per sector
|
|
52
|
-
const allSectors = new Set([...Object.keys(todaySectorInvestment), ...Object.keys(yesterdaySectorInvestment)]);
|
|
53
|
-
for (const sector of allSectors) {
|
|
54
|
-
const todayAmount = todaySectorInvestment[sector] || 0;
|
|
55
|
-
const yesterdayAmount = yesterdaySectorInvestment[sector] || 0;
|
|
56
|
-
const change = todayAmount - yesterdayAmount;
|
|
57
|
-
|
|
58
|
-
// Only record if there is a change
|
|
59
|
-
if (change !== 0) {
|
|
60
|
-
if (!this.sectorFlow[sector]) {
|
|
61
|
-
this.sectorFlow[sector] = 0;
|
|
62
|
-
}
|
|
63
|
-
this.sectorFlow[sector] += change;
|
|
64
|
-
}
|
|
65
|
-
}
|
|
66
|
-
} else {
|
|
67
|
-
// Optional: Log why processing is skipped for a user
|
|
68
|
-
// if (!this.smartMoneyUsers.has(userId)) console.log(`User ${userId} is not smart money.`);
|
|
69
|
-
// if (!todayPortfolio) console.log(`User ${userId}: Missing today's portfolio.`);
|
|
70
|
-
// if (!yesterdayPortfolio) console.log(`User ${userId}: Missing yesterday's portfolio.`);
|
|
46
|
+
if (todayPortfolio) {
|
|
47
|
+
this.todayPortfolios[userId] = todayPortfolio;
|
|
48
|
+
}
|
|
49
|
+
if (yesterdayPortfolio) {
|
|
50
|
+
this.yesterdayPortfolios[userId] = yesterdayPortfolio;
|
|
71
51
|
}
|
|
72
52
|
}
|
|
73
53
|
|
|
@@ -149,18 +129,57 @@ class SmartMoneyFlow {
|
|
|
149
129
|
}
|
|
150
130
|
|
|
151
131
|
|
|
152
|
-
getResult() {
|
|
132
|
+
async getResult() {
|
|
133
|
+
// --- FIX: MOVED FROM process() ---
|
|
134
|
+
// 1. Identify smart money *now*, after Pass 1's getResult() has run
|
|
135
|
+
await this.identifySmartMoney();
|
|
136
|
+
|
|
137
|
+
// 2. Ensure sector map is loaded (it should be from process())
|
|
138
|
+
if (!this.sectorMap) {
|
|
139
|
+
console.error('SmartMoneyFlow: Sector map not loaded, cannot get result.');
|
|
140
|
+
return { smart_money_flow: {} };
|
|
141
|
+
}
|
|
142
|
+
// --- END FIX ---
|
|
143
|
+
|
|
144
|
+
const sectorFlow = {};
|
|
145
|
+
|
|
146
|
+
// 3. Loop through the cached portfolios
|
|
147
|
+
for (const userId of this.smartMoneyUsers) {
|
|
148
|
+
const todayPortfolio = this.todayPortfolios[userId];
|
|
149
|
+
const yesterdayPortfolio = this.yesterdayPortfolios[userId];
|
|
150
|
+
|
|
151
|
+
if (todayPortfolio && yesterdayPortfolio) {
|
|
152
|
+
const todaySectorInvestment = this.calculateSectorInvestment(todayPortfolio);
|
|
153
|
+
const yesterdaySectorInvestment = this.calculateSectorInvestment(yesterdayPortfolio);
|
|
154
|
+
|
|
155
|
+
// Calculate change in investment per sector
|
|
156
|
+
const allSectors = new Set([...Object.keys(todaySectorInvestment), ...Object.keys(yesterdaySectorInvestment)]);
|
|
157
|
+
for (const sector of allSectors) {
|
|
158
|
+
const todayAmount = todaySectorInvestment[sector] || 0;
|
|
159
|
+
const yesterdayAmount = yesterdaySectorInvestment[sector] || 0;
|
|
160
|
+
const change = todayAmount - yesterdayAmount;
|
|
161
|
+
|
|
162
|
+
// Only record if there is a change
|
|
163
|
+
if (change !== 0) {
|
|
164
|
+
if (!sectorFlow[sector]) {
|
|
165
|
+
sectorFlow[sector] = 0;
|
|
166
|
+
}
|
|
167
|
+
sectorFlow[sector] += change;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
|
|
153
173
|
// Return only sectors with non-zero flow if desired, or the full object
|
|
154
174
|
const filteredFlow = {};
|
|
155
|
-
for (const sector in
|
|
156
|
-
if (
|
|
157
|
-
filteredFlow[sector] =
|
|
175
|
+
for (const sector in sectorFlow) {
|
|
176
|
+
if (sectorFlow[sector] !== 0) {
|
|
177
|
+
filteredFlow[sector] = sectorFlow[sector];
|
|
158
178
|
}
|
|
159
179
|
}
|
|
160
|
-
|
|
180
|
+
console.log("Final Smart Money Flow:", filteredFlow);
|
|
161
181
|
return { smart_money_flow: filteredFlow };
|
|
162
|
-
// Or return the full object: return { smart_money_flow: this.sectorFlow };
|
|
163
182
|
}
|
|
164
183
|
}
|
|
165
184
|
|
|
166
|
-
module.exports = SmartMoneyFlow;
|
|
185
|
+
module.exports = SmartMoneyFlow;
|