# Signal Quality Optimization Roadmap **Goal:** Optimize signal quality thresholds and scoring logic using data-driven analysis **Current Status:** Phase 4 Complete βœ… - Automated price tracking operational | Phase 1-2 Active - Collecting + analyzing data **Last Updated:** November 24, 2025 **πŸŽ‰ MAJOR UPDATE: Phase 4 Complete (Nov 19-22, 2025)** - BlockedSignalTracker deployed and fully operational - 34 signals tracked: 21 multi-timeframe + 13 quality-blocked - Price tracking at 1/5/15/30 min intervals with TP/SL hit detection - First validation: Quality 80 signal blocked, would've profited +0.52% **πŸš€ v8 Money Line Indicator (Nov 18, 2025)** - Sticky trend detection with 0.6% flip threshold + momentum confirmation - 8 trades completed: 57.1% WR, +$262.70 total, 93.6 avg quality - Perfect quality separation: All winners β‰₯95, all losers ≀90 --- ## Overview This roadmap guides the systematic improvement of signal quality filtering. We follow a **data-first approach**: collect evidence, analyze patterns, then make changes. No premature optimization. ### Current System - **Quality Score Threshold:** 91 points (raised from 81 on Nov 21, 2025 after trade #7 analysis) - **Trade #7:** ADX 19.0, quality 90 β†’ -$387 loss (weak trend, emergency stop) - **Perfect Separation:** Analysis of 7 v8 trades: - ALL 4 winners had quality β‰₯95 (95, 95, 100, 105) βœ… - ALL 3 losers had quality ≀90 (80, 90, 90) ❌ - 91 threshold would have prevented 100% of losses (-$624.90) - **v8 Performance:** 7 trades, 57.1% WR, $262.70 total, 93.6 avg quality - **Historical Performance (v5/v6):** 157 total, +$3.43 P&L, 44.5% WR --- ## Phase 1: Data Collection (CURRENT) βœ… IN PROGRESS **Status:** Infrastructure complete, collecting data **Started:** November 11, 2025 **Target:** Collect 10-20 blocked signals (1-2 weeks) ### Completed (Nov 11, 2025) - [x] Created `BlockedSignal` database table - [x] Implemented automatic saving in check-risk endpoint - [x] Deployed to production (trading-bot-v4 container) - [x] Created tracking documentation (BLOCKED_SIGNALS_TRACKING.md) ### What's Being Tracked Every blocked signal captures: - **Metrics:** ATR, ADX, RSI, volume ratio, price position, timeframe - **Score:** Quality score (0-100), version, detailed breakdown - **Block Reason:** Quality score, cooldown, hourly limit, daily drawdown - **Context:** Symbol, direction, price at signal time, timestamp ### What We're Looking For 1. How many signals score 60-64 (just below threshold)? 2. What are their characteristics (ADX, ATR, price position)? 3. Are there patterns (extreme positions, specific timeframes)? 4. Do they cluster around specific block reasons? ### Phase 1 Completion Criteria - [ ] Minimum 10 blocked signals with quality scores 55-64 - [ ] At least 2 signals in 60-64 range (close calls) - [ ] Mix of block reasons (not all quality score) - [ ] Data spans multiple market conditions (trending, choppy, volatile) ### SQL Queries for Phase 1 ```sql -- Check progress SELECT COUNT(*) as total_blocked FROM "BlockedSignal"; -- Score distribution SELECT CASE WHEN signalQualityScore >= 60 THEN '60-64 (Close)' WHEN signalQualityScore >= 55 THEN '55-59 (Marginal)' WHEN signalQualityScore >= 50 THEN '50-54 (Weak)' ELSE '0-49 (Very Weak)' END as tier, COUNT(*) as count FROM "BlockedSignal" WHERE blockReason = 'QUALITY_SCORE_TOO_LOW' GROUP BY tier ORDER BY MIN(signalQualityScore) DESC; ``` --- ## Phase 1.5: Signal Frequency Penalties βœ… DEPLOYED Nov 14, 2025 **Status:** Production deployment complete (with critical bug fix) **Initial Commit:** 111e3ed (07:28 CET) **Bug Fix Commit:** 795026a (09:22 CET) **Container:** trading-bot-v4 ### What Was Implemented Real-time database analysis that detects overtrading and flip-flop patterns before trade execution. ### Penalties Applied 1. **Overtrading (3+ signals in 30min):** -20 points - Counts both executed trades AND blocked signals - Prevents excessive trading in consolidation zones 2. **Flip-flop with price context (opposite direction <15min):** -25 points - **NEW:** Only applies if price moved <2% from opposite signal - Distinguishes chop from reversals - Example chop: $154.50 SHORT β†’ $154.30 LONG (0.13% move) = blocked ⚠️ - Example reversal: $170 SHORT β†’ $153 LONG (10% move) = allowed βœ… - Blocks rapid longβ†’shortβ†’long whipsaws in tight ranges - **BUG FIX (795026a):** Now uses Pyth price data for accurate calculations - Previous issue: showed "100% move" for 0.2% actual movement (allowed false flip-flop) 3. **Alternating pattern (last 3 trades):** -30 points - Detects choppy market conditions - Pattern: longβ†’shortβ†’long = chop detection ### Technical Details - **Function:** `getRecentSignals()` in `lib/database/trades.ts` - **Price source:** Pyth price monitor via `getPythPriceMonitor()` in check-risk - **Architecture:** `scoreSignalQuality()` now async - **Endpoints updated:** check-risk, execute, reentry-check - **Performance:** Indexed queries, <10ms overhead - **Validation:** Logs "πŸ” Flip-flop price check: $X β†’ $Y = Z%" for debugging ### Expected Impact - Eliminate tight-range flip-flops (Nov 14 chart: $141-145 SOL) - Reduce overtrading during sideways markets - Target: +5-10% win rate improvement - Better capital preservation in chop ### Monitoring Watch for detailed penalty and allowance messages in logs: ``` πŸ” Flip-flop price check: $143.86 β†’ $143.58 = 0.20% ⚠️ Overtrading zone: 3 signals in 30min (-20 pts) ⚠️ Flip-flop in tight range: 4min ago, only 0.20% move ($143.86 β†’ $143.58) (-25 pts) βœ… Direction change after 10.0% move ($170.00 β†’ $153.00, 12min ago) - reversal allowed ⚠️ Chop pattern: last 3 trades alternating (long β†’ short β†’ long) (-30 pts) ``` ### Known Issues Fixed - **Nov 14, 06:05 CET:** Initial deployment allowed 0.2% flip-flop due to incorrect price data - Trade: SHORT at $143.58 (should have been blocked) - Result: -$1.56 loss in 5 minutes - Fix deployed: 09:22 CET (795026a) - now uses Pyth price monitor ### Validation Plan 1. Monitor next 5-10 signals for accurate price calculations 2. Verify penalties trigger with correct percentages 3. Analyze if blocked signals would have lost 4. If effective, proceed to Phase 6 (range compression) --- ## Phase 2: Pattern Analysis πŸ”œ NEXT **Prerequisites:** 10-20 blocked signals collected **Estimated Duration:** 2-3 days **Owner:** Manual analysis + SQL queries ### Analysis Tasks #### 2.1: Score Distribution Analysis ```sql -- Analyze blocked signals by score range SELECT CASE WHEN signalQualityScore >= 60 THEN '60-64' WHEN signalQualityScore >= 55 THEN '55-59' ELSE '50-54' END as score_range, COUNT(*) as count, ROUND(AVG(atr)::numeric, 2) as avg_atr, ROUND(AVG(adx)::numeric, 1) as avg_adx, ROUND(AVG(pricePosition)::numeric, 1) as avg_price_pos, ROUND(AVG(volumeRatio)::numeric, 2) as avg_volume FROM "BlockedSignal" WHERE blockReason = 'QUALITY_SCORE_TOO_LOW' GROUP BY score_range ORDER BY MIN(signalQualityScore) DESC; ``` #### 2.2: Compare with Executed Trades ```sql -- Find executed trades with similar scores to blocked signals SELECT 'Executed' as type, signalQualityScore, COUNT(*) as trades, ROUND(AVG(realizedPnL)::numeric, 2) as avg_pnl, ROUND(100.0 * SUM(CASE WHEN realizedPnL > 0 THEN 1 ELSE 0 END) / COUNT(*)::numeric, 1) as win_rate FROM "Trade" WHERE exitReason IS NOT NULL AND signalQualityScore BETWEEN 60 AND 69 GROUP BY signalQualityScore ORDER BY signalQualityScore; ``` #### 2.3: ADX Pattern Analysis Key finding from existing data: ADX 20-25 is a trap zone! ```sql -- ADX distribution in blocked signals SELECT CASE WHEN adx >= 25 THEN 'Strong (25+)' WHEN adx >= 20 THEN 'Moderate (20-25)' WHEN adx >= 15 THEN 'Weak (15-20)' ELSE 'Very Weak (<15)' END as adx_tier, COUNT(*) as count, ROUND(AVG(signalQualityScore)::numeric, 1) as avg_score FROM "BlockedSignal" WHERE blockReason = 'QUALITY_SCORE_TOO_LOW' AND adx IS NOT NULL GROUP BY adx_tier ORDER BY MIN(adx) DESC; ``` #### 2.4: Extreme Position Analysis Test hypothesis: Extremes (<10% or >90%) need different thresholds ```sql -- Blocked signals at range extremes SELECT direction, signalQualityScore, ROUND(pricePosition::numeric, 1) as pos, ROUND(adx::numeric, 1) as adx, ROUND(volumeRatio::numeric, 2) as vol FROM "BlockedSignal" WHERE blockReason = 'QUALITY_SCORE_TOO_LOW' AND (pricePosition < 10 OR pricePosition > 90) ORDER BY signalQualityScore DESC; ``` ### Phase 2 Deliverables - [ ] Score distribution report - [ ] ADX pattern analysis - [ ] Extreme position analysis - [ ] Comparison with executed trades - [ ] **DECISION:** Keep threshold at 65, lower to 60, or implement dual-threshold system --- ## Phase 3: Implementation (Conditional) 🎯 FUTURE **Trigger:** Analysis shows clear pattern worth exploiting **Prerequisites:** Phase 2 complete + statistical significance (15+ blocked signals) ### Option A: Dual-Threshold System (Recommended) **IF** data shows extreme positions (price <10% or >90%) with scores 60-64 are profitable: **Implementation:** ```typescript // In check-risk endpoint const isExtremePosition = pricePosition < 10 || pricePosition > 90 const requiredScore = isExtremePosition ? 60 : 65 if (qualityScore.score < requiredScore) { // Block signal } ``` **Changes Required:** - `app/api/trading/check-risk/route.ts` - Add dual threshold logic - `lib/trading/signal-quality.ts` - Add `isExtremePosition` helper - `config/trading.ts` - Add `minScoreForExtremes` config option - Update AI instructions with new logic ### Option B: ADX-Based Gates (Alternative) **IF** data shows strong ADX trends (25+) with lower scores are profitable: **Implementation:** ```typescript const requiredScore = adx >= 25 ? 60 : 65 ``` **Changes Required:** - Similar to Option A but based on ADX threshold ### Option C: Keep Current (If No Clear Pattern) **IF** data shows no consistent profit opportunity in blocked signals: - No changes needed - Continue monitoring - Revisit in 20 more trades ### Phase 3 Checklist - [ ] Decision made based on Phase 2 analysis - [ ] Code changes implemented - [ ] Updated signalQualityVersion to 'v5' in database - [ ] AI instructions updated - [ ] Tested with historical blocked signals - [ ] Deployed to production - [ ] Monitoring for 10 trades to validate improvement --- ## Phase 4: Price Analysis Automation βœ… COMPLETE **Goal:** Automatically track if blocked signals would have been profitable **Status:** Deployed Nov 19-22, 2025 - Fully operational **Implementation:** BlockedSignalTracker background service ### Architecture βœ… ``` BlockedSignalTracker (runs every 5 min) ↓ Fetch BlockedSignal records where: - analysisComplete = false - createdAt within last 30 minutes ↓ For each signal (both DATA_COLLECTION_ONLY and QUALITY_SCORE_TOO_LOW): - Query current price from Drift oracle - Calculate profit % based on direction - Check if TP1 (~0.86%), TP2 (~1.72%), SL (~1.29%) would have hit - Update priceAfter1Min/5Min/15Min/30Min - Track maxFavorableExcursion and maxAdverseExcursion - Set wouldHitTP1/TP2/SL flags - Mark analysisComplete = true after 30 minutes ↓ Save results back to database ``` ### Implementation Complete βœ… - [x] Created BlockedSignalTracker service (`lib/analysis/blocked-signal-tracker.ts`) - [x] Price tracking from Drift oracle (not history, but real-time monitoring) - [x] TP/SL hit calculation using ATR-based targets - [x] Background job running every 5 minutes - [x] Auto-starts on container startup - [x] API endpoint (`/api/analytics/signal-tracking`) for monitoring - [x] **Enhanced Nov 22:** Tracks both multi-timeframe AND quality-blocked signals ### Current Data (Nov 24, 2025) - **34 total blocked signals tracked** - 21 multi-timeframe (DATA_COLLECTION_ONLY): 19 complete - 13 quality-blocked (QUALITY_SCORE_TOO_LOW): 6 complete - **First validation result:** Quality 80 signal would have profited +0.52% (+$43) ### Success Metrics βœ… - System validates if blocks were correct (SL hits) vs missed opportunities (TP hits) - Enables data-driven threshold optimization - Risk-free analysis of non-executed signals --- ## Phase 5: ML-Based Scoring (DISTANT FUTURE) πŸ€– **Status:** Future consideration - requires extensive data **Estimated Start:** Q2 2026 or later **Prerequisites:** 500+ trades with quality scores, proven manual optimization ### Approach 1. Build ML model to predict trade success from metrics 2. Use predicted success rate as quality score 3. Continuously learn from new trades 4. Auto-adjust weights based on market regime ### Requirements - Sufficient training data (500+ trades minimum) - Market regime classification system - ML infrastructure (model training, deployment) - Monitoring for model drift ### Risks - Overfitting to past data - Model degrades as markets change - Black box decision-making - Increased system complexity **Note:** Only pursue if manual optimization plateaus or if pursuing ML as learning exercise. --- ## Phase 6: TradingView Range Compression Metrics (PLANNED) πŸ“ **Status:** Planned - Next after frequency penalties prove effective **Estimated Start:** November 2025 (after Phase 1 validation) **Prerequisites:** Phase 1 deployed, 5-10 signals monitored ### What It Does Adds NEW metrics to TradingView alerts to detect range compression and momentum mismatches that indicate choppy markets. ### New TradingView Calculations ```javascript // 1. Range compression (20-bar high/low range as % of price) rangePercent = ((highest(high, 20) - lowest(low, 20)) / close) * 100 // 2. Price change over 5 bars (momentum check) priceChange5bars = ((close - close[5]) / close[5]) * 100 // 3. ADX-momentum mismatch (ADX says trend but price not moving) adxMismatch = (adx > 15 AND abs(priceChange5bars) < 0.3) ``` ### Quality Score Penalties - **Range < 1.5Γ— ATR**: -20 points (compressed range = chop likely) - **ADX 15+ but price change < 0.3%**: -20 points (fake trend signal) - **Price oscillating around MA**: -15 points (whipsaw zone) ### Why This Helps Current system can pass ADX 12-22 even when price just bouncing in tight zone. This detects the mismatch between "ADX says trending" vs "price says chopping." **Example from Nov 14 chart:** Multiple signals in $141-145 range passed quality check despite obvious consolidation. Range compression would have caught this. ### Implementation Steps 1. Add calculations to TradingView strategy (30 min) 2. Update webhook JSON to include new fields (15 min) 3. Modify `scoreSignalQuality()` to use range metrics (30 min) 4. Test alerts on historical data (1 hour) 5. Deploy and monitor (ongoing) ### Expected Impact - Catch "fake trends" where ADX misleads - Reduce entries in tight consolidation zones - Improve win rate by 3-5% in choppy markets - Complement frequency penalties (Phase 1) ### Success Metrics - Reduction in flip-flop losses - Fewer blocked signals in validated trending moves - Better P&L in sideways market conditions --- ## Phase 7: Volume Profile Integration (ADVANCED) πŸ“Š **Status:** Future consideration - most complex but most powerful **Estimated Start:** December 2025 or Q1 2026 **Prerequisites:** Phase 6 completed, Volume S/R Zones V2 indicator expertise ### What It Does Uses Volume S/R Zones V2 indicator to detect when price is stuck in high-volume consolidation nodes where flip-flops are most likely. ### How Volume Profile Works - Shows horizontal bars representing volume at each price level - **Volume nodes** (thick bars) = high volume = price gets stuck (S/R zones) - **Thin zones** (low volume) = price moves through quickly (breakout zones) - Price bouncing inside volume node = high probability chop ### Required Indicator Modifications Expose these values from Volume S/R Zones V2: ```javascript // New indicator outputs (requires Pine Script modifications) inVolumeNode: true/false // Is price inside thick volume bar? nearVolumeEdge: true/false // Near top/bottom of node? (breakout setup) nodeStrength: 0-100 // Volume concentration at this level distanceFromNode: % // How far from nearest node? volumeNodeWidth: % // How wide is current node? (tight = strong) ``` ### Quality Score Adjustments **Penalties:** - **In volume node (stuck)**: -25 points (high chop probability) - **Node strength > 80**: -30 points (VERY strong S/R = rejection likely) - **Tight node width (<1%)**: -35 points (extreme consolidation) **Bonuses:** - **Near volume edge + high volume**: +10 points (breakout setup) - **Distance from node > 2%**: +5 points (free movement zone) - **Breaking through node with volume**: +15 points (momentum trade) ### Why This Is Powerful **Example from Nov 14 chart:** Price bouncing $141-145. Volume profile would show THICK volume node at that exact level - instant warning. System would: 1. Detect price in node β†’ apply -25 to -35 penalty 2. Block most entries in that zone 3. Wait for breakout above/below node 4. Bonus points when price clears node with volume ### Implementation Complexity **High - Requires:** 1. Modify Volume S/R Zones indicator source code (Pine Script) 2. Expose new variables in indicator settings 3. Add webhook outputs from indicator (JSON formatting) 4. Parse in n8n workflow (new data structure) 5. Update quality scorer with volume logic (complex conditionals) 6. Test on historical data with indicator overlays 7. Validate against manual chart analysis **Estimated Time:** 2-3 hours + TradingView Pine Script knowledge ### Risks & Considerations - Indicator must stay updated (TradingView updates can break) - Volume profile changes dynamically (recalculates with new data) - May over-filter in ranging markets (miss valid mean-reversion trades) - Complexity increases debugging difficulty ### Success Metrics - Elimination of entries in obvious consolidation zones - Higher win rate specifically in ranging markets - Reduction in whipsaw losses (target: 30-50% fewer) - Improved P&L per trade (better entries near node edges) ### Alternatives to Consider - Use simpler "volume concentration" metric (easier to calculate) - Implement fixed support/resistance zones instead of dynamic profile - Combine with Phase 6 range compression (may be sufficient) **Recommendation:** Only implement if Phase 1 + Phase 6 don't adequately solve flip-flop problem. Volume profile is most powerful but also most fragile. --- ## Progress Tracking --- ## Key Principles ### 1. Data Before Action - Minimum 10 samples before any decision - Prefer 20+ for statistical confidence - No changes based on 1-2 outliers ### 2. Incremental Changes - Change one variable at a time - Test for 10-20 trades after each change - Revert if performance degrades ### 3. Version Tracking - Every scoring logic change gets new version (v4 β†’ v5) - Store version with each trade/blocked signal - Enables A/B testing and rollback ### 4. Document Everything - Update this roadmap after each phase - Record decisions and rationale - Link to SQL queries and analysis --- ## Progress Tracking ### Milestones - [x] Nov 11, 2025: Phase 1 infrastructure complete (blocked signals tracking) - [x] Nov 14, 2025: Phase 1.5 complete (signal frequency penalties deployed) - [x] Nov 19, 2025: **Phase 4 COMPLETE** (multi-timeframe price tracking deployed) - [x] Nov 22, 2025: **Phase 4 ENHANCED** (quality threshold validation added) - [ ] Target: ~Nov 20-25, 2025: Phase 2 analysis complete (10-20 blocked signals) - [ ] Target: ~Nov 25-30, 2025: Phase 3 implementation (threshold adjustment) - [ ] Target: ~Dec 1-7, 2025: Phase 6 implementation (TradingView range metrics) - [ ] Target: ~Dec 15-31, 2025: Phase 7 evaluation (Volume Profile integration) - [ ] TBD: Phase 5 ML-based scoring (Q2 2026 or later) ### Metrics to Watch - **Blocked signals collected:** 34/10 minimum βœ… (21 multi-timeframe + 13 quality-blocked) - **Data collection complete:** 25/34 signals (73.5% completion rate) βœ… - **Quality-blocked signals:** 13 collected, 6 complete (Nov 22 enhancement) - **Multi-timeframe signals:** 21 collected, 19 complete (Nov 19 deployment) - **First validation:** Quality 80 blocked signal would've profited +0.52% (+$43) - FALSE NEGATIVE - **Days of data collection:** 5 days (Nov 19-24) - ongoing - **Market conditions covered:** 3/3 (trending, choppy, volatile) βœ… ### Review Schedule - **Weekly:** Check blocked signal count - **After 10 blocked:** Run Phase 2 analysis - **After Phase 2:** Decide on Phase 3 implementation - **Monthly:** Review overall system performance --- ## Questions to Answer ### Phase 1 Questions - [ ] How many signals get blocked per day? - [ ] What's the score distribution of blocked signals? - [ ] Are most blocks from quality score or other reasons? ### Phase 2 Questions - [ ] Do blocked signals at 60-64 have common characteristics? - [ ] Would lowering threshold to 60 improve performance? - [ ] Do extreme positions need different treatment? - [ ] Is ADX pattern valid in blocked signals? ### Phase 3 Questions - [ ] Did the change improve win rate? - [ ] Did it increase profitability? - [ ] Any unintended side effects? --- ## Appendix: Historical Context ### Why This Roadmap Exists **Date:** November 11, 2025 **Situation:** Three TradingView signals fired: 1. SHORT at 05:15 - Executed (score likely 65+) β†’ Losing trade 2. LONG at 05:20 - Executed (score likely 65+) β†’ Losing trade 3. SHORT at 05:30 - **BLOCKED** (score 45) β†’ Would have been profitable **User Question:** "What can we do about this?" **Analysis Findings:** - Only 2 historical trades scored 60-64 (both winners +$45.78) - Sample size too small for confident decision - ADX 20-25 is a trap zone (-$23.41 in 23 trades) - Low volume (<0.8x) outperforms high volume (counterintuitive!) **Decision:** Build data collection system instead of changing thresholds prematurely **This Roadmap:** Systematic approach to optimization with proper data backing --- **Remember:** The goal isn't to catch every winning trade. The goal is to optimize the **risk-adjusted return** by catching more winners than losers at each threshold level. Sometimes blocking a potential winner is correct if it also blocks 3 losers.