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()