aiden-shared-calculations-unified 1.0.83 → 1.0.84

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.
Files changed (71) hide show
  1. package/calculations/core/asset-pnl-status.js +122 -104
  2. package/calculations/core/asset-position-size.js +110 -73
  3. package/calculations/core/average-daily-pnl-all-users.js +17 -3
  4. package/calculations/core/average-daily-pnl-per-sector.js +83 -75
  5. package/calculations/core/average-daily-pnl-per-stock.js +84 -73
  6. package/calculations/core/average-daily-position-pnl.js +2 -2
  7. package/calculations/core/holding-duration-per-asset.js +24 -23
  8. package/calculations/core/instrument-price-change-1d.js +72 -82
  9. package/calculations/core/instrument-price-momentum-20d.js +66 -100
  10. package/calculations/core/long-position-per-stock.js +21 -13
  11. package/calculations/core/overall-holding-duration.js +8 -3
  12. package/calculations/core/overall-profitability-ratio.js +2 -2
  13. package/calculations/core/platform-buy-sell-sentiment.js +75 -22
  14. package/calculations/core/platform-daily-bought-vs-sold-count.js +19 -10
  15. package/calculations/core/platform-daily-ownership-delta.js +39 -15
  16. package/calculations/core/platform-ownership-per-sector.js +38 -18
  17. package/calculations/core/platform-total-positions-held.js +36 -14
  18. package/calculations/core/pnl-distribution-per-stock.js +39 -36
  19. package/calculations/core/price-metrics.js +70 -172
  20. package/calculations/core/profitability-ratio-per-sector.js +23 -29
  21. package/calculations/core/profitability-ratio-per-stock.js +20 -13
  22. package/calculations/core/profitability-skew-per-stock.js +20 -13
  23. package/calculations/core/profitable-and-unprofitable-status.js +34 -10
  24. package/calculations/core/sentiment-per-stock.js +20 -9
  25. package/calculations/core/short-position-per-stock.js +23 -37
  26. package/calculations/core/social-activity-aggregation.js +41 -115
  27. package/calculations/core/social-asset-posts-trend.js +77 -94
  28. package/calculations/core/social-event-correlation.js +87 -106
  29. package/calculations/core/social-sentiment-aggregation.js +56 -138
  30. package/calculations/core/social-top-mentioned-words.js +74 -106
  31. package/calculations/core/social-topic-interest-evolution.js +94 -94
  32. package/calculations/core/social-topic-sentiment-matrix.js +90 -74
  33. package/calculations/core/social-word-mentions-trend.js +92 -106
  34. package/calculations/core/speculator-asset-sentiment.js +63 -92
  35. package/calculations/core/speculator-danger-zone.js +77 -90
  36. package/calculations/core/speculator-distance-to-stop-loss-per-leverage.js +75 -90
  37. package/calculations/core/speculator-distance-to-tp-per-leverage.js +75 -88
  38. package/calculations/core/speculator-entry-distance-to-sl-per-leverage.js +75 -90
  39. package/calculations/core/speculator-entry-distance-to-tp-per-leverage.js +74 -89
  40. package/calculations/core/speculator-leverage-per-asset.js +62 -57
  41. package/calculations/core/speculator-leverage-per-sector.js +53 -65
  42. package/calculations/core/speculator-risk-reward-ratio-per-asset.js +71 -76
  43. package/calculations/core/speculator-stop-loss-distance-by-sector-short-long-breakdown.js +60 -81
  44. package/calculations/core/speculator-stop-loss-distance-by-ticker-short-long-breakdown.js +57 -77
  45. package/calculations/core/speculator-stop-loss-per-asset.js +43 -80
  46. package/calculations/core/speculator-take-profit-per-asset.js +45 -69
  47. package/calculations/core/speculator-tsl-per-asset.js +42 -49
  48. package/calculations/core/total-long-figures.js +19 -19
  49. package/calculations/core/total-long-per-sector.js +39 -36
  50. package/calculations/core/total-short-figures.js +19 -19
  51. package/calculations/core/total-short-per-sector.js +39 -36
  52. package/calculations/core/users-processed.js +52 -25
  53. package/calculations/gauss/cohort-capital-flow.js +38 -29
  54. package/calculations/gauss/cohort-definer.js +17 -25
  55. package/calculations/gauss/daily-dna-filter.js +10 -4
  56. package/calculations/gauss/gauss-divergence-signal.js +28 -6
  57. package/calculations/gem/cohort-momentum-state.js +113 -92
  58. package/calculations/gem/cohort-skill-definition.js +23 -53
  59. package/calculations/gem/platform-conviction-divergence.js +62 -116
  60. package/calculations/gem/quant-skill-alpha-signal.js +107 -123
  61. package/calculations/gem/skilled-cohort-flow.js +178 -167
  62. package/calculations/gem/skilled-unskilled-divergence.js +73 -113
  63. package/calculations/gem/unskilled-cohort-flow.js +176 -166
  64. package/calculations/helix/helix-contrarian-signal.js +91 -83
  65. package/calculations/helix/herd-consensus-score.js +135 -97
  66. package/calculations/helix/winner-loser-flow.js +14 -16
  67. package/calculations/pyro/risk-appetite-index.js +121 -123
  68. package/calculations/pyro/squeeze-potential.js +93 -125
  69. package/calculations/pyro/volatility-signal.js +109 -97
  70. package/package.json +5 -5
  71. package/README.MD +0 -155
