aiden-shared-calculations-unified 1.0.108 → 1.0.110

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 (24) hide show
  1. package/calculations/core/insights-daily-bought-vs-sold-count.js +20 -15
  2. package/calculations/core/insights-daily-ownership-delta.js +12 -10
  3. package/calculations/core/instrument-price-change-1d.js +16 -31
  4. package/calculations/core/instrument-price-momentum-20d.js +16 -26
  5. package/calculations/core/ownership-vs-performance-ytd.js +15 -52
  6. package/calculations/core/ownership-vs-volatility.js +27 -36
  7. package/calculations/core/platform-daily-bought-vs-sold-count.js +28 -26
  8. package/calculations/core/platform-daily-ownership-delta.js +28 -31
  9. package/calculations/core/price-metrics.js +15 -54
  10. package/calculations/core/short-interest-growth.js +6 -13
  11. package/calculations/core/trending-ownership-momentum.js +16 -28
  12. package/calculations/core/user-history-reconstructor.js +48 -49
  13. package/calculations/gauss/cohort-capital-flow.js +34 -71
  14. package/calculations/gauss/cohort-definer.js +61 -142
  15. package/calculations/gem/cohort-momentum-state.js +27 -77
  16. package/calculations/gem/skilled-cohort-flow.js +36 -114
  17. package/calculations/gem/unskilled-cohort-flow.js +36 -112
  18. package/calculations/ghost-book/retail-gamma-exposure.js +14 -61
  19. package/calculations/helix/herd-consensus-score.js +27 -90
  20. package/calculations/helix/winner-loser-flow.js +21 -90
  21. package/calculations/predicative-alpha/cognitive-dissonance.js +25 -91
  22. package/calculations/predicative-alpha/diamond-hand-fracture.js +17 -72
  23. package/calculations/predicative-alpha/mimetic-latency.js +21 -100
  24. package/package.json +1 -1
