2025-11-26 21:14:01 +01:00
|
|
|
|
"""
|
|
|
|
|
|
📱 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
|
2026-05-12 10:12:25 +02:00
|
|
|
|
import logging
|
|
|
|
|
|
from datetime import datetime
|
2025-11-26 21:14:01 +01:00
|
|
|
|
from typing import Dict, List, Optional
|
|
|
|
|
|
import os
|
|
|
|
|
|
|
2026-05-12 10:12:25 +02:00
|
|
|
|
logger = logging.getLogger(__name__)
|
|
|
|
|
|
|
2025-11-26 21:14:01 +01:00
|
|
|
|
|
|
|
|
|
|
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}"
|
|
|
|
|
|
|
2026-05-12 10:12:25 +02:00
|
|
|
|
def test_connection(self) -> bool:
|
|
|
|
|
|
"""Test Telegram API connection — call explicitly, not in __init__"""
|
2025-11-26 21:14:01 +01:00
|
|
|
|
try:
|
|
|
|
|
|
response = requests.get(f"{self.base_url}/getMe", timeout=5)
|
|
|
|
|
|
if response.status_code == 200:
|
2026-05-12 10:12:25 +02:00
|
|
|
|
username = response.json()['result']['username']
|
|
|
|
|
|
logger.info(f"Telegram Bot connected: @{username}")
|
|
|
|
|
|
return True
|
2025-11-26 21:14:01 +01:00
|
|
|
|
else:
|
2026-05-12 10:12:25 +02:00
|
|
|
|
logger.warning(f"Telegram connection issue: {response.status_code}")
|
|
|
|
|
|
return False
|
|
|
|
|
|
except requests.RequestException as e:
|
|
|
|
|
|
logger.error(f"Telegram connection failed: {e}")
|
|
|
|
|
|
return False
|
2025-11-26 21:14:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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:
|
2026-05-12 10:12:25 +02:00
|
|
|
|
logger.warning(f"Telegram send failed: {response.status_code}")
|
2025-11-26 21:14:01 +01:00
|
|
|
|
return False
|
|
|
|
|
|
|
2026-05-12 10:12:25 +02:00
|
|
|
|
except requests.RequestException as e:
|
|
|
|
|
|
logger.error(f"Telegram error: {e}")
|
2025-11-26 21:14:01 +01:00
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
|
|
|
|
|
# TRADE NOTIFICATIONS
|
|
|
|
|
|
# ==========================================
|
|
|
|
|
|
|
2026-05-12 10:12:25 +02:00
|
|
|
|
def notify_trade_entry(self, trade_data: Dict) -> bool:
|
2025-11-26 21:14:01 +01:00
|
|
|
|
"""
|
|
|
|
|
|
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
|
|
|
|
|
|
"""
|
2026-05-12 10:12:25 +02:00
|
|
|
|
return self.send_message(message)
|
2025-11-26 21:14:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
2026-05-12 10:12:25 +02:00
|
|
|
|
def notify_trade_exit(self, trade_data: Dict) -> bool:
|
2025-11-26 21:14:01 +01:00
|
|
|
|
"""
|
|
|
|
|
|
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 "🔴"
|
|
|
|
|
|
|
|
|
|
|
|
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
|
|
|
|
|
|
"""
|
2026-05-12 10:12:25 +02:00
|
|
|
|
return self.send_message(message)
|
2025-11-26 21:14:01 +01:00
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
# ==========================================
|
|
|
|
|
|
# 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)
|