aiden-shared-calculations-unified 1.0.97 → 1.0.99

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,7 +1,7 @@
1
1
  /**
2
2
  * @fileoverview CORE Product Line (Pass 1 - Meta)
3
3
  * Calculates annualized volatility.
4
- * Safe for sharded execution (accumulates results).
4
+ * Clean: System automatically handles sharding for large result sets.
5
5
  */
6
6
  class AssetVolatilityEstimator {
7
7
  constructor() {
@@ -37,16 +37,10 @@ class AssetVolatilityEstimator {
37
37
  const { compute, priceExtractor } = math;
38
38
 
39
39
  if (!prices || !prices.history) return;
40
-
41
- // Efficiently extract only histories present in this shard/context
42
40
  const allHistories = priceExtractor.getAllHistories(prices);
43
41
 
44
- const batchResult = {};
45
-
46
42
  for (const [key, candles] of allHistories.entries()) {
47
43
  let ticker = key;
48
-
49
- // Resolve ticker logic
50
44
  if (prices.history[key] && prices.history[key].instrumentId) {
51
45
  const instId = prices.history[key].instrumentId;
52
46
  if (mappings && mappings.instrumentToTicker && mappings.instrumentToTicker[instId]) {
@@ -54,7 +48,6 @@ class AssetVolatilityEstimator {
54
48
  }
55
49
  }
56
50
 
57
- // Guard: Need enough data for a trend
58
51
  if (!candles || candles.length < 10) continue;
59
52
 
60
53
  const logReturns = [];
@@ -63,36 +56,32 @@ class AssetVolatilityEstimator {
63
56
  for (let i = 1; i < candles.length; i++) {
64
57
  const prev = candles[i-1].price;
65
58
  const curr = candles[i].price;
66
-
67
- // Guard: Prevent log(0) or log(negative) errors
68
59
  if (prev > 0 && curr > 0) {
69
60
  logReturns.push(Math.log(curr / prev));
70
61
  lastPrice = curr;
71
62
  }
72
63
  }
73
64
 
74
- const LOOKBACK = 30;
75
- const relevantReturns = logReturns.slice(-LOOKBACK);
76
-
77
- // Guard: Need enough returns for Standard Deviation
65
+ const relevantReturns = logReturns.slice(-30);
78
66
  if (relevantReturns.length < 5) continue;
79
67
 
80
68
  const stdDev = compute.standardDeviation(relevantReturns);
81
69
  const annualizedVol = stdDev * Math.sqrt(365);
82
70
 
83
- batchResult[ticker] = {
71
+ this.result[ticker] = {
84
72
  volatility_30d: Number(annualizedVol.toFixed(4)),
85
73
  last_price: lastPrice,
86
74
  data_points: relevantReturns.length
87
75
  };
88
76
  }
89
-
90
- // Accumulate results (handling batched execution)
91
- Object.assign(this.result, batchResult);
92
77
  }
93
78
 
94
- async getResult() { return this.result; }
79
+ async getResult() {
80
+ // No manual sharding needed.
81
+ // If this object > 1MB, the system auto-shards it.
82
+ return this.result;
83
+ }
84
+
95
85
  reset() { this.result = {}; }
96
86
  }
97
-
98
87
  module.exports = AssetVolatilityEstimator;
@@ -13,6 +13,7 @@ class InsightsTotalLongFigures {
13
13
  type: 'meta',
14
14
  rootDataDependencies: ['insights'],
15
15
  isHistorical: false,
16
+ userType: 'n/a',
16
17
  category: 'core_sentiment'
17
18
  };
18
19
  }
@@ -32,9 +33,14 @@ class InsightsTotalLongFigures {
32
33
 
33
34
  process(context) {
34
35
  const { insights: insightsHelper } = context.math;
35
- const insights = insightsHelper.getInsights(context);
36
+ const rawInsights = insightsHelper.getInsights(context);
36
37
 
37
- if (!insights) return;
38
+ // FIX: Extract the 'today' array from the wrapper object
39
+ const insights = (rawInsights && Array.isArray(rawInsights.today))
40
+ ? rawInsights.today
41
+ : (Array.isArray(rawInsights) ? rawInsights : []);
42
+
43
+ if (insights.length === 0) return;
38
44
 
39
45
  for (const insight of insights) {
40
46
  this.totalPositions += insightsHelper.getLongCount(insight);
@@ -43,7 +49,6 @@ class InsightsTotalLongFigures {
43
49
 
44
50
  getResult() {
45
51
  return {
46
- total_long_exposure_weight: 0, // Not available in Insights
47
52
  total_positions_count: this.totalPositions
48
53
  };
49
54
  }
@@ -1,12 +1,9 @@
1
1
  /**
2
2
  * @fileoverview Core Metric (Pass 2)
3
- * REFACTORED: Buckets P&L status by User Profile.
4
- * - Pivots data to be User-Centric (User -> Winners/Losers).
5
- * - Removes sharding complexity (fits within 1MB via structure optimization).
3
+ * Clean: System automatically handles sharding (e.g. 20k users).
6
4
  */
7
5
  class AssetPnlStatus {
8
6
  constructor() {
9
- // Map<UserId, { winners: Set<String>, losers: Set<String> }>
10
7
  this.userStats = new Map();
11
8
  }
12
9
 
@@ -28,9 +25,8 @@ class AssetPnlStatus {
28
25
  "properties": {
29
26
  "by_user": {
30
27
  "type": "object",
31
- "description": "Map of User IDs to their winning/losing assets and sectors.",
32
28
  "patternProperties": {
33
- "^[0-9]+$": { // Matches User IDs (CIDs)
29
+ "^[0-9]+$": {
34
30
  "type": "object",
35
31
  "properties": {
36
32
  "winners": { "type": "array", "items": { "type": "string" } },
@@ -56,11 +52,9 @@ class AssetPnlStatus {
56
52
  const { mappings, user } = context;
57
53
  const userId = user.id;
58
54
 
59
- // 1. Get Positions using the standard extractor
60
55
  const positions = extract.getPositions(user.portfolio.today, user.type);
61
56
  if (!positions || positions.length === 0) return;
62
57
 
63
- // 2. Lazy init stats only if needed
64
58
  let stats = null;
65
59
 
66
60
  for (const pos of positions) {
@@ -68,7 +62,7 @@ class AssetPnlStatus {
68
62
  if (!instId) continue;
69
63
 
70
64
  const pnl = extract.getNetProfit(pos);
71
- if (pnl === 0) continue; // Ignore flat positions
65
+ if (pnl === 0) continue;
72
66
 
73
67
  const ticker = mappings.instrumentToTicker[instId];
74
68
  const sector = mappings.instrumentToSector[instId];
@@ -76,15 +70,11 @@ class AssetPnlStatus {
76
70
 
77
71
  if (ticker || sector) {
78
72
  if (!stats) stats = this._initUser(userId);
79
-
80
73
  if (ticker) {
81
- if (isWinner) stats.winners.add(ticker);
82
- else stats.losers.add(ticker);
74
+ if (isWinner) stats.winners.add(ticker); else stats.losers.add(ticker);
83
75
  }
84
-
85
76
  if (sector) {
86
- if (isWinner) stats.winners.add(sector);
87
- else stats.losers.add(sector);
77
+ if (isWinner) stats.winners.add(sector); else stats.losers.add(sector);
88
78
  }
89
79
  }
90
80
  }
@@ -94,7 +84,6 @@ class AssetPnlStatus {
94
84
  const byUser = {};
95
85
 
96
86
  for (const [userId, stats] of this.userStats) {
97
- // Only include users who actually have relevant P&L data
98
87
  if (stats.winners.size > 0 || stats.losers.size > 0) {
99
88
  byUser[userId] = {
100
89
  winners: Array.from(stats.winners),
@@ -103,12 +92,11 @@ class AssetPnlStatus {
103
92
  }
104
93
  }
105
94
 
95
+ // Return flat object. Orchestrator handles 1MB limit.
106
96
  return { by_user: byUser };
107
97
  }
108
98
 
109
- reset() {
110
- this.userStats.clear();
111
- }
99
+ reset() { this.userStats.clear(); }
112
100
  }
113
101
 
114
102
  module.exports = AssetPnlStatus;
@@ -1,74 +1,62 @@
1
- /**
2
- * @fileoverview Calculation (Pass 1) for daily bought vs. sold count.
3
- * REFACTORED: Uses INSIGHTS DATA as Single Source of Truth.
4
- * TYPE: META (Runs once against global data)
5
- */
6
1
  class InsightsDailyBoughtVsSoldCount {
7
- constructor() {
8
- this.results = {};
2
+ constructor() { this.results = {}; }
3
+
4
+ static getMetadata() {
5
+ return {
6
+ type: 'meta',
7
+ rootDataDependencies: ['insights'],
8
+ isHistorical: true,
9
+ userType: 'n/a',
10
+ category: 'core_metrics'
11
+ };
9
12
  }
10
-
11
- static getMetadata() {
12
- return {
13
- type: 'meta',
14
- rootDataDependencies: ['insights'], // explicit dependency on insights
15
- isHistorical: true,
16
- category: 'core_metrics'
17
- };
18
- }
19
-
13
+
20
14
  static getDependencies() { return []; }
21
-
15
+
22
16
  static getSchema() {
23
- const tickerSchema = {
24
- "type": "object",
25
- "properties": {
26
- "positions_bought": { "type": "number" },
27
- "positions_sold": { "type": "number" },
28
- "net_change": { "type": "number" }
29
- },
30
- "required": ["positions_bought", "positions_sold", "net_change"]
17
+ const tickerSchema = {
18
+ "type": "object",
19
+ "properties": {
20
+ "positions_bought": { "type": "number" },
21
+ "positions_sold": { "type": "number" },
22
+ "net_change": { "type": "number" }
23
+ },
24
+ "required": ["positions_bought", "positions_sold", "net_change"]
31
25
  };
32
26
  return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
33
27
  }
34
-
28
+
35
29
  process(context) {
36
- const { insights: insightsHelper } = context.math; // Maps to InsightsExtractor
37
- const insights = insightsHelper.getInsights(context);
30
+ const { insights: insightsHelper } = context.math;
31
+ const rawInsights = insightsHelper.getInsights(context);
38
32
  const { mappings } = context;
39
33
  const tickerMap = mappings.instrumentToTicker || {};
40
34
 
41
- if (!insights || !Array.isArray(insights)) return;
35
+ // FIX: Extract the 'today' array from the wrapper object
36
+ const insights = (rawInsights && Array.isArray(rawInsights.today))
37
+ ? rawInsights.today
38
+ : (Array.isArray(rawInsights) ? rawInsights : []);
39
+
40
+ if (insights.length === 0) return;
42
41
 
43
42
  for (const insight of insights) {
44
43
  const instId = insight.instrumentId;
45
44
  const ticker = tickerMap[instId] || `id_${instId}`;
46
-
47
45
  const netChange = insightsHelper.getNetOwnershipChange(insight);
48
-
49
- // Insights schema only provides Net Growth.
50
- // We cannot strictly separate Bought vs Sold.
51
- // Logic: If Net Positive -> Bought = Net, Sold = 0.
52
- // If Net Negative -> Bought = 0, Sold = Abs(Net).
53
46
  const bought = netChange > 0 ? netChange : 0;
54
47
  const sold = netChange < 0 ? Math.abs(netChange) : 0;
55
48
 
56
49
  if (bought > 0 || sold > 0) {
57
- this.results[ticker] = {
58
- positions_bought: bought,
59
- positions_sold: sold,
60
- net_change: netChange
50
+ this.results[ticker] = {
51
+ positions_bought: bought,
52
+ positions_sold: sold,
53
+ net_change: netChange
61
54
  };
62
55
  }
63
56
  }
64
57
  }
65
-
66
- async getResult() {
67
- return this.results;
68
- }
69
-
70
- reset() {
71
- this.results = {};
72
- }
58
+
59
+ async getResult() { return this.results; }
60
+ reset() { this.results = {}; }
73
61
  }
74
62
  module.exports = InsightsDailyBoughtVsSoldCount;
@@ -1,70 +1,62 @@
1
- /**
2
- * @fileoverview Calculation (Pass 1) for ownership delta (users added/lost per asset).
3
- * REFACTORED: Uses INSIGHTS DATA.
4
- * TYPE: META
5
- */
6
1
  class InsightsDailyOwnershipDelta {
7
- constructor() {
8
- this.results = {};
2
+ constructor() { this.results = {}; }
3
+
4
+ static getMetadata() {
5
+ return {
6
+ type: 'meta',
7
+ rootDataDependencies: ['insights'],
8
+ isHistorical: true,
9
+ userType: 'n/a',
10
+ category: 'core_metrics'
11
+ };
9
12
  }
10
-
11
- static getMetadata() {
12
- return {
13
- type: 'meta',
14
- rootDataDependencies: ['insights'],
15
- isHistorical: true,
16
- category: 'core_metrics'
17
- };
18
- }
19
-
13
+
20
14
  static getDependencies() { return []; }
21
-
15
+
22
16
  static getSchema() {
23
- const tickerSchema = {
24
- "type": "object",
25
- "properties": {
26
- "owners_added": { "type": "number" },
27
- "owners_removed": { "type": "number" },
28
- "net_ownership_change": { "type": "number" }
29
- },
30
- "required": ["owners_added", "owners_removed", "net_ownership_change"]
17
+ const tickerSchema = {
18
+ "type": "object",
19
+ "properties": {
20
+ "owners_added": { "type": "number" },
21
+ "owners_removed": { "type": "number" },
22
+ "net_ownership_change": { "type": "number" }
23
+ },
24
+ "required": ["owners_added", "owners_removed", "net_ownership_change"]
31
25
  };
32
26
  return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
33
27
  }
34
-
28
+
35
29
  process(context) {
36
30
  const { insights: insightsHelper } = context.math;
37
- const insights = insightsHelper.getInsights(context);
31
+ const rawInsights = insightsHelper.getInsights(context);
38
32
  const { mappings } = context;
39
33
  const tickerMap = mappings.instrumentToTicker || {};
40
34
 
41
- if (!insights) return;
35
+ // FIX: Extract the 'today' array from the wrapper object
36
+ const insights = (rawInsights && Array.isArray(rawInsights.today))
37
+ ? rawInsights.today
38
+ : (Array.isArray(rawInsights) ? rawInsights : []);
39
+
40
+ if (insights.length === 0) return;
42
41
 
43
42
  for (const insight of insights) {
44
43
  const netChange = insightsHelper.getNetOwnershipChange(insight);
45
44
  if (netChange === 0) continue;
46
-
45
+
47
46
  const instId = insight.instrumentId;
48
47
  const ticker = tickerMap[instId] || `id_${instId}`;
49
-
50
- // Approximate added/removed based on Net Change logic
51
48
  const added = netChange > 0 ? netChange : 0;
52
49
  const removed = netChange < 0 ? Math.abs(netChange) : 0;
53
50
 
54
- this.results[ticker] = {
55
- owners_added: added,
56
- owners_removed: removed,
57
- net_ownership_change: netChange
51
+ this.results[ticker] = {
52
+ owners_added: added,
53
+ owners_removed: removed,
54
+ net_ownership_change: netChange
58
55
  };
59
56
  }
60
57
  }
61
-
62
- async getResult() {
63
- return this.results;
64
- }
65
-
66
- reset() {
67
- this.results = {};
68
- }
58
+
59
+ async getResult() { return this.results; }
60
+ reset() { this.results = {}; }
69
61
  }
70
62
  module.exports = InsightsDailyOwnershipDelta;
@@ -1,68 +1,62 @@
1
- /**
2
- * @fileoverview Calculation (Pass 1) for sentiment per stock.
3
- * REFACTORED: Uses INSIGHTS DATA.
4
- * TYPE: META
5
- */
6
1
  class InsightsSentimentPerStock {
7
- constructor() {
8
- this.results = {};
9
- }
10
-
2
+ constructor() { this.results = {}; }
3
+
11
4
  static getSchema() {
12
- const tickerSchema = {
13
- "type": "object",
14
- "properties": {
15
- "long_count": { "type": "number" },
16
- "short_count": { "type": "number" },
17
- "sentiment_ratio": { "type": ["number", "null"] }
18
- },
19
- "required": ["long_count", "short_count", "sentiment_ratio"]
5
+ const tickerSchema = {
6
+ "type": "object",
7
+ "properties": {
8
+ "long_count": { "type": "number" },
9
+ "short_count": { "type": "number" },
10
+ "sentiment_ratio": { "type": ["number", "null"] }
11
+ },
12
+ "required": ["long_count", "short_count", "sentiment_ratio"]
20
13
  };
21
14
  return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
22
15
  }
23
-
24
- static getMetadata() {
25
- return {
26
- type: 'meta',
27
- rootDataDependencies: ['insights'],
28
- isHistorical: false,
29
- category: 'core_sentiment'
30
- };
16
+
17
+ static getMetadata() {
18
+ return {
19
+ type: 'meta',
20
+ rootDataDependencies: ['insights'],
21
+ isHistorical: false,
22
+ userType: 'n/a',
23
+ category: 'core_sentiment'
24
+ };
31
25
  }
32
-
26
+
33
27
  static getDependencies() { return []; }
34
-
28
+
35
29
  process(context) {
36
30
  const { insights: insightsHelper } = context.math;
37
- const insights = insightsHelper.getInsights(context);
31
+ const rawInsights = insightsHelper.getInsights(context);
38
32
  const { mappings } = context;
39
33
  const tickerMap = mappings.instrumentToTicker || {};
40
34
 
41
- if (!insights) return;
35
+ // FIX: Extract the 'today' array from the wrapper object
36
+ const insights = (rawInsights && Array.isArray(rawInsights.today))
37
+ ? rawInsights.today
38
+ : (Array.isArray(rawInsights) ? rawInsights : []);
39
+
40
+ if (insights.length === 0) return;
42
41
 
43
42
  for (const insight of insights) {
44
43
  const longCount = insightsHelper.getLongCount(insight);
45
44
  const shortCount = insightsHelper.getShortCount(insight);
46
-
45
+
47
46
  if (longCount === 0 && shortCount === 0) continue;
48
-
47
+
49
48
  const instId = insight.instrumentId;
50
49
  const ticker = tickerMap[instId] || `id_${instId}`;
51
50
 
52
- this.results[ticker] = {
53
- long_count: longCount,
54
- short_count: shortCount,
55
- sentiment_ratio: (shortCount > 0) ? (longCount / shortCount) : null
51
+ this.results[ticker] = {
52
+ long_count: longCount,
53
+ short_count: shortCount,
54
+ sentiment_ratio: (shortCount > 0) ? (longCount / shortCount) : null
56
55
  };
57
56
  }
58
57
  }
59
-
60
- async getResult() {
61
- return this.results;
62
- }
63
-
64
- reset() {
65
- this.results = {};
66
- }
58
+
59
+ async getResult() { return this.results; }
60
+ reset() { this.results = {}; }
67
61
  }
68
62
  module.exports = InsightsSentimentPerStock;
@@ -13,6 +13,7 @@ class InsightsTotalLongPerSector {
13
13
  type: 'meta',
14
14
  rootDataDependencies: ['insights'],
15
15
  isHistorical: false,
16
+ userType: 'n/a',
16
17
  category: 'core_sentiment'
17
18
  };
18
19
  }
@@ -33,11 +34,16 @@ class InsightsTotalLongPerSector {
33
34
 
34
35
  process(context) {
35
36
  const { insights: insightsHelper } = context.math;
36
- const insights = insightsHelper.getInsights(context);
37
+ const rawInsights = insightsHelper.getInsights(context);
37
38
  const { mappings } = context;
38
39
  const sectorMap = mappings.instrumentToSector || {};
39
40
 
40
- if (!insights) return;
41
+ // FIX: Extract the 'today' array from the wrapper object
42
+ const insights = (rawInsights && Array.isArray(rawInsights.today))
43
+ ? rawInsights.today
44
+ : (Array.isArray(rawInsights) ? rawInsights : []);
45
+
46
+ if (insights.length === 0) return;
41
47
 
42
48
  for (const insight of insights) {
43
49
  const longCount = insightsHelper.getLongCount(insight);
@@ -58,7 +64,6 @@ class InsightsTotalLongPerSector {
58
64
  for (const [sector, data] of this.sectorData.entries()) {
59
65
  if (data.count > 0) {
60
66
  result[sector] = {
61
- total_long_exposure_weight: 0, // Not available
62
67
  total_positions_count: data.count
63
68
  };
64
69
  }
@@ -1,49 +1,43 @@
1
- /**
2
- * @fileoverview Calculation (Pass 1) for total positions count.
3
- * REFACTORED: Uses INSIGHTS DATA.
4
- * TYPE: META
5
- */
6
1
  class InsightsTotalPositionsHeld {
7
- constructor() {
8
- this.totalPositions = 0;
2
+ constructor() { this.totalPositions = 0; }
3
+
4
+ static getMetadata() {
5
+ return {
6
+ type: 'meta',
7
+ rootDataDependencies: ['insights'],
8
+ isHistorical: false,
9
+ userType: 'n/a',
10
+ category: 'Global-Platform-Metrics'
11
+ };
9
12
  }
10
-
11
- static getMetadata() {
12
- return {
13
- type: 'meta',
14
- rootDataDependencies: ['insights'],
15
- isHistorical: false,
16
- category: 'Global-Platform-Metrics'
17
- };
18
- }
19
-
13
+
20
14
  static getDependencies() { return []; }
21
-
22
- static getSchema() {
23
- return {
24
- "type": "object",
25
- "properties": {
26
- "total_positions_count": { "type": "number" }
27
- },
28
- "required": ["total_positions_count"]
29
- };
15
+
16
+ static getSchema() {
17
+ return {
18
+ "type": "object",
19
+ "properties": { "total_positions_count": { "type": "number" } },
20
+ "required": ["total_positions_count"]
21
+ };
30
22
  }
31
-
23
+
32
24
  process(context) {
33
25
  const { insights: insightsHelper } = context.math;
34
- const insights = insightsHelper.getInsights(context);
26
+ const rawInsights = insightsHelper.getInsights(context);
35
27
 
36
- if (!insights) return;
28
+ // FIX: Extract the 'today' array from the wrapper object
29
+ const insights = (rawInsights && Array.isArray(rawInsights.today))
30
+ ? rawInsights.today
31
+ : (Array.isArray(rawInsights) ? rawInsights : []);
32
+
33
+ if (insights.length === 0) return;
37
34
 
38
35
  for (const insight of insights) {
39
36
  this.totalPositions += insightsHelper.getTotalOwners(insight);
40
37
  }
41
38
  }
42
-
43
- getResult() {
44
- return { total_positions_count: this.totalPositions };
45
- }
46
-
39
+
40
+ getResult() { return { total_positions_count: this.totalPositions }; }
47
41
  reset() { this.totalPositions = 0; }
48
42
  }
49
43
  module.exports = InsightsTotalPositionsHeld;
@@ -8,7 +8,10 @@ class CostBasisDensity {
8
8
  static getMetadata() {
9
9
  return {
10
10
  type: 'meta', // Runs ONCE per day
11
- dependencies: ['asset-cost-basis-profile']
11
+ dependencies: ['asset-cost-basis-profile'],
12
+ userType: 'n/a', // FIXED: Added missing field
13
+ isHistorical: false, // FIXED: Explicitly defined
14
+ category: 'ghost_book'
12
15
  };
13
16
  }
14
17
 
@@ -34,37 +37,30 @@ class CostBasisDensity {
34
37
  const { computed, math } = context;
35
38
  const { signals: SignalPrimitives } = math;
36
39
 
37
- // 1. Get Union of Tickers (Safe Iteration)
38
40
  const tickers = SignalPrimitives.getUnionKeys(computed, ['asset-cost-basis-profile']);
39
41
 
40
42
  for (const ticker of tickers) {
41
- // 2. Safe Data Access
42
43
  const data = computed['asset-cost-basis-profile'][ticker];
43
44
 
44
- // Check for 'profile' specifically as it contains the density curve
45
45
  if (!data || !Array.isArray(data.profile) || data.profile.length < 3) {
46
46
  continue;
47
47
  }
48
48
 
49
- const profile = data.profile; // Array of {price, density}
49
+ const profile = data.profile;
50
50
  const currentPrice = data.current_price;
51
51
 
52
52
  const resistance = [];
53
53
  const support = [];
54
54
  let maxDensity = 0;
55
55
 
56
- // 3. Peak Detection Algorithm
57
- // Iterate through the KDE curve to find local maxima
58
56
  for (let i = 1; i < profile.length - 1; i++) {
59
57
  const prev = profile[i-1].density;
60
58
  const curr = profile[i].density;
61
59
  const next = profile[i+1].density;
62
60
 
63
- // Simple Peak Check
64
61
  if (curr > prev && curr > next) {
65
62
  const priceVal = Number(profile[i].price.toFixed(2));
66
63
 
67
- // Classify as Resistance (Overhead Supply) or Support (Underlying Demand)
68
64
  if (profile[i].price > currentPrice) {
69
65
  resistance.push(priceVal);
70
66
  } else {
@@ -75,20 +71,12 @@ class CostBasisDensity {
75
71
  }
76
72
  }
77
73
 
78
- // 4. Sort Walls by proximity to current price?
79
- // Currently slice(0,3) takes the first found, which are lower prices in a sorted KDE.
80
- // Support: We want HIGHEST prices below current (closest to current).
81
- // Resistance: We want LOWEST prices above current (closest to current).
82
-
83
- // Sort Descending (Highest Price First)
84
74
  support.sort((a, b) => b - a);
85
-
86
- // Sort Ascending (Lowest Price First)
87
75
  resistance.sort((a, b) => a - b);
88
76
 
89
77
  this.walls[ticker] = {
90
- resistance_zones: resistance.slice(0, 3), // Closest 3 resistance levels
91
- support_zones: support.slice(0, 3), // Closest 3 support levels
78
+ resistance_zones: resistance.slice(0, 3),
79
+ support_zones: support.slice(0, 3),
92
80
  nearest_wall_strength: Number(maxDensity.toFixed(4))
93
81
  };
94
82
  }
@@ -4,7 +4,10 @@ class LiquidityVacuum {
4
4
  static getMetadata() {
5
5
  return {
6
6
  type: 'meta',
7
- dependencies: ['asset-cost-basis-profile']
7
+ dependencies: ['asset-cost-basis-profile'],
8
+ userType: 'n/a', // FIXED: Added missing field
9
+ isHistorical: false, // FIXED: Explicitly defined
10
+ category: 'ghost_book'
8
11
  };
9
12
  }
10
13
 
@@ -22,16 +25,12 @@ class LiquidityVacuum {
22
25
 
23
26
  for (const ticker of tickers) {
24
27
  const data = computed['asset-cost-basis-profile'][ticker];
25
- // BUG FIX: Ensure data and profile exist before accessing length/integration
26
28
  if (!data || !data.profile || !Array.isArray(data.profile)) continue;
27
29
 
28
30
  const current = data.current_price;
29
31
  const totalInv = data.total_inventory_weight;
30
32
 
31
- // Integrate Danger Zone (0% to -5% drop)
32
33
  const riskVol = distribution.integrateProfile(data.profile, current * 0.95, current);
33
-
34
- // Ratio: At-Risk Inventory / Total Inventory
35
34
  const ratio = (totalInv > 0) ? (riskVol / totalInv) * 10 : 0;
36
35
 
37
36
  let status = "STABLE";
@@ -10,6 +10,8 @@ class RetailGammaExposure {
10
10
  type: 'meta',
11
11
  dependencies: ['skilled-cohort-flow', 'instrument-price-change-1d'],
12
12
  isHistorical: true, // Requires t-1, t-2... for rolling regression
13
+ userType: 'n/a', // FIXED: Added missing field
14
+ category: 'ghost_book'
13
15
  };
14
16
  }
15
17
 
@@ -33,20 +35,16 @@ class RetailGammaExposure {
33
35
 
34
36
  process(context) {
35
37
  const { computed, previousComputed, math } = context;
36
- // FIX: Destructure correct keys from context.math
37
- // 'signals' maps to SignalPrimitives, 'distribution' maps to DistributionAnalytics
38
38
  const { signals, distribution } = math;
39
39
 
40
40
  const tickers = signals.getUnionKeys(computed, ['skilled-cohort-flow']);
41
41
 
42
42
  for (const ticker of tickers) {
43
- // 1. Inputs
44
43
  const flow = signals.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
45
44
  const priceChange = signals.getMetric(computed, 'instrument-price-change-1d', ticker, 'change_1d_pct', 0);
46
45
 
47
- // 2. State Management (Rolling Window)
48
46
  const prevResult = signals.getPreviousState(previousComputed, 'retail-gamma-exposure', ticker);
49
- const bufferSize = 14; // 2-week regression window
47
+ const bufferSize = 14;
50
48
 
51
49
  let flowBuffer = prevResult?._state?.flow_buffer || [];
52
50
  let priceBuffer = prevResult?._state?.price_buffer || [];
@@ -59,14 +57,12 @@ class RetailGammaExposure {
59
57
  priceBuffer.shift();
60
58
  }
61
59
 
62
- // 3. Regression: Flow ~ Alpha + Beta * PriceChange
63
60
  const regression = distribution.linearRegression(priceBuffer, flowBuffer);
64
61
  const beta = regression.slope;
65
62
 
66
- // 4. Regime Logic
67
63
  let regime = "NEUTRAL";
68
- if (beta > 0.5) regime = "ACCELERANT"; // Volatility Explosion Watch
69
- else if (beta < -0.5) regime = "STABILIZER"; // Chop Zone
64
+ if (beta > 0.5) regime = "ACCELERANT";
65
+ else if (beta < -0.5) regime = "STABILIZER";
70
66
 
71
67
  this.gammaResults[ticker] = {
72
68
  gamma_beta: Number(beta.toFixed(4)),
@@ -1,18 +1,18 @@
1
1
  /**
2
2
  * @fileoverview Cognitive Dissonance Arbitrage (CDA) v2.2
3
- * REFACTORED: Adheres to System Architecture and Schema v1.
3
+ * Clean: System automatically handles sharding.
4
4
  */
5
5
  class CognitiveDissonance {
6
6
  constructor() {
7
7
  this.cdaResults = {};
8
- this.alpha = 2 / (20 + 1); // EMA Alpha
8
+ this.alpha = 2 / (20 + 1);
9
9
  }
10
10
 
11
11
  static getMetadata() {
12
12
  return {
13
- type: 'meta', // Runs after standard calculations
13
+ type: 'meta',
14
14
  rootDataDependencies: [],
15
- isHistorical: true, // Requires t-1 state
15
+ isHistorical: true,
16
16
  userType: 'aggregate'
17
17
  };
18
18
  }
@@ -22,7 +22,6 @@ class CognitiveDissonance {
22
22
  }
23
23
 
24
24
  static getSchema() {
25
- // Schema remains strictly compliant with user definition
26
25
  const metricSchema = {
27
26
  "type": "object",
28
27
  "properties": {
@@ -31,7 +30,7 @@ class CognitiveDissonance {
31
30
  "z_sentiment": { "type": "number" },
32
31
  "z_flow": { "type": "number" },
33
32
  "price_confirmation": { "type": "boolean" },
34
- "_state": { "type": "object" } // Opaque state object
33
+ "_state": { "type": "object" }
35
34
  }
36
35
  };
37
36
  return { "type": "object", "patternProperties": { "^.*$": metricSchema } };
@@ -44,28 +43,24 @@ class CognitiveDissonance {
44
43
  const tickers = SignalPrimitives.getUnionKeys(computed, CognitiveDissonance.getDependencies());
45
44
 
46
45
  for (const ticker of tickers) {
47
- // 1. Get Metrics (Safe Access)
48
- // MAP: 'social-topic-sentiment-matrix' uses 'net_sentiment' NOT 'sentiment_score'
49
46
  const rawSentiment = SignalPrimitives.getMetric(computed, 'social-topic-sentiment-matrix', ticker, 'net_sentiment', 0);
50
47
  const rawFlow = SignalPrimitives.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
51
- const priceChange = SignalPrimitives.getMetric(computed, 'instrument-price-change-1d', ticker, 'change_1d_pct', 0); // Map to correct field
48
+ const priceChange = SignalPrimitives.getMetric(computed, 'instrument-price-change-1d', ticker, 'change_1d_pct', 0);
52
49
 
53
- // 2. Get Previous State
50
+ // Transparent State Access
51
+ // The system has already re-assembled previousComputed from shards if necessary.
54
52
  const prevResult = SignalPrimitives.getPreviousState(previousComputed, 'cognitive-dissonance', ticker);
55
53
  const prevState = prevResult ? prevResult._state : { sent_mean: 0, sent_var: 1, flow_mean: 0, flow_var: 1 };
56
54
 
57
- // 3. Update Statistics (Math Layer)
58
55
  const sentStats = TimeSeries.updateEMAState(rawSentiment, { mean: prevState.sent_mean, variance: prevState.sent_var }, this.alpha);
59
56
  const flowStats = TimeSeries.updateEMAState(rawFlow, { mean: prevState.flow_mean, variance: prevState.flow_var }, this.alpha);
60
57
 
61
58
  const sentStdDev = Math.sqrt(sentStats.variance);
62
59
  const flowStdDev = Math.sqrt(flowStats.variance);
63
60
 
64
- // 4. Compute Z-Scores
65
61
  const zSentiment = (sentStdDev > 0.001) ? (rawSentiment - sentStats.mean) / sentStdDev : 0;
66
62
  const zFlow = (flowStdDev > 0.001) ? (rawFlow - flowStats.mean) / flowStdDev : 0;
67
63
 
68
- // 5. Logic (Voice vs Hands)
69
64
  const interaction = zSentiment * zFlow;
70
65
  let cdaScore = 0;
71
66
  let regime = "NEUTRAL";
@@ -76,8 +71,7 @@ class CognitiveDissonance {
76
71
  const activeHands = Math.abs(zFlow) > 0.5;
77
72
 
78
73
  if (disagree && loudVoice && activeHands) {
79
- cdaScore = -interaction; // Positive score = Bearish Dissonance (Euphoria + Selling)
80
-
74
+ cdaScore = -interaction;
81
75
  const priceAgreesWithSentiment = (Math.sign(priceChange) === Math.sign(zSentiment));
82
76
  const priceIsFlat = Math.abs(priceChange) < 0.5;
83
77
 
@@ -106,7 +100,7 @@ class CognitiveDissonance {
106
100
  }
107
101
  }
108
102
 
109
- getResult() { return this.cdaResults; }
103
+ async getResult() { return this.cdaResults; }
110
104
  reset() { this.cdaResults = {}; }
111
105
  }
112
106
  module.exports = CognitiveDissonance;
@@ -1,7 +1,6 @@
1
1
  /**
2
- * @fileoverview Mimetic Latency Oscillator (MLO) v2.2
3
- * Measures the lag between "Smart Money" flow and "Herd" conviction.
4
- * Self-healing state: Warms up over 15-30 days automatically.
2
+ * @fileoverview Mimetic Latency Oscillator (MLO) v2.3
3
+ * FIXED: Safe state access to prevent 'undefined' property errors.
5
4
  */
6
5
  class MimeticLatencyOscillator {
7
6
  constructor() {
@@ -47,25 +46,24 @@ class MimeticLatencyOscillator {
47
46
  const rawFlow = SignalPrimitives.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
48
47
  const rawHerd = SignalPrimitives.getMetric(computed, 'herd-consensus-score', ticker, 'herd_conviction_score', 0);
49
48
 
50
- // 2. Restore State (Handle Cold Start)
49
+ // 2. Restore State (FIX: Safe Access)
51
50
  const prevResult = SignalPrimitives.getPreviousState(previousComputed, 'mimetic-latency', ticker);
52
- const prevState = prevResult ? prevResult._state : { flow_buffer: [], herd_buffer: [], last_flow: 0, last_herd: 0 };
51
+ const prevState = prevResult ? prevResult._state : null;
53
52
 
54
- const prevFlow = (prevState.last_flow !== undefined) ? prevState.last_flow : 0;
55
- const prevHerd = (prevState.last_herd !== undefined) ? prevState.last_herd : 0;
53
+ // FIX: Check if prevState exists before accessing properties
54
+ const prevFlow = (prevState && prevState.last_flow !== undefined) ? prevState.last_flow : 0;
55
+ const prevHerd = (prevState && prevState.last_herd !== undefined) ? prevState.last_herd : 0;
56
+ const flowBuffer = (prevState && Array.isArray(prevState.flow_buffer)) ? [...prevState.flow_buffer] : [];
57
+ const herdBuffer = (prevState && Array.isArray(prevState.herd_buffer)) ? [...prevState.herd_buffer] : [];
56
58
 
57
59
  // 3. Calculate Detrended Delta
58
60
  const flowDelta = rawFlow - prevFlow;
59
61
  const herdDelta = rawHerd - prevHerd;
60
62
 
61
63
  // 4. Update Buffers
62
- let flowBuffer = [...(prevState.flow_buffer || [])];
63
- let herdBuffer = [...(prevState.herd_buffer || [])];
64
-
65
64
  flowBuffer.push(flowDelta);
66
65
  herdBuffer.push(herdDelta);
67
66
 
68
- // Cap memory usage
69
67
  if (flowBuffer.length > this.windowSize) flowBuffer.shift();
70
68
  if (herdBuffer.length > this.windowSize) herdBuffer.shift();
71
69
 
@@ -74,7 +72,6 @@ class MimeticLatencyOscillator {
74
72
  let bestLag = 0;
75
73
  let regime = "WARM_UP";
76
74
 
77
- // Only compute if we have statistical significance (>= 15 samples)
78
75
  if (flowBuffer.length >= 15) {
79
76
  for (let k = 0; k <= this.maxLag; k++) {
80
77
  const len = flowBuffer.length;
@@ -91,7 +88,6 @@ class MimeticLatencyOscillator {
91
88
  }
92
89
  }
93
90
 
94
- // 6. Regime Classification
95
91
  if (maxCorr > 0.3) {
96
92
  if (bestLag >= 3) regime = "EARLY_ALPHA";
97
93
  else if (bestLag >= 1) regime = "MARKUP";
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiden-shared-calculations-unified",
3
- "version": "1.0.97",
3
+ "version": "1.0.99",
4
4
  "description": "Shared calculation modules for the BullTrackers Computation System.",
5
5
  "main": "index.js",
6
6
  "files": [