@@ -1,108 +1,39 @@
1
- /**
2
- * @fileoverview HELIX Product Line (Pass 2)
3
- * REFACTORED: Uses context.math.extract.
4
- */
5
1
  class WinnerLoserFlow {
6
- constructor() {
7
- this.assetFlows = new Map();
8
- this.tickerMap = null;
9
- }
10
-
11
- static getMetadata() {
12
- return {
13
- type: 'standard',
14
- rootDataDependencies: ['portfolio'],
15
- isHistorical: true,
16
- userType: 'all',
17
- category: 'helix'
18
- };
19
- }s
20
-
2
+ constructor() { this.assetFlows = new Map(); this.tickerMap = null; }
3
+ static getMetadata() { return { type: 'standard', rootDataDependencies: ['portfolio'], isHistorical: true, userType: 'all', category: 'helix' }; }
21
4
  static getDependencies() { return []; }
22
5
 
23
6
  static getSchema() {
24
- const tickerSchema = {
25
- "type": "object",
26
- "properties": {
27
- "net_winner_flow": { "type": "number" },
28
- "net_loser_flow": { "type": "number" },
29
- "raw_counts": { "type": "object" }
30
- },
31
- "required": ["net_winner_flow", "net_loser_flow", "raw_counts"]
32
- };
33
- return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
34
- }
35
-
36
- _getHoldings(positions, extract) {
37
- const map = new Map();
38
- for (const pos of positions) {
39
- const id = extract.getInstrumentId(pos);
40
- if (id) map.set(id, { pnl: extract.getNetProfit(pos) });
41
- }
42
- return map;
43
- }
44
-
45
- _initAsset(ticker) {
46
- if (!this.assetFlows.has(ticker)) {
47
- this.assetFlows.set(ticker, { winners_joined: 0, winners_left: 0, losers_joined: 0, losers_left: 0 });
48
- }
7
+ const s = { "type": "object", "properties": { "net_winner_flow": { "type": ["number", "null"] }, "net_loser_flow": { "type": ["number", "null"] }, "total_winners_today": { "type": "number" }, "total_losers_today": { "type": "number" } }, "required": ["net_winner_flow", "net_loser_flow", "total_winners_today", "total_losers_today"] };
8
+ return { "type": "object", "patternProperties": { "^.*$": s } };
49
9
  }
50
10
 
51
11
  process(context) {
52
- const { user, mappings, math } = context;
53
- const { extract } = math;
12
+ const { user, mappings, math } = context; const { extract } = math;
54
13
  if (!this.tickerMap) this.tickerMap = mappings.instrumentToTicker;
55
-
56
- const yPos = extract.getPositions(user.portfolio.yesterday, user.type);
57
14
  const tPos = extract.getPositions(user.portfolio.today, user.type);
58
-
59
- const yHoldings = this._getHoldings(yPos, extract);
60
- const tHoldings = this._getHoldings(tPos, extract);
61
-
62
- const allIds = new Set([...yHoldings.keys(), ...tHoldings.keys()]);
63
-
64
- for (const instId of allIds) {
65
- const ticker = this.tickerMap[instId];
66
- if (!ticker) continue;
67
-
68
- const tPnl = tHoldings.get(instId)?.pnl || 0;
69
- const isWinner = tPnl > 0;
70
- const isLoser = tPnl < 0;
71
- if (!isWinner && !isLoser) continue;
72
-
73
- const heldYesterday = yHoldings.has(instId);
74
- const holdsToday = tHoldings.has(instId);
75
- if (heldYesterday === holdsToday) continue;
76
-
77
- this._initAsset(ticker);
78
- const stats = this.assetFlows.get(ticker);
79
-
80
- if (isWinner) {
81
- if (holdsToday && !heldYesterday) stats.winners_joined++;
82
- if (!holdsToday && heldYesterday) stats.winners_left++;
83
- }
84
- if (isLoser) {
85
- if (holdsToday && !heldYesterday) stats.losers_joined++;
86
- if (!holdsToday && heldYesterday) stats.losers_left++;
15
+ const yPos = user.portfolio.yesterday ? extract.getPositions(user.portfolio.yesterday, user.type) : [];
16
+ const yH = new Map(yPos.map(p => [extract.getInstrumentId(p), extract.getNetProfit(p)]));
17
+ const tH = new Map(tPos.map(p => [extract.getInstrumentId(p), extract.getNetProfit(p)]));
18
+ const ids = new Set([...yH.keys(), ...tH.keys()]);
19
+ for (const id of ids) {
20
+ const tick = this.tickerMap[id]; if (!tick) continue;
21
+ if (!this.assetFlows.has(tick)) this.assetFlows.set(tick, { wJ: 0, wL: 0, lJ: 0, lL: 0, wT: 0, lT: 0, hasY: !!user.portfolio.yesterday });
22
+ const s = this.assetFlows.get(tick), tPnl = tH.get(id), yPnl = yH.get(id);
23
+ if (tH.has(id)) { if (tPnl > 0) s.wT++; if (tPnl < 0) s.lT++; }
24
+ if (user.portfolio.yesterday) {
25
+ if (tH.has(id) && !yH.has(id)) { if (tPnl > 0) s.wJ++; if (tPnl < 0) s.lJ++; }
26
+ if (!tH.has(id) && yH.has(id)) { if (yPnl > 0) s.wL++; if (yPnl < 0) s.lL++; }
87
27
  }
88
28
  }
89
29
  }
90
30
 
91
31
  async getResult() {
92
- const result = {};
93
- for (const [ticker, data] of this.assetFlows.entries()) {
94
- result[ticker] = {
95
- net_winner_flow: data.winners_joined - data.winners_left,
96
- net_loser_flow: data.losers_joined - data.losers_left,
97
- raw_counts: data
98
- };
32
+ const res = {}; for (const [tick, d] of this.assetFlows.entries()) {
33
+ res[tick] = { net_winner_flow: d.hasY ? d.wJ - d.wL : null, net_loser_flow: d.hasY ? d.lJ - d.lL : null, total_winners_today: d.wT, total_losers_today: d.lT };
99
34
  }
100
- return result;
101
- }
102
-
103
- reset() {
104
- this.assetFlows.clear();
105
- this.tickerMap = null;
35
+ return res;
106
36
  }
37
+ reset() { this.assetFlows.clear(); this.tickerMap = null; }
107
38
  }
108
39
  module.exports = WinnerLoserFlow;
@@ -1,105 +1,39 @@
1
- /**
2
- * @fileoverview Cognitive Dissonance Arbitrage (CDA) v2.2
3
- * Clean: System automatically handles sharding.
4
- */
5
1
  class CognitiveDissonance {
6
- constructor() {
7
- this.cdaResults = {};
8
- this.alpha = 2 / (20 + 1);
9
- }
10
-
11
- static getMetadata() {
12
- return {
13
- type: 'meta',
14
- rootDataDependencies: [],
15
- isHistorical: true,
16
- userType: 'aggregate'
17
- };
18
- }
19
-
20
- static getDependencies() {
21
- return ['social-topic-sentiment-matrix', 'skilled-cohort-flow', 'instrument-price-change-1d'];
22
- }
2
+ constructor() { this.cdaResults = {}; this.alpha = 2 / (20 + 1); }
3
+ static getMetadata() { return { type: 'meta', rootDataDependencies: [], isHistorical: true, userType: 'aggregate' }; }
4
+ static getDependencies() { return ['social-topic-sentiment-matrix', 'skilled-cohort-flow', 'instrument-price-change-1d']; }
23
5
 
24
6
  static getSchema() {
25
- const metricSchema = {
26
- "type": "object",
27
- "properties": {
28
- "cda_score": { "type": "number" },
29
- "regime": { "type": "string" },
30
- "z_sentiment": { "type": "number" },
31
- "z_flow": { "type": "number" },
32
- "price_confirmation": { "type": "boolean" },
33
- "_state": { "type": "object" }
34
- }
35
- };
36
- return { "type": "object", "patternProperties": { "^.*$": metricSchema } };
7
+ return { "type": "object", "patternProperties": { "^.*$": { "type": "object", "properties": { "cda_score": { "type": ["number", "null"] }, "regime": { "type": "string" }, "_state": { "type": "object" } } } } };
37
8
  }
38
9
 
39
10
  process(context) {
40
11
  const { computed, previousComputed, math } = context;
41
- const { signals: SignalPrimitives, TimeSeries } = math;
42
-
43
- const tickers = SignalPrimitives.getUnionKeys(computed, CognitiveDissonance.getDependencies());
44
-
12
+ const { signals, TimeSeries } = math;
13
+ const tickers = signals.getUnionKeys(computed, CognitiveDissonance.getDependencies());
45
14
  for (const ticker of tickers) {
46
- const rawSentiment = SignalPrimitives.getMetric(computed, 'social-topic-sentiment-matrix', ticker, 'net_sentiment', 0);
47
- const rawFlow = SignalPrimitives.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
48
- const priceChange = SignalPrimitives.getMetric(computed, 'instrument-price-change-1d', ticker, 'change_1d_pct', 0);
49
-
50
- // Transparent State Access
51
- // The system has already re-assembled previousComputed from shards if necessary.
52
- const prevResult = SignalPrimitives.getPreviousState(previousComputed, 'cognitive-dissonance', ticker);
53
- const prevState = prevResult ? prevResult._state : { sent_mean: 0, sent_var: 1, flow_mean: 0, flow_var: 1 };
54
-
55
- const sentStats = TimeSeries.updateEMAState(rawSentiment, { mean: prevState.sent_mean, variance: prevState.sent_var }, this.alpha);
56
- const flowStats = TimeSeries.updateEMAState(rawFlow, { mean: prevState.flow_mean, variance: prevState.flow_var }, this.alpha);
57
-
58
- const sentStdDev = Math.sqrt(sentStats.variance);
59
- const flowStdDev = Math.sqrt(flowStats.variance);
60
-
61
- const zSentiment = (sentStdDev > 0.001) ? (rawSentiment - sentStats.mean) / sentStdDev : 0;
62
- const zFlow = (flowStdDev > 0.001) ? (rawFlow - flowStats.mean) / flowStdDev : 0;
63
-
64
- const interaction = zSentiment * zFlow;
65
- let cdaScore = 0;
66
- let regime = "NEUTRAL";
67
- let priceConfirmation = false;
68
-
69
- const disagree = (Math.sign(zSentiment) !== Math.sign(zFlow));
70
- const loudVoice = Math.abs(zSentiment) > 1.65;
71
- const activeHands = Math.abs(zFlow) > 0.5;
72
-
73
- if (disagree && loudVoice && activeHands) {
74
- cdaScore = -interaction;
75
- const priceAgreesWithSentiment = (Math.sign(priceChange) === Math.sign(zSentiment));
76
- const priceIsFlat = Math.abs(priceChange) < 0.5;
77
-
78
- if (priceAgreesWithSentiment && !priceIsFlat) {
79
- priceConfirmation = true;
80
- regime = "CONVERGENT";
81
- cdaScore = 0;
82
- } else {
83
- regime = (zSentiment > 0) ? "BEARISH_DISSONANCE" : "BULLISH_DISSONANCE";
84
- }
85
- } else if (!disagree && loudVoice) {
86
- regime = "CONVERGENT";
15
+ const sent = signals.getMetric(computed, 'social-topic-sentiment-matrix', ticker, 'net_sentiment', 0);
16
+ const flow = signals.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
17
+ const pChg = signals.getMetric(computed, 'instrument-price-change-1d', ticker, 'change_1d_pct', 0);
18
+ const prev = signals.getPreviousState(previousComputed, 'cognitive-dissonance', ticker);
19
+ const pS = prev ? prev._state : { sent_mean: sent, sent_var: 1, flow_mean: flow, flow_var: 1 };
20
+ const sS = TimeSeries.updateEMAState(sent, { mean: pS.sent_mean, variance: pS.sent_var }, this.alpha);
21
+ const fS = TimeSeries.updateEMAState(flow, { mean: pS.flow_mean, variance: pS.flow_var }, this.alpha);
22
+ const sDev = Math.sqrt(sS.variance), fDev = Math.sqrt(fS.variance);
23
+ const zS = sDev > 0.001 ? (sent - sS.mean) / sDev : 0, zF = fDev > 0.001 ? (flow - fS.mean) / fDev : 0;
24
+ let cda = null, regime = "WARM_UP";
25
+ if (prev) {
26
+ const interact = zS * zF; cda = 0; regime = "NEUTRAL";
27
+ const disagree = Math.sign(zS) !== Math.sign(zF), loud = Math.abs(zS) > 1.65, active = Math.abs(zF) > 0.5;
28
+ if (disagree && loud && active) {
29
+ cda = -interact;
30
+ if (Math.sign(pChg) === Math.sign(zS) && Math.abs(pChg) > 0.5) { cda = 0; regime = "CONVERGENT"; }
31
+ else regime = zS > 0 ? "BEARISH_DISSONANCE" : "BULLISH_DISSONANCE";
32
+ } else if (!disagree && loud) regime = "CONVERGENT";
87
33
  }
88
-
89
- this.cdaResults[ticker] = {
90
- cda_score: Number(cdaScore.toFixed(4)),
91
- regime: regime,
92
- z_sentiment: Number(zSentiment.toFixed(4)),
93
- z_flow: Number(zFlow.toFixed(4)),
94
- price_confirmation: priceConfirmation,
95
- _state: {
96
- sent_mean: sentStats.mean, sent_var: sentStats.variance,
97
- flow_mean: flowStats.mean, flow_var: flowStats.variance
98
- }
99
- };
34
+ this.cdaResults[ticker] = { cda_score: (cda !== null && isFinite(cda)) ? Number(cda.toFixed(4)) : null, regime, _state: { sent_mean: sS.mean, sent_var: sS.variance, flow_mean: fS.mean, flow_var: fS.variance } };
100
35
  }
101
36
  }
102
-
103
37
  async getResult() { return this.cdaResults; }
104
38
  reset() { this.cdaResults = {}; }
105
39
  }
@@ -1,88 +1,33 @@
1
- /**
2
- * @fileoverview Diamond Hand Fracture Coefficient (DHFC) v2.2
3
- * REFACTORED: Adheres to System Architecture.
4
- */
5
1
  class DiamondHandFracture {
6
2
  constructor() { this.fractureResults = {}; }
7
-
8
- static getMetadata() {
9
- return {
10
- type: 'meta',
11
- rootDataDependencies: [],
12
- isHistorical: true,
13
- userType: 'aggregate'
14
- };
15
- }
16
-
17
- static getDependencies() {
18
- return ['holding-duration-per-asset', 'average-daily-pnl-per-stock'];
19
- }
3
+ static getMetadata() { return { type: 'meta', rootDataDependencies: [], isHistorical: true, userType: 'aggregate' }; }
4
+ static getDependencies() { return ['holding-duration-per-asset', 'average-daily-pnl-per-stock']; }
20
5
 
21
6
  static getSchema() {
22
- const metricSchema = {
23
- "type": "object",
24
- "properties": {
25
- "fracture_velocity": { "type": "number" },
26
- "capitulation_score": { "type": "number" },
27
- "regime": { "type": "string" },
28
- "expected_duration_hours": { "type": "number" },
29
- "actual_duration_hours": { "type": "number" }
30
- }
31
- };
32
- return { "type": "object", "patternProperties": { "^.*$": metricSchema } };
7
+ return { "type": "object", "patternProperties": { "^.*$": { "type": "object", "properties": { "fracture_velocity": { "type": ["number", "null"] }, "regime": { "type": "string" }, "actual_duration_hours": { "type": "number" } } } } };
33
8
  }
34
9
 
35
10
  process(context) {
36
11
  const { computed, previousComputed, math } = context;
37
- const { signals: SignalPrimitives } = math; // fixed?
38
-
39
- const tickers = SignalPrimitives.getUnionKeys(computed, DiamondHandFracture.getDependencies());
40
-
12
+ const { signals } = math;
13
+ const tickers = signals.getUnionKeys(computed, DiamondHandFracture.getDependencies());
41
14
  for (const ticker of tickers) {
42
- // 1. Current State
43
- const H_t = SignalPrimitives.getMetric(computed, 'holding-duration-per-asset', ticker, 'avg_duration_hours', 0);
44
- const OI_t = SignalPrimitives.getMetric(computed, 'holding-duration-per-asset', ticker, 'count', 0);
45
- const avgPnl = SignalPrimitives.getMetric(computed, 'average-daily-pnl-per-stock', ticker, 'avg_daily_pnl_pct', 0);
46
-
47
- // 2. Previous State (T-1)
48
- // Note: We fetch 'holding-duration-per-asset' from *previous* computed results
49
- const prevData = SignalPrimitives.getPreviousState(previousComputed, 'holding-duration-per-asset', ticker);
50
- const H_prev = prevData ? (prevData.avg_duration_hours || 0) : 0;
51
- const OI_prev = prevData ? (prevData.count || 0) : 0;
52
-
53
- // Init Check
54
- if (H_prev === 0 || OI_prev === 0) {
55
- this.fractureResults[ticker] = { fracture_velocity: 0, capitulation_score: 0, regime: "STABLE", expected_duration_hours: H_t, actual_duration_hours: H_t };
15
+ const H_t = signals.getMetric(computed, 'holding-duration-per-asset', ticker, 'avg_duration_hours', 0);
16
+ const OI_t = signals.getMetric(computed, 'holding-duration-per-asset', ticker, 'count', 0);
17
+ const pnl = signals.getMetric(computed, 'average-daily-pnl-per-stock', ticker, 'avg_daily_pnl_pct', 0);
18
+ const prev = signals.getPreviousState(previousComputed, 'holding-duration-per-asset', ticker);
19
+ const H_p = prev?.avg_duration_hours || 0, OI_p = prev?.count || 0;
20
+ if (H_p === 0 || OI_p === 0) {
21
+ this.fractureResults[ticker] = { fracture_velocity: null, capitulation_score: 0, regime: "COLD_START", expected_duration_hours: H_t, actual_duration_hours: H_t };
56
22
  continue;
57
23
  }
58
-
59
- // 3. Logic: Inventory Dilution
60
- let dilutionFactor = (OI_t > 0) ? (OI_prev / OI_t) : 1.0;
61
- if (dilutionFactor > 2.0) dilutionFactor = 1.0; // Clamp extreme dilution
62
-
63
- const H_expected = H_prev * dilutionFactor;
64
- const phi = H_expected - H_t;
65
- const phi_normalized = (H_prev > 0) ? (phi / H_prev) * 100 : 0;
66
-
67
- // 4. Capitulation Score
68
- const painFactor = (avgPnl < 0) ? Math.abs(avgPnl) : 0;
69
- const capitulationScore = phi_normalized * painFactor;
70
-
71
- let regime = "STABLE";
72
- if (phi_normalized > 5.0) regime = "FRACTURE";
73
- if (capitulationScore > 20.0) regime = "CAPITULATION";
74
- if (phi_normalized < -5.0) regime = "ACCUMULATION";
75
-
76
- this.fractureResults[ticker] = {
77
- fracture_velocity: Number(phi_normalized.toFixed(4)),
78
- capitulation_score: Number(capitulationScore.toFixed(4)),
79
- regime: regime,
80
- expected_duration_hours: Number(H_expected.toFixed(2)),
81
- actual_duration_hours: Number(H_t.toFixed(2))
82
- };
24
+ let dil = (OI_t > 0) ? (OI_p / OI_t) : 1.0; if (dil > 2.0) dil = 1.0;
25
+ const H_exp = H_p * dil, phi = H_exp - H_t, phi_n = (H_p > 0) ? (phi / H_p) * 100 : 0;
26
+ const cap = (pnl < 0) ? Math.abs(pnl) * phi_n : 0;
27
+ let reg = "STABLE"; if (phi_n > 5.0) reg = "FRACTURE"; if (cap > 20.0) reg = "CAPITULATION"; if (phi_n < -5.0) reg = "ACCUMULATION";
28
+ this.fractureResults[ticker] = { fracture_velocity: Number(phi_n.toFixed(4)), capitulation_score: Number(cap.toFixed(4)), regime: reg, expected_duration_hours: Number(H_exp.toFixed(2)), actual_duration_hours: Number(H_t.toFixed(2)) };
83
29
  }
84
30
  }
85
-
86
31
  getResult() { return this.fractureResults; }
87
32
  reset() { this.fractureResults = {}; }
88
33
  }
@@ -1,116 +1,37 @@
1
- /**
2
- * @fileoverview Mimetic Latency Oscillator (MLO) v2.3
3
- * FIXED: Safe state access to prevent 'undefined' property errors.
4
- */
5
1
  class MimeticLatencyOscillator {
6
- constructor() {
7
- this.mloResults = {};
8
- this.windowSize = 30;
9
- this.maxLag = 10;
10
- }
11
-
12
- static getMetadata() {
13
- return {
14
- type: 'meta',
15
- rootDataDependencies: [],
16
- isHistorical: true,
17
- userType: 'aggregate'
18
- };
19
- }
20
-
21
- static getDependencies() {
22
- return ['skilled-cohort-flow', 'herd-consensus-score'];
23
- }
2
+ constructor() { this.mloResults = {}; this.windowSize = 30; this.maxLag = 10; }
3
+ static getMetadata() { return { type: 'meta', rootDataDependencies: [], isHistorical: true, userType: 'aggregate' }; }
4
+ static getDependencies() { return ['skilled-cohort-flow', 'herd-consensus-score']; }
24
5
 
25
6
  static getSchema() {
26
- const metricSchema = {
27
- "type": "object",
28
- "properties": {
29
- "lag_days": { "type": "integer" },
30
- "correlation_strength": { "type": "number" },
31
- "regime": { "type": "string" },
32
- "_state": { "type": "object" }
33
- }
34
- };
35
- return { "type": "object", "patternProperties": { "^.*$": metricSchema } };
7
+ return { "type": "object", "patternProperties": { "^.*$": { "type": "object", "properties": { "lag_days": { "type": ["number", "null"] }, "regime": { "type": "string" }, "_state": { "type": "object" } } } } };
36
8
  }
37
9
 
38
10
  process(context) {
39
11
  const { computed, previousComputed, math } = context;
40
- const { signals: SignalPrimitives, TimeSeries } = math;
41
-
42
- const tickers = SignalPrimitives.getUnionKeys(computed, MimeticLatencyOscillator.getDependencies());
43
-
12
+ const { signals, TimeSeries } = math;
13
+ const tickers = signals.getUnionKeys(computed, MimeticLatencyOscillator.getDependencies());
44
14
  for (const ticker of tickers) {
45
- // 1. Inputs
46
- const rawFlow = SignalPrimitives.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
47
- const rawHerd = SignalPrimitives.getMetric(computed, 'herd-consensus-score', ticker, 'herd_conviction_score', 0);
48
-
49
- // 2. Restore State (FIX: Safe Access)
50
- const prevResult = SignalPrimitives.getPreviousState(previousComputed, 'mimetic-latency', ticker);
51
- const prevState = prevResult ? prevResult._state : null;
52
-
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] : [];
58
-
59
- // 3. Calculate Detrended Delta
60
- const flowDelta = rawFlow - prevFlow;
61
- const herdDelta = rawHerd - prevHerd;
62
-
63
- // 4. Update Buffers
64
- flowBuffer.push(flowDelta);
65
- herdBuffer.push(herdDelta);
66
-
67
- if (flowBuffer.length > this.windowSize) flowBuffer.shift();
68
- if (herdBuffer.length > this.windowSize) herdBuffer.shift();
69
-
70
- // 5. Lagged Cross-Correlation
71
- let maxCorr = -1.0;
72
- let bestLag = 0;
73
- let regime = "WARM_UP";
74
-
75
- if (flowBuffer.length >= 15) {
15
+ const flow = signals.getMetric(computed, 'skilled-cohort-flow', ticker, 'net_flow_pct', 0);
16
+ const herd = signals.getMetric(computed, 'herd-consensus-score', ticker, 'herd_conviction_score', 0);
17
+ const prev = signals.getPreviousState(previousComputed, 'mimetic-latency', ticker);
18
+ const pS = prev?._state || null;
19
+ const pF = pS?.last_flow || 0, pH = pS?.last_herd || 0, fBuf = [...(pS?.flow_buffer || [])], hBuf = [...(pS?.herd_buffer || [])];
20
+ fBuf.push(flow - pF); hBuf.push(herd - pH);
21
+ if (fBuf.length > this.windowSize) { fBuf.shift(); hBuf.shift(); }
22
+ let maxCorr = -1.0, bestLag = null, regime = "WARM_UP";
23
+ if (fBuf.length >= 15) {
76
24
  for (let k = 0; k <= this.maxLag; k++) {
77
- const len = flowBuffer.length;
78
- if (len - k < 5) continue;
79
-
80
- const slicedFlow = flowBuffer.slice(0, len - k);
81
- const slicedHerd = herdBuffer.slice(k, len);
82
-
83
- const r = TimeSeries.pearsonCorrelation(slicedFlow, slicedHerd);
84
-
85
- if (r > maxCorr) {
86
- maxCorr = r;
87
- bestLag = k;
88
- }
89
- }
90
-
91
- if (maxCorr > 0.3) {
92
- if (bestLag >= 3) regime = "EARLY_ALPHA";
93
- else if (bestLag >= 1) regime = "MARKUP";
94
- else regime = "FOMO_TRAP";
95
- } else {
96
- regime = "DECOUPLING";
25
+ const len = fBuf.length; if (len - k < 5) continue;
26
+ const r = TimeSeries.pearsonCorrelation(fBuf.slice(0, len - k), hBuf.slice(k, len));
27
+ if (r > maxCorr) { maxCorr = r; bestLag = k; }
97
28
  }
29
+ if (maxCorr > 0.3) regime = bestLag >= 3 ? "EARLY_ALPHA" : (bestLag >= 1 ? "MARKUP" : "FOMO_TRAP");
30
+ else regime = "DECOUPLING";
98
31
  }
99
-
100
- this.mloResults[ticker] = {
101
- lag_days: bestLag,
102
- correlation_strength: Number(maxCorr.toFixed(4)),
103
- regime: regime,
104
- _state: {
105
- flow_buffer: flowBuffer,
106
- herd_buffer: herdBuffer,
107
- last_flow: rawFlow,
108
- last_herd: rawHerd
109
- }
110
- };
32
+ this.mloResults[ticker] = { lag_days: bestLag, correlation_strength: Number(maxCorr.toFixed(4)), regime, _state: { flow_buffer: fBuf, herd_buffer: hBuf, last_flow: flow, last_herd: herd } };
111
33
  }
112
34
  }
113
-
114
35
  getResult() { return this.mloResults; }
115
36
  reset() { this.mloResults = {}; }
116
37
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "aiden-shared-calculations-unified",
3
- "version": "1.0.108",
3
+ "version": "1.0.110",
4
4
  "description": "Shared calculation modules for the BullTrackers Computation System.",
5
5
  "main": "index.js",
6
6
  "files": [