trading_bot.py 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221
  1. #!/usr/bin/env python3
  2. """
  3. Hyperliquid Manual Trading Bot - Main Launcher
  4. A simple launcher for systemd deployment.
  5. This is the ONLY file you need to run - it handles everything.
  6. """
  7. import sys
  8. import os
  9. import asyncio
  10. import logging
  11. import signal
  12. from datetime import datetime
  13. from pathlib import Path
  14. # Bot version
  15. BOT_VERSION = "2.1.1"
  16. # Add src directory to Python path
  17. sys.path.insert(0, str(Path(__file__).parent / "src"))
  18. try:
  19. from config import Config
  20. from telegram_bot import TelegramTradingBot
  21. from trading_stats import TradingStats
  22. except ImportError as e:
  23. print(f"❌ Import error: {e}")
  24. print("💡 Make sure you're in the correct directory and dependencies are installed")
  25. sys.exit(1)
  26. # Global variables for graceful shutdown
  27. bot_instance = None
  28. is_shutting_down = False
  29. class BotManager:
  30. """Manages the trading bot with simple startup and shutdown."""
  31. def __init__(self):
  32. self.bot = None
  33. self.setup_logging()
  34. # Ensure logs directory exists
  35. os.makedirs("logs", exist_ok=True)
  36. def setup_logging(self):
  37. """Set up comprehensive logging."""
  38. # Create logs directory
  39. os.makedirs("logs", exist_ok=True)
  40. # Set up file logging
  41. log_file = f"logs/trading_bot_{datetime.now().strftime('%Y%m%d')}.log"
  42. logging.basicConfig(
  43. level=getattr(logging, Config.LOG_LEVEL if hasattr(Config, 'LOG_LEVEL') else 'INFO'),
  44. format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
  45. handlers=[
  46. logging.FileHandler(log_file),
  47. logging.StreamHandler(sys.stdout)
  48. ]
  49. )
  50. self.logger = logging.getLogger(__name__)
  51. self.logger.info(f"Logging initialized - Log file: {log_file}")
  52. def print_banner(self):
  53. """Print startup banner."""
  54. banner = f"""
  55. ╔══════════════════════════════════════════════════════════════╗
  56. ║ 📱 HYPERLIQUID TRADING BOT ║
  57. ║ Version {BOT_VERSION} ║
  58. ╠══════════════════════════════════════════════════════════════╣
  59. ║ ║
  60. ║ 🤖 Manual phone control via Telegram ║
  61. ║ 📊 Comprehensive trading statistics ║
  62. ║ 🛡️ Systemd managed service ║
  63. ║ 💾 Persistent data between restarts ║
  64. ║ 📱 Professional mobile interface ║
  65. ║ ║
  66. ╚══════════════════════════════════════════════════════════════╝
  67. 🚀 Starting at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
  68. 📁 Working directory: {os.getcwd()}
  69. 🌐 Network: {'Testnet' if Config.HYPERLIQUID_TESTNET else '🚨 MAINNET 🚨'}
  70. """
  71. print(banner)
  72. def validate_configuration(self):
  73. """Validate bot configuration."""
  74. self.logger.info("🔍 Validating configuration...")
  75. missing_config = []
  76. if not hasattr(Config, 'HYPERLIQUID_PRIVATE_KEY') or not Config.HYPERLIQUID_PRIVATE_KEY:
  77. missing_config.append("HYPERLIQUID_PRIVATE_KEY")
  78. if not hasattr(Config, 'TELEGRAM_BOT_TOKEN') or not Config.TELEGRAM_BOT_TOKEN:
  79. missing_config.append("TELEGRAM_BOT_TOKEN")
  80. if not hasattr(Config, 'TELEGRAM_CHAT_ID') or not Config.TELEGRAM_CHAT_ID:
  81. missing_config.append("TELEGRAM_CHAT_ID")
  82. if not hasattr(Config, 'TELEGRAM_ENABLED') or not Config.TELEGRAM_ENABLED:
  83. missing_config.append("TELEGRAM_ENABLED (must be true)")
  84. if missing_config:
  85. error_msg = f"❌ Missing configuration: {', '.join(missing_config)}"
  86. self.logger.error(error_msg)
  87. print(f"\n{error_msg}")
  88. print("\n💡 Setup steps:")
  89. print("1. Copy config: cp config/env.example .env")
  90. print("2. Get Telegram setup: python utils/get_telegram_chat_id.py")
  91. print("3. Edit .env with your details")
  92. print("4. See: SETUP_GUIDE.md for detailed instructions")
  93. return False
  94. self.logger.info("✅ Configuration validation passed")
  95. return True
  96. def check_stats_persistence(self):
  97. """Check and report on statistics persistence."""
  98. stats_file = "trading_stats.json"
  99. if os.path.exists(stats_file):
  100. try:
  101. stats = TradingStats()
  102. basic_stats = stats.get_basic_stats()
  103. self.logger.info(f"📊 Existing stats found - {basic_stats['total_trades']} trades since {basic_stats.get('start_date', 'unknown')}")
  104. return True
  105. except Exception as e:
  106. self.logger.warning(f"⚠️ Stats file exists but couldn't load: {e}")
  107. return False
  108. else:
  109. self.logger.info("📊 No existing stats - will create new tracking from launch")
  110. return False
  111. async def run_bot(self):
  112. """Run the main bot."""
  113. global is_shutting_down
  114. try:
  115. self.logger.info("🤖 Creating TelegramTradingBot instance...")
  116. self.bot = TelegramTradingBot()
  117. # Set version for bot to use in messages
  118. self.bot.version = BOT_VERSION
  119. self.logger.info("📊 Checking statistics persistence...")
  120. self.check_stats_persistence()
  121. self.logger.info("🚀 Starting Telegram bot...")
  122. # Run the bot
  123. await self.bot.run()
  124. except KeyboardInterrupt:
  125. self.logger.info("👋 Bot stopped by user (Ctrl+C)")
  126. is_shutting_down = True
  127. except Exception as e:
  128. self.logger.error(f"❌ Bot error: {e}")
  129. raise
  130. async def start(self):
  131. """Main entry point."""
  132. try:
  133. self.print_banner()
  134. if not self.validate_configuration():
  135. return False
  136. self.logger.info("🎯 All systems ready - starting trading bot...")
  137. print("💡 Send /start to your Telegram bot for quick actions")
  138. print("🛑 Press Ctrl+C to stop\n")
  139. await self.run_bot()
  140. return True
  141. except Exception as e:
  142. self.logger.error(f"❌ Fatal error in bot manager: {e}")
  143. print(f"\n💥 Fatal error: {e}")
  144. return False
  145. def signal_handler(signum, frame):
  146. """Handle shutdown signals gracefully."""
  147. global is_shutting_down, bot_instance
  148. print("\n🛑 Shutdown signal received...")
  149. is_shutting_down = True
  150. def main():
  151. """Main function."""
  152. global bot_instance
  153. # Set up signal handlers for graceful shutdown
  154. signal.signal(signal.SIGINT, signal_handler)
  155. signal.signal(signal.SIGTERM, signal_handler)
  156. try:
  157. bot_manager = BotManager()
  158. bot_instance = bot_manager
  159. # Run the bot
  160. success = asyncio.run(bot_manager.start())
  161. if success:
  162. print("\n✅ Bot session completed successfully")
  163. else:
  164. print("\n❌ Bot session failed")
  165. sys.exit(1)
  166. except KeyboardInterrupt:
  167. print("\n👋 Bot stopped by user")
  168. except Exception as e:
  169. print(f"\n💥 Unexpected error: {e}")
  170. sys.exit(1)
  171. finally:
  172. print("📊 Your trading statistics have been saved")
  173. if __name__ == "__main__":
  174. main()