aiden-shared-calculations-unified 1.0.76 → 1.0.77
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/{pnl/asset_pnl_status.js → core/asset-pnl-status.js} +20 -0
- package/calculations/{asset_metrics/asset_position_size.js → core/asset-position-size.js} +25 -1
- package/calculations/{pnl/average_daily_pnl_all_users.js → core/average-daily-pnl-all-users.js} +22 -0
- package/calculations/{pnl/average_daily_pnl_per_sector.js → core/average-daily-pnl-per-sector.js} +22 -0
- package/calculations/{pnl/average_daily_pnl_per_stock.js → core/average-daily-pnl-per-stock.js} +22 -0
- package/calculations/{pnl/average_daily_position_pnl.js → core/average-daily-position-pnl.js} +22 -0
- package/calculations/{behavioural/historical/holding_duration_per_asset.js → core/holding-duration-per-asset.js} +44 -4
- package/calculations/{meta/gem_instrument-price-momentum.js → core/instrument-price-momentum-20d.js} +17 -4
- package/calculations/{short_and_long_stats/long_position_per_stock.js → core/long-position-per-stock.js} +24 -0
- package/calculations/{behavioural/overall_holding_duration.js → core/overall-holding-duration.js} +27 -3
- package/calculations/{pnl/overall_profitability_ratio.js → core/overall-profitability-ratio.js} +24 -0
- package/calculations/{insights/daily_buy_sell_sentiment_count.js → core/platform-buy-sell-sentiment.js} +22 -0
- package/calculations/{insights/historical/daily_bought_vs_sold_count.js → core/platform-daily-bought-vs-sold-count.js} +22 -0
- package/calculations/{insights/historical/daily_ownership_delta.js → core/platform-daily-ownership-delta.js} +22 -0
- package/calculations/{insights/daily_ownership_per_sector.js → core/platform-ownership-per-sector.js} +22 -0
- package/calculations/{insights/daily_total_positions_held.js → core/platform-total-positions-held.js} +22 -0
- package/calculations/{pnl/pnl_distribution_per_stock.js → core/pnl-distribution-per-stock.js} +24 -0
- package/calculations/{pnl/profitability_ratio_per_sector,js → core/profitability-ratio-per-sector.js} +35 -5
- package/calculations/{pnl/profitability_ratio_per_stock.js → core/profitability-ratio-per-stock.js} +24 -0
- package/calculations/{pnl/profitability_skew_per_stock.js → core/profitability-skew-per-stock.js} +24 -0
- package/calculations/{pnl/profitable_and_unprofitable_status.js → core/profitable-and-unprofitable-status.js} +24 -0
- package/calculations/{short_and_long_stats/sentiment_per_stock.js → core/sentiment-per-stock.js} +20 -0
- package/calculations/{short_and_long_stats/short_position_per_stock.js → core/short-position-per-stock.js} +24 -0
- package/calculations/{socialPosts/social_activity_aggregation.js → core/social-activity-aggregation.js} +32 -8
- package/calculations/{socialPosts → core}/social-asset-posts-trend.js +30 -8
- package/calculations/{socialPosts/social_event_correlation.js → core/social-event-correlation.js} +24 -2
- package/calculations/{socialPosts/social_sentiment_aggregation.js → core/social-sentiment-aggregation.js} +23 -0
- package/calculations/{socialPosts → core}/social-top-mentioned-words.js +31 -8
- package/calculations/{socialPosts → core}/social-topic-interest-evolution.js +35 -11
- package/calculations/{socialPosts → core}/social-topic-sentiment-matrix.js +34 -10
- package/calculations/{socialPosts → core}/social-word-mentions-trend.js +36 -11
- package/calculations/{speculators/speculator_asset_sentiment.js → core/speculator-asset-sentiment.js} +20 -0
- package/calculations/{speculators/speculator_danger_zone.js → core/speculator-danger-zone.js} +22 -0
- package/calculations/{speculators/distance_to_stop_loss_per_leverage.js → core/speculator-distance-to-stop-loss-per-leverage.js} +24 -0
- package/calculations/{speculators/distance_to_tp_per_leverage.js → core/speculator-distance-to-tp-per-leverage.js} +24 -0
- package/calculations/{speculators/entry_distance_to_sl_per_leverage.js → core/speculator-entry-distance-to-sl-per-leverage.js} +24 -0
- package/calculations/{speculators/entry_distance_to_tp_per_leverage.js → core/speculator-entry-distance-to-tp-per-leverage.js} +24 -0
- package/calculations/{speculators/leverage_per_asset.js → core/speculator-leverage-per-asset.js} +20 -0
- package/calculations/{speculators/leverage_per_sector.js → core/speculator-leverage-per-sector.js} +22 -0
- package/calculations/{speculators/risk_reward_ratio_per_asset.js → core/speculator-risk-reward-ratio-per-asset.js} +20 -0
- package/calculations/{speculators/stop_loss_distance_by_sector_short_long_breakdown.js → core/speculator-stop-loss-distance-by-sector-short-long-breakdown.js} +22 -0
- package/calculations/{speculators/stop_loss_distance_by_ticker_short_long_breakdown.js → core/speculator-stop-loss-distance-by-ticker-short-long-breakdown.js} +24 -0
- package/calculations/{speculators/stop_loss_per_asset.js → core/speculator-stop-loss-per-asset.js} +24 -0
- package/calculations/{speculators/take_profit_per_asset.js → core/speculator-take-profit-per-asset.js} +24 -0
- package/calculations/{speculators/tsl_per_asset.js → core/speculator-tsl-per-asset.js} +24 -0
- package/calculations/{short_and_long_stats/total_long_figures.js → core/total-long-figures.js} +24 -0
- package/calculations/{sectors/total_long_per_sector.js → core/total-long-per-sector.js} +22 -0
- package/calculations/{short_and_long_stats/total_short_figures.js → core/total-short-figures.js} +24 -0
- package/calculations/{sectors/total_short_per_sector.js → core/total-short-per-sector.js} +22 -0
- package/calculations/{sanity/users_processed.js → core/users-processed.js} +22 -0
- package/calculations/gauss/cohort-capital-flow.js +216 -0
- package/calculations/gauss/cohort-definer.js +211 -0
- package/calculations/gauss/daily-dna-filter.js +130 -0
- package/calculations/gauss/gauss-divergence-signal.js +160 -0
- package/calculations/{meta/gem_cohort-momentum-state.js → gem/cohort-momentum-state.js} +22 -7
- package/calculations/{behavioural/historical/gem_cohort-skill-definition.js → gem/cohort-skill-definition.js} +18 -1
- package/calculations/{sentiment/gem_platform-conviction-divergence.js → gem/platform-conviction-divergence.js} +13 -0
- package/calculations/{meta/gem_quant-skill-alpha-signal.js → gem/quant-skill-alpha-signal.js} +25 -8
- package/calculations/{behavioural/historical/gem_skilled-cohort-flow.js → gem/skilled-cohort-flow.js} +16 -2
- package/calculations/{meta/gem_skilled-unskilled-divergence.js → gem/skilled-unskilled-divergence.js} +18 -4
- package/calculations/{behavioural/historical/gem_unskilled-cohort-flow.js → gem/unskilled-cohort-flow.js} +16 -2
- package/calculations/helix/helix-contrarian-signal.js +154 -0
- package/calculations/helix/herd-consensus-score.js +152 -0
- package/calculations/helix/winner-loser-flow.js +206 -0
- package/calculations/{behavioural/historical → legacy}/asset_crowd_flow.js +1 -1
- package/calculations/{sentiment/historical → legacy}/crowd_conviction_score.js +1 -1
- package/calculations/{activity/historical → legacy}/daily_asset_activity.js +1 -1
- package/calculations/{behavioural/historical → legacy}/dumb-cohort-flow.js +1 -1
- package/calculations/{behavioural/historical → legacy}/in_loss_asset_crowd_flow.js +1 -1
- package/calculations/{behavioural/historical → legacy}/in_profit_asset_crowd_flow.js +1 -1
- package/calculations/{speculators/historical → legacy}/risk_appetite_change.js +3 -1
- package/calculations/{sectors/historical → legacy}/sector_rotation.js +1 -1
- package/calculations/{behavioural/historical → legacy}/smart-cohort-flow.js +1 -1
- package/calculations/{behavioural/historical → legacy}/smart_money_flow.js +1 -1
- package/calculations/{behavioural/historical → legacy}/user-investment-profile.js +2 -2
- package/calculations/pyro/risk-appetite-index.js +153 -0
- package/calculations/pyro/squeeze-potential.js +158 -0
- package/calculations/pyro/volatility-signal.js +133 -0
- package/package.json +1 -1
- package/calculations/socialPosts/gem_social_sentiment_aggregation.js +0 -146
- /package/calculations/{activity/historical → legacy}/activity_by_pnl_status.js +0 -0
- /package/calculations/{meta → legacy}/capital_deployment_strategy.js +0 -0
- /package/calculations/{meta → legacy}/capital_liquidation_performance.js +0 -0
- /package/calculations/{meta → legacy}/capital_vintage_performance.js +0 -0
- /package/calculations/{meta → legacy}/cash-flow-deployment.js +0 -0
- /package/calculations/{meta → legacy}/cash-flow-liquidation.js +0 -0
- /package/calculations/{capital_flow/historical → legacy}/crowd-cash-flow-proxy.js +0 -0
- /package/calculations/{meta → legacy}/crowd_sharpe_ratio_proxy.js +0 -0
- /package/calculations/{activity/historical → legacy}/daily_user_activity_tracker.js +0 -0
- /package/calculations/{capital_flow/historical → legacy}/deposit_withdrawal_percentage.js +0 -0
- /package/calculations/{sectors/historical → legacy}/diversification_pnl.js +0 -0
- /package/calculations/{behavioural/historical → legacy}/drawdown_response.js +0 -0
- /package/calculations/{behavioural/historical → legacy}/gain_response.js +0 -0
- /package/calculations/{behavioural/historical → legacy}/historical_performance_aggregator.js +0 -0
- /package/calculations/{meta → legacy}/negative_expectancy_cohort_flow.js +0 -0
- /package/calculations/{capital_flow/historical → legacy}/new_allocation_percentage.js +0 -0
- /package/calculations/{behavioural/historical → legacy}/paper_vs_diamond_hands.js +0 -0
- /package/calculations/{behavioural/historical → legacy}/position_count_pnl.js +0 -0
- /package/calculations/{meta → legacy}/positive_expectancy_cohort_flow.js +0 -0
- /package/calculations/{meta → legacy}/profit_cohort_divergence.js +0 -0
- /package/calculations/{pnl/historical → legacy}/profitability_migration.js +0 -0
- /package/calculations/{capital_flow/historical → legacy}/reallocation_increase_percentage.js +0 -0
- /package/calculations/{meta → legacy}/shark_attack_signal.js +0 -0
- /package/calculations/{meta → legacy}/smart-dumb-divergence-index.js +0 -0
- /package/calculations/{meta → legacy}/smart_dumb_divergence_index_v2.js +0 -0
- /package/calculations/{meta → legacy}/social-predictive-regime-state.js +0 -0
- /package/calculations/{meta → legacy}/social-topic-driver-index.js +0 -0
- /package/calculations/{meta → legacy}/social-topic-predictive-potential.js +0 -0
- /package/calculations/{meta → legacy}/social_flow_correlation.js +0 -0
- /package/calculations/{activity/historical → legacy}/speculator_adjustment_activity.js +0 -0
- /package/calculations/{backtests → legacy}/strategy-performance.js +0 -0
- /package/calculations/{speculators/historical → legacy}/tsl_effectiveness.js +0 -0
- /package/calculations/{meta → legacy}/user_expectancy_score.js +0 -0
- /package/calculations/{pnl/historical → legacy}/user_profitability_tracker.js +0 -0
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview PYRO Product Line (Pass 3)
|
|
3
|
+
*
|
|
4
|
+
* This metric answers: "For each asset, what is the 'Squeeze Potential'
|
|
5
|
+
* for both longs and shorts?"
|
|
6
|
+
*
|
|
7
|
+
* It identifies "trapped" speculators by looking at:
|
|
8
|
+
* 1. How many are in the "danger zone" (close to their SL).
|
|
9
|
+
* 2. Which direction the price is moving (momentum).
|
|
10
|
+
*
|
|
11
|
+
* A high "short squeeze" score means many shorts are in danger
|
|
12
|
+
* AND the price is moving *against* them (i.e., momentum is positive).
|
|
13
|
+
*/
|
|
14
|
+
class SqueezePotential {
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Defines the output schema for this calculation.
|
|
18
|
+
* @returns {object} JSON Schema object
|
|
19
|
+
*/
|
|
20
|
+
static getSchema() {
|
|
21
|
+
const tickerSchema = {
|
|
22
|
+
"type": "object",
|
|
23
|
+
"properties": {
|
|
24
|
+
"short_squeeze_score": {
|
|
25
|
+
"type": "number",
|
|
26
|
+
"description": "Score (0-10) indicating potential for a short squeeze."
|
|
27
|
+
},
|
|
28
|
+
"long_squeeze_score": {
|
|
29
|
+
"type": "number",
|
|
30
|
+
"description": "Score (0-10) indicating potential for a long squeeze (capitulation)."
|
|
31
|
+
},
|
|
32
|
+
"momentum_20d_pct": {
|
|
33
|
+
"type": "number",
|
|
34
|
+
"description": "The 20-day price momentum used in the calculation."
|
|
35
|
+
}
|
|
36
|
+
},
|
|
37
|
+
"required": ["short_squeeze_score", "long_squeeze_score", "momentum_20d_pct"]
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
return {
|
|
41
|
+
"type": "object",
|
|
42
|
+
"description": "Calculates a squeeze potential score for longs and shorts.",
|
|
43
|
+
"patternProperties": {
|
|
44
|
+
"^.*$": tickerSchema // Ticker
|
|
45
|
+
},
|
|
46
|
+
"additionalProperties": tickerSchema
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Statically defines all metadata for the manifest builder.
|
|
52
|
+
*/
|
|
53
|
+
static getMetadata() {
|
|
54
|
+
return {
|
|
55
|
+
type: 'meta',
|
|
56
|
+
rootDataDependencies: [],
|
|
57
|
+
isHistorical: false,
|
|
58
|
+
userType: 'n/a',
|
|
59
|
+
category: 'pyro'
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Statically declare dependencies.
|
|
65
|
+
*/
|
|
66
|
+
static getDependencies() {
|
|
67
|
+
return [
|
|
68
|
+
'speculator-danger-zone', // from core
|
|
69
|
+
'speculator-asset-sentiment', // from core
|
|
70
|
+
'instrument-price-momentum-20d' // from core
|
|
71
|
+
];
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
/**
|
|
75
|
+
* Simple min-max normalization, clamped 0-1.
|
|
76
|
+
*/
|
|
77
|
+
_normalize(value, min, max) {
|
|
78
|
+
const normalized = (value - min) / (max - min);
|
|
79
|
+
return Math.max(0, Math.min(1, normalized));
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* This is a 'meta' calculation. It runs once.
|
|
84
|
+
* @param {string} dateStr - The date string 'YYYY-MM-DD'.
|
|
85
|
+
* @param {object} dependencies - The shared dependencies (e.g., logger).
|
|
86
|
+
* @param {object} config - The computation system configuration.
|
|
87
|
+
* @param {object} fetchedDependencies - Results from previous passes.
|
|
88
|
+
* @returns {Promise<object>} The calculation result.
|
|
89
|
+
*/
|
|
90
|
+
async process(dateStr, dependencies, config, fetchedDependencies) {
|
|
91
|
+
const { logger } = dependencies;
|
|
92
|
+
|
|
93
|
+
const dangerData = fetchedDependencies['speculator-danger-zone'];
|
|
94
|
+
const sentimentData = fetchedDependencies['speculator-asset-sentiment'];
|
|
95
|
+
const momentumData = fetchedDependencies['instrument-price-momentum-20d'];
|
|
96
|
+
|
|
97
|
+
if (!dangerData || !sentimentData || !momentumData) {
|
|
98
|
+
logger.log('WARN', `[pyro/squeeze-potential] Missing core dependencies for ${dateStr}. Skipping.`);
|
|
99
|
+
return {};
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
const allTickers = new Set([
|
|
103
|
+
...Object.keys(dangerData),
|
|
104
|
+
...Object.keys(sentimentData),
|
|
105
|
+
...Object.keys(momentumData)
|
|
106
|
+
]);
|
|
107
|
+
|
|
108
|
+
const result = {};
|
|
109
|
+
|
|
110
|
+
for (const ticker of allTickers) {
|
|
111
|
+
const danger = dangerData[ticker];
|
|
112
|
+
const sentiment = sentimentData[ticker];
|
|
113
|
+
const momentum = momentumData[ticker];
|
|
114
|
+
|
|
115
|
+
// If any core data is missing for this ticker, skip it
|
|
116
|
+
if (!danger || !sentiment || !momentum) {
|
|
117
|
+
continue;
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
const mom_pct = momentum.momentum_20d_pct || 0;
|
|
121
|
+
const short_danger_pct = danger.short_danger_pct || 0;
|
|
122
|
+
const long_danger_pct = danger.long_danger_pct || 0;
|
|
123
|
+
|
|
124
|
+
let short_squeeze_score = 0;
|
|
125
|
+
let long_squeeze_score = 0;
|
|
126
|
+
|
|
127
|
+
// Calculate Short Squeeze:
|
|
128
|
+
// Needs positive momentum (price rising) and shorts in danger.
|
|
129
|
+
if (mom_pct > 0 && sentiment.short.count > 0) {
|
|
130
|
+
// Normalize momentum (e.g., 0-20%) and danger (0-100%)
|
|
131
|
+
const norm_mom = this._normalize(mom_pct, 0, 20);
|
|
132
|
+
const norm_danger = this._normalize(short_danger_pct, 0, 100);
|
|
133
|
+
// Combine and scale to 0-10
|
|
134
|
+
short_squeeze_score = (norm_mom * 0.5 + norm_danger * 0.5) * 10;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Calculate Long Squeeze:
|
|
138
|
+
// Needs negative momentum (price falling) and longs in danger.
|
|
139
|
+
if (mom_pct < 0 && sentiment.long.count > 0) {
|
|
140
|
+
// Normalize momentum (e.g., 0 to -20%) and danger (0-100%)
|
|
141
|
+
const norm_mom = this._normalize(Math.abs(mom_pct), 0, 20);
|
|
142
|
+
const norm_danger = this._normalize(long_danger_pct, 0, 100);
|
|
143
|
+
// Combine and scale to 0-10
|
|
144
|
+
long_squeeze_score = (norm_mom * 0.5 + norm_danger * 0.5) * 10;
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
result[ticker] = {
|
|
148
|
+
short_squeeze_score: short_squeeze_score,
|
|
149
|
+
long_squeeze_score: long_squeeze_score,
|
|
150
|
+
momentum_20d_pct: mom_pct
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
return result;
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = SqueezePotential;
|
|
@@ -0,0 +1,133 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview PYRO Product Line (Pass 4)
|
|
3
|
+
*
|
|
4
|
+
* This metric answers: "What is the final PYRO volatility signal?"
|
|
5
|
+
*
|
|
6
|
+
* It combines the 'Squeeze Potential' (trapped traders) with the
|
|
7
|
+
* 'Risk Appetite' (conviction).
|
|
8
|
+
*
|
|
9
|
+
* A high score means many traders are trapped AND the rest of
|
|
10
|
+
* the speculator cohort is highly confident/leveraged,
|
|
11
|
+
* creating a perfect storm for a sharp move.
|
|
12
|
+
*/
|
|
13
|
+
class VolatilitySignal {
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* Defines the output schema for this calculation.
|
|
17
|
+
* @returns {object} JSON Schema object
|
|
18
|
+
*/
|
|
19
|
+
static getSchema() {
|
|
20
|
+
const tickerSchema = {
|
|
21
|
+
"type": "object",
|
|
22
|
+
"properties": {
|
|
23
|
+
"signal": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"enum": ["High Short Squeeze Potential", "High Long Squeeze Potential", "Short Squeeze Watch", "Long Squeeze Watch", "Stable"]
|
|
26
|
+
},
|
|
27
|
+
"pyro_score": {
|
|
28
|
+
"type": "number",
|
|
29
|
+
"description": "Final signal score (-10 to +10). Positive = Short Squeeze, Negative = Long Squeeze."
|
|
30
|
+
},
|
|
31
|
+
"risk_appetite": {
|
|
32
|
+
"type": "number",
|
|
33
|
+
"description": "The risk-appetite-index score (0-10)."
|
|
34
|
+
}
|
|
35
|
+
},
|
|
36
|
+
"required": ["signal", "pyro_score", "risk_appetite"]
|
|
37
|
+
};
|
|
38
|
+
|
|
39
|
+
return {
|
|
40
|
+
"type": "object",
|
|
41
|
+
"description": "Calculates the final PYRO volatility/squeeze signal.",
|
|
42
|
+
"patternProperties": {
|
|
43
|
+
"^.*$": tickerSchema // Ticker
|
|
44
|
+
},
|
|
45
|
+
"additionalProperties": tickerSchema
|
|
46
|
+
};
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Statically defines all metadata for the manifest builder.
|
|
51
|
+
*/
|
|
52
|
+
static getMetadata() {
|
|
53
|
+
return {
|
|
54
|
+
type: 'meta',
|
|
55
|
+
rootDataDependencies: [],
|
|
56
|
+
isHistorical: false,
|
|
57
|
+
userType: 'n/a',
|
|
58
|
+
category: 'pyro'
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
/**
|
|
63
|
+
* Statically declare dependencies.
|
|
64
|
+
*/
|
|
65
|
+
static getDependencies() {
|
|
66
|
+
return [
|
|
67
|
+
'risk-appetite-index', // from pyro (Pass 2)
|
|
68
|
+
'squeeze-potential' // from pyro (Pass 3)
|
|
69
|
+
];
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/**
|
|
73
|
+
* This is a 'meta' calculation. It runs once.
|
|
74
|
+
* @param {string} dateStr - The date string 'YYYY-MM-DD'.
|
|
75
|
+
* @param {object} dependencies - The shared dependencies (e.g., logger).
|
|
76
|
+
* @param {object} config - The computation system configuration.
|
|
77
|
+
* @param {object} fetchedDependencies - Results from previous passes.
|
|
78
|
+
* @returns {Promise<object>} The calculation result.
|
|
79
|
+
*/
|
|
80
|
+
async process(dateStr, dependencies, config, fetchedDependencies) {
|
|
81
|
+
const { logger } = dependencies;
|
|
82
|
+
|
|
83
|
+
const appetiteData = fetchedDependencies['risk-appetite-index'];
|
|
84
|
+
const squeezeData = fetchedDependencies['squeeze-potential'];
|
|
85
|
+
|
|
86
|
+
if (!appetiteData || !squeezeData) {
|
|
87
|
+
logger.log('WARN', `[pyro/volatility-signal] Missing dependencies for ${dateStr}. Skipping.`);
|
|
88
|
+
return {};
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
const allTickers = new Set([
|
|
92
|
+
...Object.keys(appetiteData),
|
|
93
|
+
...Object.keys(squeezeData)
|
|
94
|
+
]);
|
|
95
|
+
|
|
96
|
+
const result = {};
|
|
97
|
+
const HIGH_THRESHOLD = 7.0; // Min score for "High"
|
|
98
|
+
const MED_THRESHOLD = 3.0; // Min score for "Watch"
|
|
99
|
+
|
|
100
|
+
for (const ticker of allTickers) {
|
|
101
|
+
const appetite = appetiteData[ticker]?.risk_appetite_score || 0;
|
|
102
|
+
const short_squeeze = squeezeData[ticker]?.short_squeeze_score || 0;
|
|
103
|
+
const long_squeeze = squeezeData[ticker]?.long_squeeze_score || 0;
|
|
104
|
+
|
|
105
|
+
// The final score is the difference.
|
|
106
|
+
// Positive = Short Squeeze risk
|
|
107
|
+
// Negative = Long Squeeze risk
|
|
108
|
+
const pyro_score = short_squeeze - long_squeeze;
|
|
109
|
+
|
|
110
|
+
let signal = "Stable";
|
|
111
|
+
|
|
112
|
+
if (pyro_score > HIGH_THRESHOLD && appetite > HIGH_THRESHOLD) {
|
|
113
|
+
signal = "High Short Squeeze Potential";
|
|
114
|
+
} else if (pyro_score < -HIGH_THRESHOLD && appetite > HIGH_THRESHOLD) {
|
|
115
|
+
signal = "High Long Squeeze Potential";
|
|
116
|
+
} else if (pyro_score > MED_THRESHOLD) {
|
|
117
|
+
signal = "Short Squeeze Watch";
|
|
118
|
+
} else if (pyro_score < -MED_THRESHOLD) {
|
|
119
|
+
signal = "Long Squeeze Watch";
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
result[ticker] = {
|
|
123
|
+
signal: signal,
|
|
124
|
+
pyro_score: pyro_score,
|
|
125
|
+
risk_appetite: appetite
|
|
126
|
+
};
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
return result;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
module.exports = VolatilitySignal;
|
package/package.json
CHANGED
|
@@ -1,146 +0,0 @@
|
|
|
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;
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/calculations/{behavioural/historical → legacy}/historical_performance_aggregator.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/package/calculations/{capital_flow/historical → legacy}/reallocation_increase_percentage.js
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|