aiden-shared-calculations-unified 1.0.34 → 1.0.36
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/README.MD +77 -77
- package/calculations/activity/historical/activity_by_pnl_status.js +85 -85
- package/calculations/activity/historical/daily_asset_activity.js +85 -85
- package/calculations/activity/historical/daily_user_activity_tracker.js +144 -144
- package/calculations/activity/historical/speculator_adjustment_activity.js +76 -76
- package/calculations/asset_metrics/asset_position_size.js +57 -57
- package/calculations/backtests/strategy-performance.js +229 -245
- package/calculations/behavioural/historical/asset_crowd_flow.js +165 -170
- package/calculations/behavioural/historical/drawdown_response.js +58 -58
- package/calculations/behavioural/historical/dumb-cohort-flow.js +249 -249
- package/calculations/behavioural/historical/gain_response.js +57 -57
- package/calculations/behavioural/historical/in_loss_asset_crowd_flow.js +98 -98
- package/calculations/behavioural/historical/in_profit_asset_crowd_flow.js +99 -99
- package/calculations/behavioural/historical/paper_vs_diamond_hands.js +39 -39
- package/calculations/behavioural/historical/position_count_pnl.js +67 -67
- package/calculations/behavioural/historical/smart-cohort-flow.js +250 -250
- package/calculations/behavioural/historical/smart_money_flow.js +165 -165
- package/calculations/behavioural/historical/user-investment-profile.js +412 -412
- package/calculations/capital_flow/historical/crowd-cash-flow-proxy.js +121 -121
- package/calculations/capital_flow/historical/deposit_withdrawal_percentage.js +117 -117
- package/calculations/capital_flow/historical/new_allocation_percentage.js +49 -49
- package/calculations/insights/daily_bought_vs_sold_count.js +55 -55
- package/calculations/insights/daily_buy_sell_sentiment_count.js +49 -49
- package/calculations/insights/daily_ownership_delta.js +55 -55
- package/calculations/insights/daily_total_positions_held.js +39 -39
- package/calculations/meta/capital_deployment_strategy.js +129 -137
- package/calculations/meta/capital_liquidation_performance.js +121 -163
- package/calculations/meta/capital_vintage_performance.js +121 -158
- package/calculations/meta/cash-flow-deployment.js +110 -124
- package/calculations/meta/cash-flow-liquidation.js +126 -142
- package/calculations/meta/crowd_sharpe_ratio_proxy.js +83 -91
- package/calculations/meta/profit_cohort_divergence.js +77 -91
- package/calculations/meta/smart-dumb-divergence-index.js +116 -138
- package/calculations/meta/social_flow_correlation.js +99 -125
- package/calculations/pnl/asset_pnl_status.js +46 -46
- package/calculations/pnl/historical/profitability_migration.js +57 -57
- package/calculations/pnl/historical/user_profitability_tracker.js +117 -117
- package/calculations/pnl/profitable_and_unprofitable_status.js +64 -64
- package/calculations/sectors/historical/diversification_pnl.js +76 -76
- package/calculations/sectors/historical/sector_rotation.js +67 -67
- package/calculations/sentiment/historical/crowd_conviction_score.js +80 -80
- package/calculations/socialPosts/social-asset-posts-trend.js +52 -52
- package/calculations/socialPosts/social-top-mentioned-words.js +102 -102
- package/calculations/socialPosts/social-topic-interest-evolution.js +53 -53
- package/calculations/socialPosts/social-word-mentions-trend.js +62 -62
- package/calculations/socialPosts/social_activity_aggregation.js +103 -103
- package/calculations/socialPosts/social_event_correlation.js +121 -121
- package/calculations/socialPosts/social_sentiment_aggregation.js +114 -114
- package/calculations/speculators/historical/risk_appetite_change.js +54 -54
- package/calculations/speculators/historical/tsl_effectiveness.js +74 -74
- package/index.js +33 -33
- package/package.json +32 -32
- package/utils/firestore_utils.js +76 -76
- package/utils/price_data_provider.js +142 -142
- package/utils/sector_mapping_provider.js +74 -74
- package/calculations/capital_flow/historical/reallocation_increase_percentage.js +0 -63
- package/calculations/speculators/stop_loss_distance_by_sector_short_long_breakdown.js +0 -91
- package/calculations/speculators/stop_loss_distance_by_ticker_short_long_breakdown.js +0 -73
|
@@ -1,159 +1,122 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* @fileoverview Meta-calculation (Pass 3) that tracks the performance
|
|
3
|
-
* of capital "vintages" by analyzing the market returns of assets
|
|
4
|
-
* that were bought following a crowd-wide deposit signal.
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
this.
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
// 3. Define performance windows
|
|
123
|
-
// "Before" window: 7 days leading up to the signal
|
|
124
|
-
const preSignalStart = this._getDateStr(signalDate, -this.PERFORMANCE_WINDOW_DAYS);
|
|
125
|
-
const preSignalEnd = signalDate;
|
|
126
|
-
|
|
127
|
-
// "After" window: 7 days starting from the deployment
|
|
128
|
-
const postDeployStart = deploymentDate;
|
|
129
|
-
const postDeployEnd = this._getDateStr(deploymentDate, this.PERFORMANCE_WINDOW_DAYS);
|
|
130
|
-
|
|
131
|
-
// 4. Calculate performance
|
|
132
|
-
const preSignalReturnPct = this._calculateBasketPerformance(
|
|
133
|
-
topAssets, preSignalStart, preSignalEnd
|
|
134
|
-
);
|
|
135
|
-
|
|
136
|
-
const postDeploymentReturnPct = this._calculateBasketPerformance(
|
|
137
|
-
topAssets, postDeployStart, postDeployEnd
|
|
138
|
-
);
|
|
139
|
-
|
|
140
|
-
const momentum = postDeploymentReturnPct - preSignalReturnPct;
|
|
141
|
-
|
|
142
|
-
return {
|
|
143
|
-
status: 'analysis_complete',
|
|
144
|
-
signal_date: signalDate,
|
|
145
|
-
deployment_date: deploymentDate,
|
|
146
|
-
performance_window_days: this.PERFORMANCE_WINDOW_DAYS,
|
|
147
|
-
deployed_assets: topAssets.map(a => a.ticker),
|
|
148
|
-
pre_signal_return_pct: preSignalReturnPct,
|
|
149
|
-
post_deployment_return_pct: postDeploymentReturnPct,
|
|
150
|
-
return_momentum: momentum,
|
|
151
|
-
interpretation: "Measures the 7-day return of deployed assets *after* deployment vs. 7-days *before* the signal."
|
|
152
|
-
};
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
async getResult() { return null; }
|
|
156
|
-
reset() {}
|
|
157
|
-
}
|
|
158
|
-
|
|
1
|
+
/**
|
|
2
|
+
* @fileoverview Meta-calculation (Pass 3) that tracks the performance
|
|
3
|
+
* of capital "vintages" by analyzing the market returns of assets
|
|
4
|
+
* that were bought following a crowd-wide deposit signal.
|
|
5
|
+
*/
|
|
6
|
+
|
|
7
|
+
class CapitalVintagePerformance {
|
|
8
|
+
constructor() {
|
|
9
|
+
this.PERFORMANCE_WINDOW_DAYS = 7;
|
|
10
|
+
this.dependenciesLoaded = false;
|
|
11
|
+
this.priceMap = null;
|
|
12
|
+
this.tickerToIdMap = null;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
async _loadDependencies(calculationUtils) {
|
|
16
|
+
if (this.dependenciesLoaded) return;
|
|
17
|
+
const { loadAllPriceData, loadInstrumentMappings } = calculationUtils;
|
|
18
|
+
const [priceData, mappings] = await Promise.all([
|
|
19
|
+
loadAllPriceData(),
|
|
20
|
+
loadInstrumentMappings()
|
|
21
|
+
]);
|
|
22
|
+
this.priceMap = priceData;
|
|
23
|
+
this.tickerToIdMap = {};
|
|
24
|
+
if (mappings && mappings.instrumentToTicker) {
|
|
25
|
+
for (const [id, ticker] of Object.entries(mappings.instrumentToTicker)) {
|
|
26
|
+
this.tickerToIdMap[ticker] = id;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
this.dependenciesLoaded = true;
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
_getDateStr(baseDateStr, daysOffset) {
|
|
33
|
+
const date = new Date(baseDateStr + 'T00:00:00Z');
|
|
34
|
+
date.setUTCDate(date.getUTCDate() + daysOffset);
|
|
35
|
+
return date.toISOString().slice(0, 10);
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
_calculateBasketPerformance(assets, startDateStr, endDateStr) {
|
|
39
|
+
if (!assets || assets.length === 0) return 0;
|
|
40
|
+
let totalReturn = 0;
|
|
41
|
+
let validAssets = 0;
|
|
42
|
+
for (const asset of assets) {
|
|
43
|
+
const ticker = asset.ticker;
|
|
44
|
+
const instrumentId = this.tickerToIdMap[ticker];
|
|
45
|
+
if (!instrumentId || !this.priceMap[instrumentId]) continue;
|
|
46
|
+
const startPrice = this.priceMap[instrumentId][startDateStr];
|
|
47
|
+
const endPrice = this.priceMap[instrumentId][endDateStr];
|
|
48
|
+
if (startPrice && endPrice && startPrice > 0) {
|
|
49
|
+
const assetReturn = (endPrice - startPrice) / startPrice;
|
|
50
|
+
totalReturn += assetReturn;
|
|
51
|
+
validAssets++;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
if (validAssets === 0) return 0;
|
|
55
|
+
return (totalReturn / validAssets) * 100;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* @param {string} dateStr The date to run the analysis for (e.g., "2025-10-31").
|
|
60
|
+
* @param {object} dependencies The shared dependencies (db, logger, calculationUtils).
|
|
61
|
+
* @param {object} config The computation system configuration.
|
|
62
|
+
* @param {object} computedDependencies In-memory results from previous passes.
|
|
63
|
+
* @returns {Promise<object|null>} The analysis result or null.
|
|
64
|
+
*/
|
|
65
|
+
async process(dateStr, dependencies, config, computedDependencies) {
|
|
66
|
+
const { db, logger, calculationUtils } = dependencies;
|
|
67
|
+
|
|
68
|
+
// 1. Load all price/mapping data
|
|
69
|
+
await this._loadDependencies(calculationUtils);
|
|
70
|
+
|
|
71
|
+
// 2. Get dependency from in-memory cache
|
|
72
|
+
const data = computedDependencies['cash-flow-deployment'];
|
|
73
|
+
|
|
74
|
+
if (!data || data.status !== 'analysis_complete') {
|
|
75
|
+
logger.log('WARN', `[CapitalVintage] Skipping ${dateStr}, no valid 'cash-flow-deployment' data found.`);
|
|
76
|
+
return null;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
const topAssets = data.top_deployment_assets; // [{ ticker: 'AAPL', ... }]
|
|
80
|
+
const signalDate = data.signal_date; // The day the deposit signal occurred
|
|
81
|
+
const deploymentDate = data.analysis_date; // The day the capital was spent (dateStr)
|
|
82
|
+
|
|
83
|
+
if (!topAssets || topAssets.length === 0) {
|
|
84
|
+
logger.log('INFO', `[CapitalVintage] No top assets deployed on ${dateStr}.`);
|
|
85
|
+
return { status: 'no_deployment' };
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// 3. Define performance windows
|
|
89
|
+
const preSignalStart = this._getDateStr(signalDate, -this.PERFORMANCE_WINDOW_DAYS);
|
|
90
|
+
const preSignalEnd = signalDate;
|
|
91
|
+
const postDeployStart = deploymentDate;
|
|
92
|
+
const postDeployEnd = this._getDateStr(deploymentDate, this.PERFORMANCE_WINDOW_DAYS);
|
|
93
|
+
|
|
94
|
+
// 4. Calculate performance
|
|
95
|
+
const preSignalReturnPct = this._calculateBasketPerformance(
|
|
96
|
+
topAssets, preSignalStart, preSignalEnd
|
|
97
|
+
);
|
|
98
|
+
|
|
99
|
+
const postDeploymentReturnPct = this._calculateBasketPerformance(
|
|
100
|
+
topAssets, postDeployStart, postDeployEnd
|
|
101
|
+
);
|
|
102
|
+
|
|
103
|
+
const momentum = postDeploymentReturnPct - preSignalReturnPct;
|
|
104
|
+
|
|
105
|
+
return {
|
|
106
|
+
status: 'analysis_complete',
|
|
107
|
+
signal_date: signalDate,
|
|
108
|
+
deployment_date: deploymentDate,
|
|
109
|
+
performance_window_days: this.PERFORMANCE_WINDOW_DAYS,
|
|
110
|
+
deployed_assets: topAssets.map(a => a.ticker),
|
|
111
|
+
pre_signal_return_pct: preSignalReturnPct,
|
|
112
|
+
post_deployment_return_pct: postDeploymentReturnPct,
|
|
113
|
+
return_momentum: momentum,
|
|
114
|
+
interpretation: "Measures the 7-day return of deployed assets *after* deployment vs. 7-days *before* the signal."
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
async getResult() { return null; }
|
|
119
|
+
reset() {}
|
|
120
|
+
}
|
|
121
|
+
|
|
159
122
|
module.exports = CapitalVintagePerformance;
|
|
@@ -1,125 +1,111 @@
|
|
|
1
|
-
const { FieldValue } = require('@google-cloud/firestore');
|
|
2
|
-
|
|
3
|
-
class CashFlowDeployment {
|
|
4
|
-
constructor() {
|
|
5
|
-
this.lookbackDays = 7;
|
|
6
|
-
this.correlationWindow = 3;
|
|
7
|
-
this.depositSignalThreshold = -0.005; // Formerly -1.0
|
|
8
|
-
}
|
|
9
|
-
|
|
10
|
-
_getDateStr(baseDate, daysAgo) {
|
|
11
|
-
const date = new Date(baseDate + 'T00:00:00Z');
|
|
12
|
-
date.setUTCDate(date.getUTCDate() - daysAgo);
|
|
13
|
-
return date.toISOString().slice(0, 10);
|
|
14
|
-
}
|
|
15
|
-
|
|
16
|
-
async process(dateStr, dependencies, config) {
|
|
17
|
-
const { db, logger } = dependencies;
|
|
18
|
-
const collection = config.resultsCollection;
|
|
19
|
-
|
|
20
|
-
//
|
|
21
|
-
const
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
}
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
const dataMap = new Map();
|
|
44
|
-
snapshots.forEach((snap, idx) => {
|
|
45
|
-
if (snap.exists) dataMap.set(idx, snap.data());
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
//
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
return {
|
|
76
|
-
status: '
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
};
|
|
80
|
-
}
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
analysis_date: dateStr,
|
|
112
|
-
signal_date: depositSignalDay,
|
|
113
|
-
days_since_signal: daysSinceSignal,
|
|
114
|
-
signal_deposit_proxy_pct: netDepositPct,
|
|
115
|
-
day_net_spend_pct: netSpendPct,
|
|
116
|
-
pct_of_deposit_deployed_today: (netSpendPct / netDepositPct) * 100,
|
|
117
|
-
top_deployment_assets: topBuys
|
|
118
|
-
};
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
async getResult() { return null; }
|
|
122
|
-
reset() {}
|
|
123
|
-
}
|
|
124
|
-
|
|
1
|
+
const { FieldValue } = require('@google-cloud/firestore');
|
|
2
|
+
|
|
3
|
+
class CashFlowDeployment {
|
|
4
|
+
constructor() {
|
|
5
|
+
this.lookbackDays = 7;
|
|
6
|
+
this.correlationWindow = 3;
|
|
7
|
+
this.depositSignalThreshold = -0.005; // Formerly -1.0
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
_getDateStr(baseDate, daysAgo) {
|
|
11
|
+
const date = new Date(baseDate + 'T00:00:00Z');
|
|
12
|
+
date.setUTCDate(date.getUTCDate() - daysAgo);
|
|
13
|
+
return date.toISOString().slice(0, 10);
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
async process(dateStr, dependencies, config, computedDependencies) {
|
|
17
|
+
const { db, logger } = dependencies;
|
|
18
|
+
const collection = config.resultsCollection;
|
|
19
|
+
|
|
20
|
+
// --- MODIFICATION: Get same-day dependencies from cache ---
|
|
21
|
+
const cashFlowData = computedDependencies['crowd-cash-flow-proxy'];
|
|
22
|
+
const assetFlowData = computedDependencies['asset-crowd-flow'];
|
|
23
|
+
|
|
24
|
+
if (!cashFlowData || !assetFlowData) {
|
|
25
|
+
logger.log('WARN', `[CashFlowDeployment] Missing critical in-memory dependency data for ${dateStr}. Skipping.`);
|
|
26
|
+
return null;
|
|
27
|
+
}
|
|
28
|
+
// --- END MODIFICATION ---
|
|
29
|
+
|
|
30
|
+
// --- Historical lookback for signal still uses Firestore ---
|
|
31
|
+
const refs = [];
|
|
32
|
+
const dates = [];
|
|
33
|
+
for (let i = 1; i <= this.lookbackDays; i++) {
|
|
34
|
+
const checkDate = this._getDateStr(dateStr, i);
|
|
35
|
+
dates.push({ date: checkDate, category: 'capital_flow', computation: 'crowd-cash-flow-proxy' });
|
|
36
|
+
}
|
|
37
|
+
const histRefs = dates.map(d =>
|
|
38
|
+
db.collection(collection).doc(d.date)
|
|
39
|
+
.collection('results').doc(d.category)
|
|
40
|
+
.collection('computations').doc(d.computation)
|
|
41
|
+
);
|
|
42
|
+
const snapshots = await db.getAll(...histRefs);
|
|
43
|
+
const dataMap = new Map();
|
|
44
|
+
snapshots.forEach((snap, idx) => {
|
|
45
|
+
if (snap.exists) dataMap.set(idx, snap.data());
|
|
46
|
+
});
|
|
47
|
+
// --- End historical lookback ---
|
|
48
|
+
|
|
49
|
+
|
|
50
|
+
// find deposit signal
|
|
51
|
+
let depositSignal = null;
|
|
52
|
+
let depositSignalDay = null;
|
|
53
|
+
|
|
54
|
+
for (let i = 0; i < this.lookbackDays; i++) {
|
|
55
|
+
const flowData = dataMap.get(i);
|
|
56
|
+
const dateUsed = dates[i].date;
|
|
57
|
+
if (flowData && flowData.cash_flow_effect_proxy < this.depositSignalThreshold) {
|
|
58
|
+
depositSignal = flowData;
|
|
59
|
+
depositSignalDay = dateUsed;
|
|
60
|
+
break;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
if (!depositSignal) {
|
|
65
|
+
return {
|
|
66
|
+
status: 'no_signal_found',
|
|
67
|
+
lookback_days: this.lookbackDays,
|
|
68
|
+
signal_threshold: this.depositSignalThreshold
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const daysSinceSignal = (new Date(dateStr) - new Date(depositSignalDay)) / (1000 * 60 * 60 * 24);
|
|
73
|
+
|
|
74
|
+
if (daysSinceSignal <= 0 || daysSinceSignal > this.correlationWindow) {
|
|
75
|
+
return {
|
|
76
|
+
status: 'outside_correlation_window',
|
|
77
|
+
signal_day: depositSignalDay,
|
|
78
|
+
days_since_signal: daysSinceSignal
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
// Use the in-memory data for today
|
|
83
|
+
const netSpendPct = cashFlowData.components?.trading_effect || 0;
|
|
84
|
+
const netDepositPct = Math.abs(depositSignal.cash_flow_effect_proxy);
|
|
85
|
+
|
|
86
|
+
const topBuys = Object.entries(assetFlowData)
|
|
87
|
+
.filter(([ticker, data]) => data.net_crowd_flow_pct > 0)
|
|
88
|
+
.sort(([, a], [, b]) => b.net_crowd_flow_pct - a.net_crowd_flow_pct)
|
|
89
|
+
.slice(0, 10)
|
|
90
|
+
.map(([ticker, data]) => ({
|
|
91
|
+
ticker,
|
|
92
|
+
net_flow_pct: data.net_crowd_flow_pct
|
|
93
|
+
}));
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
status: 'analysis_complete',
|
|
97
|
+
analysis_date: dateStr,
|
|
98
|
+
signal_date: depositSignalDay,
|
|
99
|
+
days_since_signal: daysSinceSignal,
|
|
100
|
+
signal_deposit_proxy_pct: netDepositPct,
|
|
101
|
+
day_net_spend_pct: netSpendPct,
|
|
102
|
+
pct_of_deposit_deployed_today: (netSpendPct / netDepositPct) * 100,
|
|
103
|
+
top_deployment_assets: topBuys
|
|
104
|
+
};
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
async getResult() { return null; }
|
|
108
|
+
reset() {}
|
|
109
|
+
}
|
|
110
|
+
|
|
125
111
|
module.exports = CashFlowDeployment;
|