Fix scoring math; add 10-min auto-scan A-grade alerts with news block
- engine: composite-score denominator now confidence-weighted, so the output actually spans -100..+100 (the prior formula put confidence in the numerator only, capping the realistic score around ±25-30 and making STRONG_BUY ≥40 essentially unreachable). - engine: ATR percentile uses iloc[-50:-1] to exclude the current bar from its own comparison (off-by-one in volatility regime). - signal_aggregator: always blend primary score with MTF average. The prior code only blended on agreement, leaving the primary unblended on disagreement — backwards. Disagreement is exactly when the score should be pulled toward consensus. - telegram_bot: JobQueue auto-scan every 10 min that pushes A/A+ to ALERT_CHAT_ID with a prominent News & Events block (sentiment + headline summary + event-risk + alignment hint). Per-bar dedup so persistent setups alert once per new candle, not every 10 min. Suppresses alerts when event_risk = "danger". - telegram_bot: /myid returns chat ID for ALERT_CHAT_ID setup. Auto-scan silently disabled when ALERT_CHAT_ID is unset. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -499,7 +499,8 @@ class TechnicalEngine:
|
||||
|
||||
# Compare to historical ATR
|
||||
if len(atr) >= 50:
|
||||
atr_percentile = (atr.iloc[-1] > atr.iloc[-50:]).mean() * 100
|
||||
# Exclude current bar so ATR isn't compared against itself
|
||||
atr_percentile = (atr.iloc[-1] > atr.iloc[-50:-1]).mean() * 100
|
||||
else:
|
||||
atr_percentile = 50.0
|
||||
|
||||
@@ -844,7 +845,8 @@ class TechnicalEngine:
|
||||
- Confidence scaling
|
||||
"""
|
||||
total_score = 0.0
|
||||
total_weight = 0.0
|
||||
score_weight = 0.0 # denominator for score: weight × confidence
|
||||
weight_sum = 0.0 # denominator for confidence average: weight only
|
||||
total_confidence = 0.0
|
||||
|
||||
regime_weights = {
|
||||
@@ -863,16 +865,18 @@ class TechnicalEngine:
|
||||
regime_mult = active_regime_weights.get(name, 1.0)
|
||||
weight *= regime_mult
|
||||
|
||||
conf_factor = ind.confidence / 100.0
|
||||
signal_score = ind.signal.value # -2 to +2
|
||||
weighted_score = signal_score * weight * (ind.confidence / 100.0)
|
||||
|
||||
total_score += weighted_score
|
||||
total_weight += weight
|
||||
total_score += signal_score * weight * conf_factor
|
||||
score_weight += weight * conf_factor
|
||||
weight_sum += weight
|
||||
total_confidence += ind.confidence * weight
|
||||
|
||||
if total_weight > 0:
|
||||
normalized_score = (total_score / total_weight) * 50 # scale to -100..+100
|
||||
avg_confidence = total_confidence / total_weight
|
||||
if score_weight > 0:
|
||||
# Confidence-weighted average of signal_score (∈ [-2,+2]); ×50 → [-100,+100]
|
||||
normalized_score = (total_score / score_weight) * 50
|
||||
avg_confidence = total_confidence / weight_sum if weight_sum > 0 else 0
|
||||
else:
|
||||
normalized_score = 0
|
||||
avg_confidence = 0
|
||||
|
||||
Reference in New Issue
Block a user