bulltrackers-module 1.0.192 → 1.0.194

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.
@@ -20,6 +20,57 @@ const pLimit = require('p-limit'); // Ensure p-limit is required
20
20
  */
21
21
  function groupByPass(manifest) { return manifest.reduce((acc, calc) => { (acc[calc.pass] = acc[calc.pass] || []).push(calc); return acc; }, {}); }
22
22
 
23
+ /**
24
+ * --- NEW HELPER: PASSIVE DATA VALIDATION ---
25
+ * Scans a result set for suspicious patterns (e.g., a field is NULL for 100% of tickers).
26
+ * Logs warnings but DOES NOT block the commit.
27
+ */
28
+ function validateResultPatterns(logger, calcName, results, category) {
29
+ // 1. Skip Speculators (Too sparse, nulls are expected)
30
+ if (category === 'speculator' || category === 'speculators') return;
31
+
32
+ const tickers = Object.keys(results);
33
+ const totalItems = tickers.length;
34
+
35
+ // 2. Need a decent sample size to judge patterns
36
+ if (totalItems < 5) return;
37
+
38
+ // 3. Get all keys from the first valid object
39
+ // We assume schema is roughly consistent across tickers
40
+ const sampleTicker = tickers.find(t => results[t] && typeof results[t] === 'object');
41
+ if (!sampleTicker) return;
42
+
43
+ const keys = Object.keys(results[sampleTicker]);
44
+
45
+ keys.forEach(key => {
46
+ // Skip internal keys or metadata
47
+ if (key.startsWith('_')) return;
48
+
49
+ let nullCount = 0;
50
+ let nanCount = 0;
51
+ let undefinedCount = 0;
52
+
53
+ for (const t of tickers) {
54
+ const val = results[t][key];
55
+ if (val === null) nullCount++;
56
+ if (val === undefined) undefinedCount++;
57
+ if (typeof val === 'number' && isNaN(val)) nanCount++;
58
+ }
59
+
60
+ // 4. Define Thresholds
61
+ // If 100% of data is NaN or Undefined, that's almost certainly a bug.
62
+ if (nanCount === totalItems) {
63
+ logger.log('ERROR', `[DataQuality] Calc '${calcName}' field '${key}' is NaN for 100% of ${totalItems} items. Code bug likely.`);
64
+ } else if (undefinedCount === totalItems) {
65
+ logger.log('ERROR', `[DataQuality] Calc '${calcName}' field '${key}' is UNDEFINED for 100% of ${totalItems} items. Code bug likely.`);
66
+ }
67
+ // 5. Nulls are tricky. warn if >90%, but don't error (might be valid logic like "no shorts")
68
+ else if (nullCount > (totalItems * 0.9)) {
69
+ logger.log('WARN', `[DataQuality] Calc '${calcName}' field '${key}' is NULL for ${nullCount}/${totalItems} items. Check logic if this is unexpected.`);
70
+ }
71
+ });
72
+ }
73
+
23
74
  /**
24
75
  * Checks if all root data dependencies for a given calculation are met.
25
76
  */
@@ -277,6 +328,11 @@ async function commitResults(stateObj, dStr, passName, config, deps, skipStatusW
277
328
  }
278
329
 
279
330
  if (Object.keys(standardRes).length) {
331
+ // --- NEW: Run Passive Validation ---
332
+ // We do this BEFORE marking it completed, but we do NOT stop the write.
333
+ validateResultPatterns(deps.logger, name, standardRes, calc.manifest.category);
334
+ // -----------------------------------
335
+
280
336
  standardRes._completed = true;
281
337
  writes.push({
282
338
  ref: deps.db.collection(config.resultsCollection).doc(dStr)
@@ -382,9 +438,14 @@ async function runBatchPriceComputation(config, deps, dateStrings, calcs, target
382
438
 
383
439
  // Optional Filtering for Subset Mode
384
440
  if (targetInstrumentIds.length > 0) {
385
- // (Logic omitted for brevity, but safe to include if strictly needed)
441
+ const requestedSet = new Set(targetInstrumentIds);
442
+ // Iterate over the loaded data and delete anything we didn't ask for
443
+ for (const loadedInstrumentId in pricesData) {
444
+ if (!requestedSet.has(loadedInstrumentId)) {
445
+ delete pricesData[loadedInstrumentId];
446
+ }
447
+ }
386
448
  }
387
-
388
449
  const writes = [];
389
450
 
390
451
  // --- CALCULATION PHASE ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.192",
3
+ "version": "1.0.194",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [