bulltrackers-module 1.0.693 → 1.0.694

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.
@@ -420,7 +420,8 @@ async function writeSingleResult(result, docRef, name, dateContext, category, lo
420
420
  }
421
421
 
422
422
  const rootUpdate = updates.find(u => u.ref.path === docRef.path && u.type !== 'DELETE');
423
- if (rootUpdate) { rootUpdate.options = { merge: rootMergeOption }; }
423
+ // FIX: Always use merge: false to ensure old fields (like _compressed/payload) are wiped
424
+ if (rootUpdate) { rootUpdate.options = { merge: false }; }
424
425
 
425
426
  const writes = updates.filter(u => u.type !== 'DELETE').length;
426
427
  const deletes = updates.filter(u => u.type === 'DELETE').length;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.693",
3
+ "version": "1.0.694",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [
@@ -1,172 +0,0 @@
1
- /**
2
- * file: alert-system/helpers/alert_type_registry.js
3
- */
4
- const ALERT_TYPES = {
5
- increasedRisk: {
6
- id: 'increasedRisk',
7
- name: 'Increased Risk',
8
- description: 'Alert when a Popular Investor\'s risk score increases',
9
- computationName: 'RiskScoreIncrease',
10
- category: 'alerts',
11
- messageTemplate: '{piUsername}\'s risk score increased by {change} points (from {previous} to {current})',
12
- severity: 'high',
13
- enabled: true
14
- },
15
- volatilityChanges: {
16
- id: 'volatilityChanges',
17
- name: 'Significant Volatility',
18
- description: 'Alert when a Popular Investor\'s portfolio volatility exceeds 50%',
19
- computationName: 'SignificantVolatility',
20
- category: 'alerts',
21
- messageTemplate: '{piUsername}\'s portfolio volatility is {volatility}% (threshold: {threshold}%)',
22
- severity: 'medium',
23
- enabled: true
24
- },
25
- newSector: {
26
- id: 'newSector',
27
- name: 'New Sector Entry',
28
- description: 'Alert when a Popular Investor enters a new sector',
29
- computationName: 'NewSectorExposure',
30
- category: 'alerts',
31
- messageTemplate: '{piUsername} entered new sector(s): {sectorName}',
32
- severity: 'low',
33
- enabled: true
34
- },
35
- increasedPositionSize: {
36
- id: 'increasedPositionSize',
37
- name: 'Increased Position Size',
38
- description: 'Alert when a Popular Investor significantly increases a position size (>5%)',
39
- computationName: 'PositionInvestedIncrease',
40
- category: 'alerts',
41
- messageTemplate: '{piUsername} increased position size for {symbol} by {diff}% (from {prev}% to {curr}%)',
42
- severity: 'medium',
43
- enabled: true
44
- },
45
- newSocialPost: {
46
- id: 'newSocialPost',
47
- name: 'New Social Post',
48
- description: 'Alert when a Popular Investor makes a new social post',
49
- computationName: 'NewSocialPost',
50
- category: 'alerts',
51
- messageTemplate: '{piUsername} posted a new update: {title}',
52
- severity: 'low',
53
- enabled: true
54
- },
55
- // [NEW] Behavioral Anomaly Registration
56
- behavioralAnomaly: {
57
- id: 'behavioralAnomaly',
58
- name: 'Behavioral Anomaly',
59
- description: 'Alert when a Popular Investor deviates significantly from their baseline behavior',
60
- computationName: 'BehavioralAnomaly',
61
- category: 'alerts',
62
- // Uses metadata keys from Behaviour.js: primaryDriver, driverSignificance, anomalyScore
63
- messageTemplate: 'Behavioral Alert for {piUsername}: {primaryDriver} Deviation ({driverSignificance}) detected.',
64
- severity: 'high',
65
- enabled: true
66
- },
67
- testSystemProbe: {
68
- id: 'testSystemProbe',
69
- name: 'Test System Probe',
70
- description: 'Always-on debug alert',
71
- computationName: 'TestSystemProbe',
72
- category: 'alerts',
73
- messageTemplate: 'Probe Triggered for {status} at {timestamp}',
74
- severity: 'info',
75
- enabled: true
76
- },
77
- };
78
-
79
- /**
80
- * Get alert type by ID
81
- */
82
- function getAlertType(alertTypeId) {
83
- return ALERT_TYPES[alertTypeId] || null;
84
- }
85
-
86
- /**
87
- * Get alert type by computation name
88
- */
89
- function getAlertTypeByComputation(computationName) {
90
- for (const [id, alertType] of Object.entries(ALERT_TYPES)) {
91
- if (alertType.computationName === computationName) {
92
- return alertType;
93
- }
94
- }
95
- return null;
96
- }
97
-
98
- /**
99
- * Get all enabled alert types
100
- */
101
- function getAllAlertTypes() {
102
- return Object.values(ALERT_TYPES).filter(type => type.enabled);
103
- }
104
-
105
- /**
106
- * Check if a computation is an alert computation
107
- */
108
- function isAlertComputation(computationName) {
109
- return getAlertTypeByComputation(computationName) !== null;
110
- }
111
-
112
- /**
113
- * Generate alert message from template and metadata
114
- */
115
- function generateAlertMessage(alertType, piUsername, metadata = {}) {
116
- let message = alertType.messageTemplate;
117
-
118
- // Replace placeholders
119
- message = message.replace('{piUsername}', piUsername || 'Unknown');
120
- message = message.replace('{count}', metadata.count || metadata.positions?.length || metadata.moveCount || 0);
121
- message = message.replace('{change}', metadata.change || metadata.changePercent || metadata.diff || 'N/A');
122
- message = message.replace('{previous}', metadata.previous || metadata.previousValue || metadata.prev || metadata.previousRisk || 'N/A');
123
- message = message.replace('{current}', metadata.current || metadata.currentValue || metadata.curr || metadata.currentRisk || 'N/A');
124
- message = message.replace('{sectorName}', metadata.sectorName || (metadata.newExposures && metadata.newExposures.length > 0 ? metadata.newExposures.join(', ') : 'Unknown'));
125
- message = message.replace('{ticker}', metadata.ticker || metadata.symbol || 'Unknown');
126
-
127
- // Format numeric values
128
- message = message.replace('{volatility}', metadata.volatility ? `${(metadata.volatility * 100).toFixed(1)}` : 'N/A');
129
- message = message.replace('{threshold}', metadata.threshold ? `${(metadata.threshold * 100).toFixed(0)}` : 'N/A');
130
- message = message.replace('{diff}', metadata.diff ? `${metadata.diff.toFixed(1)}` : 'N/A');
131
- message = message.replace('{prev}', metadata.prev ? `${metadata.prev.toFixed(1)}` : 'N/A');
132
- message = message.replace('{curr}', metadata.curr ? `${metadata.curr.toFixed(1)}` : 'N/A');
133
- message = message.replace('{title}', metadata.title || 'New Update');
134
-
135
- // [FIX] Probe Placeholders (Missing in original)
136
- message = message.replace('{status}', metadata.status || 'Unknown Status');
137
- message = message.replace('{timestamp}', metadata.timestamp || new Date().toISOString());
138
-
139
- // [NEW] Behavioral Anomaly Placeholders
140
- message = message.replace('{primaryDriver}', metadata.primaryDriver || 'Unknown Factor');
141
- message = message.replace('{driverSignificance}', metadata.driverSignificance || 'N/A');
142
- message = message.replace('{anomalyScore}', metadata.anomalyScore || 'N/A');
143
-
144
- // Handle positions list if available
145
- if (metadata.positions && Array.isArray(metadata.positions) && metadata.positions.length > 0) {
146
- const positionsList = metadata.positions
147
- .slice(0, 3)
148
- .map(p => p.ticker || p.instrumentId)
149
- .join(', ');
150
- message = message.replace('{positions}', positionsList);
151
- }
152
-
153
- // Handle moves array for PositionInvestedIncrease
154
- if (metadata.moves && Array.isArray(metadata.moves) && metadata.moves.length > 0) {
155
- const firstMove = metadata.moves[0];
156
- message = message.replace('{symbol}', firstMove.symbol || 'Unknown');
157
- message = message.replace('{diff}', firstMove.diff ? `${firstMove.diff.toFixed(1)}` : 'N/A');
158
- message = message.replace('{prev}', firstMove.prev ? `${firstMove.prev.toFixed(1)}` : 'N/A');
159
- message = message.replace('{curr}', firstMove.curr ? `${firstMove.curr.toFixed(1)}` : 'N/A');
160
- }
161
-
162
- return message;
163
- }
164
-
165
- module.exports = {
166
- ALERT_TYPES,
167
- getAlertType,
168
- getAlertTypeByComputation,
169
- getAllAlertTypes,
170
- isAlertComputation,
171
- generateAlertMessage
172
- };