core.py 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309
  1. #!/usr/bin/env python3
  2. """
  3. Core Telegram Bot - Handles only bot setup, authentication, and basic messaging.
  4. """
  5. import asyncio
  6. import logging
  7. from datetime import datetime
  8. from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
  9. from telegram.ext import Application, ContextTypes, CommandHandler, CallbackQueryHandler, MessageHandler, filters
  10. from src.config.config import Config
  11. from src.trading.trading_engine import TradingEngine
  12. from src.monitoring.market_monitor import MarketMonitor
  13. from src.notifications.notification_manager import NotificationManager
  14. from src.commands.trading_commands import TradingCommands
  15. from src.commands.info_commands import InfoCommands
  16. from src.commands.management_commands import ManagementCommands
  17. logger = logging.getLogger(__name__)
  18. class TelegramTradingBot:
  19. """Core Telegram bot handling only authentication, messaging, and command routing."""
  20. def __init__(self):
  21. """Initialize the core bot with minimal responsibilities."""
  22. # Core bot attributes
  23. self.application = None
  24. self.version = "Unknown"
  25. # Initialize subsystems
  26. self.trading_engine = TradingEngine()
  27. self.market_monitor = MarketMonitor(self.trading_engine)
  28. self.notification_manager = NotificationManager()
  29. # Connect notification manager to market monitor
  30. self.market_monitor.set_notification_manager(self.notification_manager)
  31. # Initialize command handlers
  32. self.trading_commands = TradingCommands(self.trading_engine, self.notification_manager)
  33. self.info_commands = InfoCommands(self.trading_engine)
  34. self.management_commands = ManagementCommands(self.trading_engine, self.market_monitor)
  35. def is_authorized(self, chat_id: str) -> bool:
  36. """Check if the chat ID is authorized to use the bot."""
  37. return str(chat_id) == str(Config.TELEGRAM_CHAT_ID)
  38. async def send_message(self, text: str, parse_mode: str = 'HTML') -> None:
  39. """Send a message to the authorized chat."""
  40. if self.application and Config.TELEGRAM_CHAT_ID:
  41. try:
  42. await self.application.bot.send_message(
  43. chat_id=Config.TELEGRAM_CHAT_ID,
  44. text=text,
  45. parse_mode=parse_mode
  46. )
  47. except Exception as e:
  48. logger.error(f"Failed to send message: {e}")
  49. def setup_handlers(self):
  50. """Set up command handlers for the bot."""
  51. if not self.application:
  52. return
  53. # Basic bot commands
  54. self.application.add_handler(CommandHandler("start", self.start_command))
  55. self.application.add_handler(CommandHandler("help", self.help_command))
  56. # Trading commands
  57. self.application.add_handler(CommandHandler("long", self.trading_commands.long_command))
  58. self.application.add_handler(CommandHandler("short", self.trading_commands.short_command))
  59. self.application.add_handler(CommandHandler("exit", self.trading_commands.exit_command))
  60. self.application.add_handler(CommandHandler("sl", self.trading_commands.sl_command))
  61. self.application.add_handler(CommandHandler("tp", self.trading_commands.tp_command))
  62. self.application.add_handler(CommandHandler("coo", self.trading_commands.coo_command))
  63. # Info commands
  64. self.application.add_handler(CommandHandler("balance", self.info_commands.balance_command))
  65. self.application.add_handler(CommandHandler("positions", self.info_commands.positions_command))
  66. self.application.add_handler(CommandHandler("orders", self.info_commands.orders_command))
  67. self.application.add_handler(CommandHandler("stats", self.info_commands.stats_command))
  68. self.application.add_handler(CommandHandler("trades", self.info_commands.trades_command))
  69. self.application.add_handler(CommandHandler("market", self.info_commands.market_command))
  70. self.application.add_handler(CommandHandler("price", self.info_commands.price_command))
  71. self.application.add_handler(CommandHandler("performance", self.info_commands.performance_command))
  72. self.application.add_handler(CommandHandler("daily", self.info_commands.daily_command))
  73. self.application.add_handler(CommandHandler("weekly", self.info_commands.weekly_command))
  74. self.application.add_handler(CommandHandler("monthly", self.info_commands.monthly_command))
  75. self.application.add_handler(CommandHandler("risk", self.info_commands.risk_command))
  76. self.application.add_handler(CommandHandler("balance_adjustments", self.info_commands.balance_adjustments_command))
  77. self.application.add_handler(CommandHandler("commands", self.info_commands.commands_command))
  78. self.application.add_handler(CommandHandler("c", self.info_commands.commands_command)) # Alias
  79. # Management commands
  80. self.application.add_handler(CommandHandler("monitoring", self.management_commands.monitoring_command))
  81. self.application.add_handler(CommandHandler("alarm", self.management_commands.alarm_command))
  82. self.application.add_handler(CommandHandler("logs", self.management_commands.logs_command))
  83. self.application.add_handler(CommandHandler("debug", self.management_commands.debug_command))
  84. self.application.add_handler(CommandHandler("version", self.management_commands.version_command))
  85. self.application.add_handler(CommandHandler("keyboard", self.management_commands.keyboard_command))
  86. # Callback and message handlers
  87. self.application.add_handler(CallbackQueryHandler(self.trading_commands.button_callback))
  88. async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
  89. """Handle the /start command."""
  90. if not self.is_authorized(update.effective_chat.id):
  91. await update.message.reply_text("❌ Unauthorized access.")
  92. return
  93. # Determine risk management and stop loss details from Config
  94. risk_enabled = getattr(Config, 'RISK_MANAGEMENT_ENABLED', False)
  95. stop_loss_percentage = getattr(Config, 'STOP_LOSS_PERCENTAGE', 0)
  96. bot_heartbeat = getattr(Config, 'BOT_HEARTBEAT_SECONDS', 10)
  97. welcome_text = f"""
  98. 🤖 <b>Welcome to Hyperliquid Trading Bot v{self.version}</b>
  99. 📱 <b>Quick Actions:</b>
  100. • Trading: /long {Config.DEFAULT_TRADING_TOKEN} 100 or /short {Config.DEFAULT_TRADING_TOKEN} 50
  101. • Exit: /exit {Config.DEFAULT_TRADING_TOKEN} (closes position)
  102. • Info: /balance, /positions, /orders
  103. 📊 <b>Market Data:</b>
  104. • /market - Detailed market overview
  105. • /price - Quick price check
  106. <b>⚡ Quick Commands:</b>
  107. • /balance - Account balance
  108. • /positions - Open positions
  109. • /orders - Active orders
  110. • /market - Market data & prices
  111. <b>🚀 Trading:</b>
  112. • /long {Config.DEFAULT_TRADING_TOKEN} 100 - Long position
  113. • /long {Config.DEFAULT_TRADING_TOKEN} 100 45000 - Limit order
  114. • /long {Config.DEFAULT_TRADING_TOKEN} 100 sl:44000 - With stop loss
  115. • /short {Config.DEFAULT_TRADING_TOKEN} 50 - Short position
  116. • /short {Config.DEFAULT_TRADING_TOKEN} 50 3500 sl:3600 - With stop loss
  117. • /exit {Config.DEFAULT_TRADING_TOKEN} - Close position
  118. • /coo {Config.DEFAULT_TRADING_TOKEN} - Cancel open orders
  119. <b>🛡️ Risk Management:</b>
  120. • Enabled: {'✅ Yes' if risk_enabled else '❌ No'}
  121. • Auto Stop Loss: {stop_loss_percentage}%
  122. • Order Stop Loss: Use sl:price parameter
  123. • /sl {Config.DEFAULT_TRADING_TOKEN} 44000 - Manual stop loss
  124. • /tp {Config.DEFAULT_TRADING_TOKEN} 50000 - Take profit order
  125. <b>📈 Performance & Analytics:</b>
  126. • /stats - Complete trading statistics
  127. • /performance - Token performance ranking & detailed stats
  128. • /daily - Daily performance (last 10 days)
  129. • /weekly - Weekly performance (last 10 weeks)
  130. • /monthly - Monthly performance (last 10 months)
  131. • /risk - Sharpe ratio, drawdown, VaR
  132. • /version - Bot version & system information
  133. • /trades - Recent trade history
  134. <b>🔔 Price Alerts:</b>
  135. • /alarm - List all active alarms
  136. • /alarm {Config.DEFAULT_TRADING_TOKEN} 50000 - Set alarm for {Config.DEFAULT_TRADING_TOKEN} at $50,000
  137. • /alarm {Config.DEFAULT_TRADING_TOKEN} - Show all {Config.DEFAULT_TRADING_TOKEN} alarms
  138. • /alarm 3 - Remove alarm ID 3
  139. <b>🔄 Automatic Monitoring:</b>
  140. • Real-time order fill alerts
  141. • Position opened/closed notifications
  142. • P&L calculations on trade closure
  143. • Price alarm triggers
  144. • External trade detection & sync
  145. • Auto stats synchronization
  146. • Automatic stop loss placement
  147. • {bot_heartbeat}-second monitoring interval
  148. <b>📊 Universal Trade Tracking:</b>
  149. • Bot trades: Full logging & notifications
  150. • Platform trades: Auto-detected & synced
  151. • Mobile app trades: Monitored & recorded
  152. • API trades: Tracked & included in stats
  153. Type /help for detailed command information.
  154. <b>🔄 Order Monitoring:</b>
  155. • /monitoring - View monitoring status
  156. • /logs - View log file statistics and cleanup
  157. <b>⚙️ Configuration:</b>
  158. • Default Token: {Config.DEFAULT_TRADING_TOKEN}
  159. • Network: {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}
  160. <b>🛡️ Safety Features:</b>
  161. • All trades logged automatically
  162. • Comprehensive performance tracking
  163. • Real-time balance monitoring
  164. • Risk metrics calculation
  165. • Automatic stop loss protection
  166. <b>📱 Mobile Optimized:</b>
  167. • Quick action buttons via /commands
  168. • Instant notifications
  169. • Clean, readable layout
  170. <b>💡 Quick Access:</b>
  171. • /commands or /c - One-tap button menu for all commands
  172. For support, contact your bot administrator.
  173. """
  174. await update.message.reply_text(welcome_text, parse_mode='HTML')
  175. async def help_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
  176. """Handle the /help command."""
  177. if not self.is_authorized(update.effective_chat.id):
  178. await update.message.reply_text("❌ Unauthorized access.")
  179. return
  180. help_text = """
  181. 📖 <b>Complete Command Reference</b>
  182. 🔄 <b>Trading Commands:</b>
  183. • /long [token] [USDC] [price] [sl:price] - Open long position
  184. • /short [token] [USDC] [price] [sl:price] - Open short position
  185. • /exit [token] - Close position (market order)
  186. • /sl [token] [price] - Set stop loss order
  187. • /tp [token] [price] - Set take profit order
  188. • /coo [token] - Cancel all open orders
  189. 📊 <b>Account Info:</b>
  190. • /balance - Account balance and equity
  191. • /positions - Open positions with P&L
  192. • /orders - Active orders
  193. • /trades - Recent trade history
  194. • /stats - Comprehensive trading statistics
  195. 📈 <b>Market Data:</b>
  196. • /market [token] - Market data and orderbook
  197. • /price [token] - Quick price check
  198. ⚙️ <b>Management:</b>
  199. • /monitoring - View/toggle order monitoring
  200. • /alarm [token] [price] - Set price alerts
  201. • /logs - View recent bot logs
  202. • /debug - Bot internal state (troubleshooting)
  203. For support or issues, check the logs or contact the administrator.
  204. """
  205. await update.message.reply_text(help_text, parse_mode='HTML')
  206. async def run(self):
  207. """Run the Telegram bot."""
  208. if not Config.TELEGRAM_BOT_TOKEN:
  209. logger.error("❌ TELEGRAM_BOT_TOKEN not configured")
  210. return
  211. if not Config.TELEGRAM_CHAT_ID:
  212. logger.error("❌ TELEGRAM_CHAT_ID not configured")
  213. return
  214. try:
  215. # Create application
  216. self.application = Application.builder().token(Config.TELEGRAM_BOT_TOKEN).build()
  217. # Connect notification manager to the bot application
  218. self.notification_manager.set_bot_application(self.application)
  219. # Set up handlers
  220. self.setup_handlers()
  221. logger.info("🚀 Starting Telegram trading bot...")
  222. # Send startup notification
  223. await self.send_message(
  224. f"🤖 <b>Manual Trading Bot v{self.version} Started</b>\n\n"
  225. f"✅ Connected to Hyperliquid {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}\n"
  226. f"📊 Default Symbol: {Config.DEFAULT_TRADING_TOKEN}\n"
  227. f"🔄 All systems ready!\n\n"
  228. "Use /start for quick actions or /help for all commands."
  229. )
  230. # Start subsystems
  231. await self.market_monitor.start()
  232. # Start polling for updates using the modern approach
  233. logger.info("🔄 Starting bot polling...")
  234. await self.application.run_polling(
  235. drop_pending_updates=True
  236. # By default, run_polling handles SIGINT, SIGTERM, SIGABRT.
  237. # No need to specify stop_signals=None if we want this default behavior.
  238. )
  239. except asyncio.CancelledError:
  240. logger.info("🛑 Bot polling cancelled")
  241. raise
  242. except Exception as e:
  243. logger.error(f"❌ Error in telegram bot: {e}")
  244. raise
  245. finally:
  246. # Clean shutdown
  247. try:
  248. await self.market_monitor.stop()
  249. if self.application:
  250. await self.application.stop()
  251. await self.application.shutdown()
  252. except Exception as e:
  253. logger.error(f"Error during shutdown: {e}")