aiden-shared-calculations-unified 1.0.96 → 1.0.97
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.
- package/calculations/core/Insights-total-long-per-stock +56 -0
- package/calculations/core/insights-daily-bought-vs-sold-count.js +74 -0
- package/calculations/core/insights-daily-ownership-delta.js +70 -0
- package/calculations/core/insights-sentimet-per-stock.js +68 -0
- package/calculations/core/insights-total-long-per-sector +73 -0
- package/calculations/core/insights-total-positions-held.js +49 -0
- package/calculations/ghost-book/liquidity-vacuum.js +3 -2
- package/calculations/helix/winner-loser-flow.js +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for total long figures.
|
|
3
|
+
* REFACTORED: Uses INSIGHTS DATA.
|
|
4
|
+
* TYPE: META
|
|
5
|
+
*/
|
|
6
|
+
class InsightsTotalLongFigures {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.totalPositions = 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static getMetadata() {
|
|
12
|
+
return {
|
|
13
|
+
type: 'meta',
|
|
14
|
+
rootDataDependencies: ['insights'],
|
|
15
|
+
isHistorical: false,
|
|
16
|
+
category: 'core_sentiment'
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getDependencies() { return []; }
|
|
21
|
+
|
|
22
|
+
static getSchema() {
|
|
23
|
+
return {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"total_long_exposure_weight": { "type": "number" },
|
|
27
|
+
"total_positions_count": { "type": "number" }
|
|
28
|
+
},
|
|
29
|
+
"required": ["total_long_exposure_weight", "total_positions_count"]
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
process(context) {
|
|
34
|
+
const { insights: insightsHelper } = context.math;
|
|
35
|
+
const insights = insightsHelper.getInsights(context);
|
|
36
|
+
|
|
37
|
+
if (!insights) return;
|
|
38
|
+
|
|
39
|
+
for (const insight of insights) {
|
|
40
|
+
this.totalPositions += insightsHelper.getLongCount(insight);
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
getResult() {
|
|
45
|
+
return {
|
|
46
|
+
total_long_exposure_weight: 0, // Not available in Insights
|
|
47
|
+
total_positions_count: this.totalPositions
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
reset() {
|
|
52
|
+
this.totalPositions = 0;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = InsightsTotalLongFigures;
|
|
@@ -0,0 +1,74 @@
|
|
|
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
|
+
class InsightsDailyBoughtVsSoldCount {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.results = {};
|
|
9
|
+
}
|
|
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
|
+
|
|
20
|
+
static getDependencies() { return []; }
|
|
21
|
+
|
|
22
|
+
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"]
|
|
31
|
+
};
|
|
32
|
+
return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
process(context) {
|
|
36
|
+
const { insights: insightsHelper } = context.math; // Maps to InsightsExtractor
|
|
37
|
+
const insights = insightsHelper.getInsights(context);
|
|
38
|
+
const { mappings } = context;
|
|
39
|
+
const tickerMap = mappings.instrumentToTicker || {};
|
|
40
|
+
|
|
41
|
+
if (!insights || !Array.isArray(insights)) return;
|
|
42
|
+
|
|
43
|
+
for (const insight of insights) {
|
|
44
|
+
const instId = insight.instrumentId;
|
|
45
|
+
const ticker = tickerMap[instId] || `id_${instId}`;
|
|
46
|
+
|
|
47
|
+
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
|
+
const bought = netChange > 0 ? netChange : 0;
|
|
54
|
+
const sold = netChange < 0 ? Math.abs(netChange) : 0;
|
|
55
|
+
|
|
56
|
+
if (bought > 0 || sold > 0) {
|
|
57
|
+
this.results[ticker] = {
|
|
58
|
+
positions_bought: bought,
|
|
59
|
+
positions_sold: sold,
|
|
60
|
+
net_change: netChange
|
|
61
|
+
};
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
async getResult() {
|
|
67
|
+
return this.results;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
reset() {
|
|
71
|
+
this.results = {};
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
module.exports = InsightsDailyBoughtVsSoldCount;
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for ownership delta (users added/lost per asset).
|
|
3
|
+
* REFACTORED: Uses INSIGHTS DATA.
|
|
4
|
+
* TYPE: META
|
|
5
|
+
*/
|
|
6
|
+
class InsightsDailyOwnershipDelta {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.results = {};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static getMetadata() {
|
|
12
|
+
return {
|
|
13
|
+
type: 'meta',
|
|
14
|
+
rootDataDependencies: ['insights'],
|
|
15
|
+
isHistorical: true,
|
|
16
|
+
category: 'core_metrics'
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getDependencies() { return []; }
|
|
21
|
+
|
|
22
|
+
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"]
|
|
31
|
+
};
|
|
32
|
+
return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
process(context) {
|
|
36
|
+
const { insights: insightsHelper } = context.math;
|
|
37
|
+
const insights = insightsHelper.getInsights(context);
|
|
38
|
+
const { mappings } = context;
|
|
39
|
+
const tickerMap = mappings.instrumentToTicker || {};
|
|
40
|
+
|
|
41
|
+
if (!insights) return;
|
|
42
|
+
|
|
43
|
+
for (const insight of insights) {
|
|
44
|
+
const netChange = insightsHelper.getNetOwnershipChange(insight);
|
|
45
|
+
if (netChange === 0) continue;
|
|
46
|
+
|
|
47
|
+
const instId = insight.instrumentId;
|
|
48
|
+
const ticker = tickerMap[instId] || `id_${instId}`;
|
|
49
|
+
|
|
50
|
+
// Approximate added/removed based on Net Change logic
|
|
51
|
+
const added = netChange > 0 ? netChange : 0;
|
|
52
|
+
const removed = netChange < 0 ? Math.abs(netChange) : 0;
|
|
53
|
+
|
|
54
|
+
this.results[ticker] = {
|
|
55
|
+
owners_added: added,
|
|
56
|
+
owners_removed: removed,
|
|
57
|
+
net_ownership_change: netChange
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
async getResult() {
|
|
63
|
+
return this.results;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
reset() {
|
|
67
|
+
this.results = {};
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
module.exports = InsightsDailyOwnershipDelta;
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for sentiment per stock.
|
|
3
|
+
* REFACTORED: Uses INSIGHTS DATA.
|
|
4
|
+
* TYPE: META
|
|
5
|
+
*/
|
|
6
|
+
class InsightsSentimentPerStock {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.results = {};
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
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"]
|
|
20
|
+
};
|
|
21
|
+
return { "type": "object", "patternProperties": { "^.*$": tickerSchema } };
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
static getMetadata() {
|
|
25
|
+
return {
|
|
26
|
+
type: 'meta',
|
|
27
|
+
rootDataDependencies: ['insights'],
|
|
28
|
+
isHistorical: false,
|
|
29
|
+
category: 'core_sentiment'
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
static getDependencies() { return []; }
|
|
34
|
+
|
|
35
|
+
process(context) {
|
|
36
|
+
const { insights: insightsHelper } = context.math;
|
|
37
|
+
const insights = insightsHelper.getInsights(context);
|
|
38
|
+
const { mappings } = context;
|
|
39
|
+
const tickerMap = mappings.instrumentToTicker || {};
|
|
40
|
+
|
|
41
|
+
if (!insights) return;
|
|
42
|
+
|
|
43
|
+
for (const insight of insights) {
|
|
44
|
+
const longCount = insightsHelper.getLongCount(insight);
|
|
45
|
+
const shortCount = insightsHelper.getShortCount(insight);
|
|
46
|
+
|
|
47
|
+
if (longCount === 0 && shortCount === 0) continue;
|
|
48
|
+
|
|
49
|
+
const instId = insight.instrumentId;
|
|
50
|
+
const ticker = tickerMap[instId] || `id_${instId}`;
|
|
51
|
+
|
|
52
|
+
this.results[ticker] = {
|
|
53
|
+
long_count: longCount,
|
|
54
|
+
short_count: shortCount,
|
|
55
|
+
sentiment_ratio: (shortCount > 0) ? (longCount / shortCount) : null
|
|
56
|
+
};
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
async getResult() {
|
|
61
|
+
return this.results;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
reset() {
|
|
65
|
+
this.results = {};
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
module.exports = InsightsSentimentPerStock;
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for long figures per sector.
|
|
3
|
+
* REFACTORED: Uses INSIGHTS DATA.
|
|
4
|
+
* TYPE: META
|
|
5
|
+
*/
|
|
6
|
+
class InsightsTotalLongPerSector {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.sectorData = new Map();
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static getMetadata() {
|
|
12
|
+
return {
|
|
13
|
+
type: 'meta',
|
|
14
|
+
rootDataDependencies: ['insights'],
|
|
15
|
+
isHistorical: false,
|
|
16
|
+
category: 'core_sentiment'
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
static getDependencies() { return []; }
|
|
21
|
+
|
|
22
|
+
static getSchema() {
|
|
23
|
+
const schema = {
|
|
24
|
+
"type": "object",
|
|
25
|
+
"properties": {
|
|
26
|
+
"total_long_exposure_weight": { "type": "number" },
|
|
27
|
+
"total_positions_count": { "type": "number" }
|
|
28
|
+
},
|
|
29
|
+
"required": ["total_long_exposure_weight", "total_positions_count"]
|
|
30
|
+
};
|
|
31
|
+
return { "type": "object", "patternProperties": { "^.*$": schema } };
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
process(context) {
|
|
35
|
+
const { insights: insightsHelper } = context.math;
|
|
36
|
+
const insights = insightsHelper.getInsights(context);
|
|
37
|
+
const { mappings } = context;
|
|
38
|
+
const sectorMap = mappings.instrumentToSector || {};
|
|
39
|
+
|
|
40
|
+
if (!insights) return;
|
|
41
|
+
|
|
42
|
+
for (const insight of insights) {
|
|
43
|
+
const longCount = insightsHelper.getLongCount(insight);
|
|
44
|
+
if (longCount <= 0) continue;
|
|
45
|
+
|
|
46
|
+
const sector = sectorMap[insight.instrumentId] || 'Unknown';
|
|
47
|
+
|
|
48
|
+
if (!this.sectorData.has(sector)) {
|
|
49
|
+
this.sectorData.set(sector, { count: 0 });
|
|
50
|
+
}
|
|
51
|
+
const data = this.sectorData.get(sector);
|
|
52
|
+
data.count += longCount;
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
async getResult() {
|
|
57
|
+
const result = {};
|
|
58
|
+
for (const [sector, data] of this.sectorData.entries()) {
|
|
59
|
+
if (data.count > 0) {
|
|
60
|
+
result[sector] = {
|
|
61
|
+
total_long_exposure_weight: 0, // Not available
|
|
62
|
+
total_positions_count: data.count
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
return result;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
reset() {
|
|
70
|
+
this.sectorData.clear();
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
module.exports = InsightsTotalLongPerSector;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Calculation (Pass 1) for total positions count.
|
|
3
|
+
* REFACTORED: Uses INSIGHTS DATA.
|
|
4
|
+
* TYPE: META
|
|
5
|
+
*/
|
|
6
|
+
class InsightsTotalPositionsHeld {
|
|
7
|
+
constructor() {
|
|
8
|
+
this.totalPositions = 0;
|
|
9
|
+
}
|
|
10
|
+
|
|
11
|
+
static getMetadata() {
|
|
12
|
+
return {
|
|
13
|
+
type: 'meta',
|
|
14
|
+
rootDataDependencies: ['insights'],
|
|
15
|
+
isHistorical: false,
|
|
16
|
+
category: 'Global-Platform-Metrics'
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
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
|
+
};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
process(context) {
|
|
33
|
+
const { insights: insightsHelper } = context.math;
|
|
34
|
+
const insights = insightsHelper.getInsights(context);
|
|
35
|
+
|
|
36
|
+
if (!insights) return;
|
|
37
|
+
|
|
38
|
+
for (const insight of insights) {
|
|
39
|
+
this.totalPositions += insightsHelper.getTotalOwners(insight);
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
getResult() {
|
|
44
|
+
return { total_positions_count: this.totalPositions };
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
reset() { this.totalPositions = 0; }
|
|
48
|
+
}
|
|
49
|
+
module.exports = InsightsTotalPositionsHeld;
|
|
@@ -16,13 +16,14 @@ class LiquidityVacuum {
|
|
|
16
16
|
|
|
17
17
|
process(context) {
|
|
18
18
|
const { computed, math } = context;
|
|
19
|
-
const { distribution } = math;
|
|
19
|
+
const { distribution } = math;
|
|
20
20
|
|
|
21
21
|
const tickers = Object.keys(computed['asset-cost-basis-profile'] || {});
|
|
22
22
|
|
|
23
23
|
for (const ticker of tickers) {
|
|
24
24
|
const data = computed['asset-cost-basis-profile'][ticker];
|
|
25
|
-
|
|
25
|
+
// BUG FIX: Ensure data and profile exist before accessing length/integration
|
|
26
|
+
if (!data || !data.profile || !Array.isArray(data.profile)) continue;
|
|
26
27
|
|
|
27
28
|
const current = data.current_price;
|
|
28
29
|
const totalInv = data.total_inventory_weight;
|