bulltrackers-module 1.0.733 → 1.0.734

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 (56) hide show
  1. package/functions/computation-system-v2/README.md +152 -0
  2. package/functions/computation-system-v2/computations/PopularInvestorProfileMetrics.js +720 -0
  3. package/functions/computation-system-v2/computations/PopularInvestorRiskAssessment.js +176 -0
  4. package/functions/computation-system-v2/computations/PopularInvestorRiskMetrics.js +294 -0
  5. package/functions/computation-system-v2/computations/TestComputation.js +46 -0
  6. package/functions/computation-system-v2/computations/UserPortfolioSummary.js +172 -0
  7. package/functions/computation-system-v2/config/bulltrackers.config.js +317 -0
  8. package/functions/computation-system-v2/framework/core/Computation.js +73 -0
  9. package/functions/computation-system-v2/framework/core/Manifest.js +223 -0
  10. package/functions/computation-system-v2/framework/core/RuleInjector.js +53 -0
  11. package/functions/computation-system-v2/framework/core/Rules.js +231 -0
  12. package/functions/computation-system-v2/framework/core/RunAnalyzer.js +163 -0
  13. package/functions/computation-system-v2/framework/cost/CostTracker.js +154 -0
  14. package/functions/computation-system-v2/framework/data/DataFetcher.js +399 -0
  15. package/functions/computation-system-v2/framework/data/QueryBuilder.js +232 -0
  16. package/functions/computation-system-v2/framework/data/SchemaRegistry.js +287 -0
  17. package/functions/computation-system-v2/framework/execution/Orchestrator.js +498 -0
  18. package/functions/computation-system-v2/framework/execution/TaskRunner.js +35 -0
  19. package/functions/computation-system-v2/framework/execution/middleware/CostTrackerMiddleware.js +32 -0
  20. package/functions/computation-system-v2/framework/execution/middleware/LineageMiddleware.js +32 -0
  21. package/functions/computation-system-v2/framework/execution/middleware/Middleware.js +14 -0
  22. package/functions/computation-system-v2/framework/execution/middleware/ProfilerMiddleware.js +47 -0
  23. package/functions/computation-system-v2/framework/index.js +45 -0
  24. package/functions/computation-system-v2/framework/lineage/LineageTracker.js +147 -0
  25. package/functions/computation-system-v2/framework/monitoring/Profiler.js +80 -0
  26. package/functions/computation-system-v2/framework/resilience/Checkpointer.js +66 -0
  27. package/functions/computation-system-v2/framework/scheduling/ScheduleValidator.js +327 -0
  28. package/functions/computation-system-v2/framework/storage/StateRepository.js +286 -0
  29. package/functions/computation-system-v2/framework/storage/StorageManager.js +469 -0
  30. package/functions/computation-system-v2/framework/storage/index.js +9 -0
  31. package/functions/computation-system-v2/framework/testing/ComputationTester.js +86 -0
  32. package/functions/computation-system-v2/framework/utils/Graph.js +205 -0
  33. package/functions/computation-system-v2/handlers/dispatcher.js +109 -0
  34. package/functions/computation-system-v2/handlers/index.js +23 -0
  35. package/functions/computation-system-v2/handlers/onDemand.js +289 -0
  36. package/functions/computation-system-v2/handlers/scheduler.js +327 -0
  37. package/functions/computation-system-v2/index.js +163 -0
  38. package/functions/computation-system-v2/rules/index.js +49 -0
  39. package/functions/computation-system-v2/rules/instruments.js +465 -0
  40. package/functions/computation-system-v2/rules/metrics.js +304 -0
  41. package/functions/computation-system-v2/rules/portfolio.js +534 -0
  42. package/functions/computation-system-v2/rules/rankings.js +655 -0
  43. package/functions/computation-system-v2/rules/social.js +562 -0
  44. package/functions/computation-system-v2/rules/trades.js +545 -0
  45. package/functions/computation-system-v2/scripts/migrate-sectors.js +73 -0
  46. package/functions/computation-system-v2/test/test-dispatcher.js +317 -0
  47. package/functions/computation-system-v2/test/test-framework.js +500 -0
  48. package/functions/computation-system-v2/test/test-real-execution.js +166 -0
  49. package/functions/computation-system-v2/test/test-real-integration.js +194 -0
  50. package/functions/computation-system-v2/test/test-refactor-e2e.js +131 -0
  51. package/functions/computation-system-v2/test/test-results.json +31 -0
  52. package/functions/computation-system-v2/test/test-risk-metrics-computation.js +329 -0
  53. package/functions/computation-system-v2/test/test-scheduler.js +204 -0
  54. package/functions/computation-system-v2/test/test-storage.js +449 -0
  55. package/functions/orchestrator/index.js +18 -26
  56. package/package.json +3 -2
