157 lines
6.3 KiB
Python
157 lines
6.3 KiB
Python
"""
|
|
Adaptive Rhythm Manager - Extracted from Notebook
|
|
Manages adaptive trading intervals based on volatility and session
|
|
"""
|
|
|
|
import MetaTrader5 as mt
|
|
import pandas as pd
|
|
import pandas_ta as ta
|
|
import pytz
|
|
from datetime import datetime, time
|
|
import logging
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
class AdaptiveRhythmManager:
|
|
"""
|
|
Adaptive Trading Rhythm Manager
|
|
|
|
Verwaltet adaptiven Trading-Rhythmus basierend auf:
|
|
- Marktvolatilität (ATR)
|
|
- Trading-Session (Asian/London/NY/Overlap)
|
|
- Marktregime
|
|
"""
|
|
|
|
def __init__(self, symbol="XAUUSD"):
|
|
self.symbol = symbol
|
|
self.current_interval = 5
|
|
|
|
# Zeitintervalle in Minuten
|
|
self.intervals = {
|
|
'fast': 5, # Hohe Volatilität, aktive Sessions
|
|
'medium': 15, # Moderate Volatilität, Standard
|
|
'slow': 30 # Niedrige Volatilität, ruhige Sessions
|
|
}
|
|
|
|
# ATR-Schwellenwerte für XAUUSD (Gold)
|
|
self.atr_thresholds = {
|
|
'high': 15.0, # Hohe Volatilität
|
|
'medium': 8.0, # Moderate Volatilität
|
|
'low': 5.0 # Niedrige Volatilität
|
|
}
|
|
|
|
# Session-Zeiten (UTC)
|
|
self.sessions = {
|
|
'asian': (time(0, 0), time(8, 0)), # 00:00-08:00 UTC
|
|
'london': (time(8, 0), time(16, 0)), # 08:00-16:00 UTC
|
|
'ny': (time(13, 0), time(21, 0)), # 13:00-21:00 UTC
|
|
'overlap': (time(13, 0), time(16, 0)) # London-NY Overlap
|
|
}
|
|
|
|
def get_current_session(self):
|
|
"""Ermittelt die aktuelle Trading-Session"""
|
|
now_utc = datetime.now(pytz.UTC).time()
|
|
|
|
# Overlap hat höchste Priorität
|
|
if self.sessions['overlap'][0] <= now_utc <= self.sessions['overlap'][1]:
|
|
return 'overlap'
|
|
elif self.sessions['london'][0] <= now_utc < self.sessions['london'][1]:
|
|
return 'london'
|
|
elif self.sessions['ny'][0] <= now_utc < self.sessions['ny'][1]:
|
|
return 'ny'
|
|
return 'asian'
|
|
|
|
def get_volatility_level(self, atr_value):
|
|
"""Klassifiziert die Volatilität basierend auf ATR"""
|
|
if atr_value >= self.atr_thresholds['high']:
|
|
return 'high'
|
|
elif atr_value >= self.atr_thresholds['medium']:
|
|
return 'medium'
|
|
return 'low'
|
|
|
|
def get_market_data(self):
|
|
"""Hole Marktdaten für ATR-Analyse"""
|
|
try:
|
|
rates = mt.copy_rates_from_pos(self.symbol, mt.TIMEFRAME_H1, 0, 50)
|
|
if rates is None:
|
|
return None
|
|
|
|
df = pd.DataFrame(rates)
|
|
df['time'] = pd.to_datetime(df['time'], unit='s')
|
|
df.set_index('time', inplace=True)
|
|
df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)
|
|
return df
|
|
except Exception as e:
|
|
logger.error(f"Fehler beim Laden der Marktdaten: {e}")
|
|
return None
|
|
|
|
def calculate_optimal_interval(self):
|
|
"""Berechnet optimales Trading-Intervall"""
|
|
session = self.get_current_session()
|
|
df = self.get_market_data()
|
|
|
|
if df is None:
|
|
return self.current_interval
|
|
|
|
current_atr = df['atr'].iloc[-1]
|
|
volatility = self.get_volatility_level(current_atr)
|
|
optimal_interval = self._determine_interval(session, volatility)
|
|
|
|
# Logge Änderungen
|
|
if optimal_interval != self.current_interval:
|
|
logger.info(f"🔄 Rhythmus-Änderung: {self.current_interval}m → {optimal_interval}m")
|
|
logger.info(f" Session: {session}, Volatilität: {volatility} (ATR: {current_atr:.2f})")
|
|
|
|
self.current_interval = optimal_interval
|
|
return optimal_interval
|
|
|
|
def _determine_interval(self, session, volatility):
|
|
"""
|
|
Intervall-Entscheidungs-Matrix:
|
|
|
|
Session │ Hohe Vol │ Mittlere Vol │ Niedrige Vol
|
|
───────────┼──────────┼──────────────┼─────────────
|
|
Overlap │ 5min │ 15min │ 15min
|
|
London/NY │ 5min │ 15min │ 30min
|
|
Asian │ 15min │ 30min │ 30min
|
|
"""
|
|
if session == 'overlap':
|
|
return self.intervals['fast'] if volatility == 'high' else self.intervals['medium']
|
|
elif session in ['london', 'ny']:
|
|
if volatility == 'high':
|
|
return self.intervals['fast']
|
|
elif volatility == 'medium':
|
|
return self.intervals['medium']
|
|
return self.intervals['slow']
|
|
else: # asian
|
|
return self.intervals['medium'] if volatility == 'high' else self.intervals['slow']
|
|
|
|
def get_status_report(self):
|
|
"""Erstellt Status-Report"""
|
|
session = self.get_current_session()
|
|
df = self.get_market_data()
|
|
|
|
if df is not None:
|
|
current_atr = df['atr'].iloc[-1]
|
|
volatility = self.get_volatility_level(current_atr)
|
|
else:
|
|
current_atr = 0
|
|
volatility = 'unknown'
|
|
|
|
return f"""
|
|
╔════════════════════════════════════════════════════════╗
|
|
║ ADAPTIVE RHYTHM STATUS - {datetime.now().strftime('%H:%M:%S UTC')} ║
|
|
╠════════════════════════════════════════════════════════╣
|
|
║ Aktuelles Intervall: {self.current_interval:>2} Minuten ║
|
|
║ Trading Session: {session.upper():<15} ║
|
|
║ Volatilitätslevel: {volatility.upper():<15} ║
|
|
║ ATR (H1): {current_atr:>6.2f} ║
|
|
╠════════════════════════════════════════════════════════╣
|
|
║ INTERVALL-SCHEMA: ║
|
|
║ • Overlap (13-16 UTC): 5-15 Min (aktivste Phase) ║
|
|
║ • London/NY: 5-30 Min (volatilitätsabh.) ║
|
|
║ • Asian Session: 15-30 Min (ruhigere Phase) ║
|
|
╚════════════════════════════════════════════════════════╝
|
|
"""
|