bulltrackers-module 1.0.768 → 1.0.770
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/functions/computation-system-v2/UserPortfolioMetrics.js +50 -0
- package/functions/computation-system-v2/computations/BehavioralAnomaly.js +557 -337
- package/functions/computation-system-v2/computations/GlobalAumPerAsset30D.js +103 -0
- package/functions/computation-system-v2/computations/PIDailyAssetAUM.js +134 -0
- package/functions/computation-system-v2/computations/PiFeatureVectors.js +227 -0
- package/functions/computation-system-v2/computations/PiRecommender.js +359 -0
- package/functions/computation-system-v2/computations/RiskScoreIncrease.js +13 -13
- package/functions/computation-system-v2/computations/SignedInUserMirrorHistory.js +138 -0
- package/functions/computation-system-v2/computations/SignedInUserPIProfileMetrics.js +106 -0
- package/functions/computation-system-v2/computations/SignedInUserProfileMetrics.js +324 -0
- package/functions/computation-system-v2/config/bulltrackers.config.js +30 -128
- package/functions/computation-system-v2/core-api.js +17 -9
- package/functions/computation-system-v2/data_schema_reference.MD +108 -0
- package/functions/computation-system-v2/devtools/builder/builder.js +362 -0
- package/functions/computation-system-v2/devtools/builder/examples/user-metrics.yaml +26 -0
- package/functions/computation-system-v2/devtools/index.js +36 -0
- package/functions/computation-system-v2/devtools/shared/MockDataFactory.js +235 -0
- package/functions/computation-system-v2/devtools/shared/SchemaTemplates.js +475 -0
- package/functions/computation-system-v2/devtools/shared/SystemIntrospector.js +517 -0
- package/functions/computation-system-v2/devtools/shared/index.js +16 -0
- package/functions/computation-system-v2/devtools/simulation/DAGAnalyzer.js +243 -0
- package/functions/computation-system-v2/devtools/simulation/MockDataFetcher.js +306 -0
- package/functions/computation-system-v2/devtools/simulation/MockStorageManager.js +336 -0
- package/functions/computation-system-v2/devtools/simulation/SimulationEngine.js +525 -0
- package/functions/computation-system-v2/devtools/simulation/SimulationServer.js +581 -0
- package/functions/computation-system-v2/devtools/simulation/index.js +17 -0
- package/functions/computation-system-v2/devtools/simulation/simulate.js +324 -0
- package/functions/computation-system-v2/devtools/vscode-computation/package.json +90 -0
- package/functions/computation-system-v2/devtools/vscode-computation/snippets/computation.json +128 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/extension.ts +401 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/codeActions.ts +152 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/completions.ts +207 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/diagnostics.ts +205 -0
- package/functions/computation-system-v2/devtools/vscode-computation/src/providers/hover.ts +205 -0
- package/functions/computation-system-v2/devtools/vscode-computation/tsconfig.json +22 -0
- package/functions/computation-system-v2/docs/HowToCreateComputations.MD +602 -0
- package/functions/computation-system-v2/framework/data/DataFetcher.js +250 -184
- package/functions/computation-system-v2/framework/data/MaterializedViewManager.js +84 -0
- package/functions/computation-system-v2/framework/data/QueryBuilder.js +38 -38
- package/functions/computation-system-v2/framework/execution/Orchestrator.js +215 -129
- package/functions/computation-system-v2/framework/scheduling/ScheduleValidator.js +17 -19
- package/functions/computation-system-v2/framework/storage/StateRepository.js +32 -2
- package/functions/computation-system-v2/framework/storage/StorageManager.js +105 -67
- package/functions/computation-system-v2/framework/testing/ComputationTester.js +12 -6
- package/functions/computation-system-v2/handlers/dispatcher.js +57 -29
- package/functions/computation-system-v2/handlers/scheduler.js +172 -203
- package/functions/computation-system-v2/legacy/PiAssetRecommender.js.old +115 -0
- package/functions/computation-system-v2/legacy/PiSimilarityMatrix.js +104 -0
- package/functions/computation-system-v2/legacy/PiSimilarityVector.js +71 -0
- package/functions/computation-system-v2/scripts/debug_aggregation.js +25 -0
- package/functions/computation-system-v2/scripts/test-invalidation-scenarios.js +234 -0
- package/package.json +1 -1
|
@@ -14,6 +14,8 @@ const rules = require('../rules');
|
|
|
14
14
|
const fs = require('fs');
|
|
15
15
|
const path = require('path');
|
|
16
16
|
|
|
17
|
+
const RESULT_TABLE_NAME = 'computation_results_v3';
|
|
18
|
+
|
|
17
19
|
// Dynamic Computation Loader
|
|
18
20
|
function loadComputations() {
|
|
19
21
|
const computationsDir = path.join(__dirname, '../computations');
|
|
@@ -73,7 +75,7 @@ module.exports = {
|
|
|
73
75
|
// Each table entry tells the framework:
|
|
74
76
|
// - dateField: Which column is used for date partitioning (null if not partitioned)
|
|
75
77
|
// - entityField: Which column identifies the entity (user, asset, etc.)
|
|
76
|
-
// -
|
|
78
|
+
// - clusterFields: Which columns are clustered (sorted) for optimization
|
|
77
79
|
//
|
|
78
80
|
// The framework will automatically discover the full schema from BigQuery.
|
|
79
81
|
// These hints just tell it how to interpret the data.
|
|
@@ -84,7 +86,7 @@ module.exports = {
|
|
|
84
86
|
'portfolio_snapshots': {
|
|
85
87
|
dateField: 'date',
|
|
86
88
|
entityField: 'user_id',
|
|
87
|
-
|
|
89
|
+
clusterFields: ['user_type', 'user_id'], // Clustered by user_type, user_id
|
|
88
90
|
description: 'Daily portfolio snapshots for all users'
|
|
89
91
|
},
|
|
90
92
|
|
|
@@ -92,7 +94,7 @@ module.exports = {
|
|
|
92
94
|
'trade_history_snapshots': {
|
|
93
95
|
dateField: 'date',
|
|
94
96
|
entityField: 'user_id',
|
|
95
|
-
|
|
97
|
+
clusterFields: ['user_type', 'user_id'], // Clustered by user_type, user_id
|
|
96
98
|
description: 'Daily trade history snapshots'
|
|
97
99
|
},
|
|
98
100
|
|
|
@@ -100,7 +102,7 @@ module.exports = {
|
|
|
100
102
|
'social_post_snapshots': {
|
|
101
103
|
dateField: 'date',
|
|
102
104
|
entityField: 'user_id',
|
|
103
|
-
|
|
105
|
+
clusterFields: ['user_type', 'user_id'], // Clustered by user_type, user_id
|
|
104
106
|
description: 'Daily social post snapshots'
|
|
105
107
|
},
|
|
106
108
|
|
|
@@ -108,7 +110,7 @@ module.exports = {
|
|
|
108
110
|
'asset_prices': {
|
|
109
111
|
dateField: 'date',
|
|
110
112
|
entityField: 'instrument_id',
|
|
111
|
-
|
|
113
|
+
clusterFields: ['ticker', 'instrument_id'], // Clustered by ticker, instrument_id
|
|
112
114
|
description: 'Daily asset prices'
|
|
113
115
|
},
|
|
114
116
|
|
|
@@ -116,7 +118,7 @@ module.exports = {
|
|
|
116
118
|
'pi_rankings': {
|
|
117
119
|
dateField: 'date',
|
|
118
120
|
entityField: 'pi_id',
|
|
119
|
-
|
|
121
|
+
clusterFields: ['pi_id', 'category'], // Clustered by pi_id, category
|
|
120
122
|
description: 'Daily PI rankings snapshot'
|
|
121
123
|
},
|
|
122
124
|
|
|
@@ -124,7 +126,7 @@ module.exports = {
|
|
|
124
126
|
'pi_master_list': {
|
|
125
127
|
dateField: null, // Not date-partitioned
|
|
126
128
|
entityField: 'cid',
|
|
127
|
-
|
|
129
|
+
clusterFields: ['cid'], // Clustered by cid
|
|
128
130
|
description: 'Master list of all Popular Investors'
|
|
129
131
|
},
|
|
130
132
|
|
|
@@ -132,7 +134,7 @@ module.exports = {
|
|
|
132
134
|
'pi_ratings': {
|
|
133
135
|
dateField: 'date',
|
|
134
136
|
entityField: 'pi_id',
|
|
135
|
-
|
|
137
|
+
clusterFields: ['pi_id'], // Clustered by pi_id
|
|
136
138
|
description: 'Daily PI ratings'
|
|
137
139
|
},
|
|
138
140
|
|
|
@@ -140,7 +142,7 @@ module.exports = {
|
|
|
140
142
|
'pi_page_views': {
|
|
141
143
|
dateField: 'date',
|
|
142
144
|
entityField: 'pi_id',
|
|
143
|
-
|
|
145
|
+
clusterFields: ['pi_id'], // Clustered by pi_id
|
|
144
146
|
description: 'Daily PI page view metrics'
|
|
145
147
|
},
|
|
146
148
|
|
|
@@ -148,7 +150,7 @@ module.exports = {
|
|
|
148
150
|
'watchlist_membership': {
|
|
149
151
|
dateField: 'date',
|
|
150
152
|
entityField: 'pi_id',
|
|
151
|
-
|
|
153
|
+
clusterFields: ['pi_id'], // Clustered by pi_id
|
|
152
154
|
description: 'Daily watchlist membership counts'
|
|
153
155
|
},
|
|
154
156
|
|
|
@@ -156,7 +158,7 @@ module.exports = {
|
|
|
156
158
|
'pi_alert_history': {
|
|
157
159
|
dateField: 'date',
|
|
158
160
|
entityField: 'pi_id',
|
|
159
|
-
|
|
161
|
+
clusterFields: ['pi_id', 'alert_type'], // Clustered by pi_id, alert_type
|
|
160
162
|
description: 'Daily alert trigger history'
|
|
161
163
|
},
|
|
162
164
|
|
|
@@ -164,7 +166,7 @@ module.exports = {
|
|
|
164
166
|
'instrument_insights': {
|
|
165
167
|
dateField: 'date',
|
|
166
168
|
entityField: 'instrument_id',
|
|
167
|
-
//
|
|
169
|
+
// Note: Clustering not specified in metadata provided, assuming similar to others or unclustered
|
|
168
170
|
description: 'Daily instrument insights'
|
|
169
171
|
},
|
|
170
172
|
|
|
@@ -172,30 +174,32 @@ module.exports = {
|
|
|
172
174
|
'ticker_mappings': {
|
|
173
175
|
dateField: null,
|
|
174
176
|
entityField: 'instrument_id',
|
|
175
|
-
|
|
177
|
+
clusterFields: ['instrument_id'], // Clustered by instrument_id
|
|
176
178
|
description: 'Instrument ID to ticker symbol mappings'
|
|
177
179
|
},
|
|
178
180
|
|
|
179
181
|
// Computation Results
|
|
180
182
|
'computation_results': {
|
|
183
|
+
tableName: RESULT_TABLE_NAME,
|
|
181
184
|
dateField: 'date',
|
|
182
185
|
entityField: null, // Keyed by computation_name
|
|
183
|
-
|
|
186
|
+
clusterFields: ['computation_name', 'category'], // Optimization for result lookups
|
|
184
187
|
description: 'Stored computation results'
|
|
185
188
|
},
|
|
186
|
-
|
|
189
|
+
|
|
190
|
+
// Sector Mappings Table
|
|
187
191
|
'sector_mappings': {
|
|
188
192
|
dateField: null, // Static data
|
|
189
|
-
entityField: 'symbol',
|
|
190
|
-
//
|
|
193
|
+
entityField: 'symbol',
|
|
194
|
+
// Assuming fast lookup on symbol is desired
|
|
191
195
|
description: 'Ticker to Sector mappings migrated from Firestore'
|
|
192
196
|
},
|
|
193
197
|
|
|
194
|
-
//
|
|
198
|
+
// Behavioral Features
|
|
195
199
|
'behavioral_features': {
|
|
196
200
|
tableName: 'daily_behavioral_features',
|
|
197
201
|
dateField: 'date',
|
|
198
|
-
entityField: 'user_id',
|
|
202
|
+
entityField: 'user_id',
|
|
199
203
|
schema: [
|
|
200
204
|
{ name: 'user_id', type: 'STRING' },
|
|
201
205
|
{ name: 'hhi_score', type: 'FLOAT' },
|
|
@@ -205,23 +209,20 @@ module.exports = {
|
|
|
205
209
|
},
|
|
206
210
|
|
|
207
211
|
// NEW: Data to load globally for every computation
|
|
212
|
+
// FIX: Define fields to satisfy QueryBuilder safety checks
|
|
208
213
|
referenceData: [
|
|
209
|
-
|
|
214
|
+
{
|
|
215
|
+
table: 'sector_mappings',
|
|
216
|
+
fields: ['symbol', 'sector'] // Adjust these column names if your DB differs
|
|
217
|
+
}
|
|
210
218
|
],
|
|
211
219
|
|
|
212
220
|
// =========================================================================
|
|
213
221
|
// RESULT STORAGE CONFIGURATION
|
|
214
222
|
// =========================================================================
|
|
215
|
-
//
|
|
216
|
-
// Using a separate v2 table to avoid conflicts with v1 schema.
|
|
217
|
-
// v1 table: computation_results (date, computation_name, category, result_data, metadata, created_at)
|
|
218
|
-
// v2 table: computation_results_v2 (with entity_id, code_hash, etc.)
|
|
219
|
-
// =========================================================================
|
|
220
223
|
|
|
221
224
|
resultStore: {
|
|
222
|
-
|
|
223
|
-
// Jobs-based inserts are FREE and don't have streaming buffer issues
|
|
224
|
-
table: 'computation_results_v3',
|
|
225
|
+
table: RESULT_TABLE_NAME,
|
|
225
226
|
partitionField: 'date',
|
|
226
227
|
clusterFields: ['computation_name', 'category']
|
|
227
228
|
},
|
|
@@ -229,19 +230,12 @@ module.exports = {
|
|
|
229
230
|
// =========================================================================
|
|
230
231
|
// COMPUTATIONS
|
|
231
232
|
// =========================================================================
|
|
232
|
-
//
|
|
233
|
-
// Computations are registered here. During development, we add them one
|
|
234
|
-
// by one as they're migrated from v1.
|
|
235
|
-
// =========================================================================
|
|
236
233
|
|
|
237
234
|
computations: loadComputations(),
|
|
238
235
|
|
|
239
236
|
// =========================================================================
|
|
240
237
|
// PREDEFINED FILTER SETS
|
|
241
238
|
// =========================================================================
|
|
242
|
-
//
|
|
243
|
-
// Computations can reference these by name instead of hardcoding filters.
|
|
244
|
-
// =========================================================================
|
|
245
239
|
|
|
246
240
|
filterSets: {
|
|
247
241
|
'popular_investors': {
|
|
@@ -258,14 +252,6 @@ module.exports = {
|
|
|
258
252
|
// =========================================================================
|
|
259
253
|
// BUSINESS RULES
|
|
260
254
|
// =========================================================================
|
|
261
|
-
//
|
|
262
|
-
// Rules are automatically injected into computations.
|
|
263
|
-
// When a rule changes, all computations using it are re-run.
|
|
264
|
-
//
|
|
265
|
-
// Usage in computation:
|
|
266
|
-
// const positions = rules.portfolio.extractPositions(data);
|
|
267
|
-
// const sharpe = rules.metrics.calculateSharpeRatio(returns);
|
|
268
|
-
// =========================================================================
|
|
269
255
|
|
|
270
256
|
rules,
|
|
271
257
|
|
|
@@ -274,54 +260,28 @@ module.exports = {
|
|
|
274
260
|
// =========================================================================
|
|
275
261
|
|
|
276
262
|
execution: {
|
|
277
|
-
// Max concurrent entity processing (per-entity computations)
|
|
278
|
-
// Higher = faster but more memory. Tune based on your Cloud Function memory.
|
|
279
263
|
entityConcurrency: 50,
|
|
280
|
-
|
|
281
|
-
// Batch size for BigQuery inserts
|
|
282
264
|
insertBatchSize: 500,
|
|
283
|
-
|
|
284
265
|
fetchBatchSize: 30000,
|
|
285
|
-
|
|
286
|
-
// Memory safety: max entities to load for a dependency
|
|
287
|
-
// If a dependency has more entities than this, use getDependency(name, entityId) instead
|
|
288
|
-
// This prevents OOM when running many concurrent per-entity computations
|
|
289
|
-
// Example: 20 concurrent * 50KB per entity * 50000 entities = 50GB (bad!)
|
|
290
|
-
// With limit: 20 concurrent * 50KB per entity * 10000 entities = 10GB (still risky at 2GB RAM)
|
|
291
|
-
// Recommendation: Set this based on your Cloud Function memory
|
|
292
266
|
maxDependencyEntities: 10000
|
|
293
267
|
},
|
|
294
268
|
|
|
295
269
|
// =========================================================================
|
|
296
270
|
// SCHEDULING CONFIGURATION
|
|
297
271
|
// =========================================================================
|
|
298
|
-
//
|
|
299
|
-
// Controls how computations are scheduled and dispatched.
|
|
300
|
-
// Cloud Tasks handles throttling and retry via queue configuration.
|
|
301
|
-
// =========================================================================
|
|
302
272
|
|
|
303
273
|
scheduling: {
|
|
304
|
-
// Default schedule for computations that don't declare one
|
|
305
274
|
default: {
|
|
306
275
|
frequency: 'daily',
|
|
307
276
|
time: '02:00',
|
|
308
277
|
timezone: 'UTC'
|
|
309
278
|
},
|
|
310
|
-
|
|
311
|
-
// Minimum gap between dependent computations (minutes).
|
|
312
|
-
// When a computation completes, its direct dependents are scheduled
|
|
313
|
-
// via Cloud Tasks to run at least this many minutes after the latest
|
|
314
|
-
// dependency completion time (see Orchestrator._scheduleDependents).
|
|
315
279
|
dependencyGapMinutes: 5
|
|
316
280
|
},
|
|
317
281
|
|
|
318
282
|
// =========================================================================
|
|
319
283
|
// CLOUD TASKS CONFIGURATION
|
|
320
284
|
// =========================================================================
|
|
321
|
-
//
|
|
322
|
-
// Single queue handles all scheduled triggers.
|
|
323
|
-
// Queue settings (maxConcurrent, retry) are configured in GCP, not here.
|
|
324
|
-
// =========================================================================
|
|
325
285
|
|
|
326
286
|
cloudTasks: {
|
|
327
287
|
projectId: process.env.GCP_PROJECT_ID || 'stocks-12345',
|
|
@@ -329,8 +289,6 @@ module.exports = {
|
|
|
329
289
|
queueName: 'computation-triggers',
|
|
330
290
|
dispatcherUrl: process.env.DISPATCHER_URL ||
|
|
331
291
|
'https://europe-west1-stocks-12345.cloudfunctions.net/compute-dispatcher',
|
|
332
|
-
// Service account for OIDC authentication when invoking Dispatcher
|
|
333
|
-
// This SA needs roles/cloudfunctions.invoker on the Dispatcher function
|
|
334
292
|
serviceAccountEmail: process.env.CLOUD_TASKS_SA_EMAIL ||
|
|
335
293
|
'879684846540-compute@developer.gserviceaccount.com'
|
|
336
294
|
},
|
|
@@ -338,86 +296,30 @@ module.exports = {
|
|
|
338
296
|
// =========================================================================
|
|
339
297
|
// ON-DEMAND API CONFIGURATION
|
|
340
298
|
// =========================================================================
|
|
341
|
-
//
|
|
342
|
-
// Frontend-triggered computation requests.
|
|
343
|
-
// Routes through Dispatcher for validation.
|
|
344
|
-
// =========================================================================
|
|
345
299
|
|
|
346
300
|
onDemand: {
|
|
347
|
-
// Rate limiting per user
|
|
348
301
|
maxRequestsPerMinute: 5,
|
|
349
|
-
|
|
350
|
-
// Request timeout (ms) - frontend is waiting
|
|
351
302
|
timeout: 60000,
|
|
352
|
-
|
|
353
|
-
// Which computations can be triggered on-demand
|
|
354
|
-
// null = all computations allowed
|
|
355
|
-
// array = only listed computations allowed
|
|
356
303
|
allowedComputations: null
|
|
357
304
|
},
|
|
358
305
|
|
|
359
306
|
// =========================================================================
|
|
360
307
|
// WORKER POOL CONFIGURATION (SERVERLESS WORKERS)
|
|
361
308
|
// =========================================================================
|
|
362
|
-
//
|
|
363
|
-
// Enables offloading per-entity computations to a serverless worker pool.
|
|
364
|
-
// Workers run as separate Cloud Functions with high concurrency.
|
|
365
|
-
//
|
|
366
|
-
// Benefits:
|
|
367
|
-
// - Massive parallelism (100s of concurrent entity computations)
|
|
368
|
-
// - Cost efficient (workers scale to zero, high concurrency per instance)
|
|
369
|
-
// - Fault isolation (one entity failure doesn't affect others)
|
|
370
|
-
// - Memory efficient (workers only load one entity's data at a time)
|
|
371
|
-
//
|
|
372
|
-
// Data Flow:
|
|
373
|
-
// 1. Orchestrator packages entity data → GCS
|
|
374
|
-
// 2. Orchestrator invokes workers in parallel
|
|
375
|
-
// 3. Workers load data from GCS, execute, return result
|
|
376
|
-
// 4. Orchestrator collects results, commits to storage
|
|
377
|
-
// =========================================================================
|
|
378
309
|
|
|
379
310
|
workerPool: {
|
|
380
|
-
// Master switch - set to true to enable worker pool
|
|
381
311
|
enabled: process.env.WORKER_POOL_ENABLED === 'true',
|
|
382
|
-
|
|
383
|
-
// Local mode for testing - runs workers in-process without GCS/HTTP
|
|
384
|
-
// Set WORKER_LOCAL_MODE=true or pass localMode: true in config
|
|
385
312
|
localMode: process.env.WORKER_LOCAL_MODE === 'true',
|
|
386
|
-
|
|
387
|
-
// Worker Cloud Function URL
|
|
388
313
|
workerUrl: process.env.WORKER_URL ||
|
|
389
314
|
'https://europe-west1-stocks-12345.cloudfunctions.net/computation-worker',
|
|
390
|
-
|
|
391
|
-
// GCS bucket for temporary context packages
|
|
392
|
-
// Should have lifecycle rule to auto-delete after 1 day
|
|
393
315
|
tempBucket: process.env.WORKER_TEMP_BUCKET || 'bulltrackers-worker-staging',
|
|
394
|
-
|
|
395
|
-
// Max concurrent worker invocations
|
|
396
|
-
// Higher = faster but more network/GCS load
|
|
397
|
-
// Recommended: 100-200 for production
|
|
398
316
|
concurrency: 100,
|
|
399
|
-
|
|
400
|
-
// Worker invocation timeout (ms)
|
|
401
|
-
// Should be slightly less than worker function timeout
|
|
402
317
|
timeout: parseInt(process.env.WORKER_TIMEOUT || '60000', 10),
|
|
403
|
-
|
|
404
|
-
// Retry count for transient failures
|
|
405
318
|
retries: 2,
|
|
406
|
-
|
|
407
|
-
// Minimum entities to trigger worker pool
|
|
408
|
-
// Below this threshold, run locally (overhead not worth it)
|
|
409
|
-
minEntitiesForOffload: parseInt(process.env.WORKER_MIN_ENTITIES || '50', 10),
|
|
410
|
-
|
|
411
|
-
// Computations that should NEVER use worker pool
|
|
412
|
-
// (e.g., need persistent state, special middleware)
|
|
319
|
+
minEntitiesForOffload: 100, // Fixed duplicate key issue (removed the lower value)
|
|
413
320
|
excludeComputations: [],
|
|
414
|
-
|
|
415
|
-
// Computations that MUST use worker pool (override threshold)
|
|
416
|
-
// Useful for testing specific computations
|
|
417
321
|
forceOffloadComputations: process.env.WORKER_FORCE_COMPUTATIONS
|
|
418
322
|
? process.env.WORKER_FORCE_COMPUTATIONS.split(',')
|
|
419
323
|
: [],
|
|
420
|
-
|
|
421
|
-
minEntitiesForOffload: 100,
|
|
422
324
|
}
|
|
423
325
|
};
|
|
@@ -4,14 +4,15 @@
|
|
|
4
4
|
* Separated from index.js to prevent circular dependencies with handlers.
|
|
5
5
|
*/
|
|
6
6
|
|
|
7
|
-
const { Orchestrator } = require('./framework');
|
|
7
|
+
const { Orchestrator } = require('./framework/execution/Orchestrator');
|
|
8
8
|
const config = require('./config/bulltrackers.config');
|
|
9
|
-
const { ManifestBuilder } = require('./framework/core/Manifest');
|
|
10
|
-
const { Computation } = require('./framework/core/Computation');
|
|
11
9
|
|
|
12
10
|
// Singleton orchestrator instance
|
|
13
11
|
let orchestrator = null;
|
|
14
12
|
|
|
13
|
+
/**
|
|
14
|
+
* Lazy-load the orchestrator (Singleton)
|
|
15
|
+
*/
|
|
15
16
|
async function getOrchestrator(customConfig = null, logger = null) {
|
|
16
17
|
if (!orchestrator || customConfig) {
|
|
17
18
|
const cfg = customConfig || config;
|
|
@@ -60,20 +61,27 @@ async function warmCache(options = {}) {
|
|
|
60
61
|
return orch.schemaRegistry.warmCache(allTables);
|
|
61
62
|
}
|
|
62
63
|
|
|
64
|
+
/**
|
|
65
|
+
* NEW: Trigger Fan-Out for Deployment
|
|
66
|
+
* Uses getOrchestrator to ensure initialization.
|
|
67
|
+
*/
|
|
68
|
+
async function triggerBackfill(computationName) {
|
|
69
|
+
const orch = await getOrchestrator();
|
|
70
|
+
// Orchestrator internal logic handles its own initialization if needed
|
|
71
|
+
return orch.triggerDeploymentBackfill(computationName);
|
|
72
|
+
}
|
|
73
|
+
|
|
63
74
|
function reset() {
|
|
64
75
|
orchestrator = null;
|
|
65
76
|
}
|
|
66
77
|
|
|
67
78
|
module.exports = {
|
|
79
|
+
getOrchestrator,
|
|
68
80
|
analyze,
|
|
69
81
|
execute,
|
|
70
82
|
runComputation,
|
|
71
83
|
getManifest,
|
|
72
84
|
warmCache,
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
config,
|
|
76
|
-
ManifestBuilder,
|
|
77
|
-
Computation,
|
|
78
|
-
...require('./framework')
|
|
85
|
+
triggerBackfill, // Exported correctly now
|
|
86
|
+
reset
|
|
79
87
|
};
|
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
portfolio_snapshots has :
|
|
2
|
+
|
|
3
|
+
Row date user_id user_type portfolio_data fetched_at
|
|
4
|
+
1 2026-01-24 24790725 SIGNED_IN_USER {"AggregatedMirrors":[],"AggregatedPositions":[{"Direction":"Buy","InstrumentID":1002,"Invested":7.763874,"NetProfit":89.633941,"Value":11.011448},{"Direction":"Buy","InstrumentID":1004,"Invested":4.866607,"NetProfit":7.792456,"Value":3.923417},{"Direction":"Buy","InstrumentID":1005,"Invested":4.158885,"NetProfit":63.883984,"Value":5.09757},{"Direction":"Buy","InstrumentID":1028,"Invested":3.918246,"NetProfit":-8.899259,"Value":2.669706},{"Direction":"Buy","InstrumentID":1029,"Invested":0.870721,"NetProfit":8.536667,"Value":0.706815},{"Direction":"Buy","InstrumentID":1041,"Invested":3.337765,"NetProfit":10.33913,"Value":2.754452},{"Direction":"Buy","InstrumentID":1043,"Invested":3.192645,"NetProfit":-6.43,"Value":2.234278},{"Direction":"Buy","InstrumentID":1046,"Invested":5.079208,"NetProfit":7.571429,"Value":4.086418},{"Direction":"Buy","InstrumentID":2380,"Invested":3.470115,"NetProfit":40.12546,"Value":3.636728},{"Direction":"Buy","InstrumentID":3006,"Invested":7.373559,"NetProfit":35.868136,"Value":7.492808},{"Direction":"Buy","InstrumentID":1137,"Invested":5.921689,"NetProfit":42.619359,"Value":6.316463},{"Direction":"Buy","InstrumentID":4316,"Invested":3.960534,"NetProfit":68.702229,"Value":4.997174},{"Direction":"Buy","InstrumentID":1832,"Invested":2.321924,"NetProfit":121.71625,"Value":3.850307},{"Direction":"Buy","InstrumentID":4124,"Invested":4.643847,"NetProfit":8.063125,"Value":3.753231},{"Direction":"Buy","InstrumentID":4251,"Invested":2.727361,"NetProfit":0.197938,"Value":2.04386},{"Direction":"Buy","InstrumentID":4072,"Invested":1.741443,"NetProfit":0.29,"Value":1.306221},{"Direction":"Buy","InstrumentID":1484,"Invested":5.0741,"NetProfit":-10.776552,"Value":3.386007},{"Direction":"Buy","InstrumentID":1481,"Invested":3.144059,"NetProfit":3.17283,"Value":2.426084},{"Direction":"Buy","InstrumentID":4331,"Invested":1.451202,"NetProfit":20.232,"Value":1.304962},{"Direction":"Buy","InstrumentID":2070,"Invested":1.306024,"NetProfit":48.004356,"Value":1.445691},{"Direction":"Buy","InstrumentID":1590,"Invested":3.062182,"NetProfit":-14.095067,"Value":1.967428},{"Direction":"Buy","InstrumentID":1567,"Invested":1.451202,"NetProfit":51.236,"Value":1.64147},{"Direction":"Buy","InstrumentID":8925,"Invested":2.612164,"NetProfit":0.904444,"Value":1.971336},{"Direction":"Buy","InstrumentID":9427,"Invested":2.188326,"NetProfit":11.431489,"Value":1.823769},{"Direction":"Buy","InstrumentID":4481,"Invested":4.884631,"NetProfit":117.733636,"Value":7.954394},{"Direction":"Buy","InstrumentID":4346,"Invested":3.637468,"NetProfit":17.301278,"Value":3.191183},{"Direction":"Buy","InstrumentID":6434,"Invested":2.902405,"NetProfit":127.519,"Value":4.938846},{"Direction":"Buy","InstrumentID":6844,"Invested":1.430624,"NetProfit":-10.665233,"Value":0.955864},{"Direction":"Buy","InstrumentID":4403,"Invested":0.891764,"NetProfit":-2.27502,"Value":0.651786}],"AggregatedPositionsByInstrumentTypeID":[{"Direction":"Buy","InstrumentTypeID":5,"Invested":92.011015,"NetProfit":33.757927,"Value":92.046908},{"Direction":"Buy","InstrumentTypeID":6,"Invested":7.373559,"NetProfit":35.868136,"Value":7.492808}],"AggregatedPositionsByStockIndustryID":[],"CreditByRealizedEquity":0.615426,"CreditByUnrealizedEquity":0.460284,"fetchedAt":"2026-01-24T07:51:41.112Z","username":"24790725"} 2026-01-24 07:51:41.112000 UTC
|
|
5
|
+
2 2026-01-24 24790725 POPULAR_INVESTOR {"AggregatedMirrors":[],"AggregatedPositions":[{"Direction":"Buy","InstrumentID":1002,"Invested":7.763874,"NetProfit":89.633941,"Value":11.011448},{"Direction":"Buy","InstrumentID":1004,"Invested":4.866607,"NetProfit":7.792456,"Value":3.923417},{"Direction":"Buy","InstrumentID":1005,"Invested":4.158885,"NetProfit":63.883984,"Value":5.09757},{"Direction":"Buy","InstrumentID":1028,"Invested":3.918246,"NetProfit":-8.899259,"Value":2.669706},{"Direction":"Buy","InstrumentID":1029,"Invested":0.870721,"NetProfit":8.536667,"Value":0.706815},{"Direction":"Buy","InstrumentID":1041,"Invested":3.337765,"NetProfit":10.33913,"Value":2.754452},{"Direction":"Buy","InstrumentID":1043,"Invested":3.192645,"NetProfit":-6.43,"Value":2.234278},{"Direction":"Buy","InstrumentID":1046,"Invested":5.079208,"NetProfit":7.571429,"Value":4.086418},{"Direction":"Buy","InstrumentID":1137,"Invested":5.921689,"NetProfit":42.619359,"Value":6.316463},{"Direction":"Buy","InstrumentID":1481,"Invested":3.144059,"NetProfit":3.17283,"Value":2.426084},{"Direction":"Buy","InstrumentID":1484,"Invested":5.0741,"NetProfit":-10.776552,"Value":3.386007},{"Direction":"Buy","InstrumentID":1567,"Invested":1.451202,"NetProfit":51.236,"Value":1.64147},{"Direction":"Buy","InstrumentID":1590,"Invested":3.062182,"NetProfit":-14.095067,"Value":1.967428},{"Direction":"Buy","InstrumentID":1832,"Invested":2.321924,"NetProfit":121.71625,"Value":3.850307},{"Direction":"Buy","InstrumentID":2070,"Invested":1.306024,"NetProfit":48.004356,"Value":1.445691},{"Direction":"Buy","InstrumentID":2380,"Invested":3.470115,"NetProfit":40.12546,"Value":3.636728},{"Direction":"Buy","InstrumentID":3006,"Invested":7.373559,"NetProfit":35.868136,"Value":7.492808},{"Direction":"Buy","InstrumentID":4316,"Invested":3.960534,"NetProfit":68.702229,"Value":4.997174},{"Direction":"Buy","InstrumentID":4124,"Invested":4.643847,"NetProfit":8.063125,"Value":3.753231},{"Direction":"Buy","InstrumentID":4251,"Invested":2.727361,"NetProfit":0.197938,"Value":2.04386},{"Direction":"Buy","InstrumentID":4072,"Invested":1.741443,"NetProfit":0.29,"Value":1.306221},{"Direction":"Buy","InstrumentID":8925,"Invested":2.612164,"NetProfit":0.904444,"Value":1.971336},{"Direction":"Buy","InstrumentID":9427,"Invested":2.188326,"NetProfit":11.431489,"Value":1.823769},{"Direction":"Buy","InstrumentID":4481,"Invested":4.884631,"NetProfit":117.733636,"Value":7.954394},{"Direction":"Buy","InstrumentID":4331,"Invested":1.451202,"NetProfit":20.232,"Value":1.304962},{"Direction":"Buy","InstrumentID":4346,"Invested":3.637468,"NetProfit":17.301278,"Value":3.191183},{"Direction":"Buy","InstrumentID":6434,"Invested":2.902405,"NetProfit":127.519,"Value":4.938846},{"Direction":"Buy","InstrumentID":6844,"Invested":1.430624,"NetProfit":-10.665233,"Value":0.955864},{"Direction":"Buy","InstrumentID":4403,"Invested":0.891764,"NetProfit":-2.27502,"Value":0.651786}],"AggregatedPositionsByInstrumentTypeID":[{"Direction":"Buy","InstrumentTypeID":5,"Invested":92.011015,"NetProfit":33.757927,"Value":92.046908},{"Direction":"Buy","InstrumentTypeID":6,"Invested":7.373559,"NetProfit":35.868136,"Value":7.492808}],"AggregatedPositionsByStockIndustryID":[],"CreditByRealizedEquity":0.615426,"CreditByUnrealizedEquity":0.460284,"cid":"24790725","fetchedAt":"2026-01-24T07:51:41.655Z","username":"24790725"} 2026-01-24 07:51:41.656000 UTC
|
|
6
|
+
|
|
7
|
+
pi_ratings has :
|
|
8
|
+
|
|
9
|
+
Row date pi_id average_rating total_ratings ratings_by_user reviews last_updated
|
|
10
|
+
1 2026-01-10 31075566 5.0 1 {"29312236":5} [{"action":"edit","actualUserCid":29312236,"comment":"You already know.","createdAt":"2025-12-30T18:28:43.750Z","isAnonymous":false,"isImpersonating":false,"loggedAt":"2026-01-10T18:55:56.880Z","piCid":31075566,"rating":5,"reviewId":"29312236_31075566","reviewerUsername":"marau2021","updatedAt":"2026-01-10T18:55:56.880Z","userCid":29312236}] 2026-01-22 20:20:11.389000 UTC
|
|
11
|
+
|
|
12
|
+
sector_mappings has :
|
|
13
|
+
|
|
14
|
+
Row symbol sector
|
|
15
|
+
9801 ZPDE.DE N/A
|
|
16
|
+
9802 ZPDH.DE N/A
|
|
17
|
+
9803 ZPDT.DE N/A
|
|
18
|
+
9804 ZPG.L N/A
|
|
19
|
+
9805 ZPHR.L Energy
|
|
20
|
+
9806 ZPRI.DE N/A
|
|
21
|
+
9807 ZPRR.DE N/A
|
|
22
|
+
9808 ZPTA Technology
|
|
23
|
+
9809 ZROZ N/A
|
|
24
|
+
9810 ZRX N/A
|
|
25
|
+
9811 ZS Technology
|
|
26
|
+
9812 ZSANQ N/A
|
|
27
|
+
9813 ZTF.L Basic Materials
|
|
28
|
+
9814 ZTO Industrials
|
|
29
|
+
9815 ZTS Healthcare
|
|
30
|
+
9816 ZUMZ Consumer Cyclical
|
|
31
|
+
|
|
32
|
+
pi_rankings has :
|
|
33
|
+
|
|
34
|
+
Row date pi_id username rank category rankings_data fetched_at
|
|
35
|
+
1 2025-12-23 12078064 Vincent870724 150 null {"AUMTier":3,"AUMTierDesc":"$100K-$300K","AUMTierV2":3,"AUMValue":254597.41,"ActiveWeeks":156,"ActiveWeeksPct":100,"AffiliateId":66235,"AvgPosSize":3.63,"BaseLineCopiers":229,"Blocked":false,"BonusOnly":false,"CopiedTrades":0,"Copiers":231,"CopiersGain":0.87,"CopyBlock":false,"CopyInvestmentPct":0,"CopyTradesPct":0,"Country":"Taiwan","CustomerId":12078064,"DailyDD":-5.33,"DailyGain":0.56,"DisplayFullName":true,"Exposure":76.23,"FirstActivity":"2023-01-01T00:00:00","FullName":"Pin Cheng Wu","FundType":0,"Gain":255.78,"HasAvatar":true,"HighLeveragePct":0,"InstrumentPct":0,"IsBronze":false,"IsFund":false,"IsProInvestor":false,"IsSocialConnected":false,"IsTestAccount":false,"LastActivity":"2025-12-23T00:00:00","LongPosPct":100,"LowLeveragePct":92.85714,"MaxDailyRiskScore":6,"MaxMonthlyRiskScore":6,"MediumLeveragePct":7.14286,"OptimalCopyPosSize":0.004547,"PeakToValley":-25.66,"PeakToValleyEnd":"2024-07-10T00:00:00","PeakToValleyStart":"2024-07-10T00:00:00","PopularInvestor":true,"ProfitableMonthsPct":58.33,"ProfitableWeeksPct":59.62,"RiskScore":4,"Tags":[57,59,137,150],"ThisWeekGain":0.56,"TopTradedAssetClassId":5,"TopTradedInstrumentId":1137,"TopTradedInstrumentPct":20.52,"TotalTradedInstruments":22,"Trades":70,"UserName":"Vincent870724","Velocity":0,"Verified":true,"VirtualCopiers":0,"WeeklyDD":-8.85,"WeeksSinceRegistration":326,"WinRatio":74.29} 2025-12-23 23:30:46.489000 UTC
|
|
36
|
+
|
|
37
|
+
social_post_snapshots has :
|
|
38
|
+
|
|
39
|
+
Row date user_id user_type posts_data fetched_at
|
|
40
|
+
1 2026-01-07 4572356 POPULAR_INVESTOR {"cid":"4572356","fetchedAt":"2026-01-07T14:03:03.628Z","postCount":10,"posts":{"03810230-6bbe-11f0-8080-80003cd17f81":{"createdAt":"2025-07-28T14:20:29.523Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"03810230-6bbe-11f0-8080-80003cd17f81","stats":{"comments":0,"likes":2},"text":"Happy Monday, everyone!\n\nWe’re starting the week strong, and I wanted to share a quick update on how we’re performing so far this year. Our portfolio is up 7.47% year-to-date, with 57.89% of weeks closing profitably and a balanced risk score of 4.\n\nThis performance reflects our disciplined strategy—rotating capital in Motor 1 for fast, protected gains and building a steady dividend base in Motor 2 for consistent cash flow.\n\nIf you’re not copying yet, now is a great time to join and benefit from our structured, growth-focused approach.\n\n👉 Copy my portfolio and be part of the journey!\n@pquiroga10\n— Pablo Quiroga\n$SPX500 $NVDA $BTC $EURUSD $NSDQ100 "},"30b211c0-9938-11f0-8080-80010e1621f8":{"createdAt":"2025-09-24T11:18:26.268Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"30b211c0-9938-11f0-8080-80010e1621f8","stats":{"comments":0,"likes":3},"text":"Dear Copiers, Followers, and Investors:\n\n📆 Mid-Month Update – September 23rd\nOur accelerated growth strategy is delivering outstanding results! ✅\nSo far in September we are up +5.93%, and for the year 2025 we’ve already achieved +15.68%. 📈🔥\n\nThis new approach focuses on precision: only A+ entries, strict risk management, and fast capital rotation. The goal is clear — maximize growth without wasting time in unproductive trades. The results so far speak for themselves. 🚀\n\nRemember: success in trading doesn’t come from rushing, but from discipline and execution. With the right entries and stops, we can turn consistency into exponential growth. 💡📊\n\n👉 If you’re considering copying this portfolio, now is a great time. Starting with $ 500 or more gives you exposure to every move and ensures you benefit fully from the growth strategy. And if you’re already copying, you may want to increase your allocation while opportunities remain strong.\n$AMZN $BABA $RGTI $GM $TSLA \n\nWishing you continued success on this journey — let’s keep building momentum together! 💪📈\n\n— Pablo Quiroga - @pquiroga10"},"609791c0-7125-11f0-8080-80003a2fa003":{"createdAt":"2025-08-04T11:22:59.676Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"609791c0-7125-11f0-8080-80003a2fa003","stats":{"comments":0,"likes":2},"text":"Happy Monday, everyone — followers, copiers, and fellow investors! 👋\n\nI hope you’re starting the week with focus and energy. The markets may move up and down, but our strategy continues to deliver, combining strong dividend income with targeted growth opportunities. 📈💸\n\nRemember, patience and consistency are powerful allies in investing. Don’t let short-term noise distract you from long-term goals. Stay informed, stay disciplined, and trust the process.\n\nTo those already copying — thank you for your trust! 🙌\nTo anyone still on the fence: you’re always welcome to join us. The strategy is active and open to new copiers at any time.\n\nLet’s make this a productive and profitable week together! 🚀\n$SPX500 $BTC $EURUSD $DJ30 $GER40 \n\nPablo Quiroga\n@pquiroga10 "},"63a20620-6e05-11f0-8080-80000220233e":{"createdAt":"2025-07-31T11:56:27.394Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"63a20620-6e05-11f0-8080-80000220233e","stats":{"comments":0,"likes":2},"text":"📊 Our Profit Protection Strategy\nHi to all copiers, followers, and investors!\n\nLet me take a moment to share the core of our strategy—how we manage risk while maximizing potential across the different types of assets in the portfolio. This disciplined approach is what allows us to protect gains, reinvest smartly, and build long-term growth.\n\nWe divide the strategy into three types of assets, which we call Engine 1, Engine 2, and Diversification. Each plays a unique role in the portfolio and follows specific rules to balance risk and reward.\n\n🟩 Engine 1 – Capital Rotation\nThese are high-growth assets where we aim to capture fast upward momentum. $NVDA , $SMCI \n\nWe carefully choose each position based on detailed technical analysis, identifying patterns with strong breakout potential.\n\nRule: Once a position reaches +4%, we activate a positive trailing stop of 3%, locking in a minimum gain of 1%.\n\nGoal: Secure early profits and let winners run, while preventing a reversal from turning a winning trade into a losing one.\nThis also gives us time to rotate capital and reinvest it more quickly into new opportunities.\n\n🟧 Engine 2 – Recurring Dividends\nThese are high-yield dividend stocks that generate monthly or quarterly income. $MPCC.OL $SDIV \n\nIn this engine, we're less concerned about short-term price fluctuations because the main goal is to generate consistent cash flow. However, when a position rises significantly, we take the opportunity to secure profits.\n\nRule: No initial stop.\nOnce a position reaches +35%, we activate a positive trailing stop of 10%, securing a minimum gain of 25%.\n\nGoal: Protect solid profits while allowing dividend-paying positions to grow over time.\nThis engine generates consistent cash flow and allows us to benefit from the power of compounding over time.\n\n🟦 Diversification – Stability & Resilience\nLow-risk ETFs or solid companies that add long-term balance to the portfolio. $VTI $SPX500 \n\nRule: No initial stop.\nOnce a position reaches +20%, we activate a positive trailing stop of 5%, ensuring a minimum gain of 15%.\n\nGoal: Safeguard meaningful profits in slower-moving assets while maintaining growth potential.\nWith these positions, we aim to keep our eToro risk score as low as possible, diversify our holdings, and still lock in healthy gains.\n\n🎯 Why this strategy works:\nBecause it combines patience with protection. We avoid taking profits too early, but never let strong positions go to waste. With this approach, we win when we should, and we protect when it matters.\n\n🚀 Ready to join this strategy?\nYou can start copying my portfolio with any amount you feel comfortable with. However, I recommend a minimum of $ 500 to benefit from proper allocation, and at least 1 year to truly take advantage of the strategy and compounding over time.\n\nLet’s build something powerful together.\n\nPablo Quiroga\n@pquiroga10"},"64859390-76b1-11f0-8080-80003b367390":{"createdAt":"2025-08-11T12:47:51.625Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"64859390-76b1-11f0-8080-80003b367390","stats":{"comments":0,"likes":2},"text":"Good morning, copiers, followers, and investors! 👋\n\nQuick snapshot:\nYTD: +5.06%\nLast 24 months: +49.84%\nDividend Yield: 5.73%\n\nWe’ll keep doing the simple things well: protect capital, be selective with entries, let winners breathe, reinvest cash flow, and ignore the noise. Patience and discipline over FOMO—every time. 🔒📈\n$NVDA $AMD $SPX500 $BTC $GOLD \n\nIf you’re already copying, stay the course and let compounding work for you. If you’re new, you can start copying anytime and follow the same steady approach.\n\nHere’s to a focused, profitable week ahead.\n— Pablo Quiroga (@pquiroga10)"},"866316f0-7890-11f0-8080-800051d9ca09":{"createdAt":"2025-08-13T21:57:37.375Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"866316f0-7890-11f0-8080-800051d9ca09","stats":{"comments":0,"likes":1},"text":"I just closed the trade at a profit of 6.27%"},"a2cac920-6e16-11f0-8080-800121996b44":{"createdAt":"2025-07-31T13:59:54.802Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"a2cac920-6e16-11f0-8080-800121996b44","stats":{"comments":0,"likes":1},"text":"I just closed the trade at a profit of 41.77%"},"b9c95270-6bca-11f0-8080-80013e99c365":{"createdAt":"2025-07-28T15:51:29.303Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"b9c95270-6bca-11f0-8080-80013e99c365","stats":{"comments":0,"likes":1},"text":"Another great Motor 1 trade closed with a positive trail! 🚀\n$SMCI locked in a solid +10.84% gain thanks to our capital rotation strategy.\n\nPositive trails like this show the strength of our disciplined approach—quick entries, protected gains, and steady portfolio growth.\n\nLet’s keep building momentum! 💪\n$AMD $AMZN $META $GOOG \n\n👉 Not copying yet? Join the strategy and grow with us!\n@pquiroga10\n— Pablo Quiroga\n\n"},"ca687910-6de8-11f0-8080-80013b669746":{"createdAt":"2025-07-31T08:31:44.417Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"ca687910-6de8-11f0-8080-80013b669746","stats":{"comments":0,"likes":2},"text":"🚢 Reinvesting Dividends in MPCC – Solid, Smart, Strategic 📈\n\nToday, I reinvested recent dividends from other high-yield assets like $ARR , $ORC $HAUTO.OL , $EFC , into $MPCC.OL , a shipping company that continues to deliver outstanding quarterly payouts, currently around 20% annually.\n\nThis is more than just a reinvestment... It's a strategic move. Here’s why:\n\n✅ MPCC is part of our Motor 2, focused on monthly or quarterly dividend income that fuels our compounding machine.\n✅ Reinvesting dividends into another strong performer boosts our passive income without adding new risk.\n✅ It’s a stock I already hold and trust, which helps keep the portfolio focused and efficient.\n✅ Shipping remains an essential global industry, and MPCC has proven its resilience and commitment to shareholders.\n\nIf you're still watching from the sidelines, now is a great time to copy this portfolio and start building a stream of passive income that works month after month.\n\nEvery reinvestment brings us closer to the goal. No hype—just consistent, smart moves. 🎯\n\nLet’s keep growing.\nPablo Quiroga – @pquiroga10 "},"e33afe30-6c90-11f0-8080-800150ca342f":{"createdAt":"2025-07-29T15:29:59.187Z","fetchedAt":"2026-01-07T14:03:03.628Z","id":"e33afe30-6c90-11f0-8080-800150ca342f","stats":{"comments":0,"likes":1},"text":"Another positive trailing stop has been triggered today, this time with $AMD securing a +9.82% gain.\n\nAs part of our Motor 1 strategy, we use positive dynamic stops to lock in profits once positions reach key levels, allowing us to protect gains while letting winners run. This keeps our portfolio dynamic and frees up capital for new opportunities without disrupting growth.\n\nThe released capital will now be allocated to fresh setups with strong momentum, targeting fast moves of 3–10% or more, always managed with the same disciplined approach.\n\nIf you want to benefit from this strategy, make sure you’re following and copying so you don’t miss the next trade.\n$MSFT $META $NSDQ100 $BTC \n\nPablo Quiroga\n@pquiroga10"}}} 2026-01-07 14:03:03.628000 UTC
|
|
41
|
+
|
|
42
|
+
ticker_mappings has :
|
|
43
|
+
|
|
44
|
+
Row instrument_id ticker last_updated
|
|
45
|
+
1 3015 IYR 2026-01-22 18:29:37.059000 UTC
|
|
46
|
+
2 8915 CXT 2026-01-22 18:29:37.059000 UTC
|
|
47
|
+
3 1310 YNAP.MI 2026-01-22 18:29:37.059000 UTC
|
|
48
|
+
4 100096 JASMY 2026-01-22 18:29:37.059000 UTC
|
|
49
|
+
5 10125 DMRC 2026-01-22 18:29:37.059000 UTC
|
|
50
|
+
6 2082 SMIN.L 2026-01-22 18:29:37.059000 UTC
|
|
51
|
+
7 1501 GM 2026-01-22 18:29:37.059000 UTC
|
|
52
|
+
8 100185 LTCNZD 2026-01-22 18:29:37.059000 UTC
|
|
53
|
+
9 7113 IRE.ASX 2026-01-22 18:29:37.059000 UTC
|
|
54
|
+
|
|
55
|
+
trade_history_snapshots has :
|
|
56
|
+
|
|
57
|
+
Row date user_id user_type history_data fetched_at
|
|
58
|
+
1 2026-01-11 11977580 POPULAR_INVESTOR {"PublicHistoryPositions":[{"CID":11977580,"CloseDateTime":"2025-07-02T15:21:48.1Z","CloseRate":44.26,"CloseReason":0,"InstrumentID":4247,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":20.0173,"OpenDateTime":"2023-03-16T17:57:10.5Z","OpenRate":36.88,"ParentCID":0,"ParentPositionID":0,"PositionID":2406938432},{"CID":11977580,"CloseDateTime":"2025-07-02T15:06:03.253Z","CloseRate":50.4741,"CloseReason":0,"InstrumentID":6785,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":24.1958,"OpenDateTime":"2024-03-08T14:31:09.857Z","OpenRate":40.6409,"ParentCID":0,"ParentPositionID":0,"PositionID":2648215742},{"CID":11977580,"CloseDateTime":"2025-06-13T13:30:30.203Z","CloseRate":214.41,"CloseReason":0,"InstrumentID":1946,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":4.84,"OpenDateTime":"2023-03-16T17:48:17.817Z","OpenRate":204.52,"ParentCID":0,"ParentPositionID":0,"PositionID":2406927729},{"CID":11977580,"CloseDateTime":"2025-06-13T12:41:41.043Z","CloseRate":1381,"CloseReason":0,"InstrumentID":2062,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":12.61,"OpenDateTime":"2023-03-15T15:06:00.213Z","OpenRate":1241.5,"ParentCID":0,"ParentPositionID":0,"PositionID":2405670808},{"CID":11977580,"CloseDateTime":"2025-06-13T07:00:10.5Z","CloseRate":0.475,"CloseReason":0,"InstrumentID":5012,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":-102.632,"OpenDateTime":"2022-02-25T16:06:25.7Z","OpenRate":1619,"ParentCID":0,"ParentPositionID":0,"PositionID":1507919574},{"CID":11977580,"CloseDateTime":"2025-06-11T07:00:31.513Z","CloseRate":24.96,"CloseReason":0,"InstrumentID":8000,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":-24.15,"OpenDateTime":"2023-01-29T07:00:24.207Z","OpenRate":32.9,"ParentCID":0,"ParentPositionID":0,"PositionID":2372486071},{"CID":11977580,"CloseDateTime":"2025-06-10T07:00:20.007Z","CloseRate":32.02,"CloseReason":0,"InstrumentID":5888,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":-17.45,"OpenDateTime":"2023-02-15T08:00:15.05Z","OpenRate":38.3,"ParentCID":0,"ParentPositionID":0,"PositionID":2386535941},{"CID":11977580,"CloseDateTime":"2025-06-09T16:46:49.28Z","CloseRate":4.52,"CloseReason":0,"InstrumentID":5973,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":-49.04,"OpenDateTime":"2023-03-14T14:37:59.49Z","OpenRate":8.87,"ParentCID":0,"ParentPositionID":0,"PositionID":2404444581},{"CID":11977580,"CloseDateTime":"2025-06-09T16:45:54.75Z","CloseRate":10.46,"CloseReason":0,"InstrumentID":4242,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":-30.2652,"OpenDateTime":"2024-04-05T15:19:35.5Z","OpenRate":15,"ParentCID":0,"ParentPositionID":0,"PositionID":2678898495},{"CID":11977580,"CloseDateTime":"2025-04-23T07:01:50.2Z","CloseRate":28.02,"CloseReason":5,"InstrumentID":5772,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":10.952,"OpenDateTime":"2022-03-08T08:00:23.893Z","OpenRate":25.37,"ParentCID":0,"ParentPositionID":0,"PositionID":1518667248},{"CID":11977580,"CloseDateTime":"2025-01-23T19:43:18.813Z","CloseRate":410.95,"CloseReason":0,"InstrumentID":1111,"IsBuy":true,"Leverage":1,"MirrorID":0,"NetProfit":-2.269,"OpenDateTime":"2025-01-22T14:31:36.1Z","OpenRate":420.49,"ParentCID":0,"ParentPositionID":0,"PositionID":2921219124}],"cid":"11977580","fetchedAt":"2026-01-11T11:01:13.099Z"} 2026-01-11 11:01:13.099000 UTC
|
|
59
|
+
|
|
60
|
+
watchlist_membership has :
|
|
61
|
+
|
|
62
|
+
Row date pi_id total_users public_watchlist_count private_watchlist_count users last_updated
|
|
63
|
+
1 2026-01-01 31075566 1 null 1 ["29312236"] 2026-01-01 23:46:49.673000 UTC
|
|
64
|
+
2 2026-01-02 16157384 1 null 1 ["29312236"] 2026-01-02 00:33:25.113000 UTC
|
|
65
|
+
3 2026-01-02 31075566 1 null 1 ["29312236"] 2026-01-02 00:33:25.113000 UTC
|
|
66
|
+
4 2026-01-03 10161207 1 null 1 ["12336860"] 2026-01-03 01:41:09.333000 UTC
|
|
67
|
+
5 2026-01-03 12569157 1 null 1 ["12336860"] 2026-01-03 01:41:09.333000 UTC
|
|
68
|
+
6 2026-01-03 5125148 1 null 1 ["12336860"] 2026-01-03 01:41:09.333000 UTC
|
|
69
|
+
7 2026-01-03 4464869 1 null 1 ["12336860"] 2026-01-03 01:41:09.333000 UTC
|
|
70
|
+
8 2026-01-03 18002171 1 null 1 ["12336860"] 2026-01-03 01:41:09.333000 UTC
|
|
71
|
+
|
|
72
|
+
pi_page_views has :
|
|
73
|
+
|
|
74
|
+
Row date pi_id total_views unique_viewers views_by_user last_updated
|
|
75
|
+
1 2026-01-01 647267 9 1 {"29312236":{"lastViewed":{"_nanoseconds":184000000,"_seconds":1767306872},"viewCount":9}} 2026-01-01 23:36:08.954000 UTC
|
|
76
|
+
|
|
77
|
+
pi_master_list has :
|
|
78
|
+
|
|
79
|
+
Row cid username first_seen_at last_seen_at last_updated
|
|
80
|
+
1 13745113 Tom1313 2026-01-01 20:52:07.266000 UTC 2026-01-31 03:03:18.461000 UTC 2026-01-31 03:03:18.461000 UTC
|
|
81
|
+
2 7985363 tsocheva 2026-01-01 20:52:07.266000 UTC 2026-01-31 03:03:18.461000 UTC 2026-01-31 03:03:18.461000 UTC
|
|
82
|
+
3 20896541 MiguelRamos97 2026-01-01 20:52:07.266000 UTC 2026-01-31 03:03:18.461000 UTC 2026-01-31 03:03:18.461000 UTC
|
|
83
|
+
4 5842997 Jonny1983 2026-01-01 20:52:07.266000 UTC 2026-01-31 03:03:18.461000 UTC 2026-01-31 03:03:18.461000 UTC
|
|
84
|
+
5 29362790 svorca 2026-01-01 20:52:07.266000 UTC 2026-01-31 03:03:18.461000 UTC 2026-01-31 03:03:18.461000 UTC
|
|
85
|
+
6 3152816 danielhrafn 2026-01-01 20:52:07.266000 UTC 2026-01-31 03:03:18.461000 UTC 2026-01-31 03:03:18.461000 UTC
|
|
86
|
+
|
|
87
|
+
pi_alert_history has :
|
|
88
|
+
|
|
89
|
+
Row date pi_id alert_type triggered trigger_count triggered_for metadata last_triggered last_updated
|
|
90
|
+
1 2025-12-26 7534748 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
91
|
+
2 2025-12-26 29117190 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
92
|
+
3 2025-12-26 5909918 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
93
|
+
4 2025-12-26 25207339 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
94
|
+
5 2025-12-26 11276299 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
95
|
+
6 2025-12-26 5631102 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
96
|
+
7 2025-12-26 1065666 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
97
|
+
8 2025-12-26 12078064 lastUpdated false 0 [] {} null 2026-01-15 22:56:40.031000 UTC
|
|
98
|
+
9 2025-12-26 11843709 lastUpdated false 0 [] {} null
|
|
99
|
+
|
|
100
|
+
asset_prices has :
|
|
101
|
+
|
|
102
|
+
Row date instrument_id ticker price open high low close volume fetched_at
|
|
103
|
+
1 2025-11-14 10400 unknown_10400 27.06 null null null 27.06 null 2026-01-21 22:00:18.338000 UTC
|
|
104
|
+
2 2025-11-14 1640 unknown_1640 34.9 null null null 34.9 null 2026-01-21 22:00:18.338000 UTC
|
|
105
|
+
3 2025-11-14 8040 unknown_8040 2703.93 null null null 2703.93 null 2026-01-21 22:00:18.338000 UTC
|
|
106
|
+
4 2025-11-14 1121 unknown_1121 331.48 null null null 331.48 null 2026-01-21 22:00:18.336000 UTC
|
|
107
|
+
5 2025-11-14 12600 unknown_12600 51.2 null null null 51.2 null 2026-01-21 22:00:18.338000 UTC
|
|
108
|
+
6 2025-11-14 1520 unknown_1520 75.72 null null null 75.72 null 2026-01-21 22:00:18.338000 UTC
|