Commit Graph

8 Commits

Author SHA1 Message Date
mindesbunister
d2fbd125a0 fix: Make minSignalQualityScore configurable via settings + anti-chop improvements
CRITICAL BUG FIX:
- Settings page saved MIN_SIGNAL_QUALITY_SCORE to .env but check-risk had hardcoded value
- Now reads from config.minSignalQualityScore (defaults to 65, editable via /settings)
- Prevents settings changes from being ignored after restart

ANTI-CHOP FILTER FIXES:
- Fixed volume breakout bonus conflicting with anti-chop filter
- Volume breakout now requires ADX > 18 (trending market)
- Prevents high volume + low ADX from getting rewarded instead of penalized
- Anti-chop filter now properly blocks whipsaw traps at score 60

TESTING INFRASTRUCTURE:
- Added backtest script showing +17.1% P&L improvement (saved $242 in losses)
- Added test-signals.sh for comprehensive signal quality validation
- Added test-recent-signals.sh for analyzing actual trading session signals
- All tests passing: timeframe awareness, anti-chop, score thresholds

CHANGES:
- config/trading.ts: Added minSignalQualityScore to interface and defaults
- app/api/trading/check-risk/route.ts: Use config value instead of hardcoded 65
- lib/trading/signal-quality.ts: Fixed volume breakout bonus logic
- .env: Added MIN_SIGNAL_QUALITY_SCORE=65
- scripts/: Added comprehensive testing tools

BACKTEST RESULTS (Last 30 trades):
- Old system (score ≥60): $1,412.79 P&L
- New system (score ≥65 + anti-chop): $1,654.79 P&L
- Improvement: +$242.00 (+17.1%)
- Blocked 5 losing trades, missed 0 winners
2025-11-10 11:22:52 +01:00
mindesbunister
60a0035f56 Add anti-chop filter: Penalize high volume during weak trend
PROBLEM ANALYSIS:
Signal that lost -$32: ADX 14.8, VOL 2.29x → scored 70-90 (PASSED)
Signal that won +3%: ADX 15.7, VOL 1.18x → scored 45-65 (got BLOCKED before fix)

Key insight: High volume during choppy conditions (ADX < 16) indicates
whipsaw/trap, not genuine breakout. Our volume bonus (+15 pts for >1.5x)
was rewarding flip-flop signals instead of real moves.

FIX:
Add anti-chop filter in volume scoring:
- If ADX < 16 AND volume > 1.5x → -15 points (whipsaw trap)
- Overrides the normal +15 bonus for high volume
- Protects against false signals during consolidation

IMPACT ON RECENT SIGNALS:
1. 00:40 SHORT (ADX 17.2, VOL 0.98): 55→75  Still passes
2. 00:55 LONG (ADX 15, VOL 0.47): 35→55  Still blocked (correct, weak vol)
3. 01:05 SHORT (ADX 14.8, VOL 2.29): 70→60 ⚠️ Now flagged as whipsaw trap
4. 01:10 LONG (ADX 15.7, VOL 1.18): 45→65  Catches the +3% runup

Result: Loser signal now barely passes (60) with warning flag,
winner signal passes cleanly (65). Better risk/reward profile.
2025-11-10 07:46:46 +01:00
mindesbunister
4b11186d16 Fix: Add timeframe-aware signal quality scoring for 5min charts
PROBLEM:
- Long signal (ADX 15.7, ATR 0.35%) blocked with score 45/100
- Missed major +3% runup, lost -2 on short that didn't flip
- Scoring logic treated all timeframes identically (daily chart thresholds)

ROOT CAUSE:
- ADX < 18 always scored -15 points regardless of timeframe
- 5min charts naturally have lower ADX (12-22 healthy range)
- copilot-instructions mentioned timeframe awareness but wasn't implemented

FIX:
- Add timeframe parameter to RiskCheckRequest interface
- Update scoreSignalQuality() with timeframe-aware ADX thresholds:
  * 5min/15min: ADX 12-22 healthy (+5), <12 weak (-15), >22 strong (+15)
  * Higher TF: ADX 18-25 healthy (+5), <18 weak (-15), >25 strong (+15)
- Pass timeframe from n8n workflow through check-risk and execute
- Update both Check Risk nodes in Money Machine workflow

IMPACT:
Your blocked signal (ADX 15.7 on 5min) now scores:
- Was: 50 + 5 - 15 + 0 + 0 + 5 = 45 (BLOCKED)
- Now: 50 + 5 + 5 + 0 + 0 + 5 = 65 (PASSES)

