trading_bot.py 8.3 KB

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