feat: Add Trend Reversal Detector with multi-signal analysis
Deploy to Windows VPS / deploy (push) Has been cancelled
Deploy to Windows VPS / deploy (push) Has been cancelled
New features: - Reversal Detector with 5 detection signals: - RSI Divergence (bearish/bullish) - EMA Slope Change detection - Volume Spike analysis - Candlestick patterns (Doji, Engulfing, Hammer, Pin Bar) - Break of Structure detection - Integrated into enhanced_trading_check_wrapper (SCHRITT 2.5) - Defensive mode: blocks trades at 70%+ reversal score - Lot size reduction at 30-69% reversal score - Enable Overlap session (13:00-16:00 UTC) Files added: - reversal_detector.py: Core detection algorithms - reversal_integration.py: Bot integration wrapper - REVERSAL_DETECTOR_INTEGRATION.md: Documentation Modified: - TradingBot notebook: Added reversal check integration - session_filter_patch.py: Enabled overlap session Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,221 @@
|
|||||||
|
# 🔄 Reversal Detector Integration Guide
|
||||||
|
|
||||||
|
## Schnell-Integration
|
||||||
|
|
||||||
|
### Schritt 1: Import hinzufügen (neue Cell nach den Imports)
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ==========================================
|
||||||
|
# 🔄 REVERSAL DETECTOR INTEGRATION
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
from reversal_integration import (
|
||||||
|
reversal_detector,
|
||||||
|
check_reversal_risk,
|
||||||
|
get_reversal_status,
|
||||||
|
enable_reversal_check,
|
||||||
|
disable_reversal_check,
|
||||||
|
REVERSAL_CONFIG
|
||||||
|
)
|
||||||
|
|
||||||
|
print(get_reversal_status())
|
||||||
|
```
|
||||||
|
|
||||||
|
### Schritt 2: In `enhanced_trading_check_wrapper` einfügen
|
||||||
|
|
||||||
|
Füge nach **SCHRITT 2: Signal Analysis** und vor **SCHRITT 3: ENHANCED SIGNAL SCORING** folgenden Code ein:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# ==========================================
|
||||||
|
# ⭐ SCHRITT 2.5: REVERSAL CHECK (NEU!)
|
||||||
|
# ==========================================
|
||||||
|
from reversal_integration import check_reversal_risk
|
||||||
|
|
||||||
|
reversal_result = check_reversal_risk(signal_info, symbol)
|
||||||
|
|
||||||
|
print(f"\n🔄 Reversal Check: {reversal_result['action']}")
|
||||||
|
print(f" Score: {reversal_result['reversal_score']}%")
|
||||||
|
print(f" Reason: {reversal_result['reason']}")
|
||||||
|
|
||||||
|
if not reversal_result['should_trade']:
|
||||||
|
print(f"⛔ TRADE BLOCKIERT durch Reversal Detector!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Reversal Lot Multiplier mit Equity Curve kombinieren
|
||||||
|
if reversal_result['lot_multiplier'] < 1.0:
|
||||||
|
lot_multiplier *= reversal_result['lot_multiplier']
|
||||||
|
print(f"📉 Reversal: Lot Multiplier angepasst auf {lot_multiplier:.0%}")
|
||||||
|
# ==========================================
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Vollständige enhanced_trading_check_wrapper mit Reversal Check
|
||||||
|
|
||||||
|
```python
|
||||||
|
def enhanced_trading_check_wrapper(symbol="XAUUSD", debug=False):
|
||||||
|
"""
|
||||||
|
Enhanced wrapper around execute_trade_v2_adaptive
|
||||||
|
Adds multi-factor signal scoring before execution
|
||||||
|
+ Reversal Detection (NEU!)
|
||||||
|
"""
|
||||||
|
|
||||||
|
try:
|
||||||
|
# ⭐ SCHRITT 0: SESSION CHECK
|
||||||
|
from session_filter_patch import is_session_allowed
|
||||||
|
current_session = rhythm_manager.get_current_session()
|
||||||
|
session_allowed, session_reason = is_session_allowed(current_session)
|
||||||
|
|
||||||
|
if not session_allowed:
|
||||||
|
print(f"⛔ SESSION BLOCKED: {current_session.upper()}")
|
||||||
|
print(f" Reason: {session_reason}")
|
||||||
|
return None
|
||||||
|
|
||||||
|
print(f"✅ Session OK: {current_session.upper()}")
|
||||||
|
|
||||||
|
# SCHRITT 1: Position Check
|
||||||
|
max_positions = TRADING_CONFIG['risk']['max_positions']
|
||||||
|
has_position, position_info = check_existing_positions(symbol)
|
||||||
|
|
||||||
|
if position_info['count'] >= max_positions:
|
||||||
|
if debug:
|
||||||
|
print(f"🛑 TRADE BLOCKIERT: {position_info['count']}/{max_positions} Positionen aktiv")
|
||||||
|
return None
|
||||||
|
|
||||||
|
print(f"✅ Position-Check OK: {position_info['count']}/{max_positions}")
|
||||||
|
|
||||||
|
# SCHRITT 1.5: EQUITY CURVE CHECK
|
||||||
|
ec_allowed, ec_reason, lot_multiplier = equity_curve_manager.should_trade()
|
||||||
|
print(f"📈 Equity Curve: {ec_reason}")
|
||||||
|
|
||||||
|
if not ec_allowed:
|
||||||
|
print(f"⛔ TRADE BLOCKIERT durch Equity Curve Filter")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# SCHRITT 2: Signal Analysis
|
||||||
|
signal_info = extended_top_down_v2_adaptive(symbol)
|
||||||
|
if signal_info is None:
|
||||||
|
print("❌ Signal-Analyse fehlgeschlagen")
|
||||||
|
return None
|
||||||
|
|
||||||
|
entry_signal = signal_info["entry_signal"]
|
||||||
|
base_confidence = signal_info["confidence"]
|
||||||
|
adaptive_threshold = signal_info["adaptive_threshold"]
|
||||||
|
|
||||||
|
print(f"\n📊 Base Signal Analysis:")
|
||||||
|
print(f" Direction: {entry_signal}")
|
||||||
|
print(f" Base Confidence: {base_confidence:.1f}%")
|
||||||
|
print(f" Adaptive Threshold: {adaptive_threshold:.1f}%")
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# ⭐ SCHRITT 2.5: REVERSAL CHECK (NEU!)
|
||||||
|
# ==========================================
|
||||||
|
from reversal_integration import check_reversal_risk
|
||||||
|
|
||||||
|
reversal_result = check_reversal_risk(signal_info, symbol)
|
||||||
|
|
||||||
|
print(f"\n🔄 Reversal Check: {reversal_result['action']}")
|
||||||
|
print(f" Score: {reversal_result['reversal_score']}%")
|
||||||
|
print(f" Reason: {reversal_result['reason']}")
|
||||||
|
|
||||||
|
if not reversal_result['should_trade']:
|
||||||
|
print(f"⛔ TRADE BLOCKIERT durch Reversal Detector!")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Reversal Lot Multiplier kombinieren
|
||||||
|
if reversal_result['lot_multiplier'] < 1.0:
|
||||||
|
lot_multiplier *= reversal_result['lot_multiplier']
|
||||||
|
print(f"📉 Reversal: Lot Multiplier angepasst auf {lot_multiplier:.0%}")
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# ⭐ SCHRITT 3: ENHANCED SIGNAL SCORING (HYBRID 60/40)
|
||||||
|
# ... (Rest des Codes bleibt unverändert)
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Kontroll-Befehle
|
||||||
|
|
||||||
|
Nach der Integration kannst du folgende Befehle nutzen:
|
||||||
|
|
||||||
|
```python
|
||||||
|
# Status anzeigen
|
||||||
|
print(get_reversal_status())
|
||||||
|
|
||||||
|
# Reversal Check deaktivieren
|
||||||
|
disable_reversal_check()
|
||||||
|
|
||||||
|
# Reversal Check aktivieren
|
||||||
|
enable_reversal_check()
|
||||||
|
|
||||||
|
# Thresholds anpassen
|
||||||
|
REVERSAL_CONFIG['block_threshold'] = 80 # Weniger strikt
|
||||||
|
REVERSAL_CONFIG['reduce_threshold'] = 60
|
||||||
|
REVERSAL_CONFIG['caution_threshold'] = 40
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Erwartetes Output
|
||||||
|
|
||||||
|
```
|
||||||
|
✅ Session OK: ASIAN
|
||||||
|
✅ Position-Check OK: 0/1
|
||||||
|
📈 Equity Curve: ✅ Equity $108,500.00 > MA $107,200.00 (+1.2%)
|
||||||
|
|
||||||
|
📊 Base Signal Analysis:
|
||||||
|
Direction: 1
|
||||||
|
Base Confidence: 87.5%
|
||||||
|
Adaptive Threshold: 60.0%
|
||||||
|
|
||||||
|
🔄 REVERSAL CHECK (UPTREND):
|
||||||
|
--------------------------------------------------
|
||||||
|
Rsi Divergence : ✅ No divergence
|
||||||
|
Ema Slope Change : ✅ Slope: 0.0045%
|
||||||
|
Volume Spike : ✅ Volume: 1.3x average
|
||||||
|
Candlestick : ✅ No reversal pattern
|
||||||
|
Break Of Structure : ✅ Structure intact
|
||||||
|
--------------------------------------------------
|
||||||
|
✅ Reversal Score: 15% (LOW)
|
||||||
|
Action: ALLOW | Lot Mult: 100%
|
||||||
|
|
||||||
|
🔄 Reversal Check: ALLOW
|
||||||
|
Score: 15%
|
||||||
|
Reason: No significant reversal risk (15%)
|
||||||
|
|
||||||
|
🎯 Calculating Enhanced Signal Score...
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Bei hohem Reversal-Risiko
|
||||||
|
|
||||||
|
```
|
||||||
|
🔄 REVERSAL CHECK (UPTREND):
|
||||||
|
--------------------------------------------------
|
||||||
|
Rsi Divergence : ⚠️ Bearish Divergence: Price HH, RSI LH (RSI diff: 8.5)
|
||||||
|
Strength: 65%
|
||||||
|
Ema Slope Change : ⚠️ Slope weakening: 0.0089% -> 0.0012%
|
||||||
|
Strength: 45%
|
||||||
|
Volume Spike : ⚠️ Volume: 2.8x average (SPIKE!)
|
||||||
|
Strength: 40%
|
||||||
|
Candlestick : ⚠️ Shooting Star: Potential bearish reversal
|
||||||
|
Strength: 60%
|
||||||
|
Break Of Structure : ✅ Structure intact
|
||||||
|
--------------------------------------------------
|
||||||
|
🔴 Reversal Score: 78% (CRITICAL)
|
||||||
|
Action: BLOCK | Lot Mult: 0%
|
||||||
|
|
||||||
|
🔄 Reversal Check: BLOCK
|
||||||
|
Score: 78%
|
||||||
|
Reason: High reversal risk (78% >= 70%)
|
||||||
|
⛔ TRADE BLOCKIERT durch Reversal Detector!
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Dateien
|
||||||
|
|
||||||
|
- `reversal_detector.py` - Haupt-Modul mit allen Algorithmen
|
||||||
|
- `reversal_integration.py` - Integration für den Trading Bot
|
||||||
|
- `REVERSAL_DETECTOR_INTEGRATION.md` - Diese Anleitung
|
||||||
@@ -3022,6 +3022,7 @@
|
|||||||
"from enhanced_trailing_stop import EnhancedTrailingStopManager, create_enhanced_position_monitor\n",
|
"from enhanced_trailing_stop import EnhancedTrailingStopManager, create_enhanced_position_monitor\n",
|
||||||
"from equity_curve_trading import EquityCurveManager\n",
|
"from equity_curve_trading import EquityCurveManager\n",
|
||||||
"from demo_test_tracker import DemoTestTracker\n",
|
"from demo_test_tracker import DemoTestTracker\n",
|
||||||
|
"from reversal_integration import check_reversal_risk, get_reversal_status, REVERSAL_CONFIG\n",
|
||||||
"\n",
|
"\n",
|
||||||
"print(\"🚀 INITIALIZING ADVANCED OPTIMIZATIONS...\")\n",
|
"print(\"🚀 INITIALIZING ADVANCED OPTIMIZATIONS...\")\n",
|
||||||
"print(\"=\" * 70)\n",
|
"print(\"=\" * 70)\n",
|
||||||
@@ -3114,6 +3115,10 @@
|
|||||||
"print(\"✅ Demo Test Tracker initialized\")\n",
|
"print(\"✅ Demo Test Tracker initialized\")\n",
|
||||||
"print()\n",
|
"print()\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
"# 6. Reversal Detector\n",
|
||||||
|
"print(\"✅ Reversal Detector initialized\")\n",
|
||||||
|
"print(get_reversal_status())\n",
|
||||||
|
"\n",
|
||||||
"# 4. Run initial threshold optimization\n",
|
"# 4. Run initial threshold optimization\n",
|
||||||
"print(\"🔄 Running initial threshold optimization...\")\n",
|
"print(\"🔄 Running initial threshold optimization...\")\n",
|
||||||
"try:\n",
|
"try:\n",
|
||||||
@@ -3133,6 +3138,7 @@
|
|||||||
"print(\" • Enhanced Trailing: ✅ (multi-tier protection)\")\n",
|
"print(\" • Enhanced Trailing: ✅ (multi-tier protection)\")\n",
|
||||||
"print(\" • Equity Curve Trading: ✅ (auto-pause on drawdown)\")\n",
|
"print(\" • Equity Curve Trading: ✅ (auto-pause on drawdown)\")\n",
|
||||||
"print(\" • Demo Test Tracker: ✅ (go-live readiness check)\")\n",
|
"print(\" • Demo Test Tracker: ✅ (go-live readiness check)\")\n",
|
||||||
|
"print(\" • Reversal Detector: ✅ (multi-signal protection)\")\n",
|
||||||
"print()\n",
|
"print()\n",
|
||||||
"print(\"💡 Tip: Use 'threshold_optimizer.generate_report()' for details\")"
|
"print(\"💡 Tip: Use 'threshold_optimizer.generate_report()' for details\")"
|
||||||
]
|
]
|
||||||
@@ -3719,6 +3725,26 @@
|
|||||||
" print(f\" Base Confidence: {base_confidence:.1f}%\")\n",
|
" print(f\" Base Confidence: {base_confidence:.1f}%\")\n",
|
||||||
" print(f\" Adaptive Threshold: {adaptive_threshold:.1f}%\")\n",
|
" print(f\" Adaptive Threshold: {adaptive_threshold:.1f}%\")\n",
|
||||||
"\n",
|
"\n",
|
||||||
|
" # ==========================================\n",
|
||||||
|
" # ⭐ SCHRITT 2.5: REVERSAL CHECK (NEU!)\n",
|
||||||
|
" # ==========================================\n",
|
||||||
|
" from reversal_integration import check_reversal_risk\n",
|
||||||
|
"\n",
|
||||||
|
" reversal_result = check_reversal_risk(signal_info, symbol)\n",
|
||||||
|
"\n",
|
||||||
|
" print(f\"🔄 Reversal Check: {reversal_result['action']}\")\n",
|
||||||
|
" print(f\" Score: {reversal_result['reversal_score']}%\")\n",
|
||||||
|
" print(f\" Reason: {reversal_result['reason']}\")\n",
|
||||||
|
"\n",
|
||||||
|
" if not reversal_result['should_trade']:\n",
|
||||||
|
" print(f\"⛔ TRADE BLOCKIERT durch Reversal Detector!\")\n",
|
||||||
|
" return None\n",
|
||||||
|
"\n",
|
||||||
|
" # Reversal Lot Multiplier mit Equity Curve kombinieren\n",
|
||||||
|
" if reversal_result['lot_multiplier'] < 1.0:\n",
|
||||||
|
" lot_multiplier *= reversal_result['lot_multiplier']\n",
|
||||||
|
" print(f\"📉 Reversal: Lot Multiplier angepasst auf {lot_multiplier:.0%}\")\n",
|
||||||
|
"\n",
|
||||||
" # ⭐ SCHRITT 3: ENHANCED SIGNAL SCORING (HYBRID 60/40)\n",
|
" # ⭐ SCHRITT 3: ENHANCED SIGNAL SCORING (HYBRID 60/40)\n",
|
||||||
" print(f\"\\n🎯 Calculating Enhanced Signal Score...\")\n",
|
" print(f\"\\n🎯 Calculating Enhanced Signal Score...\")\n",
|
||||||
"\n",
|
"\n",
|
||||||
@@ -3899,99 +3925,10 @@
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": 74,
|
"execution_count": null,
|
||||||
"id": "a5c25689",
|
"id": "a5c25689",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [],
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"📊 DEMO TEST TRACKER\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"📊 DEMO TEST TRACKER - PERFORMANCE REPORT\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"📅 Demo Period:\n",
|
|
||||||
" Start: 2026-01-28\n",
|
|
||||||
" Days Running: 1\n",
|
|
||||||
" Last Trade: 2026-01-29\n",
|
|
||||||
"\n",
|
|
||||||
"📈 PERFORMANCE METRICS:\n",
|
|
||||||
" Total Trades: 348\n",
|
|
||||||
" Wins/Losses: 177/171\n",
|
|
||||||
" Win Rate: 50.9%\n",
|
|
||||||
" Profit Factor: 1.42\n",
|
|
||||||
"\n",
|
|
||||||
"💰 PROFIT/LOSS:\n",
|
|
||||||
" Total Profit: $4,598.21\n",
|
|
||||||
" Avg Win: $88.50\n",
|
|
||||||
" Avg Loss: $64.72\n",
|
|
||||||
" Avg Trade: $13.21\n",
|
|
||||||
" Best Trade: $915.60\n",
|
|
||||||
" Worst Trade: $-345.70\n",
|
|
||||||
"\n",
|
|
||||||
"📉 RISK METRICS:\n",
|
|
||||||
" Max Drawdown: 100.0% ($1,972.65)\n",
|
|
||||||
" Current Equity: $4,598.21\n",
|
|
||||||
" Peak Equity: $4,914.21\n",
|
|
||||||
"\n",
|
|
||||||
"⏱️ TIMING:\n",
|
|
||||||
" Avg Duration: 49 min\n",
|
|
||||||
"\n",
|
|
||||||
"🌍 SESSION BREAKDOWN:\n",
|
|
||||||
" ASIAN | Trades: 155 | Win Rate: 54.2% | Profit: $3,270.77\n",
|
|
||||||
" LONDON | Trades: 81 | Win Rate: 46.9% | Profit: $654.12\n",
|
|
||||||
" NY | Trades: 112 | Win Rate: 49.1% | Profit: $673.32\n",
|
|
||||||
"\n",
|
|
||||||
"🎯 SIGNAL QUALITY BREAKDOWN:\n",
|
|
||||||
" UNKNOWN | Trades: 348 | Win Rate: 50.9% | Profit: $4,598.21\n",
|
|
||||||
"\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"🚦 GO-LIVE READINESS CHECK\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
" ✅ Trades: 348/50\n",
|
|
||||||
" ⬜ Win Rate: 50.9% (min 55%)\n",
|
|
||||||
" ✅ Profit Factor: 1.42 (min 1.3)\n",
|
|
||||||
" ⬜ Max Drawdown: 100.0% (max 15%)\n",
|
|
||||||
" ⬜ Days Running: 1/14\n",
|
|
||||||
" ✅ Errors: 0 (max 5)\n",
|
|
||||||
" ✅ Sessions Tested: 3/2\n",
|
|
||||||
"----------------------------------------------------------------------\n",
|
|
||||||
" Passed: 4/7\n",
|
|
||||||
"\n",
|
|
||||||
" ⏳ STATUS: NOT READY YET\n",
|
|
||||||
" Still needed:\n",
|
|
||||||
" • Win Rate: 50.9% (min 55%)\n",
|
|
||||||
" • Max Drawdown: 100.0% (max 15%)\n",
|
|
||||||
" • Days Running: 1/14\n",
|
|
||||||
"======================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"📊 Daily Summary - 2026-01-29\n",
|
|
||||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━\n",
|
|
||||||
"Today: 16 trades | 9 wins | WR: 56% | P/L: $+1111.80\n",
|
|
||||||
"Overall: 348 trades | WR: 50.9% | Total: $+4598.21\n",
|
|
||||||
"━━━━━━━━━━━━━━━━━━━━━━━━━━━\n",
|
|
||||||
"\n",
|
|
||||||
"⏳ Weiter testen... Der Bot sammelt noch Daten.\n"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"name": "stderr",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"2026-01-29 10:46:29,000 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n"
|
|
||||||
]
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"source": [
|
"source": [
|
||||||
"# ==========================================\n",
|
"# ==========================================\n",
|
||||||
"# 📊 DEMO TEST TRACKER - REPORTS & GO-LIVE CHECK\n",
|
"# 📊 DEMO TEST TRACKER - REPORTS & GO-LIVE CHECK\n",
|
||||||
@@ -4561,90 +4498,11 @@
|
|||||||
"id": "cf605503",
|
"id": "cf605503",
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [
|
"outputs": [
|
||||||
{
|
|
||||||
"name": "stdout",
|
|
||||||
"output_type": "stream",
|
|
||||||
"text": [
|
|
||||||
"================================================================================\n",
|
|
||||||
"💰 MT5 P&L TRACKER - LIVE PERFORMANCE DASHBOARD\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"Generated: 2026-01-29 10:46:35\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"📊 ALL TIME PERFORMANCE\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"Total Trades: 408\n",
|
|
||||||
"Winning Trades: 202 (49.5%)\n",
|
|
||||||
"Losing Trades: 206\n",
|
|
||||||
"\n",
|
|
||||||
"Net Profit: $3513.54\n",
|
|
||||||
"Total Profit: $12873.24\n",
|
|
||||||
"Total Loss: $9359.70\n",
|
|
||||||
"Profit Factor: 1.38\n",
|
|
||||||
"\n",
|
|
||||||
"Average Win: $63.73\n",
|
|
||||||
"Average Loss: $-45.44\n",
|
|
||||||
"Largest Win: $499.30\n",
|
|
||||||
"Largest Loss: $-151.75\n",
|
|
||||||
"\n",
|
|
||||||
"Max Drawdown: $-1981.78\n",
|
|
||||||
"Avg Duration: 1.0 hours\n",
|
|
||||||
"Total Pips: 5626600.0\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"📅 THIS MONTH\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"Trades: 332 (50.6% WR)\n",
|
|
||||||
"Net Profit: $3486.41\n",
|
|
||||||
"Profit/Loss: +$12558.73 / -$9072.32\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"📅 THIS WEEK\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"Trades: 166 (58.4% WR)\n",
|
|
||||||
"Net Profit: $3545.17\n",
|
|
||||||
"Profit/Loss: +$9536.97 / -$5991.80\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"📅 TODAY\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"❌ No trades today\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"📜 RECENT TRADES (Last 10)\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"\n",
|
|
||||||
" position_id symbol type entry_time exit_time net_profit pips duration_hours status\n",
|
|
||||||
" 719790790 XAUUSD LONG 2026-01-28 18:31 2026-01-28 21:24 499.30 499300.0 2.9 ✅ WIN\n",
|
|
||||||
" 719088260 XAUUSD LONG 2026-01-28 17:07 2026-01-28 17:58 153.20 306400.0 0.9 ✅ WIN\n",
|
|
||||||
" 718932869 XAUUSD LONG 2026-01-28 16:39 2026-01-28 17:06 -59.05 -118100.0 0.5 ❌ LOSS\n",
|
|
||||||
" 718905388 XAUUSD LONG 2026-01-28 16:35 2026-01-28 16:38 -87.76 -109700.0 0.1 ❌ LOSS\n",
|
|
||||||
" 718788969 XAUUSD LONG 2026-01-28 16:12 2026-01-28 16:34 34.45 68900.0 0.4 ✅ WIN\n",
|
|
||||||
" 718746714 XAUUSD LONG 2026-01-28 16:05 2026-01-28 16:11 -106.10 -106100.0 0.1 ❌ LOSS\n",
|
|
||||||
" 718592815 XAUUSD LONG 2026-01-28 15:29 2026-01-28 16:04 131.10 262200.0 0.6 ✅ WIN\n",
|
|
||||||
" 718467996 XAUUSD LONG 2026-01-28 15:03 2026-01-28 15:28 15.00 30000.0 0.4 ✅ WIN\n",
|
|
||||||
" 718377011 XAUUSD LONG 2026-01-28 14:38 2026-01-28 15:03 15.00 30000.0 0.4 ✅ WIN\n",
|
|
||||||
" 718312889 XAUUSD LONG 2026-01-28 14:22 2026-01-28 14:37 15.00 30000.0 0.3 ✅ WIN\n",
|
|
||||||
"\n",
|
|
||||||
"================================================================================\n",
|
|
||||||
"✅ Dashboard refresh complete!\n",
|
|
||||||
"Last updated: 2026-01-29 10:46:35\n",
|
|
||||||
"================================================================================\n"
|
|
||||||
]
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
"name": "stderr",
|
"name": "stderr",
|
||||||
"output_type": "stream",
|
"output_type": "stream",
|
||||||
"text": [
|
"text": [
|
||||||
"2026-01-29 10:46:39,047 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
"2026-01-30 09:33:47,749 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n"
|
||||||
"2026-01-29 10:46:49,067 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n"
|
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
],
|
],
|
||||||
@@ -4691,8 +4549,455 @@
|
|||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
"execution_count": null,
|
"execution_count": null,
|
||||||
"metadata": {},
|
"metadata": {},
|
||||||
"outputs": [],
|
"outputs": [
|
||||||
"source": []
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"🧪 Testing Reversal Detector...\n",
|
||||||
|
"============================================================\n",
|
||||||
|
"✅ Import erfolgreich\n",
|
||||||
|
"\n",
|
||||||
|
"============================================================\n",
|
||||||
|
"🔄 REVERSAL DETECTOR STATUS\n",
|
||||||
|
"============================================================\n",
|
||||||
|
" Enabled: True\n",
|
||||||
|
" Mode: defensive\n",
|
||||||
|
" Block Threshold: 70%\n",
|
||||||
|
" Reduce Threshold: 50%\n",
|
||||||
|
" Caution Threshold: 30%\n",
|
||||||
|
"============================================================\n",
|
||||||
|
"\n",
|
||||||
|
"🔍 Testing with live market data...\n",
|
||||||
|
"🔍 Analyzing XAUUSD with V1.6 ADAPTIVE COMPLETE parameters...\n",
|
||||||
|
"\n",
|
||||||
|
"📊 V1.6 ADAPTIVE COMPLETE Trend-Analyse für XAUUSD\n",
|
||||||
|
"⚡ Adaptive Interval: 5 min | Session: LONDON\n",
|
||||||
|
"🎯 Market Regime: RANGING (Strength: 21%)\n",
|
||||||
|
"🎚️ Adaptive Threshold: 70% (RELAXED)\n",
|
||||||
|
"\n",
|
||||||
|
"+------+-----------+------------+----------+----------+---------+\n",
|
||||||
|
"| TF | Trend | Strength | ATR | Slope | Price |\n",
|
||||||
|
"|------+-----------+------------+----------+----------+---------|\n",
|
||||||
|
"| D1 | uptrend | 463.42 | 157.145 | 10.9236 | 5069.5 |\n",
|
||||||
|
"| H4 | uptrend | 362.48 | 116.225 | 6.31934 | 5069.18 |\n",
|
||||||
|
"| H1 | uptrend | 349.09 | 82.1467 | 4.30149 | 5069.18 |\n",
|
||||||
|
"| M30 | uptrend | 228.93 | 63.3682 | 2.17604 | 5069.18 |\n",
|
||||||
|
"| M15 | downtrend | 273.87 | 44.4494 | -1.82601 | 5068.79 |\n",
|
||||||
|
"| M5 | downtrend | 490.87 | 25.6075 | -1.88549 | 5068.66 |\n",
|
||||||
|
"+------+-----------+------------+----------+----------+---------+\n",
|
||||||
|
"\n",
|
||||||
|
"➡️ Standard-Trend: uptrend (Strength: 423.04)\n",
|
||||||
|
"➡️ Fast-Trend: uptrend (Required: 2/4)\n",
|
||||||
|
"➡️ Top-Down-Trend: uptrend\n",
|
||||||
|
"➡️ Confidence: 83.69% (Threshold: 70%)\n",
|
||||||
|
"➡️ Risk-Adjusted Strength: 79947.2 (Min: 80)\n",
|
||||||
|
"➡️ Signal Quality: EXCELLENT\n",
|
||||||
|
"\n",
|
||||||
|
"🚀 V1.6 Adaptive Complete: Full Features + Adaptive Rhythm\n",
|
||||||
|
"\n",
|
||||||
|
"📊 Signal Info:\n",
|
||||||
|
" Entry Signal: 1\n",
|
||||||
|
" Standard Trend: uptrend\n",
|
||||||
|
" Confidence: 83.69%\n",
|
||||||
|
"\n",
|
||||||
|
"🔄 Running Reversal Check...\n",
|
||||||
|
"\n",
|
||||||
|
"🔄 REVERSAL CHECK (UPTREND):\n",
|
||||||
|
"--------------------------------------------------\n",
|
||||||
|
" Rsi Divergence : ✅ No divergence\n",
|
||||||
|
" Ema Slope Change : ⚠️ Slope weakening: -0.1010% -> -0.4427%\n",
|
||||||
|
" Strength: 100%\n",
|
||||||
|
" Volume Spike : ✅ Volume: 0.4x average\n",
|
||||||
|
" Candlestick : ⚠️ Bearish Engulfing: Strong reversal signal\n",
|
||||||
|
" Strength: 70%\n",
|
||||||
|
" Break Of Structure : ✅ Structure intact\n",
|
||||||
|
"--------------------------------------------------\n",
|
||||||
|
" ⚠️ Reversal Score: 30% (MODERATE)\n",
|
||||||
|
" Action: CAUTION | Lot Mult: 75%\n",
|
||||||
|
"\n",
|
||||||
|
"📊 Reversal Check Result:\n",
|
||||||
|
" Should Trade: True\n",
|
||||||
|
" Reversal Score: 30%\n",
|
||||||
|
" Action: CAUTION\n",
|
||||||
|
" Lot Multiplier: 75%\n",
|
||||||
|
" Reason: Low reversal risk (30%), lot reduced to 75%\n",
|
||||||
|
"\n",
|
||||||
|
"🔍 Signal Details:\n",
|
||||||
|
" rsi_divergence: ✅ No divergence\n",
|
||||||
|
" ema_slope_change: ⚠️ Slope weakening: -0.1010% -> -0.4427%\n",
|
||||||
|
" volume_spike: ✅ Volume: 0.4x average\n",
|
||||||
|
" candlestick: ⚠️ Bearish Engulfing: Strong reversal signal\n",
|
||||||
|
" break_of_structure: ✅ Structure intact\n",
|
||||||
|
"\n",
|
||||||
|
"============================================================\n",
|
||||||
|
"✅ Reversal Detector Test Complete\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:35:18,013 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:35:28,040 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:35:38,065 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:35:48,079 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:35:54,233 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:36:54 CET)\" (scheduled at 2026-01-30 09:35:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:35:54,233 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:36:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:35:58,110 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:35:58,259 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:36:58 CET)\" (scheduled at 2026-01-30 09:35:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:35:58,261 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:36:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:36:01,020 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:37:01 CET)\" (scheduled at 2026-01-30 09:36:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:36:01,020 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:37:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:36:08,139 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:36:18,153 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:36:28,187 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:36:38,216 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:36:48,244 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:36:54,086 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:37:54 CET)\" (scheduled at 2026-01-30 09:36:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:36:54,090 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:37:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:36:58,280 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:36:58,808 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:37:58 CET)\" (scheduled at 2026-01-30 09:36:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:36:58,809 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:37:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:37:01,074 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:38:01 CET)\" (scheduled at 2026-01-30 09:37:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:37:01,076 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:38:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:37:01,731 - INFO - Running job \"Demo Tracker Sync (trigger: interval[0:05:00], next run at: 2026-01-30 09:42:01 CET)\" (scheduled at 2026-01-30 09:37:01.544620+01:00)\n",
|
||||||
|
"2026-01-30 09:37:01,842 - INFO - 📊 Trade logged: 🔴 #734745233 LONG XAUUSD | Profit: $-129.50\n",
|
||||||
|
"2026-01-30 09:37:01,844 - INFO - Job \"Demo Tracker Sync (trigger: interval[0:05:00], next run at: 2026-01-30 09:42:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"📊 Auto-synced #734745233: LONG XAUUSD | stop_loss | P/L: $-129.50\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:37:08,306 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:37:18,332 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:37:28,357 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:37:38,382 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:37:48,405 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:37:54,087 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:38:54 CET)\" (scheduled at 2026-01-30 09:37:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:37:54,089 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:38:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:37:58,258 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:38:58 CET)\" (scheduled at 2026-01-30 09:37:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:37:58,261 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:38:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:37:58,433 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:38:01,018 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:39:01 CET)\" (scheduled at 2026-01-30 09:38:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:38:01,020 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:39:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:38:08,458 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:38:18,483 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:38:28,509 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:38:38,532 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:38:48,771 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:38:54,088 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:39:54 CET)\" (scheduled at 2026-01-30 09:38:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:38:54,090 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:39:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:38:58,258 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:39:58 CET)\" (scheduled at 2026-01-30 09:38:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:38:58,260 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:39:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:38:58,795 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:39:01,015 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:40:01 CET)\" (scheduled at 2026-01-30 09:39:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:39:01,019 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:40:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:39:08,820 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:39:18,844 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:39:28,867 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:39:38,892 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:39:48,916 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:39:54,093 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:40:54 CET)\" (scheduled at 2026-01-30 09:39:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:39:54,096 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:40:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:39:58,258 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:40:58 CET)\" (scheduled at 2026-01-30 09:39:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:39:58,260 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:40:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:39:58,939 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:40:01,016 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:41:01 CET)\" (scheduled at 2026-01-30 09:40:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:40:01,020 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:41:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:40:08,963 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:40:18,987 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:40:29,011 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:40:39,039 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:40:49,063 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:40:54,089 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:41:54 CET)\" (scheduled at 2026-01-30 09:40:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:40:54,091 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:41:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:40:58,259 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:41:58 CET)\" (scheduled at 2026-01-30 09:40:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:40:58,261 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:41:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:40:59,086 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:41:01,018 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:42:01 CET)\" (scheduled at 2026-01-30 09:41:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:41:01,020 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:42:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:41:09,111 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:41:19,137 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:41:29,164 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:41:39,187 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:41:49,210 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:41:54,087 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:42:54 CET)\" (scheduled at 2026-01-30 09:41:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:41:54,089 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:42:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:41:58,257 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:42:58 CET)\" (scheduled at 2026-01-30 09:41:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:41:58,259 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:42:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:41:59,259 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:42:01,017 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:43:01 CET)\" (scheduled at 2026-01-30 09:42:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:42:01,019 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:43:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:42:01,545 - INFO - Running job \"Demo Tracker Sync (trigger: interval[0:05:00], next run at: 2026-01-30 09:47:01 CET)\" (scheduled at 2026-01-30 09:42:01.544620+01:00)\n",
|
||||||
|
"2026-01-30 09:42:01,553 - INFO - Job \"Demo Tracker Sync (trigger: interval[0:05:00], next run at: 2026-01-30 09:47:01 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:42:09,291 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:42:19,314 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:42:29,336 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:42:39,359 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:42:49,382 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:42:54,087 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:43:54 CET)\" (scheduled at 2026-01-30 09:42:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:42:54,088 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:43:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:42:58,258 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:43:58 CET)\" (scheduled at 2026-01-30 09:42:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:42:58,260 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:43:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:42:59,407 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:43:01,015 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:44:01 CET)\" (scheduled at 2026-01-30 09:43:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:43:01,018 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:44:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:43:09,429 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:43:19,454 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:43:29,478 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:43:39,502 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:43:49,527 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:43:54,087 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:44:54 CET)\" (scheduled at 2026-01-30 09:43:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:43:54,089 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:44:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:43:58,258 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:44:58 CET)\" (scheduled at 2026-01-30 09:43:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:43:58,260 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:44:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:43:59,551 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:44:01,066 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:45:01 CET)\" (scheduled at 2026-01-30 09:44:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:44:01,068 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:45:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:44:09,573 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:44:19,597 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:44:29,620 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:44:39,643 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:44:49,667 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:44:54,103 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:45:54 CET)\" (scheduled at 2026-01-30 09:44:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:44:54,105 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:45:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:44:58,257 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:45:58 CET)\" (scheduled at 2026-01-30 09:44:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:44:58,259 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:45:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:44:59,692 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:45:01,014 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:46:01 CET)\" (scheduled at 2026-01-30 09:45:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:45:01,018 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:46:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:45:09,715 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:45:19,739 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:45:29,761 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:45:39,787 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:45:49,812 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:45:54,102 - INFO - Running job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:46:54 CET)\" (scheduled at 2026-01-30 09:45:54.085516+01:00)\n",
|
||||||
|
"2026-01-30 09:45:54,104 - INFO - Job \"PositionMonitor.check_open_positions (trigger: interval[0:01:00], next run at: 2026-01-30 09:46:54 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:45:58,258 - INFO - Running job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:46:58 CET)\" (scheduled at 2026-01-30 09:45:58.257297+01:00)\n",
|
||||||
|
"2026-01-30 09:45:58,260 - INFO - Job \"create_enhanced_position_monitor.<locals>.enhanced_position_monitor (trigger: interval[0:01:00], next run at: 2026-01-30 09:46:58 CET)\" executed successfully\n",
|
||||||
|
"2026-01-30 09:45:59,836 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:46:01,016 - INFO - Running job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:47:01 CET)\" (scheduled at 2026-01-30 09:46:01.013912+01:00)\n",
|
||||||
|
"2026-01-30 09:46:01,019 - INFO - Job \"Enhanced Adaptive Trading Check (trigger: interval[0:01:00], next run at: 2026-01-30 09:47:01 CET)\" executed successfully\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stdout",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"⛔ SESSION BLOCKED: LONDON\n",
|
||||||
|
" Reason: London blocked: 12.5% win-rate, -$10/trade\n"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"name": "stderr",
|
||||||
|
"output_type": "stream",
|
||||||
|
"text": [
|
||||||
|
"2026-01-30 09:46:09,859 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:46:19,888 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n",
|
||||||
|
"2026-01-30 09:46:29,914 - INFO - HTTP Request: POST https://api.telegram.org/bot7783303065:AAHVVvwWGqmhJ2BVq8LqkLRSsicKy1CUsD8/getUpdates \"HTTP/1.1 200 OK\"\n"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"source": [
|
||||||
|
"# ==========================================\n",
|
||||||
|
"# 🧪 REVERSAL DETECTOR TEST\n",
|
||||||
|
"# ==========================================\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"🧪 Testing Reversal Detector...\")\n",
|
||||||
|
"print(\"=\" * 60)\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 1: Import prüfen\n",
|
||||||
|
"try:\n",
|
||||||
|
" from reversal_integration import check_reversal_risk, get_reversal_status, REVERSAL_CONFIG\n",
|
||||||
|
" print(\"✅ Import erfolgreich\")\n",
|
||||||
|
"except Exception as e:\n",
|
||||||
|
" print(f\"❌ Import fehlgeschlagen: {e}\")\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 2: Status anzeigen\n",
|
||||||
|
"print(\"\\n\" + get_reversal_status())\n",
|
||||||
|
"\n",
|
||||||
|
"# Test 3: Mit echten Marktdaten testen\n",
|
||||||
|
"print(\"\\n🔍 Testing with live market data...\")\n",
|
||||||
|
"\n",
|
||||||
|
"signal_info = extended_top_down_v2_adaptive(\"XAUUSD\")\n",
|
||||||
|
"\n",
|
||||||
|
"if signal_info:\n",
|
||||||
|
" print(f\"\\n📊 Signal Info:\")\n",
|
||||||
|
" print(f\" Entry Signal: {signal_info['entry_signal']}\")\n",
|
||||||
|
" print(f\" Standard Trend: {signal_info.get('standard_trend', 'N/A')}\")\n",
|
||||||
|
" print(f\" Confidence: {signal_info['confidence']}%\")\n",
|
||||||
|
" \n",
|
||||||
|
" # Reversal Check durchführen\n",
|
||||||
|
" print(\"\\n🔄 Running Reversal Check...\")\n",
|
||||||
|
" result = check_reversal_risk(signal_info, \"XAUUSD\")\n",
|
||||||
|
" \n",
|
||||||
|
" print(f\"\\n📊 Reversal Check Result:\")\n",
|
||||||
|
" print(f\" Should Trade: {result['should_trade']}\")\n",
|
||||||
|
" print(f\" Reversal Score: {result['reversal_score']}%\")\n",
|
||||||
|
" print(f\" Action: {result['action']}\")\n",
|
||||||
|
" print(f\" Lot Multiplier: {result['lot_multiplier']:.0%}\")\n",
|
||||||
|
" print(f\" Reason: {result['reason']}\")\n",
|
||||||
|
" \n",
|
||||||
|
" if 'signals' in result and result['signals']:\n",
|
||||||
|
" print(f\"\\n🔍 Signal Details:\")\n",
|
||||||
|
" for signal_name, signal_data in result['signals'].items():\n",
|
||||||
|
" status = \"⚠️\" if signal_data.get('detected', False) else \"✅\"\n",
|
||||||
|
" print(f\" {signal_name}: {status} {signal_data.get('description', 'N/A')}\")\n",
|
||||||
|
"else:\n",
|
||||||
|
" print(\"❌ Could not get signal info\")\n",
|
||||||
|
"\n",
|
||||||
|
"print(\"\\n\" + \"=\" * 60)\n",
|
||||||
|
"print(\"✅ Reversal Detector Test Complete\")"
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"cell_type": "code",
|
"cell_type": "code",
|
||||||
|
|||||||
@@ -0,0 +1,633 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
🔄 TREND REVERSAL DETECTOR
|
||||||
|
Erkennt potenzielle Trendumkehrungen durch Multi-Signal-Analyse
|
||||||
|
|
||||||
|
SIGNALE:
|
||||||
|
1. RSI Divergenz (Bullish/Bearish)
|
||||||
|
2. EMA Slope Change
|
||||||
|
3. Volume Spike
|
||||||
|
4. Candlestick Patterns
|
||||||
|
5. Break of Structure
|
||||||
|
|
||||||
|
VERWENDUNG:
|
||||||
|
from reversal_detector import ReversalDetector
|
||||||
|
|
||||||
|
detector = ReversalDetector()
|
||||||
|
result = detector.analyze(df_m15, df_h1, current_trend='uptrend')
|
||||||
|
|
||||||
|
if result['reversal_score'] >= 60:
|
||||||
|
print("Reversal-Warnung! Trade blockieren.")
|
||||||
|
"""
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
import pandas as pd
|
||||||
|
from typing import Dict, Tuple, Optional, List
|
||||||
|
import logging
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
class ReversalDetector:
|
||||||
|
"""
|
||||||
|
Multi-Signal Trend Reversal Detector
|
||||||
|
|
||||||
|
Kombiniert mehrere Indikatoren um Trendumkehrungen zu erkennen:
|
||||||
|
- RSI Divergenz
|
||||||
|
- EMA Slope Änderung
|
||||||
|
- Volume Spikes
|
||||||
|
- Candlestick Patterns
|
||||||
|
- Break of Structure
|
||||||
|
"""
|
||||||
|
|
||||||
|
def __init__(self,
|
||||||
|
rsi_period: int = 14,
|
||||||
|
ema_fast: int = 9,
|
||||||
|
ema_slow: int = 21,
|
||||||
|
volume_spike_mult: float = 2.0,
|
||||||
|
divergence_lookback: int = 10,
|
||||||
|
mode: str = "defensive"):
|
||||||
|
"""
|
||||||
|
Args:
|
||||||
|
rsi_period: RSI Berechnungsperiode
|
||||||
|
ema_fast: Schneller EMA für Slope
|
||||||
|
ema_slow: Langsamer EMA für Slope
|
||||||
|
volume_spike_mult: Multiplikator für Volume-Spike-Erkennung
|
||||||
|
divergence_lookback: Bars für Divergenz-Suche
|
||||||
|
mode: "defensive" (blockiert Trades) oder "info" (nur Logging)
|
||||||
|
"""
|
||||||
|
self.rsi_period = rsi_period
|
||||||
|
self.ema_fast = ema_fast
|
||||||
|
self.ema_slow = ema_slow
|
||||||
|
self.volume_spike_mult = volume_spike_mult
|
||||||
|
self.divergence_lookback = divergence_lookback
|
||||||
|
self.mode = mode
|
||||||
|
|
||||||
|
# Gewichtung der Signale
|
||||||
|
self.weights = {
|
||||||
|
'rsi_divergence': 30, # Sehr zuverlässig
|
||||||
|
'ema_slope_change': 20, # Früher Indikator
|
||||||
|
'volume_spike': 15, # Bestätigung
|
||||||
|
'candlestick': 15, # Pattern-basiert
|
||||||
|
'break_of_structure': 20 # Strukturbruch
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.info("=" * 60)
|
||||||
|
logger.info("🔄 REVERSAL DETECTOR INITIALIZED")
|
||||||
|
logger.info("=" * 60)
|
||||||
|
logger.info(f" Mode: {mode.upper()}")
|
||||||
|
logger.info(f" RSI Period: {rsi_period}")
|
||||||
|
logger.info(f" EMA Fast/Slow: {ema_fast}/{ema_slow}")
|
||||||
|
logger.info(f" Volume Spike Mult: {volume_spike_mult}x")
|
||||||
|
logger.info(f" Divergence Lookback: {divergence_lookback} bars")
|
||||||
|
logger.info("=" * 60)
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# MAIN ANALYSIS METHOD
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
def analyze(self,
|
||||||
|
df: pd.DataFrame,
|
||||||
|
current_trend: str,
|
||||||
|
df_higher_tf: Optional[pd.DataFrame] = None) -> Dict:
|
||||||
|
"""
|
||||||
|
Führt vollständige Reversal-Analyse durch
|
||||||
|
|
||||||
|
Args:
|
||||||
|
df: DataFrame mit OHLCV Daten (primärer Timeframe, z.B. M15)
|
||||||
|
current_trend: 'uptrend' oder 'downtrend'
|
||||||
|
df_higher_tf: Optional höherer Timeframe für Bestätigung (z.B. H1)
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict mit Reversal-Score und Details
|
||||||
|
"""
|
||||||
|
if df is None or len(df) < 50:
|
||||||
|
return self._empty_result("Insufficient data")
|
||||||
|
|
||||||
|
# Stelle sicher dass nötige Indikatoren berechnet sind
|
||||||
|
df = self._ensure_indicators(df)
|
||||||
|
|
||||||
|
signals = {}
|
||||||
|
|
||||||
|
# 1. RSI Divergenz
|
||||||
|
signals['rsi_divergence'] = self._detect_rsi_divergence(df, current_trend)
|
||||||
|
|
||||||
|
# 2. EMA Slope Change
|
||||||
|
signals['ema_slope_change'] = self._detect_ema_slope_change(df, current_trend)
|
||||||
|
|
||||||
|
# 3. Volume Spike
|
||||||
|
signals['volume_spike'] = self._detect_volume_spike(df)
|
||||||
|
|
||||||
|
# 4. Candlestick Patterns
|
||||||
|
signals['candlestick'] = self._detect_candlestick_patterns(df, current_trend)
|
||||||
|
|
||||||
|
# 5. Break of Structure
|
||||||
|
signals['break_of_structure'] = self._detect_break_of_structure(df, current_trend)
|
||||||
|
|
||||||
|
# Berechne Gesamt-Score
|
||||||
|
reversal_score = self._calculate_reversal_score(signals)
|
||||||
|
|
||||||
|
# Bestimme Reversal-Typ
|
||||||
|
if current_trend == 'uptrend':
|
||||||
|
reversal_type = 'BEARISH' if reversal_score >= 30 else 'NONE'
|
||||||
|
else:
|
||||||
|
reversal_type = 'BULLISH' if reversal_score >= 30 else 'NONE'
|
||||||
|
|
||||||
|
# Bestimme Aktion
|
||||||
|
action, lot_multiplier = self._determine_action(reversal_score)
|
||||||
|
|
||||||
|
result = {
|
||||||
|
'reversal_score': reversal_score,
|
||||||
|
'reversal_type': reversal_type,
|
||||||
|
'current_trend': current_trend,
|
||||||
|
'signals': signals,
|
||||||
|
'action': action,
|
||||||
|
'lot_multiplier': lot_multiplier,
|
||||||
|
'should_trade': action != 'BLOCK',
|
||||||
|
'mode': self.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
# Logging
|
||||||
|
self._log_analysis(result)
|
||||||
|
|
||||||
|
return result
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# SIGNAL DETECTION METHODS
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
def _detect_rsi_divergence(self, df: pd.DataFrame, trend: str) -> Dict:
|
||||||
|
"""
|
||||||
|
Erkennt RSI Divergenz
|
||||||
|
|
||||||
|
Bearish Divergenz: Preis Higher High, RSI Lower High
|
||||||
|
Bullish Divergenz: Preis Lower Low, RSI Higher Low
|
||||||
|
"""
|
||||||
|
if 'rsi' not in df.columns:
|
||||||
|
return {'detected': False, 'strength': 0, 'type': 'none', 'description': 'RSI not available'}
|
||||||
|
|
||||||
|
lookback = self.divergence_lookback
|
||||||
|
recent = df.tail(lookback)
|
||||||
|
|
||||||
|
if len(recent) < lookback:
|
||||||
|
return {'detected': False, 'strength': 0, 'type': 'none', 'description': 'Not enough data'}
|
||||||
|
|
||||||
|
prices = recent['close'].values
|
||||||
|
rsi = recent['rsi'].values
|
||||||
|
|
||||||
|
# Finde lokale Extrema
|
||||||
|
price_highs_idx = self._find_local_extrema(prices, 'high')
|
||||||
|
price_lows_idx = self._find_local_extrema(prices, 'low')
|
||||||
|
rsi_highs_idx = self._find_local_extrema(rsi, 'high')
|
||||||
|
rsi_lows_idx = self._find_local_extrema(rsi, 'low')
|
||||||
|
|
||||||
|
detected = False
|
||||||
|
div_type = 'none'
|
||||||
|
strength = 0
|
||||||
|
description = 'No divergence'
|
||||||
|
|
||||||
|
# Bearish Divergenz prüfen (für Uptrend)
|
||||||
|
if trend == 'uptrend' and len(price_highs_idx) >= 2 and len(rsi_highs_idx) >= 2:
|
||||||
|
# Preis macht Higher High
|
||||||
|
if prices[price_highs_idx[-1]] > prices[price_highs_idx[-2]]:
|
||||||
|
# RSI macht Lower High
|
||||||
|
if rsi[rsi_highs_idx[-1]] < rsi[rsi_highs_idx[-2]]:
|
||||||
|
detected = True
|
||||||
|
div_type = 'bearish'
|
||||||
|
# Stärke basierend auf Differenz
|
||||||
|
price_diff = (prices[price_highs_idx[-1]] - prices[price_highs_idx[-2]]) / prices[price_highs_idx[-2]]
|
||||||
|
rsi_diff = rsi[rsi_highs_idx[-2]] - rsi[rsi_highs_idx[-1]]
|
||||||
|
strength = min(100, int((price_diff * 1000 + rsi_diff) * 2))
|
||||||
|
description = f"Bearish Divergence: Price HH, RSI LH (RSI diff: {rsi_diff:.1f})"
|
||||||
|
|
||||||
|
# Bullish Divergenz prüfen (für Downtrend)
|
||||||
|
if trend == 'downtrend' and len(price_lows_idx) >= 2 and len(rsi_lows_idx) >= 2:
|
||||||
|
# Preis macht Lower Low
|
||||||
|
if prices[price_lows_idx[-1]] < prices[price_lows_idx[-2]]:
|
||||||
|
# RSI macht Higher Low
|
||||||
|
if rsi[rsi_lows_idx[-1]] > rsi[rsi_lows_idx[-2]]:
|
||||||
|
detected = True
|
||||||
|
div_type = 'bullish'
|
||||||
|
price_diff = (prices[price_lows_idx[-2]] - prices[price_lows_idx[-1]]) / prices[price_lows_idx[-2]]
|
||||||
|
rsi_diff = rsi[rsi_lows_idx[-1]] - rsi[rsi_lows_idx[-2]]
|
||||||
|
strength = min(100, int((price_diff * 1000 + rsi_diff) * 2))
|
||||||
|
description = f"Bullish Divergence: Price LL, RSI HL (RSI diff: {rsi_diff:.1f})"
|
||||||
|
|
||||||
|
return {
|
||||||
|
'detected': detected,
|
||||||
|
'strength': strength,
|
||||||
|
'type': div_type,
|
||||||
|
'description': description
|
||||||
|
}
|
||||||
|
|
||||||
|
def _detect_ema_slope_change(self, df: pd.DataFrame, trend: str) -> Dict:
|
||||||
|
"""
|
||||||
|
Erkennt Änderung der EMA-Steigung
|
||||||
|
|
||||||
|
Warnsignal wenn Slope sich dem Nullpunkt nähert oder Vorzeichen wechselt
|
||||||
|
"""
|
||||||
|
if f'ema_{self.ema_fast}' not in df.columns:
|
||||||
|
# Berechne EMA falls nicht vorhanden
|
||||||
|
df[f'ema_{self.ema_fast}'] = df['close'].ewm(span=self.ema_fast).mean()
|
||||||
|
|
||||||
|
ema = df[f'ema_{self.ema_fast}'].values
|
||||||
|
|
||||||
|
if len(ema) < 5:
|
||||||
|
return {'detected': False, 'strength': 0, 'slope': 0, 'description': 'Not enough data'}
|
||||||
|
|
||||||
|
# Berechne Slopes
|
||||||
|
current_slope = (ema[-1] - ema[-3]) / ema[-3] * 100 # Letzte 3 Bars
|
||||||
|
prev_slope = (ema[-4] - ema[-6]) / ema[-6] * 100 if len(ema) >= 6 else current_slope
|
||||||
|
|
||||||
|
detected = False
|
||||||
|
strength = 0
|
||||||
|
description = f"Slope: {current_slope:.4f}%"
|
||||||
|
|
||||||
|
# Slope-Wechsel erkennen
|
||||||
|
if trend == 'uptrend':
|
||||||
|
# Warnung wenn positiver Slope abflacht oder negativ wird
|
||||||
|
if current_slope < prev_slope * 0.5: # Slope halbiert sich
|
||||||
|
detected = True
|
||||||
|
strength = min(100, int(abs(prev_slope - current_slope) * 500))
|
||||||
|
description = f"Slope weakening: {prev_slope:.4f}% -> {current_slope:.4f}%"
|
||||||
|
if current_slope < 0 and prev_slope > 0: # Vorzeichenwechsel
|
||||||
|
detected = True
|
||||||
|
strength = 80
|
||||||
|
description = f"Slope turned negative: {current_slope:.4f}%"
|
||||||
|
|
||||||
|
elif trend == 'downtrend':
|
||||||
|
# Warnung wenn negativer Slope abflacht oder positiv wird
|
||||||
|
if current_slope > prev_slope * 0.5: # Slope halbiert sich
|
||||||
|
detected = True
|
||||||
|
strength = min(100, int(abs(prev_slope - current_slope) * 500))
|
||||||
|
description = f"Slope weakening: {prev_slope:.4f}% -> {current_slope:.4f}%"
|
||||||
|
if current_slope > 0 and prev_slope < 0: # Vorzeichenwechsel
|
||||||
|
detected = True
|
||||||
|
strength = 80
|
||||||
|
description = f"Slope turned positive: {current_slope:.4f}%"
|
||||||
|
|
||||||
|
return {
|
||||||
|
'detected': detected,
|
||||||
|
'strength': strength,
|
||||||
|
'slope': current_slope,
|
||||||
|
'prev_slope': prev_slope,
|
||||||
|
'description': description
|
||||||
|
}
|
||||||
|
|
||||||
|
def _detect_volume_spike(self, df: pd.DataFrame) -> Dict:
|
||||||
|
"""
|
||||||
|
Erkennt Volume-Spikes bei potenziellen Wendepunkten
|
||||||
|
"""
|
||||||
|
if 'tick_volume' not in df.columns and 'volume' not in df.columns:
|
||||||
|
return {'detected': False, 'strength': 0, 'ratio': 1.0, 'description': 'Volume not available'}
|
||||||
|
|
||||||
|
vol_col = 'tick_volume' if 'tick_volume' in df.columns else 'volume'
|
||||||
|
|
||||||
|
# Durchschnittsvolumen der letzten 20 Bars
|
||||||
|
avg_volume = df[vol_col].tail(20).mean()
|
||||||
|
current_volume = df[vol_col].iloc[-1]
|
||||||
|
|
||||||
|
if avg_volume == 0:
|
||||||
|
return {'detected': False, 'strength': 0, 'ratio': 1.0, 'description': 'No volume data'}
|
||||||
|
|
||||||
|
ratio = current_volume / avg_volume
|
||||||
|
|
||||||
|
detected = ratio >= self.volume_spike_mult
|
||||||
|
strength = min(100, int((ratio - 1) * 50)) if detected else 0
|
||||||
|
|
||||||
|
return {
|
||||||
|
'detected': detected,
|
||||||
|
'strength': strength,
|
||||||
|
'ratio': ratio,
|
||||||
|
'current_volume': current_volume,
|
||||||
|
'avg_volume': avg_volume,
|
||||||
|
'description': f"Volume: {ratio:.1f}x average" + (" (SPIKE!)" if detected else "")
|
||||||
|
}
|
||||||
|
|
||||||
|
def _detect_candlestick_patterns(self, df: pd.DataFrame, trend: str) -> Dict:
|
||||||
|
"""
|
||||||
|
Erkennt Reversal-Candlestick-Patterns
|
||||||
|
|
||||||
|
- Doji (Unentschlossenheit)
|
||||||
|
- Engulfing (Umkehr)
|
||||||
|
- Hammer/Shooting Star
|
||||||
|
- Morning/Evening Star
|
||||||
|
"""
|
||||||
|
if len(df) < 3:
|
||||||
|
return {'detected': False, 'strength': 0, 'pattern': 'none', 'description': 'Not enough data'}
|
||||||
|
|
||||||
|
# Letzte Kerzen
|
||||||
|
current = df.iloc[-1]
|
||||||
|
prev = df.iloc[-2]
|
||||||
|
prev2 = df.iloc[-3] if len(df) >= 3 else None
|
||||||
|
|
||||||
|
o, h, l, c = current['open'], current['high'], current['low'], current['close']
|
||||||
|
body = abs(c - o)
|
||||||
|
upper_wick = h - max(o, c)
|
||||||
|
lower_wick = min(o, c) - l
|
||||||
|
total_range = h - l if h != l else 0.0001
|
||||||
|
|
||||||
|
detected = False
|
||||||
|
strength = 0
|
||||||
|
pattern = 'none'
|
||||||
|
description = 'No reversal pattern'
|
||||||
|
|
||||||
|
# 1. Doji (Body < 10% der Range)
|
||||||
|
if body / total_range < 0.1:
|
||||||
|
detected = True
|
||||||
|
strength = 40
|
||||||
|
pattern = 'doji'
|
||||||
|
description = "Doji: Market indecision"
|
||||||
|
|
||||||
|
# 2. Engulfing Pattern
|
||||||
|
prev_body = abs(prev['close'] - prev['open'])
|
||||||
|
if body > prev_body * 1.5: # Aktuelle Kerze größer
|
||||||
|
if trend == 'uptrend' and c < o and prev['close'] > prev['open']:
|
||||||
|
# Bearish Engulfing
|
||||||
|
detected = True
|
||||||
|
strength = 70
|
||||||
|
pattern = 'bearish_engulfing'
|
||||||
|
description = "Bearish Engulfing: Strong reversal signal"
|
||||||
|
elif trend == 'downtrend' and c > o and prev['close'] < prev['open']:
|
||||||
|
# Bullish Engulfing
|
||||||
|
detected = True
|
||||||
|
strength = 70
|
||||||
|
pattern = 'bullish_engulfing'
|
||||||
|
description = "Bullish Engulfing: Strong reversal signal"
|
||||||
|
|
||||||
|
# 3. Hammer (Bullish) / Shooting Star (Bearish)
|
||||||
|
if lower_wick > body * 2 and upper_wick < body * 0.5:
|
||||||
|
# Hammer-Form
|
||||||
|
if trend == 'downtrend':
|
||||||
|
detected = True
|
||||||
|
strength = 60
|
||||||
|
pattern = 'hammer'
|
||||||
|
description = "Hammer: Potential bullish reversal"
|
||||||
|
|
||||||
|
if upper_wick > body * 2 and lower_wick < body * 0.5:
|
||||||
|
# Shooting Star-Form
|
||||||
|
if trend == 'uptrend':
|
||||||
|
detected = True
|
||||||
|
strength = 60
|
||||||
|
pattern = 'shooting_star'
|
||||||
|
description = "Shooting Star: Potential bearish reversal"
|
||||||
|
|
||||||
|
# 4. Pin Bar (Long Wick Rejection)
|
||||||
|
if upper_wick > total_range * 0.6 or lower_wick > total_range * 0.6:
|
||||||
|
if trend == 'uptrend' and upper_wick > lower_wick:
|
||||||
|
detected = True
|
||||||
|
strength = max(strength, 55)
|
||||||
|
pattern = 'pin_bar_bearish' if pattern == 'none' else pattern
|
||||||
|
description = "Pin Bar: Upper wick rejection"
|
||||||
|
elif trend == 'downtrend' and lower_wick > upper_wick:
|
||||||
|
detected = True
|
||||||
|
strength = max(strength, 55)
|
||||||
|
pattern = 'pin_bar_bullish' if pattern == 'none' else pattern
|
||||||
|
description = "Pin Bar: Lower wick rejection"
|
||||||
|
|
||||||
|
return {
|
||||||
|
'detected': detected,
|
||||||
|
'strength': strength,
|
||||||
|
'pattern': pattern,
|
||||||
|
'description': description
|
||||||
|
}
|
||||||
|
|
||||||
|
def _detect_break_of_structure(self, df: pd.DataFrame, trend: str) -> Dict:
|
||||||
|
"""
|
||||||
|
Erkennt Break of Structure (BOS)
|
||||||
|
|
||||||
|
Uptrend BOS: Erstes Lower Low nach Higher Highs
|
||||||
|
Downtrend BOS: Erstes Higher High nach Lower Lows
|
||||||
|
"""
|
||||||
|
lookback = 20
|
||||||
|
if len(df) < lookback:
|
||||||
|
return {'detected': False, 'strength': 0, 'description': 'Not enough data'}
|
||||||
|
|
||||||
|
recent = df.tail(lookback)
|
||||||
|
highs = recent['high'].values
|
||||||
|
lows = recent['low'].values
|
||||||
|
|
||||||
|
detected = False
|
||||||
|
strength = 0
|
||||||
|
description = 'Structure intact'
|
||||||
|
|
||||||
|
# Finde Swing Points
|
||||||
|
swing_highs = []
|
||||||
|
swing_lows = []
|
||||||
|
|
||||||
|
for i in range(2, len(highs) - 2):
|
||||||
|
# Swing High: Höher als 2 Bars links und rechts
|
||||||
|
if highs[i] > highs[i-1] and highs[i] > highs[i-2] and highs[i] > highs[i+1] and highs[i] > highs[i+2]:
|
||||||
|
swing_highs.append((i, highs[i]))
|
||||||
|
# Swing Low: Niedriger als 2 Bars links und rechts
|
||||||
|
if lows[i] < lows[i-1] and lows[i] < lows[i-2] and lows[i] < lows[i+1] and lows[i] < lows[i+2]:
|
||||||
|
swing_lows.append((i, lows[i]))
|
||||||
|
|
||||||
|
if len(swing_highs) >= 2 and len(swing_lows) >= 2:
|
||||||
|
if trend == 'uptrend':
|
||||||
|
# Check for Lower Low (BOS)
|
||||||
|
if swing_lows[-1][1] < swing_lows[-2][1]:
|
||||||
|
detected = True
|
||||||
|
diff_pct = (swing_lows[-2][1] - swing_lows[-1][1]) / swing_lows[-2][1] * 100
|
||||||
|
strength = min(100, int(diff_pct * 20))
|
||||||
|
description = f"BOS: Lower Low detected ({diff_pct:.2f}% below prev swing)"
|
||||||
|
|
||||||
|
elif trend == 'downtrend':
|
||||||
|
# Check for Higher High (BOS)
|
||||||
|
if swing_highs[-1][1] > swing_highs[-2][1]:
|
||||||
|
detected = True
|
||||||
|
diff_pct = (swing_highs[-1][1] - swing_highs[-2][1]) / swing_highs[-2][1] * 100
|
||||||
|
strength = min(100, int(diff_pct * 20))
|
||||||
|
description = f"BOS: Higher High detected ({diff_pct:.2f}% above prev swing)"
|
||||||
|
|
||||||
|
return {
|
||||||
|
'detected': detected,
|
||||||
|
'strength': strength,
|
||||||
|
'swing_highs': len(swing_highs),
|
||||||
|
'swing_lows': len(swing_lows),
|
||||||
|
'description': description
|
||||||
|
}
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# HELPER METHODS
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
def _ensure_indicators(self, df: pd.DataFrame) -> pd.DataFrame:
|
||||||
|
"""Stellt sicher dass alle nötigen Indikatoren berechnet sind"""
|
||||||
|
df = df.copy()
|
||||||
|
|
||||||
|
# RSI
|
||||||
|
if 'rsi' not in df.columns:
|
||||||
|
delta = df['close'].diff()
|
||||||
|
gain = (delta.where(delta > 0, 0)).rolling(window=self.rsi_period).mean()
|
||||||
|
loss = (-delta.where(delta < 0, 0)).rolling(window=self.rsi_period).mean()
|
||||||
|
rs = gain / loss
|
||||||
|
df['rsi'] = 100 - (100 / (1 + rs))
|
||||||
|
|
||||||
|
# EMAs
|
||||||
|
if f'ema_{self.ema_fast}' not in df.columns:
|
||||||
|
df[f'ema_{self.ema_fast}'] = df['close'].ewm(span=self.ema_fast).mean()
|
||||||
|
|
||||||
|
if f'ema_{self.ema_slow}' not in df.columns:
|
||||||
|
df[f'ema_{self.ema_slow}'] = df['close'].ewm(span=self.ema_slow).mean()
|
||||||
|
|
||||||
|
return df
|
||||||
|
|
||||||
|
def _find_local_extrema(self, data: np.ndarray, extrema_type: str, window: int = 3) -> List[int]:
|
||||||
|
"""Findet lokale Hochs/Tiefs in einem Array"""
|
||||||
|
extrema = []
|
||||||
|
for i in range(window, len(data) - window):
|
||||||
|
if extrema_type == 'high':
|
||||||
|
if all(data[i] >= data[i-j] for j in range(1, window+1)) and \
|
||||||
|
all(data[i] >= data[i+j] for j in range(1, window+1)):
|
||||||
|
extrema.append(i)
|
||||||
|
else: # low
|
||||||
|
if all(data[i] <= data[i-j] for j in range(1, window+1)) and \
|
||||||
|
all(data[i] <= data[i+j] for j in range(1, window+1)):
|
||||||
|
extrema.append(i)
|
||||||
|
return extrema
|
||||||
|
|
||||||
|
def _calculate_reversal_score(self, signals: Dict) -> int:
|
||||||
|
"""Berechnet gewichteten Reversal-Score"""
|
||||||
|
score = 0
|
||||||
|
|
||||||
|
for signal_name, signal_data in signals.items():
|
||||||
|
if signal_data.get('detected', False):
|
||||||
|
weight = self.weights.get(signal_name, 10)
|
||||||
|
signal_strength = signal_data.get('strength', 50) / 100
|
||||||
|
score += weight * signal_strength
|
||||||
|
|
||||||
|
return min(100, int(score))
|
||||||
|
|
||||||
|
def _determine_action(self, score: int) -> Tuple[str, float]:
|
||||||
|
"""
|
||||||
|
Bestimmt Aktion basierend auf Reversal-Score
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(action, lot_multiplier)
|
||||||
|
"""
|
||||||
|
if self.mode == "info":
|
||||||
|
# Info-Mode: Nur Logging, keine Änderungen
|
||||||
|
return "ALLOW", 1.0
|
||||||
|
|
||||||
|
# Defensive Mode
|
||||||
|
if score < 30:
|
||||||
|
return "ALLOW", 1.0
|
||||||
|
elif score < 50:
|
||||||
|
return "CAUTION", 0.75
|
||||||
|
elif score < 70:
|
||||||
|
return "REDUCE", 0.5
|
||||||
|
else:
|
||||||
|
return "BLOCK", 0.0
|
||||||
|
|
||||||
|
def _empty_result(self, reason: str) -> Dict:
|
||||||
|
"""Gibt leeres Ergebnis zurück"""
|
||||||
|
return {
|
||||||
|
'reversal_score': 0,
|
||||||
|
'reversal_type': 'NONE',
|
||||||
|
'current_trend': 'unknown',
|
||||||
|
'signals': {},
|
||||||
|
'action': 'ALLOW',
|
||||||
|
'lot_multiplier': 1.0,
|
||||||
|
'should_trade': True,
|
||||||
|
'error': reason,
|
||||||
|
'mode': self.mode
|
||||||
|
}
|
||||||
|
|
||||||
|
def _log_analysis(self, result: Dict):
|
||||||
|
"""Loggt Analyse-Ergebnis"""
|
||||||
|
score = result['reversal_score']
|
||||||
|
|
||||||
|
# Emoji basierend auf Score
|
||||||
|
if score < 30:
|
||||||
|
emoji = "✅"
|
||||||
|
level = "LOW"
|
||||||
|
elif score < 50:
|
||||||
|
emoji = "⚠️"
|
||||||
|
level = "MODERATE"
|
||||||
|
elif score < 70:
|
||||||
|
emoji = "🔶"
|
||||||
|
level = "HIGH"
|
||||||
|
else:
|
||||||
|
emoji = "🔴"
|
||||||
|
level = "CRITICAL"
|
||||||
|
|
||||||
|
print(f"\n🔄 REVERSAL CHECK ({result['current_trend'].upper()}):")
|
||||||
|
print("-" * 50)
|
||||||
|
|
||||||
|
for signal_name, signal_data in result['signals'].items():
|
||||||
|
status = "⚠️" if signal_data.get('detected', False) else "✅"
|
||||||
|
desc = signal_data.get('description', 'N/A')
|
||||||
|
strength = signal_data.get('strength', 0)
|
||||||
|
print(f" {signal_name.replace('_', ' ').title():20s}: {status} {desc}")
|
||||||
|
if signal_data.get('detected'):
|
||||||
|
print(f" {'':20s} Strength: {strength}%")
|
||||||
|
|
||||||
|
print("-" * 50)
|
||||||
|
print(f" {emoji} Reversal Score: {score}% ({level})")
|
||||||
|
print(f" Action: {result['action']} | Lot Mult: {result['lot_multiplier']:.0%}")
|
||||||
|
|
||||||
|
if result['action'] == 'BLOCK':
|
||||||
|
print(f" ⛔ TRADE BLOCKED due to high reversal risk!")
|
||||||
|
elif result['action'] == 'REDUCE':
|
||||||
|
print(f" 📉 Lot size reduced to {result['lot_multiplier']:.0%}")
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# QUICK CHECK METHOD
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
def quick_check(self, df: pd.DataFrame, trend: str) -> Tuple[bool, int, str]:
|
||||||
|
"""
|
||||||
|
Schnelle Reversal-Prüfung
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
(should_trade, reversal_score, reason)
|
||||||
|
"""
|
||||||
|
result = self.analyze(df, trend)
|
||||||
|
return result['should_trade'], result['reversal_score'], result['action']
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# STANDALONE TESTING
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print("=" * 60)
|
||||||
|
print("🔄 REVERSAL DETECTOR TEST")
|
||||||
|
print("=" * 60)
|
||||||
|
|
||||||
|
# Simuliere Test-Daten
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
np.random.seed(42)
|
||||||
|
|
||||||
|
# Erzeuge einen Uptrend mit Reversal-Anzeichen
|
||||||
|
n = 100
|
||||||
|
trend_base = np.linspace(100, 120, n) # Uptrend
|
||||||
|
noise = np.random.normal(0, 1, n)
|
||||||
|
|
||||||
|
# Füge Reversal-Anzeichen am Ende hinzu
|
||||||
|
trend_base[-10:] = trend_base[-10] - np.linspace(0, 3, 10) # Abflachung
|
||||||
|
|
||||||
|
prices = trend_base + noise
|
||||||
|
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'open': prices - np.random.uniform(0, 0.5, n),
|
||||||
|
'high': prices + np.random.uniform(0.5, 1.5, n),
|
||||||
|
'low': prices - np.random.uniform(0.5, 1.5, n),
|
||||||
|
'close': prices,
|
||||||
|
'tick_volume': np.random.randint(100, 1000, n)
|
||||||
|
})
|
||||||
|
|
||||||
|
# Volume Spike am Ende
|
||||||
|
df.loc[df.index[-1], 'tick_volume'] = 5000
|
||||||
|
|
||||||
|
# Test
|
||||||
|
detector = ReversalDetector(mode="defensive")
|
||||||
|
result = detector.analyze(df, current_trend='uptrend')
|
||||||
|
|
||||||
|
print(f"\n📊 Test Result:")
|
||||||
|
print(f" Reversal Score: {result['reversal_score']}%")
|
||||||
|
print(f" Should Trade: {result['should_trade']}")
|
||||||
|
print(f" Action: {result['action']}")
|
||||||
|
print(f" Lot Multiplier: {result['lot_multiplier']}")
|
||||||
@@ -0,0 +1,287 @@
|
|||||||
|
#!/usr/bin/env python3
|
||||||
|
"""
|
||||||
|
🔄 REVERSAL DETECTOR INTEGRATION
|
||||||
|
Integriert den Reversal Detector in den Trading Bot
|
||||||
|
|
||||||
|
VERWENDUNG IM NOTEBOOK:
|
||||||
|
# Am Anfang importieren (nach den anderen Imports):
|
||||||
|
from reversal_integration import reversal_detector, check_reversal_risk
|
||||||
|
|
||||||
|
# In enhanced_trading_check_wrapper nach Signal Analysis:
|
||||||
|
reversal_result = check_reversal_risk(signal_info, symbol)
|
||||||
|
if not reversal_result['should_trade']:
|
||||||
|
print(f"⛔ TRADE BLOCKIERT durch Reversal Detector")
|
||||||
|
return None
|
||||||
|
|
||||||
|
# Lot Multiplier anpassen:
|
||||||
|
lot_multiplier *= reversal_result['lot_multiplier']
|
||||||
|
"""
|
||||||
|
|
||||||
|
import logging
|
||||||
|
from typing import Dict, Optional
|
||||||
|
import pandas as pd
|
||||||
|
|
||||||
|
# Import the reversal detector
|
||||||
|
from reversal_detector import ReversalDetector
|
||||||
|
|
||||||
|
logger = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# GLOBAL REVERSAL DETECTOR INSTANCE
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
# Initialize with defensive mode (blocks/reduces trades at high reversal risk)
|
||||||
|
reversal_detector = ReversalDetector(
|
||||||
|
rsi_period=14,
|
||||||
|
ema_fast=9,
|
||||||
|
ema_slow=21,
|
||||||
|
volume_spike_mult=2.0,
|
||||||
|
divergence_lookback=10,
|
||||||
|
mode="defensive" # "defensive" or "info"
|
||||||
|
)
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# CONFIGURATION
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
REVERSAL_CONFIG = {
|
||||||
|
'enabled': True, # Reversal Check aktiviert
|
||||||
|
'block_threshold': 70, # Score >= 70 = Trade blockieren
|
||||||
|
'reduce_threshold': 50, # Score >= 50 = Lot reduzieren
|
||||||
|
'caution_threshold': 30, # Score >= 30 = Warnung
|
||||||
|
'use_m15_data': True, # M15 für Analyse verwenden
|
||||||
|
'use_h1_confirmation': True, # H1 für Bestätigung
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# INTEGRATION FUNCTION
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
def check_reversal_risk(signal_info: Dict, symbol: str = "XAUUSD") -> Dict:
|
||||||
|
"""
|
||||||
|
Prüft Reversal-Risiko basierend auf Signal-Info
|
||||||
|
|
||||||
|
Args:
|
||||||
|
signal_info: Dict von extended_top_down_v2_adaptive()
|
||||||
|
symbol: Trading Symbol
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
Dict mit:
|
||||||
|
- should_trade: bool
|
||||||
|
- reversal_score: int (0-100)
|
||||||
|
- lot_multiplier: float (1.0, 0.75, 0.5, 0.0)
|
||||||
|
- action: str (ALLOW, CAUTION, REDUCE, BLOCK)
|
||||||
|
- reason: str
|
||||||
|
"""
|
||||||
|
if not REVERSAL_CONFIG['enabled']:
|
||||||
|
return {
|
||||||
|
'should_trade': True,
|
||||||
|
'reversal_score': 0,
|
||||||
|
'lot_multiplier': 1.0,
|
||||||
|
'action': 'ALLOW',
|
||||||
|
'reason': 'Reversal check disabled'
|
||||||
|
}
|
||||||
|
|
||||||
|
if signal_info is None:
|
||||||
|
return {
|
||||||
|
'should_trade': True,
|
||||||
|
'reversal_score': 0,
|
||||||
|
'lot_multiplier': 1.0,
|
||||||
|
'action': 'ALLOW',
|
||||||
|
'reason': 'No signal info available'
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
# Bestimme aktuellen Trend
|
||||||
|
entry_signal = signal_info.get('entry_signal', 0)
|
||||||
|
standard_trend = signal_info.get('standard_trend', 'sideways')
|
||||||
|
|
||||||
|
# Trend aus entry_signal ableiten falls standard_trend nicht verfügbar
|
||||||
|
if standard_trend == 'sideways' and entry_signal != 0:
|
||||||
|
current_trend = 'uptrend' if entry_signal == 1 else 'downtrend'
|
||||||
|
else:
|
||||||
|
current_trend = standard_trend
|
||||||
|
|
||||||
|
# Hole M15 DataFrame aus trend_info
|
||||||
|
trend_info = signal_info.get('trend_info', {})
|
||||||
|
|
||||||
|
df_m15 = None
|
||||||
|
df_h1 = None
|
||||||
|
|
||||||
|
# Versuche M15 Daten zu holen
|
||||||
|
if REVERSAL_CONFIG['use_m15_data'] and 'M15' in trend_info:
|
||||||
|
m15_info = trend_info['M15']
|
||||||
|
if isinstance(m15_info, dict) and 'df' in m15_info:
|
||||||
|
df_m15 = m15_info['df']
|
||||||
|
elif hasattr(m15_info, 'df'):
|
||||||
|
df_m15 = m15_info.df
|
||||||
|
|
||||||
|
# Versuche H1 Daten zu holen
|
||||||
|
if REVERSAL_CONFIG['use_h1_confirmation'] and 'H1' in trend_info:
|
||||||
|
h1_info = trend_info['H1']
|
||||||
|
if isinstance(h1_info, dict) and 'df' in h1_info:
|
||||||
|
df_h1 = h1_info['df']
|
||||||
|
elif hasattr(h1_info, 'df'):
|
||||||
|
df_h1 = h1_info.df
|
||||||
|
|
||||||
|
# Falls keine DataFrame verfügbar, versuche get_rates
|
||||||
|
if df_m15 is None:
|
||||||
|
try:
|
||||||
|
# Import get_rates falls verfügbar
|
||||||
|
import sys
|
||||||
|
if 'get_rates' in dir(sys.modules.get('__main__', {})):
|
||||||
|
from __main__ import get_rates
|
||||||
|
df_m15 = get_rates('m15', 100, symbol)
|
||||||
|
except Exception as e:
|
||||||
|
logger.debug(f"Could not get M15 data: {e}")
|
||||||
|
|
||||||
|
if df_m15 is None or len(df_m15) < 50:
|
||||||
|
print(f"⚠️ Reversal Check: Not enough M15 data, skipping")
|
||||||
|
return {
|
||||||
|
'should_trade': True,
|
||||||
|
'reversal_score': 0,
|
||||||
|
'lot_multiplier': 1.0,
|
||||||
|
'action': 'ALLOW',
|
||||||
|
'reason': 'Insufficient data for reversal check'
|
||||||
|
}
|
||||||
|
|
||||||
|
# Führe Reversal-Analyse durch
|
||||||
|
result = reversal_detector.analyze(
|
||||||
|
df=df_m15,
|
||||||
|
current_trend=current_trend,
|
||||||
|
df_higher_tf=df_h1
|
||||||
|
)
|
||||||
|
|
||||||
|
reversal_score = result['reversal_score']
|
||||||
|
|
||||||
|
# Bestimme Aktion basierend auf Config-Thresholds
|
||||||
|
if reversal_score >= REVERSAL_CONFIG['block_threshold']:
|
||||||
|
action = 'BLOCK'
|
||||||
|
lot_multiplier = 0.0
|
||||||
|
should_trade = False
|
||||||
|
reason = f"High reversal risk ({reversal_score}% >= {REVERSAL_CONFIG['block_threshold']}%)"
|
||||||
|
elif reversal_score >= REVERSAL_CONFIG['reduce_threshold']:
|
||||||
|
action = 'REDUCE'
|
||||||
|
lot_multiplier = 0.5
|
||||||
|
should_trade = True
|
||||||
|
reason = f"Moderate reversal risk ({reversal_score}%), lot reduced to 50%"
|
||||||
|
elif reversal_score >= REVERSAL_CONFIG['caution_threshold']:
|
||||||
|
action = 'CAUTION'
|
||||||
|
lot_multiplier = 0.75
|
||||||
|
should_trade = True
|
||||||
|
reason = f"Low reversal risk ({reversal_score}%), lot reduced to 75%"
|
||||||
|
else:
|
||||||
|
action = 'ALLOW'
|
||||||
|
lot_multiplier = 1.0
|
||||||
|
should_trade = True
|
||||||
|
reason = f"No significant reversal risk ({reversal_score}%)"
|
||||||
|
|
||||||
|
return {
|
||||||
|
'should_trade': should_trade,
|
||||||
|
'reversal_score': reversal_score,
|
||||||
|
'lot_multiplier': lot_multiplier,
|
||||||
|
'action': action,
|
||||||
|
'reason': reason,
|
||||||
|
'reversal_type': result.get('reversal_type', 'NONE'),
|
||||||
|
'signals': result.get('signals', {})
|
||||||
|
}
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logger.error(f"Reversal check error: {e}")
|
||||||
|
print(f"⚠️ Reversal Check Error: {e}")
|
||||||
|
return {
|
||||||
|
'should_trade': True,
|
||||||
|
'reversal_score': 0,
|
||||||
|
'lot_multiplier': 1.0,
|
||||||
|
'action': 'ALLOW',
|
||||||
|
'reason': f'Error: {e}'
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
def get_reversal_status() -> str:
|
||||||
|
"""Gibt aktuellen Reversal Detector Status zurück"""
|
||||||
|
status = []
|
||||||
|
status.append("=" * 60)
|
||||||
|
status.append("🔄 REVERSAL DETECTOR STATUS")
|
||||||
|
status.append("=" * 60)
|
||||||
|
status.append(f" Enabled: {REVERSAL_CONFIG['enabled']}")
|
||||||
|
status.append(f" Mode: {reversal_detector.mode}")
|
||||||
|
status.append(f" Block Threshold: {REVERSAL_CONFIG['block_threshold']}%")
|
||||||
|
status.append(f" Reduce Threshold: {REVERSAL_CONFIG['reduce_threshold']}%")
|
||||||
|
status.append(f" Caution Threshold: {REVERSAL_CONFIG['caution_threshold']}%")
|
||||||
|
status.append("=" * 60)
|
||||||
|
return "\n".join(status)
|
||||||
|
|
||||||
|
|
||||||
|
def enable_reversal_check():
|
||||||
|
"""Aktiviert den Reversal Check"""
|
||||||
|
REVERSAL_CONFIG['enabled'] = True
|
||||||
|
print("✅ Reversal Check ENABLED")
|
||||||
|
|
||||||
|
|
||||||
|
def disable_reversal_check():
|
||||||
|
"""Deaktiviert den Reversal Check"""
|
||||||
|
REVERSAL_CONFIG['enabled'] = False
|
||||||
|
print("⚠️ Reversal Check DISABLED")
|
||||||
|
|
||||||
|
|
||||||
|
def set_reversal_mode(mode: str):
|
||||||
|
"""
|
||||||
|
Setzt den Reversal Detector Mode
|
||||||
|
|
||||||
|
Args:
|
||||||
|
mode: "defensive" (blockiert Trades) oder "info" (nur Logging)
|
||||||
|
"""
|
||||||
|
global reversal_detector
|
||||||
|
reversal_detector = ReversalDetector(
|
||||||
|
rsi_period=14,
|
||||||
|
ema_fast=9,
|
||||||
|
ema_slow=21,
|
||||||
|
volume_spike_mult=2.0,
|
||||||
|
divergence_lookback=10,
|
||||||
|
mode=mode
|
||||||
|
)
|
||||||
|
print(f"✅ Reversal Detector mode set to: {mode.upper()}")
|
||||||
|
|
||||||
|
|
||||||
|
# ==========================================
|
||||||
|
# STANDALONE TEST
|
||||||
|
# ==========================================
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
print(get_reversal_status())
|
||||||
|
|
||||||
|
# Test mit simulierten Daten
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
np.random.seed(42)
|
||||||
|
n = 100
|
||||||
|
prices = np.linspace(100, 110, n) + np.random.normal(0, 0.5, n)
|
||||||
|
|
||||||
|
df = pd.DataFrame({
|
||||||
|
'open': prices - np.random.uniform(0, 0.3, n),
|
||||||
|
'high': prices + np.random.uniform(0.3, 0.8, n),
|
||||||
|
'low': prices - np.random.uniform(0.3, 0.8, n),
|
||||||
|
'close': prices,
|
||||||
|
'tick_volume': np.random.randint(100, 500, n)
|
||||||
|
})
|
||||||
|
|
||||||
|
# Simuliere signal_info
|
||||||
|
mock_signal_info = {
|
||||||
|
'entry_signal': 1,
|
||||||
|
'standard_trend': 'uptrend',
|
||||||
|
'trend_info': {
|
||||||
|
'M15': {'df': df}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
print("\n🧪 Testing Reversal Check...")
|
||||||
|
result = check_reversal_risk(mock_signal_info, "XAUUSD")
|
||||||
|
|
||||||
|
print(f"\n📊 Result:")
|
||||||
|
print(f" Should Trade: {result['should_trade']}")
|
||||||
|
print(f" Reversal Score: {result['reversal_score']}%")
|
||||||
|
print(f" Action: {result['action']}")
|
||||||
|
print(f" Lot Multiplier: {result['lot_multiplier']}")
|
||||||
|
print(f" Reason: {result['reason']}")
|
||||||
@@ -20,10 +20,10 @@ PERFORMANCE-IMPACT:
|
|||||||
SESSION_WHITELIST_CONFIG = {
|
SESSION_WHITELIST_CONFIG = {
|
||||||
# Welche Sessions erlauben?
|
# Welche Sessions erlauben?
|
||||||
'enabled_sessions': {
|
'enabled_sessions': {
|
||||||
'asian': True, # ✅ BESTE SESSION: 97.8% Win-Rate, $151/Trade
|
'asian': True, # ✅ BESTE SESSION: 54.2% Win-Rate, +$21/Trade
|
||||||
'london': False, # ❌ BLOCKIERT: 12.5% Win-Rate, -$10/Trade
|
'london': False, # ❌ BLOCKIERT: 46.9% Win-Rate, +$8/Trade
|
||||||
'overlap': False, # ❌ BLOCKIERT: 14.3% Win-Rate, -$7/Trade
|
'overlap': True, # ✅ TEST: Aktiviert 29.01.2026 mit V1.6 Adaptive
|
||||||
'ny': True, # ✅ AKTIV: 43.3% Win-Rate, aber profitabel ($48/Trade)
|
'ny': True, # ✅ AKTIV: 49.1% Win-Rate, +$6/Trade
|
||||||
},
|
},
|
||||||
|
|
||||||
# Session-spezifische Confidence Thresholds (NEU 26.12.2025)
|
# Session-spezifische Confidence Thresholds (NEU 26.12.2025)
|
||||||
|
|||||||
Reference in New Issue
Block a user