This 20-point improvement from timeframe awareness would have caught the runup.
2025-11-10 07:34:21 +01:00
mindesbunister
9b767342dc feat: Implement re-entry analytics system with fresh TradingView data
- Add market data cache service (5min expiry) for storing TradingView metrics
- Create /api/trading/market-data webhook endpoint for continuous data updates
- Add /api/analytics/reentry-check endpoint for validating manual trades
- Update execute endpoint to auto-cache metrics from incoming signals
- Enhance Telegram bot with pre-execution analytics validation
- Support --force flag to override analytics blocks
- Use fresh ADX/ATR/RSI data when available, fallback to historical
- Apply performance modifiers: -20 for losing streaks, +10 for winning
- Minimum re-entry score 55 (vs 60 for new signals)
- Fail-open design: proceeds if analytics unavailable
- Show data freshness and source in Telegram responses
- Add comprehensive setup guide in docs/guides/REENTRY_ANALYTICS_QUICKSTART.md

Phase 1 implementation for smart manual trade validation.
2025-11-07 20:40:07 +01:00
mindesbunister
3c9da22a8a Add ADX > 18 requirement for extreme price positions
- Shorts/longs at < 15% range require ADX > 18 AND volume > 1.2x
- OR RSI < 35 for shorts, RSI > 60 for longs
- Increased penalty from -10 to -15 when conditions not met
- Changed threshold from < 5% to < 15% to catch more edge cases

Test results:
- Big loser (01:35): ADX 16.1, price 9.3% → Score 60 (was 90) → BLOCKED
- Today's signal (10:05): ADX 17.3, price 0.9% → Score 55 (was 85) → BLOCKED

Rationale: False breakdowns in choppy ranges (ADX < 18) cause losses.
Tradeoff: May block some profitable breakdowns, but prevents chop losses.
2025-11-07 12:19:41 +01:00
mindesbunister
db907d8074 Improve signal quality scoring for breakdowns/breakouts
- Allow shorts at range bottom (<5%) with volume >1.2x OR RSI <40
- Allow longs at range bottom with volume >1.2x OR RSI >60
- Reduce ADX penalty from -15 to -5 when strong volume (>1.2x) present
- Reduce price position penalties from -15 to -10 (less harsh)
- Volume compensation recognizes breakdowns start before ADX strengthens

Test case (blocked signal that would have profited):
- OLD: ATR 0.32, ADX 17.3, RSI 32.5, Vol 1.27x, Price 0.9% → Score 45 (blocked)
- NEW: Same metrics → Score 85 (executes)

Rationale: Breakdowns continue lower, volume confirms conviction, ADX lags price action
2025-11-07 10:58:47 +01:00
mindesbunister
0365560c5b Add timeframe-aware signal quality scoring for 5min charts
- Lower ADX/ATR thresholds for 5min timeframe (ADX 12-22, ATR 0.2-0.7%)
- Add anti-chop filter: -20 points for extreme sideways (ADX<10, ATR<0.25, Vol<0.9)
- Pass timeframe parameter through check-risk and execute endpoints
- Fixes flip-flop losses from overly strict 5min filters
- Higher timeframes unchanged (still use ADX 18+, ATR 0.4+)

5min scoring now:
- ADX 12-15: moderate trend (+5)
- ADX 22+: strong trend (+15)
- ATR 0.2-0.35: acceptable (+5)
- ATR 0.35+: healthy (+10)
- Extreme chop penalty prevents whipsaw trades
2025-11-07 08:56:19 +01:00
mindesbunister
02193b7dce fix(critical): Unify quality score calculation across check-risk and execute
PROBLEM:
- check-risk calculated quality score: 60, 70 (PASSED)
- execute calculated quality score: 35, 45 (should have BLOCKED)
- Two different functions with different logic caused trades to bypass validation

ROOT CAUSE:
Two separate scoring functions existed:
1. scoreSignalQuality() in check-risk (detailed, 95% price threshold)
2. calculateQualityScore() in execute (simpler, 90% price threshold)

Example with pricePosition=96.4%, volumeRatio=0.9:
- check-risk: Checks >95, volumeRatio>1.4 failed → -15 + bonuses = 60  PASSED
- execute: Checks >90 → -15 + bonuses = 35  Should block but already opened

SOLUTION:
1. Created lib/trading/signal-quality.ts with unified scoreSignalQuality()
2. Both endpoints now import and use SAME function
3. Consistent scoring logic: 95% price threshold, volume breakout bonus
4. Returns detailed reasons for debugging

IMPACT:
- Quality scores now MATCH between check-risk and execute
- No more trades bypassing validation due to calculation differences
- Better debugging with quality reasons logged

Files changed:
- NEW: lib/trading/signal-quality.ts (unified scoring function)
- MODIFIED: app/api/trading/check-risk/route.ts (import shared function)
- MODIFIED: app/api/trading/execute/route.ts (import shared function)
- REMOVED: Duplicate calculateQualityScore() from execute
- REMOVED: Duplicate scoreSignalQuality() from check-risk
2025-11-04 11:40:25 +01:00