feat: Trading Bot V1.8 - Aggressive Mode + Infrastructure
## Major Features - Session Filter: NY-only trading (13:00-21:00 UTC) - SQLite Database: Structured trade logging - Telegram Bot: Real-time notifications (@Xausd_digger_bot) - Streamlit Dashboard: Visual monitoring & analytics - JSON Import: Historical data migration ## Infrastructure - trading_database.py: SQLite trade storage - telegram_notifier.py: Telegram integration - infrastructure_patch.py: Combined DB + Telegram - trading_dashboard.py: Real-time web dashboard - import_json_to_db.py: JSON to SQLite migration ## Session Filter (V1.8 Aggressive Mode) - session_filter_patch.py: Whitelist-based filter - Blocks: Asian, London, Overlap sessions - Active: NY session only (best performance: 47.6% WR) - Base confidence: 60% ## Documentation - V1.8_AGGRESSIVE_MODE_AKTIVIERT.md - FIX_DUPLICATE_SCHEDULER.md - DASHBOARD_WINDOWS_SERVER.md - SQLITE_TELEGRAM_SETUP.md - PROJECT_CLEANUP.md ## Cleanup - Archived old V1.1-V1.7 versions - Removed obsolete analysis scripts (replaced by dashboard) - Added .gitignore for secrets and temp files ## Breaking Changes - Requires telegram_config.json (use template) - Requires Python packages: streamlit, plotly 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,551 @@
|
||||
"""
|
||||
📱 TELEGRAM NOTIFIER - Mobile Trading Notifications
|
||||
Sendet Trade Updates, Performance Reports und Alerts
|
||||
|
||||
FEATURES:
|
||||
- Trade Entry/Exit Notifications
|
||||
- Daily/Weekly Performance Reports
|
||||
- Error Alerts
|
||||
- Bot Status Updates
|
||||
- Custom Commands (/status, /report)
|
||||
"""
|
||||
|
||||
import requests
|
||||
import json
|
||||
from datetime import datetime, timedelta
|
||||
from typing import Dict, List, Optional
|
||||
import os
|
||||
|
||||
|
||||
class TelegramNotifier:
|
||||
"""
|
||||
Telegram Bot Integration für Trading Notifications
|
||||
"""
|
||||
|
||||
def __init__(self, bot_token: str, chat_id: str):
|
||||
"""
|
||||
Initialize Telegram Bot
|
||||
|
||||
Args:
|
||||
bot_token: Telegram Bot Token (von @BotFather)
|
||||
chat_id: Telegram Chat ID (deine User ID)
|
||||
"""
|
||||
self.bot_token = bot_token
|
||||
self.chat_id = chat_id
|
||||
self.base_url = f"https://api.telegram.org/bot{bot_token}"
|
||||
|
||||
# Test connection
|
||||
self._test_connection()
|
||||
|
||||
|
||||
def _test_connection(self):
|
||||
"""Test Telegram API connection"""
|
||||
try:
|
||||
response = requests.get(f"{self.base_url}/getMe", timeout=5)
|
||||
if response.status_code == 200:
|
||||
bot_info = response.json()
|
||||
print(f"✅ Telegram Bot connected: @{bot_info['result']['username']}")
|
||||
else:
|
||||
print(f"⚠️ Telegram connection issue: {response.status_code}")
|
||||
except Exception as e:
|
||||
print(f"❌ Telegram connection failed: {e}")
|
||||
|
||||
|
||||
def send_message(self, text: str, parse_mode: str = "Markdown") -> bool:
|
||||
"""
|
||||
Send a text message to Telegram
|
||||
|
||||
Args:
|
||||
text: Message text (supports Markdown)
|
||||
parse_mode: 'Markdown' or 'HTML'
|
||||
|
||||
Returns:
|
||||
True if successful, False otherwise
|
||||
"""
|
||||
try:
|
||||
url = f"{self.base_url}/sendMessage"
|
||||
payload = {
|
||||
'chat_id': self.chat_id,
|
||||
'text': text,
|
||||
'parse_mode': parse_mode,
|
||||
'disable_web_page_preview': True
|
||||
}
|
||||
|
||||
response = requests.post(url, json=payload, timeout=10)
|
||||
|
||||
if response.status_code == 200:
|
||||
return True
|
||||
else:
|
||||
print(f"⚠️ Telegram send failed: {response.status_code}")
|
||||
return False
|
||||
|
||||
except Exception as e:
|
||||
print(f"❌ Telegram error: {e}")
|
||||
return False
|
||||
|
||||
|
||||
# ==========================================
|
||||
# TRADE NOTIFICATIONS
|
||||
# ==========================================
|
||||
|
||||
def notify_trade_entry(self, trade_data: Dict):
|
||||
"""
|
||||
Notify about new trade entry
|
||||
|
||||
Args:
|
||||
trade_data: Dictionary with trade information
|
||||
"""
|
||||
type_emoji = "🟢" if trade_data['type'] == 'BUY' else "🔴"
|
||||
session_emoji = self._get_session_emoji(trade_data.get('session', 'unknown'))
|
||||
|
||||
message = f"""
|
||||
{type_emoji} *Trade Opened*
|
||||
|
||||
*Symbol:* {trade_data['symbol']}
|
||||
*Type:* {trade_data['type']}
|
||||
*Entry:* {trade_data['entry_price']}
|
||||
|
||||
*SL:* {trade_data.get('sl_price', 'N/A')} | *TP:* {trade_data.get('tp_price', 'N/A')}
|
||||
|
||||
*Risk:* ${trade_data.get('risk_amount', 0):.2f} ({trade_data.get('risk_pct', 0)*100:.1f}%)
|
||||
*Volume:* {trade_data.get('volume', 0)} lots
|
||||
|
||||
{session_emoji} *Session:* {trade_data.get('session', 'unknown').upper()}
|
||||
📊 *Confidence:* {trade_data.get('confidence', 0):.1f}%
|
||||
🎯 *Quality:* {trade_data.get('quality', 'unknown').upper()}
|
||||
|
||||
⏰ {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
|
||||
"""
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
def notify_trade_exit(self, trade_data: Dict):
|
||||
"""
|
||||
Notify about trade exit
|
||||
|
||||
Args:
|
||||
trade_data: Dictionary with trade and exit information
|
||||
"""
|
||||
profit = trade_data.get('net_profit', 0)
|
||||
profit_emoji = "✅" if profit > 0 else "❌"
|
||||
type_emoji = "🟢" if trade_data['type'] == 'BUY' else "🔴"
|
||||
|
||||
# Format profit/loss
|
||||
profit_text = f"+${profit:.2f}" if profit > 0 else f"${profit:.2f}"
|
||||
|
||||
message = f"""
|
||||
{profit_emoji} *Trade Closed* {type_emoji}
|
||||
|
||||
*Symbol:* {trade_data['symbol']}
|
||||
*Type:* {trade_data['type']}
|
||||
|
||||
*Entry:* {trade_data['entry_price']}
|
||||
*Exit:* {trade_data.get('exit_price', 'N/A')}
|
||||
|
||||
*Profit:* {profit_text}
|
||||
*Duration:* {trade_data.get('duration_hours', 0):.1f}h
|
||||
|
||||
*Exit Reason:* {trade_data.get('exit_reason', 'unknown').upper()}
|
||||
*R:R Ratio:* {trade_data.get('rr_ratio', 0):.2f}
|
||||
|
||||
⏰ {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
|
||||
"""
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
# ==========================================
|
||||
# PERFORMANCE REPORTS
|
||||
# ==========================================
|
||||
|
||||
def send_daily_report(self, stats: Dict):
|
||||
"""
|
||||
Send daily performance summary
|
||||
|
||||
Args:
|
||||
stats: Dictionary with daily statistics
|
||||
"""
|
||||
win_rate = stats.get('win_rate', 0)
|
||||
net_profit = stats.get('net_profit', 0)
|
||||
|
||||
# Emojis based on performance
|
||||
profit_emoji = "💰" if net_profit > 0 else "📉"
|
||||
wr_emoji = "🎯" if win_rate >= 50 else "⚠️" if win_rate >= 40 else "🔴"
|
||||
|
||||
message = f"""
|
||||
📊 *Daily Trading Report*
|
||||
📅 {datetime.now().strftime('%Y-%m-%d')}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
*Trades:* {stats.get('total_trades', 0)}
|
||||
*Wins:* {stats.get('wins', 0)} | *Losses:* {stats.get('losses', 0)}
|
||||
{wr_emoji} *Win Rate:* {win_rate:.1f}%
|
||||
|
||||
{profit_emoji} *Net Profit:* ${net_profit:.2f}
|
||||
*Gross Profit:* ${stats.get('gross_profit', 0):.2f}
|
||||
*Gross Loss:* ${stats.get('gross_loss', 0):.2f}
|
||||
|
||||
*Avg Trade:* ${stats.get('avg_trade', 0):.2f}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
✅ Bot Status: Running
|
||||
"""
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
def send_weekly_report(self, stats: Dict, session_perf: Dict = None):
|
||||
"""
|
||||
Send weekly performance summary
|
||||
|
||||
Args:
|
||||
stats: Dictionary with weekly statistics
|
||||
session_perf: Optional session performance breakdown
|
||||
"""
|
||||
win_rate = stats.get('win_rate', 0)
|
||||
net_profit = stats.get('net_profit', 0)
|
||||
profit_factor = stats.get('profit_factor', 0)
|
||||
|
||||
# Emojis
|
||||
profit_emoji = "💰" if net_profit > 0 else "📉"
|
||||
pf_emoji = "🟢" if profit_factor >= 1.5 else "🟡" if profit_factor >= 1.2 else "🔴"
|
||||
|
||||
message = f"""
|
||||
📈 *Weekly Trading Report*
|
||||
📅 {(datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d')} to {datetime.now().strftime('%Y-%m-%d')}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
|
||||
📊 *Overall Performance*
|
||||
*Total Trades:* {stats.get('total_trades', 0)}
|
||||
*Wins:* {stats.get('wins', 0)} | *Losses:* {stats.get('losses', 0)}
|
||||
*Win Rate:* {win_rate:.1f}%
|
||||
|
||||
{profit_emoji} *Net Profit:* ${net_profit:.2f}
|
||||
{pf_emoji} *Profit Factor:* {profit_factor:.2f}
|
||||
*Avg Trade:* ${stats.get('avg_trade', 0):.2f}
|
||||
|
||||
━━━━━━━━━━━━━━━━━━━━
|
||||
"""
|
||||
|
||||
# Add session breakdown if available
|
||||
if session_perf:
|
||||
message += "\n📍 *Session Performance*\n\n"
|
||||
|
||||
# Sort sessions by profit
|
||||
sorted_sessions = sorted(
|
||||
session_perf.items(),
|
||||
key=lambda x: x[1].get('total_profit', 0),
|
||||
reverse=True
|
||||
)
|
||||
|
||||
for session, data in sorted_sessions:
|
||||
session_emoji = self._get_session_emoji(session)
|
||||
profit = data.get('total_profit', 0)
|
||||
wr = data.get('win_rate', 0)
|
||||
|
||||
profit_text = f"+${profit:.2f}" if profit > 0 else f"${profit:.2f}"
|
||||
status = "✅" if profit > 0 else "❌"
|
||||
|
||||
message += f"{session_emoji} *{session.upper()}:* {profit_text} ({wr:.1f}% WR) {status}\n"
|
||||
|
||||
message += "\n━━━━━━━━━━━━━━━━━━━━\n✅ Bot Status: Running"
|
||||
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
# ==========================================
|
||||
# ALERTS & STATUS
|
||||
# ==========================================
|
||||
|
||||
def send_error_alert(self, error_message: str, context: str = ""):
|
||||
"""
|
||||
Send error alert
|
||||
|
||||
Args:
|
||||
error_message: Error description
|
||||
context: Additional context
|
||||
"""
|
||||
message = f"""
|
||||
🚨 *ERROR ALERT*
|
||||
|
||||
*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
|
||||
|
||||
*Error:* {error_message}
|
||||
|
||||
{f'*Context:* {context}' if context else ''}
|
||||
|
||||
⚠️ Please check the bot!
|
||||
"""
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
def send_bot_started(self, config: Dict):
|
||||
"""
|
||||
Notify when bot starts
|
||||
|
||||
Args:
|
||||
config: Bot configuration
|
||||
"""
|
||||
active_sessions = [s for s, enabled in config.get('enabled_sessions', {}).items() if enabled]
|
||||
|
||||
message = f"""
|
||||
🚀 *TradingBot Started*
|
||||
|
||||
*Version:* {config.get('version', 'V1.8')}
|
||||
*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
|
||||
|
||||
⚙️ *Configuration:*
|
||||
*Active Sessions:* {', '.join(s.upper() for s in active_sessions)}
|
||||
*Confidence Threshold:* {config.get('base_confidence', 60)}%
|
||||
*Max Risk/Trade:* {config.get('max_risk_per_trade', 0.01)*100:.1f}%
|
||||
|
||||
✅ Bot is now monitoring the market
|
||||
"""
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
def send_bot_stopped(self, reason: str = "Manual stop"):
|
||||
"""
|
||||
Notify when bot stops
|
||||
|
||||
Args:
|
||||
reason: Stop reason
|
||||
"""
|
||||
message = f"""
|
||||
⏸️ *TradingBot Stopped*
|
||||
|
||||
*Time:* {datetime.now().strftime('%Y-%m-%d %H:%M:%S')} UTC
|
||||
*Reason:* {reason}
|
||||
|
||||
ℹ️ Bot has stopped trading
|
||||
"""
|
||||
self.send_message(message)
|
||||
|
||||
|
||||
def send_session_blocked(self, session: str, reason: str):
|
||||
"""
|
||||
Notify when a trading session is blocked
|
||||
|
||||
Args:
|
||||
session: Session name
|
||||
reason: Block reason
|
||||
"""
|
||||
session_emoji = self._get_session_emoji(session)
|
||||
|
||||
message = f"""
|
||||
⏸️ *Trading Skipped*
|
||||
|
||||
{session_emoji} *Session:* {session.upper()}
|
||||
*Reason:* {reason}
|
||||
|
||||
💡 Bot is waiting for allowed session
|
||||
"""
|
||||
# Only send if debug mode (optional - can be noisy)
|
||||
# self.send_message(message)
|
||||
|
||||
|
||||
# ==========================================
|
||||
# BOT COMMANDS (Optional - for interactive use)
|
||||
# ==========================================
|
||||
|
||||
def handle_command(self, command: str, db) -> str:
|
||||
"""
|
||||
Handle Telegram bot commands
|
||||
|
||||
Args:
|
||||
command: Command string (e.g., '/status', '/report')
|
||||
db: TradingDatabase instance
|
||||
|
||||
Returns:
|
||||
Response message
|
||||
"""
|
||||
if command == '/status':
|
||||
return self._cmd_status(db)
|
||||
|
||||
elif command == '/report':
|
||||
return self._cmd_report(db)
|
||||
|
||||
elif command == '/today':
|
||||
return self._cmd_today(db)
|
||||
|
||||
elif command == '/help':
|
||||
return self._cmd_help()
|
||||
|
||||
else:
|
||||
return "Unknown command. Use /help for available commands."
|
||||
|
||||
|
||||
def _cmd_status(self, db) -> str:
|
||||
"""Get bot status"""
|
||||
open_positions = db.get_open_positions()
|
||||
stats = db.get_overall_statistics(days=7)
|
||||
|
||||
return f"""
|
||||
📊 *Bot Status*
|
||||
|
||||
*Open Positions:* {len(open_positions)}
|
||||
*7-Day Win Rate:* {stats.get('win_rate', 0):.1f}%
|
||||
*7-Day Profit:* ${stats.get('net_profit', 0):.2f}
|
||||
|
||||
✅ Bot is running
|
||||
"""
|
||||
|
||||
|
||||
def _cmd_report(self, db) -> str:
|
||||
"""Get performance report"""
|
||||
stats = db.get_overall_statistics(days=7)
|
||||
self.send_weekly_report(stats)
|
||||
return "Report sent!"
|
||||
|
||||
|
||||
def _cmd_today(self, db) -> str:
|
||||
"""Get today's summary"""
|
||||
stats = db.get_daily_summary()
|
||||
self.send_daily_report(stats)
|
||||
return "Today's report sent!"
|
||||
|
||||
|
||||
def _cmd_help(self) -> str:
|
||||
"""Get help text"""
|
||||
return """
|
||||
📚 *Available Commands*
|
||||
|
||||
/status - Bot status & open positions
|
||||
/report - Weekly performance report
|
||||
/today - Today's summary
|
||||
/help - Show this help
|
||||
|
||||
Bot will automatically send:
|
||||
• Trade entry/exit notifications
|
||||
• Daily reports (22:00 UTC)
|
||||
• Error alerts
|
||||
"""
|
||||
|
||||
|
||||
# ==========================================
|
||||
# HELPER FUNCTIONS
|
||||
# ==========================================
|
||||
|
||||
def _get_session_emoji(self, session: str) -> str:
|
||||
"""Get emoji for session"""
|
||||
emojis = {
|
||||
'asian': '🌙',
|
||||
'london': '🇬🇧',
|
||||
'overlap': '🔄',
|
||||
'ny': '🇺🇸'
|
||||
}
|
||||
return emojis.get(session.lower(), '❓')
|
||||
|
||||
|
||||
# ==========================================
|
||||
# CONFIGURATION
|
||||
# ==========================================
|
||||
|
||||
def load_telegram_config() -> Dict:
|
||||
"""
|
||||
Load Telegram configuration from file or environment
|
||||
|
||||
Returns:
|
||||
Dictionary with bot_token and chat_id
|
||||
"""
|
||||
# Try to load from config file
|
||||
config_file = "telegram_config.json"
|
||||
|
||||
if os.path.exists(config_file):
|
||||
with open(config_file, 'r') as f:
|
||||
return json.load(f)
|
||||
|
||||
# Try environment variables
|
||||
bot_token = os.getenv('TELEGRAM_BOT_TOKEN')
|
||||
chat_id = os.getenv('TELEGRAM_CHAT_ID')
|
||||
|
||||
if bot_token and chat_id:
|
||||
return {
|
||||
'bot_token': bot_token,
|
||||
'chat_id': chat_id
|
||||
}
|
||||
|
||||
# Return empty config if nothing found
|
||||
return {}
|
||||
|
||||
|
||||
def create_telegram_config_template():
|
||||
"""Create template configuration file"""
|
||||
template = {
|
||||
"bot_token": "YOUR_BOT_TOKEN_HERE",
|
||||
"chat_id": "YOUR_CHAT_ID_HERE",
|
||||
"notifications": {
|
||||
"trade_entry": True,
|
||||
"trade_exit": True,
|
||||
"daily_report": True,
|
||||
"weekly_report": True,
|
||||
"error_alerts": True
|
||||
},
|
||||
"daily_report_time": "22:00", # UTC
|
||||
"weekly_report_day": "Sunday"
|
||||
}
|
||||
|
||||
with open('telegram_config_template.json', 'w') as f:
|
||||
json.dump(template, f, indent=2)
|
||||
|
||||
print("✅ Created telegram_config_template.json")
|
||||
print("📝 Edit this file and rename to telegram_config.json")
|
||||
|
||||
|
||||
# ==========================================
|
||||
# USAGE EXAMPLE
|
||||
# ==========================================
|
||||
|
||||
if __name__ == "__main__":
|
||||
print("="*70)
|
||||
print("📱 TELEGRAM NOTIFIER - Setup")
|
||||
print("="*70)
|
||||
|
||||
# Create config template
|
||||
create_telegram_config_template()
|
||||
|
||||
print("""
|
||||
📋 Setup Instructions:
|
||||
|
||||
1. Create Telegram Bot:
|
||||
- Open Telegram and search for @BotFather
|
||||
- Send /newbot and follow instructions
|
||||
- Copy the Bot Token
|
||||
|
||||
2. Get your Chat ID:
|
||||
- Search for @userinfobot in Telegram
|
||||
- Send /start
|
||||
- Copy your User ID
|
||||
|
||||
3. Configure:
|
||||
- Edit telegram_config_template.json
|
||||
- Add your bot_token and chat_id
|
||||
- Rename to telegram_config.json
|
||||
|
||||
4. Test:
|
||||
- Run this script again to test connection
|
||||
|
||||
Example Usage:
|
||||
```python
|
||||
from telegram_notifier import TelegramNotifier
|
||||
|
||||
# Initialize
|
||||
notifier = TelegramNotifier(
|
||||
bot_token='YOUR_BOT_TOKEN',
|
||||
chat_id='YOUR_CHAT_ID'
|
||||
)
|
||||
|
||||
# Send trade notification
|
||||
notifier.notify_trade_entry({
|
||||
'symbol': 'XAUUSD',
|
||||
'type': 'BUY',
|
||||
'entry_price': 2650.00,
|
||||
'sl_price': 2645.00,
|
||||
'tp_price': 2660.00,
|
||||
'session': 'ny',
|
||||
'confidence': 75.5
|
||||
})
|
||||
```
|
||||
""")
|
||||
|
||||
print("="*70)
|
||||
Reference in New Issue
Block a user