aiden-shared-calculations-unified 1.0.75 → 1.0.76
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,146 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Social Calculation (Pass 1)
|
|
3
|
+
*
|
|
4
|
+
* This metric answers: "What is the aggregated social media
|
|
5
|
+
* sentiment (bullish, bearish, neutral) globally and
|
|
6
|
+
* for each ticker?"
|
|
7
|
+
*
|
|
8
|
+
* THIS IS THE GEM ITERATION, PRACITCALLY IDENTICAL TO SOCIAL SENTIMENT AGGREGATION ORIGINAL, BUT DUPLICATED FOR CLARITY OF THE GEM PRODUCT LINE
|
|
9
|
+
*/
|
|
10
|
+
class GemSocialSentimentAggregation {
|
|
11
|
+
constructor() {
|
|
12
|
+
this.global = {
|
|
13
|
+
bullish: 0,
|
|
14
|
+
bearish: 0,
|
|
15
|
+
neutral: 0
|
|
16
|
+
};
|
|
17
|
+
// { [ticker]: { bullish: 0, bearish: 0, neutral: 0 } }
|
|
18
|
+
this.perTicker = new Map();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
/**
|
|
22
|
+
* Defines the output schema for this calculation.
|
|
23
|
+
* @returns {object} JSON Schema object
|
|
24
|
+
*/
|
|
25
|
+
static getSchema() {
|
|
26
|
+
const sentimentSchema = {
|
|
27
|
+
"type": "object",
|
|
28
|
+
"properties": {
|
|
29
|
+
"bullish": { "type": "number" },
|
|
30
|
+
"bearish": { "type": "number" },
|
|
31
|
+
"neutral": { "type": "number" },
|
|
32
|
+
"total_posts": { "type": "number" },
|
|
33
|
+
"net_sentiment": { "type": "number" },
|
|
34
|
+
"net_sentiment_pct": { "type": "number" }
|
|
35
|
+
},
|
|
36
|
+
"required": ["bullish", "bearish", "neutral", "total_posts", "net_sentiment", "net_sentiment_pct"]
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"description": "Aggregates social sentiment (bullish, bearish) globally and per ticker.",
|
|
42
|
+
"properties": {
|
|
43
|
+
"global_sentiment": {
|
|
44
|
+
...sentimentSchema,
|
|
45
|
+
"description": "Aggregated sentiment across all posts."
|
|
46
|
+
},
|
|
47
|
+
"per_ticker": {
|
|
48
|
+
"type": "object",
|
|
49
|
+
"description": "Aggregated sentiment broken down by asset ticker.",
|
|
50
|
+
"patternProperties": {
|
|
51
|
+
"^.*$": {
|
|
52
|
+
...sentimentSchema,
|
|
53
|
+
"description": "Aggregated sentiment for a specific ticker."
|
|
54
|
+
} // Ticker
|
|
55
|
+
},
|
|
56
|
+
"additionalProperties": sentimentSchema
|
|
57
|
+
}
|
|
58
|
+
},
|
|
59
|
+
"required": ["global_sentiment", "per_ticker"]
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
_initTicker(ticker) {
|
|
64
|
+
if (!this.perTicker.has(ticker)) {
|
|
65
|
+
this.perTicker.set(ticker, {
|
|
66
|
+
bullish: 0,
|
|
67
|
+
bearish: 0,
|
|
68
|
+
neutral: 0
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* @param {string} dateStr - Today's date.
|
|
75
|
+
* @param {object} dependencies - db, logger.
|
|
76
|
+
* @param {object} config - Computation config.
|
|
77
|
+
* @param {object} fetchedDependencies - (UNUSED) In-memory results.
|
|
78
|
+
*/
|
|
79
|
+
async process(dateStr, dependencies, config, fetchedDependencies) {
|
|
80
|
+
const { calculationUtils } = dependencies;
|
|
81
|
+
const todaySocialPosts = await calculationUtils.loadSocialData(dateStr);
|
|
82
|
+
|
|
83
|
+
for (const post of todaySocialPosts) {
|
|
84
|
+
const sentiment = post.sentiment || 'neutral'; // 'bullish', 'bearish', 'neutral'
|
|
85
|
+
|
|
86
|
+
// 1. Aggregate global sentiment
|
|
87
|
+
if (sentiment === 'bullish') {
|
|
88
|
+
this.global.bullish++;
|
|
89
|
+
} else if (sentiment === 'bearish') {
|
|
90
|
+
this.global.bearish++;
|
|
91
|
+
} else {
|
|
92
|
+
this.global.neutral++;
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// 2. Aggregate per-ticker sentiment
|
|
96
|
+
const tickers = post.tickers || [];
|
|
97
|
+
for (const ticker of tickers) {
|
|
98
|
+
this._initTicker(ticker);
|
|
99
|
+
const data = this.perTicker.get(ticker);
|
|
100
|
+
|
|
101
|
+
if (sentiment === 'bullish') {
|
|
102
|
+
data.bullish++;
|
|
103
|
+
} else if (sentiment === 'bearish') {
|
|
104
|
+
data.bearish++;
|
|
105
|
+
} else {
|
|
106
|
+
data.neutral++;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
_calculateSentiment(data) {
|
|
113
|
+
const total = data.bullish + data.bearish + data.neutral;
|
|
114
|
+
const net = data.bullish - data.bearish;
|
|
115
|
+
return {
|
|
116
|
+
...data,
|
|
117
|
+
total_posts: total,
|
|
118
|
+
net_sentiment: net,
|
|
119
|
+
// Net sentiment as a percentage of *all* posts (bullish, bearish, neutral)
|
|
120
|
+
net_sentiment_pct: (total > 0) ? (net / total) * 100 : 0
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
async getResult() {
|
|
125
|
+
// Calculate stats for global
|
|
126
|
+
const global_sentiment = this._calculateSentiment(this.global);
|
|
127
|
+
|
|
128
|
+
// Calculate stats for per-ticker
|
|
129
|
+
const per_ticker = {};
|
|
130
|
+
for (const [ticker, data] of this.perTicker.entries()) {
|
|
131
|
+
per_ticker[ticker] = this._calculateSentiment(data);
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
return {
|
|
135
|
+
global_sentiment,
|
|
136
|
+
per_ticker
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
reset() {
|
|
141
|
+
this.global = { bullish: 0, bearish: 0, neutral: 0 };
|
|
142
|
+
this.perTicker.clear();
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
module.exports = GemSocialSentimentAggregation;
|