fix: core module review fixes (signal scoring, ML, session filter, telegram, MT filter)

enhanced_signal_scoring.py:
- mt -> mt5, add logging module, replace print() with logger
- Remove no-op df['tick_volume'] = df['tick_volume'] line
- Fix RSI division-by-zero: loss.replace(0, nan) + fillna(100)

ml_signal_predictor.py:
- Remove global warnings.filterwarnings('ignore') suppression
- Fix bare except -> except Exception with logger.warning
- Add note: default data files excluded from git, need manual export
- Add pickle security warning comment

session_confidence_filter.py:
- Move imports to file top, add logging + functools.wraps
- Remove repeated AdaptiveRhythmManager() per-call instantiation
- Add functools.wraps to preserve wrapped function metadata
- Document that extended_top_down_v2_adaptive is notebook-only
- Replace print() with logger, pass **kwargs through wrapper

telegram_notifier.py:
- Remove network call from __init__ -> explicit test_connection() method
- Add logging module, replace all print() with logger calls
- Narrow exception type: Exception -> requests.RequestException
- Remove unused imports (timedelta)
- notify_trade_entry/exit now return bool from send_message

multi_timeframe_regime_filter.py:
- Change debug default from True to False in wrapper to avoid verbose production output

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-05-12 10:12:25 +02:00
co-authored by Claude Sonnet 4.6
parent 338ed1188c
commit 4e45db967b
5 changed files with 84 additions and 86 deletions
+20 -17
View File
@@ -11,11 +11,14 @@ NEUE FEATURES:
5. Weighted Scoring System
"""
import MetaTrader5 as mt
import MetaTrader5 as mt5
import pandas as pd
import numpy as np
from typing import Dict, List, Tuple, Optional
from dataclasses import dataclass
import logging
logger = logging.getLogger(__name__)
@dataclass
@@ -96,12 +99,11 @@ class EnhancedSignalScorer:
"""
try:
# Get OHLCV data
rates = mt.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
rates = mt5.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
if rates is None or len(rates) < 20:
return 50.0 # Neutral if no data
df = pd.DataFrame(rates)
df['tick_volume'] = df['tick_volume'] # MT5 provides tick volume
# Calculate Volume MA
df['volume_ma_20'] = df['tick_volume'].rolling(20).mean()
@@ -125,7 +127,7 @@ class EnhancedSignalScorer:
return score
except Exception as e:
print(f"⚠️ Volume calculation error: {e}")
logger.warning(f"Volume calculation error: {e}")
return 50.0
# ==========================================
@@ -148,7 +150,7 @@ class EnhancedSignalScorer:
(momentum_score, details_dict)
"""
try:
rates = mt.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
rates = mt5.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
if rates is None or len(rates) < 30:
return 50.0, {}
@@ -198,7 +200,7 @@ class EnhancedSignalScorer:
return momentum_score, details
except Exception as e:
print(f"⚠️ Momentum calculation error: {e}")
logger.warning(f"Momentum calculation error: {e}")
return 50.0, {}
def _calculate_rsi(self, prices: pd.Series, period: int = 14) -> pd.Series:
@@ -206,9 +208,10 @@ class EnhancedSignalScorer:
delta = prices.diff()
gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()
loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean()
rs = gain / loss
# Avoid division by zero: when loss == 0 the RSI is 100
rs = gain / loss.replace(0, np.nan)
rsi = 100 - (100 / (1 + rs))
return rsi
return rsi.fillna(100.0)
def _calculate_macd(self,
prices: pd.Series,
@@ -249,7 +252,7 @@ class EnhancedSignalScorer:
(sr_score, details_dict)
"""
try:
rates = mt.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
rates = mt5.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
if rates is None or len(rates) < 50:
return 50.0, {}
@@ -301,7 +304,7 @@ class EnhancedSignalScorer:
return score, details
except Exception as e:
print(f"⚠️ Support/Resistance calculation error: {e}")
logger.warning(f"Support/Resistance calculation error: {e}")
return 50.0, {}
def _find_peaks(self, data: np.ndarray, distance: int = 10) -> List[float]:
@@ -334,7 +337,7 @@ class EnhancedSignalScorer:
(fib_score, details_dict)
"""
try:
rates = mt.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
rates = mt5.copy_rates_from_pos(symbol, self._tf_to_mt5(timeframe), 0, lookback)
if rates is None or len(rates) < 50:
return 50.0, {}
@@ -386,7 +389,7 @@ class EnhancedSignalScorer:
return score, details
except Exception as e:
print(f"⚠️ Fibonacci calculation error: {e}")
logger.warning(f"Fibonacci calculation error: {e}")
return 50.0, {}
# ==========================================
@@ -483,12 +486,12 @@ class EnhancedSignalScorer:
def _tf_to_mt5(self, timeframe: str):
"""Convert string timeframe to MT5 constant"""
tf_map = {
'M1': mt.TIMEFRAME_M1, 'M5': mt.TIMEFRAME_M5,
'M15': mt.TIMEFRAME_M15, 'M30': mt.TIMEFRAME_M30,
'H1': mt.TIMEFRAME_H1, 'H4': mt.TIMEFRAME_H4,
'D1': mt.TIMEFRAME_D1, 'W1': mt.TIMEFRAME_W1
'M1': mt5.TIMEFRAME_M1, 'M5': mt5.TIMEFRAME_M5,
'M15': mt5.TIMEFRAME_M15, 'M30': mt5.TIMEFRAME_M30,
'H1': mt5.TIMEFRAME_H1, 'H4': mt5.TIMEFRAME_H4,
'D1': mt5.TIMEFRAME_D1, 'W1': mt5.TIMEFRAME_W1
}
return tf_map.get(timeframe.upper(), mt.TIMEFRAME_H1)
return tf_map.get(timeframe.upper(), mt5.TIMEFRAME_H1)
# ==========================================