aiden-shared-calculations-unified 1.0.1 → 1.0.2
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.
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculates the total number of positions 'bought' vs 'sold' based on daily owner delta.
|
|
3
|
+
* Uses the 'daily_instrument_insights' collection (truth of source).
|
|
4
|
+
* 'Bought' = sum of positive deltas, 'Sold' = sum of absolute negative deltas.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class DailyBoughtVsSoldCount {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.totalBought = 0;
|
|
10
|
+
this.totalSold = 0;
|
|
11
|
+
this.processedDay = false; // Flag to run logic only once per day
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Needs insights from today and yesterday
|
|
15
|
+
async process(todayPortfolio, yesterdayPortfolio, userId, context, todayInsights, yesterdayInsights) {
|
|
16
|
+
if (this.processedDay) return;
|
|
17
|
+
this.processedDay = true;
|
|
18
|
+
|
|
19
|
+
if (!todayInsights || !todayInsights.insights || !yesterdayInsights || !yesterdayInsights.insights) {
|
|
20
|
+
console.warn('[DailyBoughtVsSoldCount] Missing insights data for today or yesterday.');
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const yesterdayTotals = new Map(yesterdayInsights.insights.map(i => [i.instrumentId, i.total]));
|
|
25
|
+
|
|
26
|
+
for (const instrument of todayInsights.insights) {
|
|
27
|
+
const instrumentId = instrument.instrumentId;
|
|
28
|
+
const todayTotal = instrument.total || 0;
|
|
29
|
+
const yesterdayTotal = yesterdayTotals.get(instrumentId) || 0;
|
|
30
|
+
|
|
31
|
+
const delta = todayTotal - yesterdayTotal;
|
|
32
|
+
|
|
33
|
+
if (delta > 0) {
|
|
34
|
+
this.totalBought += delta;
|
|
35
|
+
} else if (delta < 0) {
|
|
36
|
+
this.totalSold += Math.abs(delta); // Sum of absolute decreases
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
getResult() {
|
|
42
|
+
// Return the final aggregated counts
|
|
43
|
+
return {
|
|
44
|
+
total_positions_bought_delta: this.totalBought,
|
|
45
|
+
total_positions_sold_delta: this.totalSold
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
reset() {
|
|
50
|
+
this.totalBought = 0;
|
|
51
|
+
this.totalSold = 0;
|
|
52
|
+
this.processedDay = false;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = DailyBoughtVsSoldCount;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculates the total number of 'buy' vs 'sell' (short) positions across all instruments.
|
|
3
|
+
* Uses the 'daily_instrument_insights' collection (truth of source).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class DailyBuySellSentimentCount {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.totalBuyPositions = 0;
|
|
9
|
+
this.totalSellPositions = 0;
|
|
10
|
+
this.processedDay = false; // Flag to run logic only once per day
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// Only needs today's insights
|
|
14
|
+
async process(todayPortfolio, yesterdayPortfolio, userId, context, todayInsights, yesterdayInsights) {
|
|
15
|
+
if (this.processedDay) return;
|
|
16
|
+
this.processedDay = true;
|
|
17
|
+
|
|
18
|
+
if (!todayInsights || !todayInsights.insights) {
|
|
19
|
+
console.warn('[DailyBuySellSentimentCount] Missing insights data for today.');
|
|
20
|
+
return;
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
for (const instrument of todayInsights.insights) {
|
|
24
|
+
const totalOwners = instrument.total || 0;
|
|
25
|
+
if (totalOwners > 0) {
|
|
26
|
+
const buyPercent = (instrument.buy || 0) / 100;
|
|
27
|
+
const sellPercent = (instrument.sell || 0) / 100; // 'sell' means short here
|
|
28
|
+
|
|
29
|
+
this.totalBuyPositions += (buyPercent * totalOwners);
|
|
30
|
+
this.totalSellPositions += (sellPercent * totalOwners);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
getResult() {
|
|
36
|
+
// Return the final rounded sums
|
|
37
|
+
return {
|
|
38
|
+
total_buy_positions: Math.round(this.totalBuyPositions),
|
|
39
|
+
total_sell_positions: Math.round(this.totalSellPositions) // 'sell' are shorts
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
reset() {
|
|
44
|
+
this.totalBuyPositions = 0;
|
|
45
|
+
this.totalSellPositions = 0;
|
|
46
|
+
this.processedDay = false;
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
module.exports = DailyBuySellSentimentCount;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculates the daily change (delta) in total owners for each instrument.
|
|
3
|
+
* Uses the 'daily_instrument_insights' collection (truth of source).
|
|
4
|
+
*/
|
|
5
|
+
const { loadInstrumentMappings } = require('../../utils/sector_mapping_provider');
|
|
6
|
+
|
|
7
|
+
class DailyOwnershipDelta {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.deltaByTicker = {};
|
|
10
|
+
this.mappings = null;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
// This calculation only needs insights data, not portfolio data.
|
|
14
|
+
// It runs daily but needs 'yesterday's insights to calculate the delta.
|
|
15
|
+
async process(todayPortfolio, yesterdayPortfolio, userId, context, todayInsights, yesterdayInsights) {
|
|
16
|
+
// We only need to run the core logic once per day, not per user.
|
|
17
|
+
// Use a flag to ensure it runs only on the first user processed for the day.
|
|
18
|
+
if (this.processedDay) return;
|
|
19
|
+
this.processedDay = true; // Set flag
|
|
20
|
+
|
|
21
|
+
if (!todayInsights || !todayInsights.insights || !yesterdayInsights || !yesterdayInsights.insights) {
|
|
22
|
+
console.warn('[DailyOwnershipDelta] Missing insights data for today or yesterday.');
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
if (!this.mappings) {
|
|
27
|
+
this.mappings = await loadInstrumentMappings();
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
const yesterdayTotals = new Map(yesterdayInsights.insights.map(i => [i.instrumentId, i.total]));
|
|
31
|
+
|
|
32
|
+
for (const instrument of todayInsights.insights) {
|
|
33
|
+
const instrumentId = instrument.instrumentId;
|
|
34
|
+
const todayTotal = instrument.total || 0;
|
|
35
|
+
const yesterdayTotal = yesterdayTotals.get(instrumentId) || 0; // Default to 0 if not found yesterday
|
|
36
|
+
|
|
37
|
+
const delta = todayTotal - yesterdayTotal;
|
|
38
|
+
const ticker = this.mappings.instrumentToTicker[instrumentId] || `id_${instrumentId}`;
|
|
39
|
+
|
|
40
|
+
this.deltaByTicker[ticker] = delta;
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getResult() {
|
|
45
|
+
// Return the final calculated delta for each ticker
|
|
46
|
+
return this.deltaByTicker;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
reset() {
|
|
50
|
+
this.deltaByTicker = {};
|
|
51
|
+
this.processedDay = false; // Reset the flag for the next day
|
|
52
|
+
this.mappings = null;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = DailyOwnershipDelta;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculates the total number of positions held across all instruments for the day.
|
|
3
|
+
* Uses the 'daily_instrument_insights' collection (truth of source).
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
class DailyTotalPositionsHeld {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.totalPositions = 0;
|
|
9
|
+
this.processedDay = false; // Flag to run logic only once per day
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
// Only needs today's insights
|
|
13
|
+
async process(todayPortfolio, yesterdayPortfolio, userId, context, todayInsights, yesterdayInsights) {
|
|
14
|
+
if (this.processedDay) return;
|
|
15
|
+
this.processedDay = true;
|
|
16
|
+
|
|
17
|
+
if (!todayInsights || !todayInsights.insights) {
|
|
18
|
+
console.warn('[DailyTotalPositionsHeld] Missing insights data for today.');
|
|
19
|
+
return;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
for (const instrument of todayInsights.insights) {
|
|
23
|
+
this.totalPositions += (instrument.total || 0);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
getResult() {
|
|
28
|
+
// Return the final sum
|
|
29
|
+
return {
|
|
30
|
+
total_positions_held: this.totalPositions
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
reset() {
|
|
35
|
+
this.totalPositions = 0;
|
|
36
|
+
this.processedDay = false;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
module.exports = DailyTotalPositionsHeld;
|