bulltrackers-module 1.0.716 → 1.0.717

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.
@@ -185,6 +185,12 @@ async function commitResults(stateObj, dStr, passName, config, deps, skipStatusW
185
185
 
186
186
  runMetrics.io.writes += 1;
187
187
 
188
+ // 4. Write to BigQuery (for analytics) - same structure as other computations
189
+ // Page computations store the full result object { cid1: {...}, cid2: {...}, ... } in result_data
190
+ await writeToBigQuery(result, name, dStr, calc.manifest.category, logger, false).catch(err => {
191
+ logger.log('WARN', `[BigQuery] Failed to write page computation ${name} for ${dStr}: ${err.message}`);
192
+ });
193
+
188
194
  if (isFinalFlush && calc.manifest.hash) {
189
195
  successUpdates[name] = {
190
196
  hash: calc.manifest.hash, simHash: simHash, resultHash: resultHash,
@@ -625,6 +625,11 @@ const SCHEMAS = {
625
625
  { name: 'instrument_id', type: 'INT64', mode: 'REQUIRED' },
626
626
  { name: 'insights_data', type: 'JSON', mode: 'REQUIRED' },
627
627
  { name: 'fetched_at', type: 'TIMESTAMP', mode: 'REQUIRED' }
628
+ ],
629
+ ticker_mappings: [
630
+ { name: 'instrument_id', type: 'INT64', mode: 'REQUIRED' },
631
+ { name: 'ticker', type: 'STRING', mode: 'REQUIRED' },
632
+ { name: 'last_updated', type: 'TIMESTAMP', mode: 'REQUIRED' }
628
633
  ]
629
634
  };
630
635
 
@@ -812,6 +817,27 @@ async function ensureInstrumentInsightsTable(logger = null) {
812
817
  );
813
818
  }
814
819
 
820
+ /**
821
+ * Ensure ticker_mappings table exists
822
+ * @param {object} logger - Logger instance
823
+ * @returns {Promise<Table>}
824
+ */
825
+ async function ensureTickerMappingsTable(logger = null) {
826
+ const datasetId = process.env.BIGQUERY_DATASET_ID || 'bulltrackers_data';
827
+ const tableId = 'ticker_mappings';
828
+ const schema = getSchema(tableId);
829
+
830
+ return await ensureTableExists(
831
+ datasetId,
832
+ tableId,
833
+ schema,
834
+ {
835
+ clusterFields: ['instrument_id']
836
+ },
837
+ logger
838
+ );
839
+ }
840
+
815
841
  /**
816
842
  * Query portfolio data from BigQuery
817
843
  * @param {string} dateStr - Date string (YYYY-MM-DD)
@@ -1631,6 +1657,60 @@ async function queryAssetPrices(startDateStr = null, endDateStr = null, instrume
1631
1657
  }
1632
1658
  }
1633
1659
 
1660
+ /**
1661
+ * Query ticker mappings from BigQuery
1662
+ * Returns data in format: { instrumentId: "TICKER", ... }
1663
+ * @param {object} logger - Logger instance
1664
+ * @returns {Promise<object|null>} Ticker mappings object, or null if not found/error
1665
+ */
1666
+ async function queryTickerMappings(logger = null) {
1667
+ if (process.env.BIGQUERY_ENABLED === 'false') {
1668
+ if (logger) logger.log('DEBUG', '[BigQuery] Ticker mappings query skipped (BIGQUERY_ENABLED=false)');
1669
+ return null;
1670
+ }
1671
+
1672
+ const datasetId = process.env.BIGQUERY_DATASET_ID || 'bulltrackers_data';
1673
+ const tablePath = `${datasetId}.ticker_mappings`;
1674
+
1675
+ try {
1676
+ const sqlQuery = `
1677
+ SELECT
1678
+ instrument_id,
1679
+ ticker
1680
+ FROM \`${tablePath}\`
1681
+ ORDER BY instrument_id ASC
1682
+ `;
1683
+
1684
+ if (logger) {
1685
+ logger.log('INFO', `[BigQuery] 🔍 Querying ticker mappings from ${tablePath}`);
1686
+ }
1687
+
1688
+ const rows = await query(sqlQuery, {}, logger);
1689
+
1690
+ if (!rows || rows.length === 0) {
1691
+ if (logger) logger.log('INFO', `[BigQuery] No ticker mappings found in ${tablePath}`);
1692
+ return null;
1693
+ }
1694
+
1695
+ // Transform to expected format: { instrumentId: "TICKER" }
1696
+ const mappings = {};
1697
+ for (const row of rows) {
1698
+ mappings[String(row.instrument_id)] = row.ticker;
1699
+ }
1700
+
1701
+ if (logger) {
1702
+ logger.log('INFO', `[BigQuery] ✅ Retrieved ${Object.keys(mappings).length} ticker mappings from ${tablePath}`);
1703
+ }
1704
+
1705
+ return mappings;
1706
+ } catch (error) {
1707
+ if (logger) {
1708
+ logger.log('WARN', `[BigQuery] Ticker mappings query failed for ${tablePath}: ${error.message}`);
1709
+ }
1710
+ return null;
1711
+ }
1712
+ }
1713
+
1634
1714
  module.exports = {
1635
1715
  getBigQueryClient,
1636
1716
  getOrCreateDataset,
@@ -1647,6 +1727,7 @@ module.exports = {
1647
1727
  ensurePIMasterListTable,
1648
1728
  ensurePIRankingsTable,
1649
1729
  ensureInstrumentInsightsTable,
1730
+ ensureTickerMappingsTable,
1650
1731
  queryPortfolioData,
1651
1732
  queryHistoryData,
1652
1733
  querySocialData,
@@ -1654,6 +1735,7 @@ module.exports = {
1654
1735
  queryPIMasterList,
1655
1736
  queryPIRankings,
1656
1737
  queryInstrumentInsights,
1738
+ queryTickerMappings,
1657
1739
  queryComputationResult,
1658
1740
  queryComputationResultsRange,
1659
1741
  checkExistingRows,
package/index.js CHANGED
@@ -65,6 +65,8 @@ const { runPopularInvestorFetch } = require('./functions
65
65
  const { backfillTaskEngineData } = require('./functions/maintenance/backfill-task-engine-data/index');
66
66
  const { backfillPIMasterListRankings } = require('./functions/maintenance/backfill-pi-master-list-rankings/index');
67
67
  const { backfillInstrumentInsights } = require('./functions/maintenance/backfill-instrument-insights/index');
68
+ const { backfillTickerMappings } = require('./functions/maintenance/backfill-ticker-mappings/index');
69
+ const { backfillPriceData } = require('./functions/maintenance/backfill-price-data-from-firestore/index');
68
70
 
69
71
  // Alert System
70
72
  const { handleAlertTrigger, handleComputationResultWrite, checkAndSendAllClearNotifications } = require('./functions/alert-system/index');
@@ -135,7 +137,9 @@ const maintenance = {
135
137
  // [NEW] BigQuery backfills
136
138
  backfillTaskEngineData,
137
139
  backfillPIMasterListRankings,
138
- backfillInstrumentInsights
140
+ backfillInstrumentInsights,
141
+ backfillTickerMappings,
142
+ backfillPriceData
139
143
  };
140
144
 
141
145
  const proxy = { handlePost };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bulltrackers-module",
3
- "version": "1.0.716",
3
+ "version": "1.0.717",
4
4
  "description": "Helper Functions for Bulltrackers.",
5
5
  "main": "index.js",
6
6
  "files": [