trading_bot.py 8.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229
  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 = "data/trading_stats.json"
  106. if os.path.exists(stats_file):
  107. try:
  108. stats = TradingStats()
  109. basic_stats = stats.get_basic_stats()
  110. total_trades = basic_stats.get('total_trades_count', basic_stats.get('total_trades', 0))
  111. start_date = basic_stats.get('start_date_formatted', basic_stats.get('start_date', 'unknown'))
  112. self.logger.info(f"📊 Existing stats found - {total_trades} trades since {start_date}")
  113. return True
  114. except Exception as e:
  115. self.logger.warning(f"⚠️ Stats file {stats_file} exists but couldn't load: {e}")
  116. return False
  117. else:
  118. self.logger.info(f"📊 No existing stats file at {stats_file} - will create new tracking from launch")
  119. return False
  120. async def run_bot(self):
  121. """Run the main bot."""
  122. global is_shutting_down
  123. try:
  124. self.logger.info("🤖 Creating TelegramTradingBot instance...")
  125. self.bot = TelegramTradingBot()
  126. # Set version for bot to use in messages
  127. self.bot.version = BOT_VERSION
  128. self.logger.info("📊 Checking statistics persistence...")
  129. self.check_stats_persistence()
  130. self.logger.info("🚀 Starting Telegram bot...")
  131. # Run the bot
  132. await self.bot.run()
  133. except KeyboardInterrupt:
  134. self.logger.info("👋 Bot stopped by user (Ctrl+C)")
  135. is_shutting_down = True
  136. except Exception as e:
  137. self.logger.error(f"❌ Bot error: {e}")
  138. raise
  139. async def start(self):
  140. """Main entry point."""
  141. try:
  142. self.print_banner()
  143. if not self.validate_configuration():
  144. return False
  145. self.logger.info("🎯 All systems ready - starting trading bot...")
  146. print("💡 Send /start to your Telegram bot for quick actions")
  147. print("🛑 Press Ctrl+C to stop\n")
  148. await self.run_bot()
  149. return True
  150. except Exception as e:
  151. self.logger.error(f"❌ Fatal error in bot manager: {e}")
  152. print(f"\n💥 Fatal error: {e}")
  153. return False
  154. def signal_handler(signum, frame):
  155. """Handle shutdown signals gracefully."""
  156. global is_shutting_down, bot_instance
  157. print("\n🛑 Shutdown signal received...")
  158. is_shutting_down = True
  159. def main():
  160. """Main function."""
  161. global bot_instance
  162. # Set up signal handlers for graceful shutdown
  163. signal.signal(signal.SIGINT, signal_handler)
  164. signal.signal(signal.SIGTERM, signal_handler)
  165. try:
  166. bot_manager = BotManager()
  167. bot_instance = bot_manager
  168. # Run the bot
  169. success = asyncio.run(bot_manager.start())
  170. if success:
  171. print("\n✅ Bot session completed successfully")
  172. else:
  173. print("\n❌ Bot session failed")
  174. sys.exit(1)
  175. except KeyboardInterrupt:
  176. print("\n👋 Bot stopped by user")
  177. except Exception as e:
  178. print(f"\n💥 Unexpected error: {e}")
  179. sys.exit(1)
  180. finally:
  181. print("📊 Your trading statistics have been saved")
  182. if __name__ == "__main__":
  183. main()