@@ -0,0 +1,655 @@
1
+ /**
2
+ * @fileoverview Rankings Business Rules
3
+ *
4
+ * For extracting and calculating metrics from pi_rankings data.
5
+ * The rankings_data JSON contains comprehensive investor metrics from eToro.
6
+ *
7
+ * Usage in computation:
8
+ * ```javascript
9
+ * const rankingsData = rules.rankings.extractRankingsData(row);
10
+ * const riskScore = rules.rankings.getRiskScore(rankingsData);
11
+ * const tier = rules.rankings.getAUMTier(rankingsData);
12
+ * ```
13
+ */
14
+
15
+ // =============================================================================
16
+ // DATA EXTRACTION
17
+ // =============================================================================
18
+
19
+ /**
20
+ * Extract rankings_data from a pi_rankings row.
21
+ * Handles both string JSON and parsed object.
22
+ *
23
+ * @param {Object} row - pi_rankings row
24
+ * @returns {Object|null} Parsed rankings data
25
+ */
26
+ function extractRankingsData(row) {
27
+ if (!row) return null;
28
+
29
+ let data = row.rankings_data;
30
+
31
+ if (typeof data === 'string') {
32
+ try {
33
+ data = JSON.parse(data);
34
+ } catch (e) {
35
+ return null;
36
+ }
37
+ }
38
+
39
+ return data || null;
40
+ }
41
+
42
+ /**
43
+ * Get the PI ID from a rankings row.
44
+ * @param {Object} row - pi_rankings row
45
+ * @returns {string|number|null}
46
+ */
47
+ function getPiId(row) {
48
+ return row?.pi_id || row?.CustomerId || null;
49
+ }
50
+
51
+ /**
52
+ * Get the username from a rankings row.
53
+ * @param {Object} row - pi_rankings row
54
+ * @returns {string|null}
55
+ */
56
+ function getUsername(row) {
57
+ return row?.username || row?.UserName || extractRankingsData(row)?.UserName || null;
58
+ }
59
+
60
+ // =============================================================================
61
+ // RISK METRICS
62
+ // =============================================================================
63
+
64
+ /**
65
+ * Get the risk score (0-10 integer).
66
+ * @param {Object} data - rankings_data object
67
+ * @returns {number}
68
+ */
69
+ function getRiskScore(data) {
70
+ return data?.RiskScore ?? 0;
71
+ }
72
+
73
+ /**
74
+ * Get max daily risk score.
75
+ * @param {Object} data - rankings_data object
76
+ * @returns {number}
77
+ */
78
+ function getMaxDailyRiskScore(data) {
79
+ return data?.MaxDailyRiskScore ?? 0;
80
+ }
81
+
82
+ /**
83
+ * Get max monthly risk score.
84
+ * @param {Object} data - rankings_data object
85
+ * @returns {number}
86
+ */
87
+ function getMaxMonthlyRiskScore(data) {
88
+ return data?.MaxMonthlyRiskScore ?? 0;
89
+ }
90
+
91
+ /**
92
+ * Get daily drawdown percentage (negative number).
93
+ * @param {Object} data - rankings_data object
94
+ * @returns {number}
95
+ */
96
+ function getDailyDrawdown(data) {
97
+ return data?.DailyDD ?? 0;
98
+ }
99
+
100
+ /**
101
+ * Get weekly drawdown percentage (negative number).
102
+ * @param {Object} data - rankings_data object
103
+ * @returns {number}
104
+ */
105
+ function getWeeklyDrawdown(data) {
106
+ return data?.WeeklyDD ?? 0;
107
+ }
108
+
109
+ /**
110
+ * Get peak to valley (max drawdown).
111
+ * @param {Object} data - rankings_data object
112
+ * @returns {number}
113
+ */
114
+ function getPeakToValley(data) {
115
+ return data?.PeakToValley ?? 0;
116
+ }
117
+
118
+ /**
119
+ * Categorize risk score into a tier.
120
+ * @param {number} riskScore - Risk score 0-10
121
+ * @returns {string} 'low' | 'medium' | 'high' | 'very_high'
122
+ */
123
+ function getRiskTier(riskScore) {
124
+ if (riskScore <= 3) return 'low';
125
+ if (riskScore <= 5) return 'medium';
126
+ if (riskScore <= 7) return 'high';
127
+ return 'very_high';
128
+ }
129
+
130
+ // =============================================================================
131
+ // PERFORMANCE METRICS
132
+ // =============================================================================
133
+
134
+ /**
135
+ * Get total gain percentage (2 full years + current year).
136
+ * @param {Object} data - rankings_data object
137
+ * @returns {number}
138
+ */
139
+ function getTotalGain(data) {
140
+ return data?.Gain ?? 0;
141
+ }
142
+
143
+ /**
144
+ * Get daily gain percentage.
145
+ * @param {Object} data - rankings_data object
146
+ * @returns {number}
147
+ */
148
+ function getDailyGain(data) {
149
+ return data?.DailyGain ?? 0;
150
+ }
151
+
152
+ /**
153
+ * Get this week's gain percentage.
154
+ * @param {Object} data - rankings_data object
155
+ * @returns {number}
156
+ */
157
+ function getWeeklyGain(data) {
158
+ return data?.ThisWeekGain ?? 0;
159
+ }
160
+
161
+ /**
162
+ * Get win ratio (0-100).
163
+ * @param {Object} data - rankings_data object
164
+ * @returns {number}
165
+ */
166
+ function getWinRatio(data) {
167
+ return data?.WinRatio ?? 0;
168
+ }
169
+
170
+ /**
171
+ * Get profitable weeks percentage.
172
+ * @param {Object} data - rankings_data object
173
+ * @returns {number}
174
+ */
175
+ function getProfitableWeeksPct(data) {
176
+ return data?.ProfitableWeeksPct ?? 0;
177
+ }
178
+
179
+ /**
180
+ * Get profitable months percentage.
181
+ * @param {Object} data - rankings_data object
182
+ * @returns {number}
183
+ */
184
+ function getProfitableMonthsPct(data) {
185
+ return data?.ProfitableMonthsPct ?? 0;
186
+ }
187
+
188
+ /**
189
+ * Get copiers gain (performance of copiers).
190
+ * @param {Object} data - rankings_data object
191
+ * @returns {number}
192
+ */
193
+ function getCopiersGain(data) {
194
+ return data?.CopiersGain ?? 0;
195
+ }
196
+
197
+ // =============================================================================
198
+ // AUM & COPIERS
199
+ // =============================================================================
200
+
201
+ /**
202
+ * Get AUM (Assets Under Management) in USD.
203
+ * @param {Object} data - rankings_data object
204
+ * @returns {number}
205
+ */
206
+ function getAUM(data) {
207
+ return data?.AUMValue ?? 0;
208
+ }
209
+
210
+ /**
211
+ * Get AUM tier (1-5).
212
+ * @param {Object} data - rankings_data object
213
+ * @returns {number}
214
+ */
215
+ function getAUMTier(data) {
216
+ return data?.AUMTier ?? 0;
217
+ }
218
+
219
+ /**
220
+ * Get AUM tier description.
221
+ * @param {Object} data - rankings_data object
222
+ * @returns {string}
223
+ */
224
+ function getAUMTierDesc(data) {
225
+ return data?.AUMTierDesc || 'Unknown';
226
+ }
227
+
228
+ /**
229
+ * Get current copiers count.
230
+ * @param {Object} data - rankings_data object
231
+ * @returns {number}
232
+ */
233
+ function getCopiers(data) {
234
+ return data?.Copiers ?? 0;
235
+ }
236
+
237
+ /**
238
+ * Get baseline copiers count.
239
+ * @param {Object} data - rankings_data object
240
+ * @returns {number}
241
+ */
242
+ function getBaselineCopiers(data) {
243
+ return data?.BaseLineCopiers ?? 0;
244
+ }
245
+
246
+ /**
247
+ * Calculate copier change from baseline.
248
+ * @param {Object} data - rankings_data object
249
+ * @returns {number}
250
+ */
251
+ function getCopierChange(data) {
252
+ const current = getCopiers(data);
253
+ const baseline = getBaselineCopiers(data);
254
+ return current - baseline;
255
+ }
256
+
257
+ /**
258
+ * Calculate copier change percentage.
259
+ * @param {Object} data - rankings_data object
260
+ * @returns {number}
261
+ */
262
+ function getCopierChangePct(data) {
263
+ const baseline = getBaselineCopiers(data);
264
+ if (baseline === 0) return 0;
265
+ return ((getCopiers(data) - baseline) / baseline) * 100;
266
+ }
267
+
268
+ // =============================================================================
269
+ // TRADING STYLE
270
+ // =============================================================================
271
+
272
+ /**
273
+ * Get exposure percentage.
274
+ * @param {Object} data - rankings_data object
275
+ * @returns {number}
276
+ */
277
+ function getExposure(data) {
278
+ return data?.Exposure ?? 0;
279
+ }
280
+
281
+ /**
282
+ * Get long position percentage.
283
+ * @param {Object} data - rankings_data object
284
+ * @returns {number}
285
+ */
286
+ function getLongPosPct(data) {
287
+ return data?.LongPosPct ?? 0;
288
+ }
289
+
290
+ /**
291
+ * Get short position percentage.
292
+ * @param {Object} data - rankings_data object
293
+ * @returns {number}
294
+ */
295
+ function getShortPosPct(data) {
296
+ return 100 - (data?.LongPosPct ?? 100);
297
+ }
298
+
299
+ /**
300
+ * Get average position size percentage.
301
+ * @param {Object} data - rankings_data object
302
+ * @returns {number}
303
+ */
304
+ function getAvgPosSize(data) {
305
+ return data?.AvgPosSize ?? 0;
306
+ }
307
+
308
+ /**
309
+ * Get total trades count.
310
+ * @param {Object} data - rankings_data object
311
+ * @returns {number}
312
+ */
313
+ function getTotalTrades(data) {
314
+ return data?.Trades ?? 0;
315
+ }
316
+
317
+ /**
318
+ * Get total traded instruments count.
319
+ * @param {Object} data - rankings_data object
320
+ * @returns {number}
321
+ */
322
+ function getTotalInstruments(data) {
323
+ return data?.TotalTradedInstruments ?? 0;
324
+ }
325
+
326
+ /**
327
+ * Get leverage breakdown.
328
+ * @param {Object} data - rankings_data object
329
+ * @returns {Object} { low, medium, high }
330
+ */
331
+ function getLeverageBreakdown(data) {
332
+ return {
333
+ low: data?.LowLeveragePct ?? 0,
334
+ medium: data?.MediumLeveragePct ?? 0,
335
+ high: data?.HighLeveragePct ?? 0
336
+ };
337
+ }
338
+
339
+ /**
340
+ * Determine primary trading style.
341
+ * @param {Object} data - rankings_data object
342
+ * @returns {string}
343
+ */
344
+ function getTradingStyle(data) {
345
+ const longPct = getLongPosPct(data);
346
+ const leverage = getLeverageBreakdown(data);
347
+ const trades = getTotalTrades(data);
348
+ const instruments = getTotalInstruments(data);
349
+
350
+ // Determine direction bias
351
+ let directionStyle = 'balanced';
352
+ if (longPct >= 80) directionStyle = 'long-only';
353
+ else if (longPct <= 20) directionStyle = 'short-focused';
354
+
355
+ // Determine leverage style
356
+ let leverageStyle = 'conservative';
357
+ if (leverage.high > 30) leverageStyle = 'aggressive';
358
+ else if (leverage.medium > 40) leverageStyle = 'moderate';
359
+
360
+ // Determine diversification
361
+ let diversification = 'concentrated';
362
+ if (instruments >= 20) diversification = 'diversified';
363
+ else if (instruments >= 10) diversification = 'moderate';
364
+
365
+ return `${directionStyle}, ${leverageStyle}, ${diversification}`;
366
+ }
367
+
368
+ // =============================================================================
369
+ // TOP ASSET INFO
370
+ // =============================================================================
371
+
372
+ /**
373
+ * Get top traded instrument ID.
374
+ * @param {Object} data - rankings_data object
375
+ * @returns {number|null}
376
+ */
377
+ function getTopInstrumentId(data) {
378
+ return data?.TopTradedInstrumentId || null;
379
+ }
380
+
381
+ /**
382
+ * Get top traded instrument percentage.
383
+ * @param {Object} data - rankings_data object
384
+ * @returns {number}
385
+ */
386
+ function getTopInstrumentPct(data) {
387
+ return data?.TopTradedInstrumentPct ?? 0;
388
+ }
389
+
390
+ /**
391
+ * Get top traded asset class ID.
392
+ * @param {Object} data - rankings_data object
393
+ * @returns {number|null}
394
+ */
395
+ function getTopAssetClassId(data) {
396
+ return data?.TopTradedAssetClassId || null;
397
+ }
398
+
399
+ /**
400
+ * Get tags array.
401
+ * @param {Object} data - rankings_data object
402
+ * @returns {number[]}
403
+ */
404
+ function getTags(data) {
405
+ return data?.Tags || [];
406
+ }
407
+
408
+ // =============================================================================
409
+ // ACTIVITY & STATUS
410
+ // =============================================================================
411
+
412
+ /**
413
+ * Get active weeks count.
414
+ * @param {Object} data - rankings_data object
415
+ * @returns {number}
416
+ */
417
+ function getActiveWeeks(data) {
418
+ return data?.ActiveWeeks ?? 0;
419
+ }
420
+
421
+ /**
422
+ * Get active weeks percentage.
423
+ * @param {Object} data - rankings_data object
424
+ * @returns {number}
425
+ */
426
+ function getActiveWeeksPct(data) {
427
+ return data?.ActiveWeeksPct ?? 0;
428
+ }
429
+
430
+ /**
431
+ * Get weeks since registration.
432
+ * @param {Object} data - rankings_data object
433
+ * @returns {number}
434
+ */
435
+ function getWeeksSinceRegistration(data) {
436
+ return data?.WeeksSinceRegistration ?? 0;
437
+ }
438
+
439
+ /**
440
+ * Get first activity date.
441
+ * @param {Object} data - rankings_data object
442
+ * @returns {Date|null}
443
+ */
444
+ function getFirstActivity(data) {
445
+ return data?.FirstActivity ? new Date(data.FirstActivity) : null;
446
+ }
447
+
448
+ /**
449
+ * Get last activity date.
450
+ * @param {Object} data - rankings_data object
451
+ * @returns {Date|null}
452
+ */
453
+ function getLastActivity(data) {
454
+ return data?.LastActivity ? new Date(data.LastActivity) : null;
455
+ }
456
+
457
+ /**
458
+ * Check if investor is verified.
459
+ * @param {Object} data - rankings_data object
460
+ * @returns {boolean}
461
+ */
462
+ function isVerified(data) {
463
+ return data?.Verified === true;
464
+ }
465
+
466
+ /**
467
+ * Check if investor is blocked.
468
+ * @param {Object} data - rankings_data object
469
+ * @returns {boolean}
470
+ */
471
+ function isBlocked(data) {
472
+ return data?.Blocked === true;
473
+ }
474
+
475
+ /**
476
+ * Check if investor is a Popular Investor.
477
+ * @param {Object} data - rankings_data object
478
+ * @returns {boolean}
479
+ */
480
+ function isPopularInvestor(data) {
481
+ return data?.PopularInvestor === true;
482
+ }
483
+
484
+ /**
485
+ * Get country.
486
+ * @param {Object} data - rankings_data object
487
+ * @returns {string}
488
+ */
489
+ function getCountry(data) {
490
+ return data?.Country || 'Unknown';
491
+ }
492
+
493
+ /**
494
+ * Get full name (if displayed).
495
+ * @param {Object} data - rankings_data object
496
+ * @returns {string|null}
497
+ */
498
+ function getFullName(data) {
499
+ return data?.DisplayFullName ? data.FullName : null;
500
+ }
501
+
502
+ // =============================================================================
503
+ // CALCULATED METRICS
504
+ // =============================================================================
505
+
506
+ /**
507
+ * Calculate a simple PI quality score (0-100).
508
+ * @param {Object} data - rankings_data object
509
+ * @returns {number}
510
+ */
511
+ function calculateQualityScore(data) {
512
+ let score = 50;
513
+
514
+ // Performance (+/- 20)
515
+ const gain = getTotalGain(data);
516
+ if (gain > 100) score += 20;
517
+ else if (gain > 50) score += 10;
518
+ else if (gain < 0) score -= 20;
519
+ else if (gain < 20) score -= 10;
520
+
521
+ // Risk (+/- 15)
522
+ const risk = getRiskScore(data);
523
+ if (risk <= 3) score += 15;
524
+ else if (risk <= 5) score += 5;
525
+ else if (risk >= 8) score -= 15;
526
+ else if (risk >= 7) score -= 5;
527
+
528
+ // Drawdown (+/- 10)
529
+ const drawdown = Math.abs(getPeakToValley(data));
530
+ if (drawdown < 15) score += 10;
531
+ else if (drawdown > 40) score -= 10;
532
+
533
+ // Win ratio (+/- 10)
534
+ const winRatio = getWinRatio(data);
535
+ if (winRatio >= 70) score += 10;
536
+ else if (winRatio < 50) score -= 10;
537
+
538
+ // Copiers (+/- 5)
539
+ const copierChange = getCopierChangePct(data);
540
+ if (copierChange > 10) score += 5;
541
+ else if (copierChange < -10) score -= 5;
542
+
543
+ return Math.max(0, Math.min(100, score));
544
+ }
545
+
546
+ /**
547
+ * Summarize a PI's key metrics.
548
+ * @param {Object} row - pi_rankings row
549
+ * @returns {Object}
550
+ */
551
+ function summarize(row) {
552
+ const data = extractRankingsData(row);
553
+ if (!data) return null;
554
+
555
+ return {
556
+ piId: getPiId(row),
557
+ username: getUsername(row),
558
+ rank: row?.rank,
559
+
560
+ // Performance
561
+ totalGain: getTotalGain(data),
562
+ weeklyGain: getWeeklyGain(data),
563
+ winRatio: getWinRatio(data),
564
+ profitableWeeksPct: getProfitableWeeksPct(data),
565
+
566
+ // Risk
567
+ riskScore: getRiskScore(data),
568
+ riskTier: getRiskTier(getRiskScore(data)),
569
+ maxDrawdown: getPeakToValley(data),
570
+
571
+ // AUM & Copiers
572
+ aum: getAUM(data),
573
+ aumTier: getAUMTierDesc(data),
574
+ copiers: getCopiers(data),
575
+ copierChange: getCopierChange(data),
576
+
577
+ // Trading style
578
+ exposure: getExposure(data),
579
+ longPct: getLongPosPct(data),
580
+ avgPosSize: getAvgPosSize(data),
581
+
582
+ // Quality
583
+ qualityScore: calculateQualityScore(data),
584
+
585
+ // Status
586
+ isVerified: isVerified(data),
587
+ country: getCountry(data)
588
+ };
589
+ }
590
+
591
+ module.exports = {
592
+ // Data extraction
593
+ extractRankingsData,
594
+ getPiId,
595
+ getUsername,
596
+
597
+ // Risk metrics
598
+ getRiskScore,
599
+ getMaxDailyRiskScore,
600
+ getMaxMonthlyRiskScore,
601
+ getDailyDrawdown,
602
+ getWeeklyDrawdown,
603
+ getPeakToValley,
604
+ getRiskTier,
605
+
606
+ // Performance metrics
607
+ getTotalGain,
608
+ getDailyGain,
609
+ getWeeklyGain,
610
+ getWinRatio,
611
+ getProfitableWeeksPct,
612
+ getProfitableMonthsPct,
613
+ getCopiersGain,
614
+
615
+ // AUM & Copiers
616
+ getAUM,
617
+ getAUMTier,
618
+ getAUMTierDesc,
619
+ getCopiers,
620
+ getBaselineCopiers,
621
+ getCopierChange,
622
+ getCopierChangePct,
623
+
624
+ // Trading style
625
+ getExposure,
626
+ getLongPosPct,
627
+ getShortPosPct,
628
+ getAvgPosSize,
629
+ getTotalTrades,
630
+ getTotalInstruments,
631
+ getLeverageBreakdown,
632
+ getTradingStyle,
633
+
634
+ // Top asset
635
+ getTopInstrumentId,
636
+ getTopInstrumentPct,
637
+ getTopAssetClassId,
638
+ getTags,
639
+
640
+ // Activity & Status
641
+ getActiveWeeks,
642
+ getActiveWeeksPct,
643
+ getWeeksSinceRegistration,
644
+ getFirstActivity,
645
+ getLastActivity,
646
+ isVerified,
647
+ isBlocked,
648
+ isPopularInvestor,
649
+ getCountry,
650
+ getFullName,
651
+
652
+ // Calculated
653
+ calculateQualityScore,
654
+ summarize
655
+ };