bulltrackers-module 1.0.657 → 1.0.658
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.
|
@@ -346,5 +346,85 @@ router.get('/global-aum/:ticker', requireFirebaseAuth, async (req, res, next) =>
|
|
|
346
346
|
}
|
|
347
347
|
});
|
|
348
348
|
|
|
349
|
+
// GET /popular-investors/asset-distribution/:ticker - Get AUM distribution for a specific ticker
|
|
350
|
+
// Returns the distribution of AUM values for all Popular Investors that own this asset
|
|
351
|
+
router.get('/asset-distribution/:ticker', requireFirebaseAuth, async (req, res, next) => {
|
|
352
|
+
try {
|
|
353
|
+
const { db } = req.dependencies;
|
|
354
|
+
const { ticker } = req.params;
|
|
355
|
+
const { date } = req.query;
|
|
356
|
+
|
|
357
|
+
// Validate ticker
|
|
358
|
+
if (!ticker || typeof ticker !== 'string' || ticker.length === 0) {
|
|
359
|
+
return res.status(400).json({
|
|
360
|
+
success: false,
|
|
361
|
+
error: 'Invalid ticker symbol'
|
|
362
|
+
});
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
const tickerUpper = ticker.toUpperCase();
|
|
366
|
+
|
|
367
|
+
// Find the most recent available data (looks back up to 7 days)
|
|
368
|
+
const targetDate = date || new Date().toISOString().split('T')[0];
|
|
369
|
+
let computationData = null;
|
|
370
|
+
let foundDate = null;
|
|
371
|
+
|
|
372
|
+
// Look back up to 7 days to find available data
|
|
373
|
+
for (let i = 0; i < 7; i++) {
|
|
374
|
+
const checkDate = new Date(targetDate);
|
|
375
|
+
checkDate.setDate(checkDate.getDate() - i);
|
|
376
|
+
const dateKey = checkDate.toISOString().split('T')[0];
|
|
377
|
+
|
|
378
|
+
try {
|
|
379
|
+
const data = await getComputationResults(db, 'PIDailyAssetAUM', dateKey);
|
|
380
|
+
if (data && typeof data === 'object' && Object.keys(data).length > 0) {
|
|
381
|
+
computationData = data;
|
|
382
|
+
foundDate = dateKey;
|
|
383
|
+
break;
|
|
384
|
+
}
|
|
385
|
+
} catch (error) {
|
|
386
|
+
// Continue looking back
|
|
387
|
+
continue;
|
|
388
|
+
}
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
if (!computationData) {
|
|
392
|
+
return res.status(404).json({
|
|
393
|
+
success: false,
|
|
394
|
+
error: `No PIDailyAssetAUM data found for ticker ${tickerUpper} in the last 7 days`
|
|
395
|
+
});
|
|
396
|
+
}
|
|
397
|
+
|
|
398
|
+
// Extract AUM values for users that own this ticker
|
|
399
|
+
// Structure: { UserID: { Ticker: $Amount } }
|
|
400
|
+
const aumDistribution = [];
|
|
401
|
+
|
|
402
|
+
Object.entries(computationData).forEach(([userId, userAllocations]) => {
|
|
403
|
+
if (userAllocations && typeof userAllocations === 'object' && userAllocations[tickerUpper] !== undefined) {
|
|
404
|
+
const aumValue = Number(userAllocations[tickerUpper]);
|
|
405
|
+
if (aumValue > 0) {
|
|
406
|
+
aumDistribution.push({
|
|
407
|
+
userId: userId,
|
|
408
|
+
aum: aumValue
|
|
409
|
+
});
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
});
|
|
413
|
+
|
|
414
|
+
// Sort by AUM descending
|
|
415
|
+
aumDistribution.sort((a, b) => b.aum - a.aum);
|
|
416
|
+
|
|
417
|
+
res.json({
|
|
418
|
+
success: true,
|
|
419
|
+
ticker: tickerUpper,
|
|
420
|
+
date: foundDate,
|
|
421
|
+
count: aumDistribution.length,
|
|
422
|
+
data: aumDistribution
|
|
423
|
+
});
|
|
424
|
+
} catch (error) {
|
|
425
|
+
next(error);
|
|
426
|
+
}
|
|
427
|
+
});
|
|
428
|
+
|
|
349
429
|
|
|
350
430
|
module.exports = router;
|