@@ -7,16 +7,16 @@ _ This metric answers: "For each stock, what is the sum and
7
7
  * This helps determine if returns are skewed (e.g., many small
8
8
  * wins and a few huge losses).
9
9
  */
10
- const { loadInstrumentMappings } = require('../../utils/sector_mapping_provider');
10
+ // --- STANDARD 0: REMOVED require('../../utils/sector_mapping_provider') ---
11
11
 
12
12
  class ProfitabilitySkewPerStock {
13
13
  constructor() {
14
14
  // { [instrumentId]: { profit_sum: 0, profit_count: 0, loss_sum: 0, loss_count: 0 } }
15
15
  this.assets = new Map();
16
- this.mappings = null;
16
+ // --- STANDARD 0: RENAMED ---
17
+ this.tickerMap = null;
17
18
  }
18
19
 
19
- // --- NEW ---
20
20
  /**
21
21
  * Statically defines all metadata for the manifest builder.
22
22
  */
@@ -30,7 +30,6 @@ class ProfitabilitySkewPerStock {
30
30
  };
31
31
  }
32
32
 
33
- // --- NEW ---
34
33
  /**
35
34
  * Statically declare dependencies.
36
35
  */
@@ -40,7 +39,6 @@ class ProfitabilitySkewPerStock {
40
39
 
41
40
  /**
42
41
  * Defines the output schema for this calculation.
43
- * @returns {object} JSON Schema object
44
42
  */
45
43
  static getSchema() {
46
44
  const tickerSchema = {
@@ -80,10 +78,14 @@ class ProfitabilitySkewPerStock {
80
78
  }
81
79
  }
82
80
 
83
- // --- REFACTORED ---
84
- // Simplified signature
85
- process(portfolioData) {
86
- const positions = portfolioData.PublicPositions || portfolioData.AggregatedPositions;
81
+ // --- STANDARD 0: UPDATED SIGNATURE ---
82
+ process(todayPortfolio, yesterdayPortfolio, userId, context) {
83
+ // --- STANDARD 0: ADDED ---
84
+ if (!this.tickerMap) {
85
+ this.tickerMap = context.instrumentToTicker;
86
+ }
87
+
88
+ const positions = todayPortfolio.PublicPositions || todayPortfolio.AggregatedPositions;
87
89
  if (!positions || !Array.isArray(positions)) {
88
90
  return;
89
91
  }
@@ -107,13 +109,17 @@ class ProfitabilitySkewPerStock {
107
109
  }
108
110
 
109
111
  async getResult() {
110
- if (!this.mappings) {
111
- this.mappings = await loadInstrumentMappings();
112
+ // --- STANDARD 0: REMOVED forbidden data load ---
113
+
114
+ // Failsafe check
115
+ if (!this.tickerMap) {
116
+ return {}; // process() must run first
112
117
  }
113
118
 
114
119
  const result = {};
115
120
  for (const [instrumentId, data] of this.assets.entries()) {
116
- const ticker = this.mappings.instrumentToTicker[instrumentId] || `id_${instrumentId}`;
121
+ // --- STANDARD 0: SIMPLIFIED ---
122
+ const ticker = this.tickerMap[instrumentId] || `id_${instrumentId}`;
117
123
 
118
124
  const avgProfit = (data.profit_count > 0) ? (data.profit_sum / data.profit_count) : 0;
119
125
  const avgLoss = (data.loss_count > 0) ? (Math.abs(data.loss_sum) / data.loss_count) : 0;
@@ -131,7 +137,8 @@ class ProfitabilitySkewPerStock {
131
137
 
132
138
  reset() {
133
139
  this.assets.clear();
134
- this.mappings = null;
140
+ // --- STANDARD 0: RENAMED ---
141
+ this.tickerMap = null;
135
142
  }
136
143
  }
137
144
 
@@ -10,7 +10,6 @@ class ProfitableAndUnprofitableStatus {
10
10
  this.total_in_loss = 0;
11
11
  }
12
12
 
13
- // --- NEW ---
14
13
  /**
15
14
  * Statically defines all metadata for the manifest builder.
16
15
  */
@@ -24,7 +23,6 @@ class ProfitableAndUnprofitableStatus {
24
23
  };
25
24
  }
26
25
 
27
- // --- NEW ---
28
26
  /**
29
27
  * Statically declare dependencies.
30
28
  */
@@ -34,7 +32,6 @@ class ProfitableAndUnprofitableStatus {
34
32
 
35
33
  /**
36
34
  * Defines the output schema for this calculation.
37
- * @returns {object} JSON Schema object
38
35
  */
39
36
  static getSchema() {
40
37
  return {
@@ -58,15 +55,42 @@ class ProfitableAndUnprofitableStatus {
58
55
  };
59
56
  }
60
57
 
61
- // --- REFACTORED ---
62
- // Simplified signature
63
- process(portfolioData) {
64
- // Use the P&L from the summary, which is for the *day*
65
- const dailyPnl = portfolioData.Summary?.NetProfit || 0;
58
+ // --- UPDATED SIGNATURE ---
59
+ process(todayPortfolio, yesterdayPortfolio, userId, context) {
66
60
 
67
- if (dailyPnl > 0) {
61
+ // ---
62
+ // FIX: The 'data-generator.js' does not provide a 'Summary' object
63
+ // or a root-level 'NetProfit' field.
64
+ // We must derive the overall P&L from the individual positions,
65
+ // which *are* generated.
66
+ // ---
67
+ const positions = todayPortfolio.AggregatedPositions;
68
+ if (!positions || !Array.isArray(positions) || positions.length === 0) {
69
+ return; // No positions, no P&L status
70
+ }
71
+
72
+ let totalInvested = 0;
73
+ let weightedPnlSum = 0;
74
+
75
+ for (const pos of positions) {
76
+ const invested = pos.Invested;
77
+ const pnl = pos.NetProfit;
78
+
79
+ if (typeof invested === 'number' && typeof pnl === 'number') {
80
+ totalInvested += invested;
81
+ weightedPnlSum += (pnl * invested); // Weight the P&L by its size
82
+ }
83
+ }
84
+
85
+ if (totalInvested === 0) {
86
+ return; // No invested capital, no P&L status
87
+ }
88
+
89
+ const overallPnl = weightedPnlSum / totalInvested;
90
+
91
+ if (overallPnl > 0) {
68
92
  this.total_in_profit++;
69
- } else if (dailyPnl < 0) {
93
+ } else if (overallPnl < 0) {
70
94
  this.total_in_loss++;
71
95
  }
72
96
  }
@@ -4,18 +4,18 @@
4
4
  * This metric answers: "For each stock, what is the count
5
5
  * of long versus short positions?"
6
6
  */
7
- const { loadInstrumentMappings } = require('../../utils/sector_mapping_provider');
7
+ // --- STANDARD 0: REMOVED require('../../utils/sector_mapping_provider') ---
8
8
 
9
9
  class SentimentPerStock {
10
10
  constructor() {
11
11
  // { [instrumentId]: { long: 0, short: 0 } }
12
12
  this.assets = new Map();
13
- this.mappings = null;
13
+ // --- STANDARD 0: RENAMED ---
14
+ this.tickerMap = null;
14
15
  }
15
16
 
16
17
  /**
17
18
  * Defines the output schema for this calculation.
18
- * @returns {object} JSON Schema object
19
19
  */
20
20
  static getSchema() {
21
21
  const tickerSchema = {
@@ -77,8 +77,14 @@ class SentimentPerStock {
77
77
  }
78
78
  }
79
79
 
80
- process(portfolioData) {
81
- const positions = portfolioData.PublicPositions || portfolioData.AggregatedPositions;
80
+ // --- STANDARD 0: UPDATED SIGNATURE ---
81
+ process(todayPortfolio, yesterdayPortfolio, userId, context) {
82
+ // --- STANDARD 0: ADDED ---
83
+ if (!this.tickerMap) {
84
+ this.tickerMap = context.instrumentToTicker;
85
+ }
86
+
87
+ const positions = todayPortfolio.PublicPositions || todayPortfolio.AggregatedPositions;
82
88
  if (!positions || !Array.isArray(positions)) {
83
89
  return;
84
90
  }
@@ -99,13 +105,17 @@ class SentimentPerStock {
99
105
  }
100
106
 
101
107
  async getResult() {
102
- if (!this.mappings) {
103
- this.mappings = await loadInstrumentMappings();
108
+ // --- STANDARD 0: REMOVED forbidden data load ---
109
+
110
+ // Failsafe check
111
+ if (!this.tickerMap) {
112
+ return {}; // process() must run first
104
113
  }
105
114
 
106
115
  const result = {};
107
116
  for (const [instrumentId, data] of this.assets.entries()) {
108
- const ticker = this.mappings.instrumentToTicker[instrumentId] || `id_${instrumentId}`;
117
+ // --- STANDARD 0: SIMPLIFIED ---
118
+ const ticker = this.tickerMap[instrumentId] || `id_${instrumentId}`;
109
119
 
110
120
  if (data.long > 0 || data.short > 0) {
111
121
  result[ticker] = {
@@ -120,7 +130,8 @@ class SentimentPerStock {
120
130
 
121
131
  reset() {
122
132
  this.assets.clear();
123
- this.mappings = null;
133
+ // --- STANDARD 0: RENAMED ---
134
+ this.tickerMap = null;
124
135
  }
125
136
  }
126
137
 
@@ -1,22 +1,16 @@
1
1
  /**
2
2
  * @fileoverview Calculation (Pass 1) for short positions per stock.
3
- *
4
- * This metric answers: "How many short ('sell') positions
5
- * are there for each stock?"
3
+ * --- FIX ---
4
+ * - Logic updated to check for *both* Speculator schema (pos.IsBuy === false)
5
+ * and Normal schema (pos.Direction === 'Sell') to match schema.md.
6
6
  */
7
- const { loadInstrumentMappings } = require('../../utils/sector_mapping_provider');
8
7
 
9
8
  class ShortPositionPerStock {
10
9
  constructor() {
11
- // We will store { [instrumentId]: count }
12
10
  this.assets = new Map();
13
- this.mappings = null;
11
+ this.tickerMap = null;
14
12
  }
15
13
 
16
- // --- NEW ---
17
- /**
18
- * Statically defines all metadata for the manifest builder.
19
- */
20
14
  static getMetadata() {
21
15
  return {
22
16
  type: 'standard',
@@ -27,32 +21,18 @@ class ShortPositionPerStock {
27
21
  };
28
22
  }
29
23
 
30
- // --- NEW ---
31
- /**
32
- * Statically declare dependencies.
33
- */
34
24
  static getDependencies() {
35
25
  return [];
36
26
  }
37
27
 
38
- /**
39
- * Defines the output schema for this calculation.
40
- * @returns {object} JSON Schema object
41
- */
42
28
  static getSchema() {
43
29
  return {
44
30
  "type": "object",
45
31
  "description": "Calculates the total count of short ('sell') positions for each asset.",
46
32
  "patternProperties": {
47
- // Ticker
48
- "^.*$": {
49
- "type": "number",
50
- "description": "The total count of short positions for this asset."
51
- }
33
+ "^.*$": { "type": "number" }
52
34
  },
53
- "additionalProperties": {
54
- "type": "number"
55
- }
35
+ "additionalProperties": { "type": "number" }
56
36
  };
57
37
  }
58
38
 
@@ -62,20 +42,26 @@ class ShortPositionPerStock {
62
42
  }
63
43
  }
64
44
 
65
- // --- REFACTORED ---
66
- // Simplified signature
67
- process(portfolioData) {
68
- const positions = portfolioData.PublicPositions || portfolioData.AggregatedPositions;
45
+ process(todayPortfolio, yesterdayPortfolio, userId, context, todayInsights, yesterdayInsights, fetchedDependencies) {
46
+ if (!this.tickerMap) {
47
+ this.tickerMap = context.instrumentToTicker;
48
+ }
49
+
50
+ const positions = todayPortfolio.PublicPositions || todayPortfolio.AggregatedPositions;
69
51
  if (!positions || !Array.isArray(positions)) {
70
52
  return;
71
53
  }
72
54
 
73
55
  for (const pos of positions) {
74
- // Only count 'sell' (short) positions
75
- if (!pos.IsBuy) {
56
+ // --- THIS IS THE FIX ---
57
+ // Check for Speculator (IsBuy) OR Normal (Direction)
58
+ const isShort = (pos.IsBuy === false) || (pos.Direction === 'Sell');
59
+
60
+ if (isShort) {
61
+ // --- END FIX ---
76
62
  const instrumentId = pos.InstrumentID;
77
63
  if (!instrumentId) continue;
78
-
64
+
79
65
  this._initAsset(instrumentId);
80
66
  this.assets.set(instrumentId, this.assets.get(instrumentId) + 1);
81
67
  }
@@ -83,13 +69,13 @@ class ShortPositionPerStock {
83
69
  }
84
70
 
85
71
  async getResult() {
86
- if (!this.mappings) {
87
- this.mappings = await loadInstrumentMappings();
72
+ if (!this.tickerMap) {
73
+ return {};
88
74
  }
89
75
 
90
76
  const result = {};
91
77
  for (const [instrumentId, count] of this.assets.entries()) {
92
- const ticker = this.mappings.instrumentToTicker[instrumentId] || `id_${instrumentId}`;
78
+ const ticker = this.tickerMap[instrumentId] || `id_${instrumentId}`;
93
79
  result[ticker] = count;
94
80
  }
95
81
  return result;
@@ -97,7 +83,7 @@ class ShortPositionPerStock {
97
83
 
98
84
  reset() {
99
85
  this.assets.clear();
100
- this.mappings = null;
86
+ this.tickerMap = null;
101
87
  }
102
88
  }
103
89
 
@@ -1,155 +1,81 @@
1
1
  /**
2
- * @fileoverview Social Calculation (Pass 1)
3
- *
4
- * This metric answers: "What is the total and average number
5
- * of likes and comments on social media posts, both globally
6
- * and per ticker?"
2
+ * @fileoverview Calculation (Pass 2 - Meta) for social activity.
3
+ * --- FIX ---
4
+ * 1. Changed 'process' signature to 5-arg 'meta' standard.
5
+ * 2. Changed data access to read 'dateStr.social' (Arg 1, the metaPayload).
6
+ * 3. Changed 'socialDoc.posts' to 'socialDoc' (which IS the map of posts).
7
+ * 4. Changed 'post.comments' to 'post.commentCount'.
8
+ * 5. Changed 'post.likes' to 'post.likeCount'.
7
9
  */
8
10
  class SocialActivityAggregation {
11
+
9
12
  constructor() {
10
- this.global = {
11
- total_posts: 0,
12
- total_likes: 0,
13
- total_comments: 0
14
- };
15
- // { [ticker]: { total_posts: 0, total_likes: 0, total_comments: 0 } }
16
- this.perTicker = new Map();
13
+ this.result = {};
17
14
  }
18
15
 
19
- // --- NEW ---
20
- /**
21
- * Statically defines all metadata for the manifest builder.
22
- */
23
16
  static getMetadata() {
24
17
  return {
25
- type: 'meta', // Runs once, not per-user
26
- rootDataDependencies: ['social'], // Needs the social posts doc
18
+ type: 'meta',
19
+ rootDataDependencies: ['social'],
27
20
  isHistorical: false,
28
21
  userType: 'n/a',
29
22
  category: 'core_social'
30
23
  };
31
24
  }
32
25
 
33
- // --- NEW ---
34
- /**
35
- * Statically declare dependencies.
36
- */
37
26
  static getDependencies() {
38
27
  return [];
39
28
  }
40
29
 
41
- /**
42
- * Defines the output schema for this calculation.
43
- * @returns {object} JSON Schema object
44
- */
45
30
  static getSchema() {
46
- const statsSchema = {
31
+ return {
47
32
  "type": "object",
33
+ "description": "Aggregates the total social activity for the day.",
48
34
  "properties": {
49
35
  "total_posts": { "type": "number" },
50
- "total_likes": { "type": "number" },
51
36
  "total_comments": { "type": "number" },
52
- "avg_likes_per_post": { "type": "number" },
53
- "avg_comments_per_post": { "type": "number" }
54
- },
55
- "required": ["total_posts", "total_likes", "total_comments", "avg_likes_per_post", "avg_comments_per_post"]
56
- };
57
-
58
- return {
59
- "type": "object",
60
- "description": "Aggregates social activity (posts, likes, comments) globally and per ticker.",
61
- "properties": {
62
- "global_activity": {
63
- ...statsSchema,
64
- "description": "Aggregated activity across all posts."
65
- },
66
- "per_ticker": {
67
- "type": "object",
68
- "description": "Aggregated activity broken down by asset ticker.",
69
- "patternProperties": {
70
- "^.*$": {
71
- ...statsSchema,
72
- "description": "Aggregated activity for a specific ticker."
73
- } // Ticker
74
- },
75
- "additionalProperties": statsSchema
76
- }
37
+ "total_likes": { "type": "number" }
77
38
  },
78
- "required": ["global_activity", "per_ticker"]
39
+ "required": ["total_posts", "total_comments", "total_likes"]
79
40
  };
80
41
  }
81
42
 
82
- _initTicker(ticker) {
83
- if (!this.perTicker.has(ticker)) {
84
- this.perTicker.set(ticker, {
85
- total_posts: 0,
86
- total_likes: 0,
87
- total_comments: 0
88
- });
43
+ // --- THIS IS THE FIX ---
44
+ async process(dateStr, rootData, dependencies, config, fetchedDependencies) {
45
+
46
+ // Get social data from Arg 1 (metaPayload)
47
+ const socialDoc = dateStr.social; // This IS the map of posts
48
+
49
+ if (!socialDoc || typeof socialDoc !== 'object') {
50
+ this.result = { total_posts: 0, total_comments: 0, total_likes: 0 };
51
+ return;
89
52
  }
90
- }
91
53
 
92
- // --- REFACTORED ---
93
- /**
94
- * This is a 'meta' calculation.
95
- * @param {string} dateStr - Today's date.
96
- * @param {object} rootData - The root data object.
97
- * @param {object} dependencies - db, logger, calculationUtils.
98
- */
99
- async process(dateStr, rootData, dependencies) {
100
- const { calculationUtils } = dependencies;
101
- // The runner provides social data inside rootData
102
- const todaySocialPosts = rootData.todaySocialPostInsights || {};
54
+ const postsArray = Object.values(socialDoc);
55
+ let totalPosts = postsArray.length;
56
+ let totalComments = 0;
57
+ let totalLikes = 0;
103
58
 
104
- for (const post of Object.values(todaySocialPosts)) {
105
- const likes = post.likeCount || 0;
106
- const comments = post.commentCount || 0;
107
-
108
- // 1. Aggregate global stats
109
- this.global.total_posts++;
110
- this.global.total_likes += likes;
111
- this.global.total_comments += comments;
112
-
113
- // 2. Aggregate per-ticker stats
114
- const tickers = post.tickers || [];
115
- for (const ticker of tickers) {
116
- this._initTicker(ticker);
117
- const data = this.perTicker.get(ticker);
118
- data.total_posts++;
119
- data.total_likes += likes;
120
- data.total_comments += comments;
121
- }
59
+ for (const post of postsArray) {
60
+ // Use schema.md fields
61
+ totalComments += post.commentCount || 0;
62
+ totalLikes += post.likeCount || 0;
122
63
  }
123
- }
124
-
125
- _calculateAverages(data) {
126
- const posts = data.total_posts;
127
- return {
128
- ...data,
129
- avg_likes_per_post: (posts > 0) ? (data.total_likes / posts) : 0,
130
- avg_comments_per_post: (posts > 0) ? (data.total_comments / posts) : 0
64
+
65
+ this.result = {
66
+ total_posts: totalPosts,
67
+ total_comments: totalComments,
68
+ total_likes: totalLikes
131
69
  };
132
70
  }
71
+ // --- END FIX ---
133
72
 
134
- async getResult() {
135
- // Calculate averages for global
136
- const global_activity = this._calculateAverages(this.global);
137
-
138
- // Calculate averages for per-ticker
139
- const per_ticker = {};
140
- for (const [ticker, data] of this.perTicker.entries()) {
141
- per_ticker[ticker] = this._calculateAverages(data);
142
- }
143
-
144
- return {
145
- global_activity,
146
- per_ticker
147
- };
73
+ async getResult(fetchedDependencies) {
74
+ return this.result;
148
75
  }
149
76
 
150
77
  reset() {
151
- this.global = { total_posts: 0, total_likes: 0, total_comments: 0 };
152
- this.perTicker.clear();
78
+ this.result = {};
153
79
  }
154
80
  }
155
81