Files
Place-Order-Trading-Bot/TradingBot_V1.4_Optimized.py
T

634 lines
23 KiB
Python

"""
TradingBot V1.4 - Optimized Version
Verbesserte Entry Signal Logik basierend auf Analyse-Empfehlungen
Hauptverbesserungen:
1. Adaptive Confidence Threshold
2. Market Regime Detection
3. Entry Timing Optimization
4. Risk-Adjusted Signal Strength
5. Performance Monitoring
"""
import pandas as pd
import numpy as np
import MetaTrader5 as mt
import pandas_ta as ta
from scipy.signal import savgol_filter, find_peaks
from sklearn.linear_model import LinearRegression
from tabulate import tabulate
from datetime import datetime, timedelta
import json
# =============================================================================
# 1. MARKET REGIME DETECTION
# =============================================================================
def detect_market_regime(df, lookback=50):
"""
Erkennt das aktuelle Marktregime (Trending vs. Ranging)
Returns:
- regime: 'trending', 'ranging', 'volatile'
- strength: 0-100 (Stärke des Regimes)
"""
# ADX für Trendstärke
adx = ta.adx(df['high'], df['low'], df['close'], length=14)['ADX_14'].iloc[-1]
# Bollinger Band Squeeze für Ranging Markets
bb = ta.bbands(df['close'], length=20)
bb_width = ((bb['BBU_20_2.0'] - bb['BBL_20_2.0']) / bb['BBM_20_2.0'] * 100).iloc[-lookback:].mean()
# Price Action Analysis
price_range = (df['high'].iloc[-lookback:].max() - df['low'].iloc[-lookback:].min())
atr_avg = df['atr'].iloc[-lookback:].mean()
range_ratio = price_range / (atr_avg * lookback)
# Volatility Cluster Detection
vol_cluster = df['atr'].iloc[-10:].std() / df['atr'].iloc[-50:].mean()
# Regime-Bestimmung
if adx > 25 and range_ratio > 1.5:
regime = 'trending'
strength = min(100, adx * 2)
elif vol_cluster > 1.5:
regime = 'volatile'
strength = min(100, vol_cluster * 50)
else:
regime = 'ranging'
strength = max(0, 100 - adx * 2)
return {
'regime': regime,
'strength': strength,
'adx': adx,
'bb_width': bb_width,
'range_ratio': range_ratio,
'vol_cluster': vol_cluster
}
# =============================================================================
# 2. ADAPTIVE CONFIDENCE SYSTEM
# =============================================================================
def calculate_adaptive_confidence_threshold(regime_info, base_confidence=70):
"""
Berechnet adaptive Confidence-Schwelle basierend auf Marktregime
"""
regime = regime_info['regime']
strength = regime_info['strength']
adx = regime_info['adx']
if regime == 'trending':
# In Trending Markets: niedrigere Schwelle bei starken Trends
if adx > 30:
return max(60, base_confidence - 15)
else:
return base_confidence - 10
elif regime == 'ranging':
# In Ranging Markets: höhere Schwelle für mehr Selektivität
return base_confidence + 15
elif regime == 'volatile':
# In Volatile Markets: deutlich höhere Schwelle
return base_confidence + 20
return base_confidence
# =============================================================================
# 3. ENHANCED TREND ANALYSIS
# =============================================================================
def get_enhanced_trend(timeframe="H4", lookback=150, symbol="XAUUSD"):
"""
Verbesserte Trend-Analyse mit Regime-Awareness
"""
from your_existing_functions import get_rates # Import your existing function
# Timeframe mapping
tf_map = {"D1": "d1", "H4": "h4", "H1": "h1", "M30": "m30", "M15": "m15", "M5": "m5"}
tf = tf_map.get(timeframe, timeframe.lower())
try:
df = get_rates(tf, lookback)
if df is None or len(df) < 50:
return None
# Bestehende Trend-Logik
df['close_smooth'] = savgol_filter(df['close'], min(15, len(df)//10), 3)
df['atr'] = ta.atr(df['high'], df['low'], df['close'], length=14)
# Linear Regression
X = np.arange(len(df)).reshape(-1, 1)
y = df['close_smooth'].values
model = LinearRegression().fit(X, y)
slope = model.coef_[0]
# Market Regime Detection
regime_info = detect_market_regime(df.iloc[-50:])
# Adaptive Slope Threshold basierend auf Regime
base_threshold = df['atr'].iloc[-1] * 0.0001
if regime_info['regime'] == 'trending':
slope_threshold = base_threshold * 0.7 # Niedrigere Schwelle in Trends
elif regime_info['regime'] == 'ranging':
slope_threshold = base_threshold * 1.5 # Höhere Schwelle in Ranges
else: # volatile
slope_threshold = base_threshold * 1.2
# Trend bestimmen
if slope > slope_threshold:
trend = "uptrend"
elif slope < -slope_threshold:
trend = "downtrend"
else:
trend = "sideways"
# Enhanced Trend Strength
trend_strength = abs(slope) / slope_threshold if slope_threshold > 0 else 0
return {
"trend": trend,
"slope": slope,
"slope_threshold": slope_threshold,
"trend_strength": trend_strength,
"atr": df['atr'].iloc[-1],
"price": df['close'].iloc[-1],
"regime_info": regime_info
}
except Exception as e:
print(f"Error in get_enhanced_trend: {e}")
return None
# =============================================================================
# 4. OPTIMIZED TOP-DOWN ANALYSIS
# =============================================================================
def extended_top_down_v2(symbol="XAUUSD", lookback=150):
"""
Optimierte Top-Down-Analyse mit adaptiven Parametern
"""
timeframes = ["D1", "H4", "H1", "M30", "M15", "M5"]
trend_info = {}
# 1. Alle Timeframes analysieren
for tf in timeframes:
trend_info[tf] = get_enhanced_trend(tf, lookback, symbol)
if trend_info[tf] is None:
print(f"⚠️ Keine Daten für {tf}")
return None
# 2. Market Regime aus H4 bestimmen (repräsentativ)
main_regime = trend_info["H4"]["regime_info"]
# 3. Adaptive Confidence Threshold
adaptive_confidence_threshold = calculate_adaptive_confidence_threshold(main_regime)
# 4. Enhanced Standard-Trend (D1 + H4 mit Gewichtung)
d1_trend = trend_info["D1"]["trend"]
h4_trend = trend_info["H4"]["trend"]
d1_strength = trend_info["D1"]["trend_strength"]
h4_strength = trend_info["H4"]["trend_strength"]
# Gewichteter Standard-Trend
if d1_trend == h4_trend and d1_trend != "sideways":
standard_trend = d1_trend
standard_strength = (d1_strength * 0.6 + h4_strength * 0.4)
elif d1_strength > h4_strength * 1.5: # D1 deutlich stärker
standard_trend = d1_trend
standard_strength = d1_strength * 0.8
elif h4_strength > d1_strength * 1.5: # H4 deutlich stärker
standard_trend = h4_trend
standard_strength = h4_strength * 0.8
else:
standard_trend = "sideways"
standard_strength = 0
# 5. Enhanced Fast-Trend mit Regime-Awareness
fast_timeframes = ["H1", "M30", "M15", "M5"]
fast_trends = [trend_info[tf]["trend"] for tf in fast_timeframes]
fast_strengths = [trend_info[tf]["trend_strength"] for tf in fast_timeframes]
# Regime-abhängige Fast-Trend Logik
if main_regime['regime'] == 'trending':
# In Trends: 2 von 4 TFs reichen
required_alignment = 2
else:
# In Ranging/Volatile: 3 von 4 TFs erforderlich
required_alignment = 3
trend_counts = {'uptrend': 0, 'downtrend': 0, 'sideways': 0}
weighted_strengths = {'uptrend': 0, 'downtrend': 0}
weights = [1.0, 0.8, 0.6, 0.4] # H1, M30, M15, M5
for i, (trend, strength) in enumerate(zip(fast_trends, fast_strengths)):
trend_counts[trend] += 1
if trend != 'sideways':
weighted_strengths[trend] += strength * weights[i]
# Fast-Trend bestimmen
max_count = max(trend_counts['uptrend'], trend_counts['downtrend'])
if max_count >= required_alignment:
if trend_counts['uptrend'] > trend_counts['downtrend']:
fast_trend = "uptrend"
elif trend_counts['downtrend'] > trend_counts['uptrend']:
fast_trend = "downtrend"
else:
# Bei Gleichstand: Stärke entscheidet
if weighted_strengths['uptrend'] > weighted_strengths['downtrend']:
fast_trend = "uptrend"
else:
fast_trend = "downtrend"
else:
fast_trend = "sideways"
# 6. Top-Down-Trend Bestimmung
if standard_trend == fast_trend and standard_trend != "sideways":
top_down_trend = standard_trend
combined_strength = (standard_strength + weighted_strengths[fast_trend]) / 2
else:
top_down_trend = "sideways"
combined_strength = 0
# 7. Enhanced Confidence Calculation
weights = {"D1": 2.5, "H4": 2.0, "H1": 1.5, "M30": 1.0, "M15": 0.8, "M5": 0.6}
weighted_matching = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] == top_down_trend and trend_info[tf]["trend"] != "sideways"
)
weighted_total = sum(
weights[tf] * trend_info[tf]["trend_strength"]
for tf in timeframes
if trend_info[tf]["trend"] != "sideways"
)
confidence = round((weighted_matching / weighted_total) * 100, 2) if weighted_total > 0 else 0.0
# 8. Risk-Adjusted Signal Strength
atr = trend_info["M5"]["atr"]
rrr = 2.5 # Risk-Reward Ratio
risk_adjusted_strength = confidence * combined_strength * min(2.0, rrr)
# 9. Entry Signal mit adaptiven Kriterien
entry_signal = 0
signal_quality = "none"
if (top_down_trend != "sideways" and
confidence >= adaptive_confidence_threshold and
risk_adjusted_strength >= 100):
entry_signal = 1 if top_down_trend == "uptrend" else -1
# Signal Quality Assessment
if confidence >= 85 and risk_adjusted_strength >= 150:
signal_quality = "excellent"
elif confidence >= 75 and risk_adjusted_strength >= 120:
signal_quality = "good"
else:
signal_quality = "fair"
# 10. Enhanced Debug Output
debug_data = []
for tf in timeframes:
info = trend_info[tf]
debug_data.append([
tf,
info["trend"],
f"{info['trend_strength']:.2f}",
f"{info['atr']:.4f}",
f"{info['slope']:.6f}",
f"{info['price']:.2f}"
])
print(f"\n📊 Enhanced Trend-Analyse für {symbol}")
print(f"🎯 Market Regime: {main_regime['regime'].upper()} (Strength: {main_regime['strength']:.0f}%)")
print(f"🎚️ Adaptive Confidence Threshold: {adaptive_confidence_threshold}%")
print()
print(tabulate(debug_data, headers=["TF", "Trend", "Strength", "ATR", "Slope", "Price"], tablefmt="psql"))
print(f"\n➡️ Standard-Trend: {standard_trend} (Strength: {standard_strength:.2f})")
print(f"➡️ Fast-Trend: {fast_trend}")
print(f"➡️ Top-Down-Trend: {top_down_trend}")
print(f"➡️ Confidence: {confidence}% (Threshold: {adaptive_confidence_threshold}%)")
print(f"➡️ Risk-Adjusted Strength: {risk_adjusted_strength:.1f}")
print(f"➡️ Signal Quality: {signal_quality.upper()}")
return {
"symbol": symbol,
"trend_info": trend_info,
"market_regime": main_regime,
"standard_trend": standard_trend,
"fast_trend": fast_trend,
"top_down_trend": top_down_trend,
"confidence": confidence,
"adaptive_threshold": adaptive_confidence_threshold,
"risk_adjusted_strength": risk_adjusted_strength,
"entry_signal": entry_signal,
"signal_quality": signal_quality,
"combined_strength": combined_strength
}
# =============================================================================
# 5. ENTRY TIMING OPTIMIZATION
# =============================================================================
def check_pullback_entry(symbol, signal_info, timeframe="M5"):
"""
Prüft optimale Entry-Timing durch Pullback-Analyse
"""
if signal_info["entry_signal"] == 0:
return False, "No base signal"
try:
from your_existing_functions import get_rates # Import your existing function
df = get_rates(timeframe.lower(), 50)
if df is None or len(df) < 20:
return False, "Insufficient data"
# EMAs für Pullback-Erkennung
df['ema21'] = df['close'].ewm(span=21).mean()
df['ema50'] = df['close'].ewm(span=50).mean()
current_price = df['close'].iloc[-1]
ema21 = df['ema21'].iloc[-1]
ema50 = df['ema50'].iloc[-1]
signal_direction = signal_info["entry_signal"]
if signal_direction == 1: # Long Signal
# Pullback zu EMA21 oder Support
if current_price <= ema21 * 1.002 and ema21 > ema50:
return True, "Pullback to EMA21 for Long"
elif current_price <= ema21 * 0.998:
return True, "Below EMA21 - Good Long Entry"
elif signal_direction == -1: # Short Signal
# Pullback zu EMA21 oder Resistance
if current_price >= ema21 * 0.998 and ema21 < ema50:
return True, "Pullback to EMA21 for Short"
elif current_price >= ema21 * 1.002:
return True, "Above EMA21 - Good Short Entry"
return False, "Waiting for better entry timing"
except Exception as e:
print(f"Error in pullback check: {e}")
return True, "Using immediate entry (fallback)"
# =============================================================================
# 6. ENHANCED EXECUTE TRADE FUNCTION
# =============================================================================
def execute_trade_v2(
symbol="XAUUSD",
atr_mult=1.5,
base_confidence=70,
max_risk_per_trade=0.01,
risk_filter=True,
min_atr=0.0010,
use_pullback_entry=True,
debug=True
):
"""
Optimierte Trade-Ausführung mit allen Verbesserungen
"""
# 1. Enhanced Signal Analysis
signal_info = extended_top_down_v2(symbol)
if signal_info is None:
print("❌ Signal-Analyse fehlgeschlagen")
return None
entry_signal = signal_info["entry_signal"]
confidence = signal_info["confidence"]
adaptive_threshold = signal_info["adaptive_threshold"]
signal_quality = signal_info["signal_quality"]
market_regime = signal_info["market_regime"]
# 2. Get Price/ATR from M5
m5_info = signal_info["trend_info"]["M5"]
price = m5_info["price"]
atr = m5_info["atr"]
# 3. Enhanced Pre-checks
reason = ""
if confidence < adaptive_threshold:
reason = f"Confidence {confidence}% < adaptive threshold {adaptive_threshold}%"
elif entry_signal == 0:
reason = f"No entry signal (Trend: {signal_info['top_down_trend']}, Regime: {market_regime['regime']})"
elif price is None or atr is None:
reason = "Price/ATR not available"
elif risk_filter and atr < min_atr:
reason = f"ATR {atr:.5f} < min_atr {min_atr}"
elif signal_quality == "none":
reason = "Signal quality insufficient"
else:
# 4. Entry Timing Check
if use_pullback_entry:
pullback_ok, pullback_reason = check_pullback_entry(symbol, signal_info)
if not pullback_ok:
reason = f"Entry timing: {pullback_reason}"
if not reason:
# 5. Enhanced Risk Checks
from your_existing_functions import check_risk_limits # Import your existing function
risk_ok = check_risk_limits(symbol, max_risk_per_trade=max_risk_per_trade)
if not risk_ok:
reason = "Risk limits exceeded"
# 6. Execute Trade if all checks pass
if not reason:
# Enhanced SL/TP calculation based on regime
regime_mult = 1.0
if market_regime['regime'] == 'volatile':
regime_mult = 1.3 # Wider stops in volatile markets
elif market_regime['regime'] == 'ranging':
regime_mult = 0.8 # Tighter stops in ranging markets
adjusted_atr_mult = atr_mult * regime_mult
if entry_signal == 1: # Long
stop_loss = price - adjusted_atr_mult * atr
take_profit = price + adjusted_atr_mult * atr * 2.5 # Better RRR
else: # Short
stop_loss = price + adjusted_atr_mult * atr
take_profit = price - adjusted_atr_mult * atr * 2.5
# Dynamic Position Sizing
stop_distance = adjusted_atr_mult * atr
risk_amount = max_risk_per_trade * 10000 # Assuming account balance
volume = min(0.1, risk_amount / (stop_distance * 100000)) # Simplified calculation
# Log Enhanced Trade Info
print(f"\n🚀 ENHANCED TRADE EXECUTION")
print(f"Symbol: {symbol}")
print(f"Direction: {'LONG' if entry_signal == 1 else 'SHORT'}")
print(f"Price: {price:.5f}")
print(f"Volume: {volume:.2f}")
print(f"Stop Loss: {stop_loss:.5f}")
print(f"Take Profit: {take_profit:.5f}")
print(f"Confidence: {confidence}% (Threshold: {adaptive_threshold}%)")
print(f"Signal Quality: {signal_quality.upper()}")
print(f"Market Regime: {market_regime['regime'].upper()}")
print(f"ATR Multiplier: {adjusted_atr_mult:.2f} (Base: {atr_mult})")
print(f"Risk per Trade: {max_risk_per_trade*100:.1f}%")
# Execute the actual trade
try:
from your_existing_functions import market_order # Import your existing function
order_result = market_order(
symbol=symbol,
volume=volume,
order_type="buy" if entry_signal == 1 else "sell",
stoploss=stop_loss,
take_profit=take_profit
)
# Log Trade to Performance Monitor
log_trade_performance(signal_info, order_result)
return order_result
except Exception as e:
print(f"❌ Trade execution failed: {e}")
return None
else:
if debug:
print(f"\n⏸️ TRADE SKIPPED: {reason}")
print(f"Confidence: {confidence}% | Threshold: {adaptive_threshold}%")
print(f"Signal Quality: {signal_quality} | Regime: {market_regime['regime']}")
return None
# =============================================================================
# 7. PERFORMANCE MONITORING
# =============================================================================
def log_trade_performance(signal_info, order_result):
"""
Loggt Trade-Performance für Analyse und Optimierung
"""
trade_data = {
'timestamp': datetime.now().isoformat(),
'symbol': signal_info['symbol'],
'entry_signal': signal_info['entry_signal'],
'confidence': signal_info['confidence'],
'adaptive_threshold': signal_info['adaptive_threshold'],
'signal_quality': signal_info['signal_quality'],
'market_regime': signal_info['market_regime']['regime'],
'regime_strength': signal_info['market_regime']['strength'],
'risk_adjusted_strength': signal_info['risk_adjusted_strength'],
'order_result': str(order_result) if order_result else None
}
# Save to JSON file for analysis
try:
filename = f"trade_performance_{signal_info['symbol']}_{datetime.now().strftime('%Y%m')}.json"
try:
with open(filename, 'r') as f:
data = json.load(f)
except FileNotFoundError:
data = []
data.append(trade_data)
with open(filename, 'w') as f:
json.dump(data, f, indent=2)
except Exception as e:
print(f"Warning: Could not log performance data: {e}")
def analyze_performance(symbol="XAUUSD", days_back=30):
"""
Analysiert Performance der letzten Trades
"""
try:
filename = f"trade_performance_{symbol}_{datetime.now().strftime('%Y%m')}.json"
with open(filename, 'r') as f:
data = json.load(f)
# Filter last X days
cutoff = datetime.now() - timedelta(days=days_back)
recent_trades = [
trade for trade in data
if datetime.fromisoformat(trade['timestamp']) > cutoff
]
if not recent_trades:
print(f"No trades found in last {days_back} days")
return
# Analysis
total_trades = len(recent_trades)
by_regime = {}
by_confidence = {'high': 0, 'medium': 0, 'low': 0}
by_quality = {}
for trade in recent_trades:
# By regime
regime = trade['market_regime']
by_regime[regime] = by_regime.get(regime, 0) + 1
# By confidence
conf = trade['confidence']
if conf >= 85:
by_confidence['high'] += 1
elif conf >= 75:
by_confidence['medium'] += 1
else:
by_confidence['low'] += 1
# By quality
quality = trade['signal_quality']
by_quality[quality] = by_quality.get(quality, 0) + 1
print(f"\n📊 PERFORMANCE ANALYSIS - Last {days_back} days")
print(f"Total Trades: {total_trades}")
print(f"\nBy Market Regime:")
for regime, count in by_regime.items():
print(f" {regime.upper()}: {count} ({count/total_trades*100:.1f}%)")
print(f"\nBy Confidence Level:")
for level, count in by_confidence.items():
print(f" {level.upper()}: {count} ({count/total_trades*100:.1f}%)")
print(f"\nBy Signal Quality:")
for quality, count in by_quality.items():
print(f" {quality.upper()}: {count} ({count/total_trades*100:.1f}%)")
except Exception as e:
print(f"Could not analyze performance: {e}")
# =============================================================================
# 8. QUICK SETUP FUNCTION
# =============================================================================
def setup_optimized_trading():
"""
Quick setup für optimiertes Trading
"""
print("🚀 Setting up Optimized Trading Bot V1.4")
print("\nKey Improvements:")
print("✅ Adaptive confidence thresholds")
print("✅ Market regime detection")
print("✅ Enhanced entry timing")
print("✅ Risk-adjusted signal strength")
print("✅ Performance monitoring")
print("\nReady to trade with enhanced logic!")
if __name__ == "__main__":
setup_optimized_trading()