Signal Pipelines
News ingestion + insider-signals (smart-money) + AI predictions
Vezta runs three intelligence pipelines that feed the monitor:signals WebSocket channel and Telegram channels:
- News signal pipeline -- aggregates news + social media, classifies, links to markets
- Insider-signals pipeline -- detects smart-money Polymarket whales via 11-layer filter + 10-metric scorer
- AI predictions -- LLM-backed market predictions via OpenRouter (heuristic fallback)
News Signal Pipeline
Lives in src/modules/monitor/ingestion/, runs on the signal-ingestion BullMQ queue managed by SignalIngestionScheduler.
News Connectors
| Source | Frequency | Notes |
|---|---|---|
| RSS | Every 5 minutes | BBC, CNBC, WSJ, Al Jazeera, TechCrunch, MarketWatch, etc. |
| GDELT | Every 30 minutes | Global event database covering 100+ countries |
| NewsData | Every 15 minutes | Staggered by 2.5 min/category to avoid API rate limits |
| CryptoNews | Every 10 minutes | Cryptocurrency-focused news |
| X / Twitter | 5 / 15 / 30 min | 3 tiers: tier-1 critical (3s throttle), tier-2 important (5s), tier-3 long-tail (8s); syndication scraping + FxTwitter enrichment |
| Telegram | Every 15 minutes | GramJS MTProto when TELEGRAM_SESSION configured (real-time events + polling); HTML scraping of t.me/s/ as fallback |
| Cleanup | Daily | Removes stale signals and expired articles |
Pipeline Stages
- Language filter -- non-English articles dropped at intake
- Dedup -- cache + DB lookup ensures the same story does not reach the feed twice
- Classification -- assigns category (politics, military, financials, crypto, tech, energy, macro) and severity score (
critical/high/low) - Market linking -- matches article content to markets in the DB; stamps
marketIdandrelatedMarketIds - Geo-tagging -- extracts coordinates, country name, ISO code, flag emoji
- Broadcast -- saves
MonitorSignalrow + emits onmonitor:signalschannel
Insider-Signals Pipeline
Lives in src/modules/insider-signals/. Detects insider/smart-money wallets on Polymarket and fans alerts to Telegram (@vezta_signals), Expo push, and the in-app monitor feed. Runs on the insider-signals BullMQ queue with two job types:
classify-trade-- run filter + scorer + dispatcher on a single fresh tradecluster-refresh-- on theinsider-cluster-refreshqueue, rebuilds market clusters hourly
Stage 1 -- MmBotFilterService (11 layers, 3 tiers)
Rejects market makers, bots, copy-traders, grid strategies before any scoring. Each layer is a FilterLayer class in filters/:
| Layer | What it catches | Tier |
|---|---|---|
| L1 | Blacklist | tier-1 (immediate reject) |
| L2 | Two-sided trading | tier-1 |
| L3 | Cancel-rate | tier-1 |
| L4 / L4b | Flatness | tier-1 |
| L5a / L5b | Timing patterns | tier-1 |
| L7 | Copy-trade detection | tier-1 |
| L6 / L8 | Soft signals | tier-2 (reject at 2+) |
| L9 | Reaction patterns | tier-2 |
| L10 | Grid strategies | tier-2 |
| L11 | Cluster detection | tier-3 (feeds scorer) |
Stage 2 -- InsiderScorerService (10 metrics)
Composes metric classes in metrics/:
| Metric | Description |
|---|---|
| NET | Net position size |
| CR | Conviction ratio |
| MDR | Market dominance |
| AAB | Age-adjusted boldness |
| TSJR | Trade-size jump |
| DCS | Directional conviction (cross-market via MarketCluster) |
| RA | Rapid accumulation |
| SAS | Slow accumulation |
| PHR | Position holding ratio |
| HE | Historical edge |
Composite score โ tier:
| Score | Tier | Emoji |
|---|---|---|
| โฅ15 | HIGH_CONVICTION_INSIDER | ๐ด |
| 11-14 | STRONG_SIGNAL | ๐ |
| 7-10 | WATCH | ๐ก |
| 4-6 | LOW_PRIORITY | ๐ข |
| <4 | dropped | -- |
Stage 3 -- Dispatch Pipeline
AlertDebouncerService-- per-wallet ร market ร 24h dedup via Redis (alert:dedup:{wallet}:{marketId}TTL 24h). Higher-score duplicates bump the existing row viaupdate_existing; same/lower drops. Daily UTC caps: 50 global, 10 ๐ด (vibrant mode, 2026-04-19). Counters only increment on successful publish.CoordinatedDetectorService-- 3+ distinct EOAs same market+side within 1h โ mints a deterministiccoordinatedId(prefixsolo:when noMarketClusterrow exists). Backfills the id onto earlier alerts in the window.NotificationDispatcherService-- tier-gated fanout: all 4 tiers post to Telegram (vibrant mode), only ๐ด triggers Expo push, WS emits on every alert viagateway.broadcastToChannel('monitor:signals', 'insider-alert', ...).
Trade Producers
Two producers feed the classify-trade queue:
TradeSyncService.enqueueInsiderSignalsClassify()-- called from the hot-set trade-sync (every ~5 min, ~850 tracked markets)InsiderTradePollerService-- global recent-trades poller (every 30s). Off by default; gated byINSIDER_SIGNALS_POLLER_ENABLED=true.
Market Clustering
Feeds the DCS metric. Rule-based (no embeddings): same Polymarket event_id OR resolution date ยฑ7d + โฅ0.5 Jaccard title-token overlap. Rebuilt hourly by ClusterRefreshProcessor. Semantic-similarity upgrade deferred until embeddings land in ai-predictions.
Funding Trace
ProxyOwnerResolver maps Polymarket proxy โ owner EOA. UsdcInflowWalker + BridgeUnwinder + SourceClassifier produce a FundingClass (PRIVACY_MIXER / NO_KYC_SWAP / CEX / FIAT_ONRAMP / MM_SUBWALLET / SYBIL_CLUSTER). Cached 30d in WalletLabel.
Telegram Channels and Bots
Three Telegram channels:
| Channel (prod) | Audience |
|---|---|
@vezta_signals | Public |
@vezta_signals_beta | Beta |
| Internal | Vezta team |
Channel IDs differ per VM by design (prod has 3 distinct IDs; staging mirrors all 3 tier env vars to a single dev channel @vezta_signals_dev).
The dispatch (signals) bot is @vezta_signal_bot (prod) / @dev_vezta_signal_bot (staging). The interactive trading bot is live โ handled by the telegram-bot module (TelegramBotController, @veztabot prod / @staging_vezta_predict_bot staging; handles are env-driven) with /trade, /limit, /tpsl, /combo, /arb, and /wallet command handlers and a webhook at POST /api/v1/telegram-bot/webhook.
Prisma Models
| Model | Purpose |
|---|---|
InsiderAlert | The fanout target -- one row per published alert |
WalletLabel | Filter classifications + funding class, 30d TTL |
MarketCluster | DCS input |
InsiderAlertFeedback | FP/real votes for tuning |
TelegramBinding | User โ Telegram chat link (bot linking) |
Dedup cache is Redis-only -- a flushall drops dedup state, causing re-publish storms on the next trade burst. Clear the debouncer counters (alert:count:*) and dedup keys (alert:dedup:*) separately, not via wildcard.
AI Predictions
Lives in src/modules/ai-predictions/. Uses the OpenAI SDK (openai package) pointed at OpenRouter's API-compatible endpoint, with a heuristic fallback when OPENROUTER_API_KEY is unset.
Generates per-market predictions with confidence scoring. Stored in AiPrediction; aggregate model performance in AiModelStats.
Other Signal Detection
The signal-detector queue handles market-data-based signal detection (whale moves, smart-money patterns derived from price/volume). This is distinct from the news pipeline above, which focuses exclusively on external content sources.