|
@@ -23,27 +23,25 @@ from logging_config import setup_logging, cleanup_logs, format_log_stats
|
|
|
logger = setup_logging().getChild(__name__)
|
|
|
|
|
|
class TelegramTradingBot:
|
|
|
- """Telegram bot for manual trading with comprehensive statistics."""
|
|
|
+ """Telegram trading bot for manual trading operations."""
|
|
|
|
|
|
def __init__(self):
|
|
|
"""Initialize the Telegram trading bot."""
|
|
|
- self.client = HyperliquidClient(use_testnet=Config.HYPERLIQUID_TESTNET)
|
|
|
- self.stats = TradingStats()
|
|
|
- self.alarm_manager = AlarmManager()
|
|
|
- self.authorized_chat_id = Config.TELEGRAM_CHAT_ID
|
|
|
+ self.client = HyperliquidClient()
|
|
|
self.application = None
|
|
|
-
|
|
|
- # Order monitoring
|
|
|
- self.monitoring_active = False
|
|
|
- self.last_known_orders = set() # Track order IDs we've seen
|
|
|
- self.last_known_positions = {} # Track position sizes for P&L calculation
|
|
|
-
|
|
|
- # External trade monitoring
|
|
|
- self.last_processed_trade_time = None # Track last processed external trade
|
|
|
-
|
|
|
- # Initialize stats with current balance
|
|
|
+ self.order_monitoring_task = None
|
|
|
+ self.last_filled_orders = set()
|
|
|
+ self.alarms = [] # List to store price alarms
|
|
|
+ self.bot_heartbeat_seconds = getattr(Config, 'BOT_HEARTBEAT_SECONDS', 10)
|
|
|
+ self.external_trade_timestamps = set() # Track external trade timestamps to avoid duplicates
|
|
|
+ self.last_position_check = {} # Track last position state for comparison
|
|
|
+ self._position_tracker = {} # For enhanced position tracking
|
|
|
+ self.stats = None
|
|
|
+ self.version = "Unknown" # Will be set by launcher
|
|
|
+
|
|
|
+ # Initialize stats
|
|
|
self._initialize_stats()
|
|
|
-
|
|
|
+
|
|
|
def _initialize_stats(self):
|
|
|
"""Initialize stats with current balance."""
|
|
|
try:
|
|
@@ -54,10 +52,10 @@ class TelegramTradingBot:
|
|
|
self.stats.set_initial_balance(usdc_balance)
|
|
|
except Exception as e:
|
|
|
logger.error(f"Could not initialize stats: {e}")
|
|
|
-
|
|
|
+
|
|
|
def is_authorized(self, chat_id: str) -> bool:
|
|
|
"""Check if the chat ID is authorized to use the bot."""
|
|
|
- return str(chat_id) == str(self.authorized_chat_id)
|
|
|
+ return str(chat_id) == str(Config.TELEGRAM_CHAT_ID)
|
|
|
|
|
|
async def send_message(self, text: str, parse_mode: str = 'HTML') -> None:
|
|
|
"""Send a message to the authorized chat."""
|
|
@@ -77,54 +75,44 @@ class TelegramTradingBot:
|
|
|
await update.message.reply_text("❌ Unauthorized access.")
|
|
|
return
|
|
|
|
|
|
- welcome_text = """
|
|
|
-🤖 <b>Hyperliquid Manual Trading Bot</b>
|
|
|
+ welcome_text = f"""
|
|
|
+🤖 <b>Welcome to Hyperliquid Trading Bot</b>
|
|
|
|
|
|
-Welcome to your personal trading assistant! Control your Hyperliquid account directly from your phone.
|
|
|
+📱 <b>Quick Actions:</b>
|
|
|
+• Trading: /long BTC 100 or /short ETH 50
|
|
|
+• Exit: /exit BTC (closes position)
|
|
|
+• Info: /balance, /positions, /orders
|
|
|
|
|
|
-<b>📱 Quick Actions:</b>
|
|
|
-Tap the buttons below for instant access to key functions.
|
|
|
+📊 <b>Market Data:</b>
|
|
|
+• /market - Detailed market overview
|
|
|
+• /price - Quick price check
|
|
|
|
|
|
-<b>💼 Account Commands:</b>
|
|
|
-/balance - Account balance
|
|
|
-/positions - Open positions
|
|
|
-/orders - Open orders
|
|
|
-/stats - Trading statistics
|
|
|
+<b>⚡ Quick Commands:</b>
|
|
|
+• /balance - Account balance
|
|
|
+• /positions - Open positions
|
|
|
+• /orders - Active orders
|
|
|
+• /market - Market data & prices
|
|
|
|
|
|
-<b>📊 Market Commands:</b>
|
|
|
-/market - Market data (default token)
|
|
|
-/market SOL - Market data for SOL
|
|
|
-/price - Current price (default token)
|
|
|
-/price BTC - Price for BTC
|
|
|
-
|
|
|
-<b>🚀 Perps Trading:</b>
|
|
|
-• /long BTC 100 - Long BTC with $100 USDC (Market Order)
|
|
|
-• /long BTC 100 45000 - Long BTC with $100 USDC at $45,000 (Limit Order)
|
|
|
-• /short ETH 50 - Short ETH with $50 USDC (Market Order)
|
|
|
-• /short ETH 50 3500 - Short ETH with $50 USDC at $3,500 (Limit Order)
|
|
|
-• /exit BTC - Close BTC position with Market Order
|
|
|
+<b>🚀 Trading:</b>
|
|
|
+• /long BTC 100 - Long position
|
|
|
+• /short ETH 50 - Short position
|
|
|
+• /exit BTC - Close position
|
|
|
+• /coo BTC - Cancel open orders
|
|
|
|
|
|
<b>🛡️ Risk Management:</b>
|
|
|
-• /sl BTC 44000 - Set stop loss for BTC at $44,000
|
|
|
-• /tp BTC 50000 - Set take profit for BTC at $50,000
|
|
|
-
|
|
|
-<b>🚨 Automatic Stop Loss:</b>
|
|
|
• Enabled: {risk_enabled}
|
|
|
-• Stop Loss: {stop_loss}% (automatic execution)
|
|
|
-• Monitoring: Every {heartbeat} seconds
|
|
|
+• Auto Stop Loss: {stop_loss}%
|
|
|
+• /sl BTC 44000 - Manual stop loss
|
|
|
+• /tp BTC 50000 - Take profit order
|
|
|
|
|
|
-<b>📋 Order Management:</b>
|
|
|
-• /orders - Show all open orders
|
|
|
-• /orders BTC - Show open orders for BTC only
|
|
|
-• /coo BTC - Cancel all open orders for BTC
|
|
|
-
|
|
|
-<b>📈 Statistics & Analytics:</b>
|
|
|
+<b>📈 Performance & Analytics:</b>
|
|
|
• /stats - Complete trading statistics
|
|
|
• /performance - Token performance ranking & detailed stats
|
|
|
• /daily - Daily performance (last 10 days)
|
|
|
• /weekly - Weekly performance (last 10 weeks)
|
|
|
• /monthly - Monthly performance (last 10 months)
|
|
|
• /risk - Sharpe ratio, drawdown, VaR
|
|
|
+• /version - Bot version & system information
|
|
|
• /trades - Recent trade history
|
|
|
|
|
|
<b>🔔 Price Alerts:</b>
|
|
@@ -251,6 +239,7 @@ For support, contact your bot administrator.
|
|
|
• /stats - Complete trading statistics
|
|
|
• /performance - Win rate, profit factor, etc.
|
|
|
• /risk - Sharpe ratio, drawdown, VaR
|
|
|
+• /version - Bot version & system information
|
|
|
• /trades - Recent trade history
|
|
|
|
|
|
<b>🔔 Price Alerts:</b>
|
|
@@ -1167,6 +1156,7 @@ Tap any button below for instant access to bot functions:
|
|
|
self.application.add_handler(CommandHandler("weekly", self.weekly_command))
|
|
|
self.application.add_handler(CommandHandler("monthly", self.monthly_command))
|
|
|
self.application.add_handler(CommandHandler("risk", self.risk_command))
|
|
|
+ self.application.add_handler(CommandHandler("version", self.version_command))
|
|
|
|
|
|
# Callback query handler for inline keyboards
|
|
|
self.application.add_handler(CallbackQueryHandler(self.button_callback))
|
|
@@ -1198,7 +1188,7 @@ Tap any button below for instant access to bot functions:
|
|
|
|
|
|
# Send startup notification
|
|
|
await self.send_message(
|
|
|
- "🤖 <b>Manual Trading Bot Started</b>\n\n"
|
|
|
+ f"🤖 <b>Manual Trading Bot v{self.version} Started</b>\n\n"
|
|
|
f"✅ Connected to Hyperliquid {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}\n"
|
|
|
f"📊 Default Symbol: {Config.DEFAULT_TRADING_TOKEN}\n"
|
|
|
f"📱 Manual trading ready!\n"
|
|
@@ -2982,6 +2972,72 @@ Will trigger when {token} price moves {alarm['direction']} ${target_price:,.2f}
|
|
|
error_message = f"❌ Error processing risk command: {str(e)}"
|
|
|
await update.message.reply_text(error_message)
|
|
|
logger.error(f"Error in risk command: {e}")
|
|
|
+
|
|
|
+ async def version_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
|
|
|
+ """Handle the /version command to show bot version and system info."""
|
|
|
+ if not self.is_authorized(update.effective_chat.id):
|
|
|
+ await update.message.reply_text("❌ Unauthorized access.")
|
|
|
+ return
|
|
|
+
|
|
|
+ try:
|
|
|
+ # Get system info
|
|
|
+ import platform
|
|
|
+ import sys
|
|
|
+ from datetime import datetime
|
|
|
+
|
|
|
+ uptime_info = "Unknown"
|
|
|
+ try:
|
|
|
+ # Try to get process uptime if available
|
|
|
+ import psutil
|
|
|
+ process = psutil.Process()
|
|
|
+ create_time = datetime.fromtimestamp(process.create_time())
|
|
|
+ uptime = datetime.now() - create_time
|
|
|
+ days = uptime.days
|
|
|
+ hours, remainder = divmod(uptime.seconds, 3600)
|
|
|
+ minutes, _ = divmod(remainder, 60)
|
|
|
+ uptime_info = f"{days}d {hours}h {minutes}m"
|
|
|
+ except ImportError:
|
|
|
+ # psutil not available, skip uptime
|
|
|
+ pass
|
|
|
+
|
|
|
+ # Get stats info
|
|
|
+ basic_stats = self.stats.get_basic_stats()
|
|
|
+
|
|
|
+ version_text = f"""
|
|
|
+🤖 <b>Trading Bot Version & System Info</b>
|
|
|
+
|
|
|
+📱 <b>Bot Information:</b>
|
|
|
+• Version: <code>{self.version}</code>
|
|
|
+• Network: {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}
|
|
|
+• Uptime: {uptime_info}
|
|
|
+• Default Token: {Config.DEFAULT_TRADING_TOKEN}
|
|
|
+
|
|
|
+💻 <b>System Information:</b>
|
|
|
+• Python: {sys.version.split()[0]}
|
|
|
+• Platform: {platform.system()} {platform.release()}
|
|
|
+• Architecture: {platform.machine()}
|
|
|
+
|
|
|
+📊 <b>Trading Stats:</b>
|
|
|
+• Total Orders: {basic_stats['total_trades']}
|
|
|
+• Completed Trades: {basic_stats['completed_trades']}
|
|
|
+• Days Active: {basic_stats['days_active']}
|
|
|
+• Start Date: {basic_stats['start_date']}
|
|
|
+
|
|
|
+🔄 <b>Monitoring Status:</b>
|
|
|
+• Order Monitoring: {'✅ Active' if self.order_monitoring_task and not self.order_monitoring_task.done() else '❌ Inactive'}
|
|
|
+• External Trades: ✅ Active
|
|
|
+• Price Alarms: ✅ Active ({len(self.alarms)} active)
|
|
|
+• Risk Management: {'✅ Enabled' if Config.RISK_MANAGEMENT_ENABLED else '❌ Disabled'}
|
|
|
+
|
|
|
+⏰ <b>Current Time:</b> {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}
|
|
|
+ """
|
|
|
+
|
|
|
+ await update.message.reply_text(version_text.strip(), parse_mode='HTML')
|
|
|
+
|
|
|
+ except Exception as e:
|
|
|
+ error_message = f"❌ Error processing version command: {str(e)}"
|
|
|
+ await update.message.reply_text(error_message)
|
|
|
+ logger.error(f"Error in version command: {e}")
|
|
|
|
|
|
def _get_position_state(self, symbol: str) -> Dict[str, Any]:
|
|
|
"""Get current position state for a symbol."""
|