瀏覽代碼

Remove Telegram bot implementation - The telegram_bot.py file has been deleted as part of a refactor to streamline the codebase. This change eliminates the previous bot implementation, paving the way for a new architecture.

Carles Sentis 5 天之前
父節點
當前提交
f8db740389

+ 664 - 21
docs/commands.md

@@ -13,6 +13,9 @@ The most important commands to get started:
 /sl BTC 9000 # Set stop loss at $9,000
 /tp BTC 11000 # Set take profit at $11,000
 /monitoring  # Check order monitoring status
+/performance # Token performance ranking
+/daily       # Daily performance (last 10 days)
+/alarm BTC 50000 # Set price alert for BTC at $50,000
 /help        # Full command reference
 ```
 
@@ -53,7 +56,7 @@ Show your current account balance and P&L summary with detailed breakdown of ava
 ```
 
 ### `/positions`
-Display all open positions with unrealized P&L.
+Display all open positions with unrealized P&L and percentages.
 
 **Example:**
 ```
@@ -64,12 +67,21 @@ Display all open positions with unrealized P&L.
 ```
 📈 Open Positions
 
-📊 BTC/USDC:USDC
-   📏 Size: 0.001 contracts
+📊 BTC (LONG)
+   📏 Size: 0.001000 BTC
    💰 Entry: $45,230.50
-   🟢 PnL: $15.25
+   💵 Value: $45.23
+   🟢 P&L: $1.84 (+4.07%)
 
-💼 Total Unrealized P&L: $15.25
+📊 ETH (SHORT)
+   📏 Size: 0.010000 ETH
+   💰 Entry: $3,200.00
+   💵 Value: $32.00
+   🔴 P&L: -$0.75 (-2.34%)
+
+💼 Total Portfolio:
+   💵 Total Value: $77.23
+   🟢 Total P&L: $1.09 (+1.43%)
 ```
 
 ### `/orders [token (optional)]`
@@ -224,9 +236,197 @@ Complete trading statistics and performance metrics.
 • Max Drawdown: 8.5%
 • Volatility: 12.3%
 • VaR (95%): 3.2%
+
+🎯 Best/Worst
+• Largest Win: $125.50
+• Largest Loss: $45.25
+• Max Consecutive Wins: 5
+• Max Consecutive Losses: 2
+
+📅 Since: 2024-01-15
+```
+
+## 📈 Performance Analytics
+
+### `/performance [token (optional)]`
+Show token performance ranking or detailed stats for a specific token.
+
+**Usage:**
+```
+/performance         # Show all token rankings
+/performance <TOKEN> # Detailed stats for specific token
+```
+
+**Examples:**
+```
+/performance       # Token performance ranking
+/performance BTC   # Detailed Bitcoin performance
+/performance ETH   # Detailed Ethereum performance
+```
+
+**Response (Ranking):**
+```
+🏆 Token Performance Ranking
+
+🥇 BTC
+   🟢 P&L: $245.50 (+12.3%)
+   📊 Trades: 15 | Win: 73%
+
+🥈 ETH
+   🟢 P&L: $125.75 (+8.9%)
+   📊 Trades: 12 | Win: 67%
+
+🥉 SOL
+   🔴 P&L: -$25.00 (-2.1%)
+   📊 Trades: 8 | Win: 38%
+
+💼 Portfolio Summary:
+   🟢 Total P&L: $346.25
+   📈 Tokens Traded: 3
+   🔄 Completed Trades: 35
+
+💡 Usage: /performance BTC for detailed BTC stats
+```
+
+**Response (Detailed):**
+```
+📊 BTC Detailed Performance
+
+💰 P&L Summary:
+• 🟢 Total P&L: $245.50 (+12.3%)
+• 💵 Total Volume: $2,150.00
+• 📈 Expectancy: $16.37
+
+📊 Trading Activity:
+• Total Trades: 20
+• Completed: 15
+• Buy Orders: 11
+• Sell Orders: 9
+
+🏆 Performance Metrics:
+• Win Rate: 73.3%
+• Profit Factor: 2.85
+• Wins: 11 | Losses: 4
+
+💡 Best/Worst:
+• Largest Win: $85.50
+• Largest Loss: $35.25
+• Avg Win: $32.50
+• Avg Loss: $18.75
+
+🔄 Recent Trades:
+• 🔴 SELL $450 @ 12/15 14:30 | P&L: $25.50
+• 🟢 BUY $425 @ 12/14 09:15
+• 🔴 SELL $380 @ 12/13 16:45 | P&L: $15.25
+
+🔄 Use /performance to see all token rankings
+```
+
+### `/daily`
+Show daily performance breakdown for the last 10 days.
+
+**Example:**
+```
+/daily
+```
+
+**Response:**
+```
+📅 Daily Performance (Last 10 Days)
+
+📊 Dec 15, 2024
+   🟢 P&L: $45.25 (+2.1%)
+   🔄 Trades: 3
+
+📊 Dec 14, 2024
+   🔴 P&L: -$15.50 (-0.7%)
+   🔄 Trades: 2
+
+📊 Dec 13, 2024
+   🟢 P&L: $85.75 (+4.2%)
+   🔄 Trades: 5
+
+📊 Dec 12, 2024
+   🟢 P&L: $12.00 (+0.6%)
+   🔄 Trades: 1
+
+📊 Dec 11, 2024
+   🟢 P&L: $25.50 (+1.3%)
+   🔄 Trades: 2
+
+💼 10-Day Summary:
+   🟢 Total P&L: $153.00
+   🔄 Total Trades: 13
+   📊 Avg per Day: $15.30
+```
+
+### `/weekly`
+Show weekly performance breakdown for the last 10 weeks.
+
+**Example:**
+```
+/weekly
+```
+
+**Response:**
+```
+📊 Weekly Performance (Last 10 Weeks)
+
+📈 Week Dec 9-15, 2024
+   🟢 P&L: $125.50 (+5.8%)
+   🔄 Trades: 8
+
+📈 Week Dec 2-8, 2024
+   🟢 P&L: $85.25 (+4.1%)
+   🔄 Trades: 6
+
+📈 Week Nov 25-Dec 1, 2024
+   🔴 P&L: -$25.75 (-1.2%)
+   🔄 Trades: 4
+
+📈 Week Nov 18-24, 2024
+   🟢 P&L: $45.00 (+2.3%)
+   🔄 Trades: 3
+
+💼 10-Week Summary:
+   🟢 Total P&L: $230.00
+   🔄 Total Trades: 21
+   📊 Avg per Week: $23.00
+```
+
+### `/monthly`
+Show monthly performance breakdown for the last 10 months.
+
+**Example:**
+```
+/monthly
+```
+
+**Response:**
 ```
+📆 Monthly Performance (Last 10 Months)
+
+📅 December 2024
+   🟢 P&L: $245.50 (+11.2%)
+   🔄 Trades: 15
+
+📅 November 2024
+   🟢 P&L: $185.25 (+9.1%)
+   🔄 Trades: 12
 
-📊 Use /stats to view updated performance metrics.
+📅 October 2024
+   🔴 P&L: -$45.75 (-2.1%)
+   🔄 Trades: 8
+
+📅 September 2024
+   🟢 P&L: $125.00 (+6.5%)
+   🔄 Trades: 10
+
+💼 10-Month Summary:
+   🟢 Total P&L: $510.00
+   🔄 Total Trades: 45
+   📊 Avg per Month: $51.00
+```
 
 ## 🚀 Perps Trading
 
@@ -393,6 +593,8 @@ Close an open position using market order.
 • Order Type: Market Order
 
 ⚠️ Are you sure you want to close this LONG position?
+
+This will place a market sell order to close your entire BTC position.
 ```
 
 ## 🛡️ Risk Management
@@ -419,6 +621,29 @@ Set a stop loss order to limit downside risk.
 3. Places limit order at stop loss price
 4. Order executes automatically when price is reached
 
+**Confirmation Dialog:**
+```
+🛑 Stop Loss Order Confirmation
+
+📊 Position Details:
+• Token: BTC
+• Position: LONG
+• Size: 0.002211 contracts
+• Entry Price: $45,230.50
+• Current Price: $46,150.00
+
+🎯 Stop Loss Order:
+• Stop Price: $44,000.00
+• Action: SELL (Close LONG)
+• Amount: 0.002211 BTC
+• Order Type: Limit Order
+• 🔴 Est. P&L: -$272.15
+
+⚠️ Are you sure you want to set this stop loss?
+
+This will place a limit sell order at $44,000.00 to protect your LONG position.
+```
+
 ### `/tp [token] [price]`
 Set a take profit order to secure gains.
 
@@ -433,17 +658,250 @@ Set a take profit order to secure gains.
 /tp ETH 3800    # Take profit for Ethereum at $3,800
 ```
 
+**How it works:**
+1. Checks for existing position in the specified token
+2. Validates take profit price against position direction:
+   - **Long positions**: Take profit must be ABOVE entry price
+   - **Short positions**: Take profit must be BELOW entry price
+3. Places limit order at take profit price
+4. Order executes automatically when price is reached
+
+**Confirmation Dialog:**
+```
+🎯 Take Profit Order Confirmation
+
+📊 Position Details:
+• Token: BTC
+• Position: LONG
+• Size: 0.002211 contracts
+• Entry Price: $45,230.50
+• Current Price: $46,150.00
+
+💰 Take Profit Order:
+• Target Price: $50,000.00
+• Action: SELL (Close LONG)
+• Amount: 0.002211 BTC
+• Order Type: Limit Order
+• 🟢 Est. P&L: $1,054.35
+
+⚠️ Are you sure you want to set this take profit?
+
+This will place a limit sell order at $50,000.00 to capture profits from your LONG position.
+```
+
 ## 📊 Market Data
 
-### `/price`
-Quick price check for the default trading symbol.
+### `/price [token (optional)]`
+Quick price check for any token.
+
+**Usage:**
+```
+/price           # Default trading token price
+/price <TOKEN>   # Specific token price
+```
 
-### `/market`
+**Examples:**
+```
+/price       # Default token price
+/price BTC   # Bitcoin price
+/price ETH   # Ethereum price
+/price SOL   # Solana price
+```
+
+**Response:**
+```
+💵 BTC: $45,230.50
+⏰ Updated: 14:25:30
+💡 Usage: /price BTC or /price for default
+```
+
+### `/market [token (optional)]`
 Detailed market data with orderbook information.
 
+**Usage:**
+```
+/market           # Default trading token market data
+/market <TOKEN>   # Specific token market data
+```
+
+**Examples:**
+```
+/market       # Default token market data
+/market BTC   # Bitcoin market data
+/market ETH   # Ethereum market data
+```
+
+**Response:**
+```
+📊 Market Data - BTC
+
+💵 Current Price: $45,230.50
+📈 24h High: $46,850.00
+📉 24h Low: $44,120.00
+📊 24h Volume: 2,450.25
+
+🟢 Best Bid: $45,225.00
+🔴 Best Ask: $45,235.00
+📏 Spread: $10.00 (0.022%)
+
+💡 Usage: /market BTC or /market for default
+```
+
 ### `/trades`
 Recent trade history.
 
+**Example:**
+```
+/trades
+```
+
+**Response:**
+```
+🔄 Recent Trades
+
+🟢 BUY 0.002211 BTC/USDC:USDC
+   💰 $45,230.50 | 💵 $100.00
+   📅 12/15 14:25
+
+🔴 SELL 0.001850 ETH/USDC:USDC
+   💰 $3,200.00 | 💵 $59.20
+   📅 12/15 13:40
+
+🟢 BUY 0.008500 SOL/USDC:USDC
+   💰 $85.00 | 💵 $72.25
+   📅 12/15 12:15
+```
+
+## 🔔 Price Alerts
+
+### `/alarm [token] [price] OR [token] OR [alarm_id] OR (no args)`
+Comprehensive price alert system with multiple usage patterns.
+
+**Usage:**
+```
+/alarm                    # List all active alarms
+/alarm <TOKEN>            # List alarms for specific token
+/alarm <TOKEN> <PRICE>    # Set new alarm
+/alarm <ALARM_ID>         # Remove alarm by ID
+```
+
+**Examples:**
+```
+/alarm                # List all alarms
+/alarm BTC            # List Bitcoin alarms
+/alarm BTC 50000      # Set BTC alarm at $50,000
+/alarm ETH 3500       # Set ETH alarm at $3,500
+/alarm 3              # Remove alarm ID 3
+```
+
+**Set New Alarm:**
+```
+/alarm BTC 50000
+```
+
+**Response:**
+```
+✅ Price Alarm Created
+
+📊 Alarm Details:
+• Alarm ID: 5
+• Token: BTC
+• Target Price: $50,000.00
+• Current Price: $45,230.50
+• Direction: ABOVE
+
+📈 Alert Condition:
+Will trigger when BTC price moves above $50,000.00
+
+💰 Price Difference:
+• Distance: $4,769.50 (10.55%)
+• Status: ACTIVE ✅
+
+⏰ Created: 14:25:30
+
+💡 The alarm will be checked every 30 seconds and you'll receive a notification when triggered.
+```
+
+**List All Alarms:**
+```
+/alarm
+```
+
+**Response:**
+```
+🔔 Active Price Alarms (5 total)
+
+🚨 Alarm #1: BTC
+• Target: $50,000.00 (ABOVE)
+• Current: $45,230.50
+• Distance: $4,769.50 (10.55%)
+
+🚨 Alarm #2: ETH  
+• Target: $3,500.00 (ABOVE)
+• Current: $3,200.00
+• Distance: $300.00 (9.38%)
+
+🚨 Alarm #3: BTC
+• Target: $44,000.00 (BELOW)
+• Current: $45,230.50
+• Distance: $1,230.50 (2.72%)
+
+💡 Usage:
+• /alarm BTC - Show BTC alarms only
+• /alarm BTC 52000 - Set new BTC alarm
+• /alarm 3 - Remove alarm ID 3
+```
+
+**List Token Alarms:**
+```
+/alarm BTC
+```
+
+**Response:**
+```
+🔔 BTC Price Alarms (2 total)
+
+🚨 Alarm #1: BTC
+• Target: $50,000.00 (ABOVE)
+• Current: $45,230.50
+• Distance: $4,769.50 (10.55%)
+
+🚨 Alarm #3: BTC
+• Target: $44,000.00 (BELOW)
+• Current: $45,230.50
+• Distance: $1,230.50 (2.72%)
+
+💡 Set new: /alarm BTC 52000
+💡 Remove: /alarm 1 or /alarm 3
+```
+
+**Alarm Triggered Notification:**
+```
+🚨 PRICE ALARM TRIGGERED! 🚨
+
+📊 Alarm Details:
+• Token: BTC
+• Target Price: $50,000.00
+• Current Price: $50,125.50
+• Direction: ABOVE
+
+✅ Condition Met: BTC moved ABOVE $50,000.00
+⏰ Triggered: 16:45:22
+🎯 Alarm ID: 1 (automatically removed)
+
+💡 Price has increased by $4,895.00 (+10.82%) since alarm was set.
+```
+
+**Remove Alarm:**
+```
+/alarm 3
+```
+
+**Response:**
+```
+✅ Alarm ID 3 has been removed.
+```
+
 ## 🔄 Order Monitoring & Notifications
 
 The bot automatically monitors your orders and positions every 30 seconds and sends real-time notifications when orders are filled.
@@ -463,6 +921,8 @@ The bot automatically monitors your orders and positions every 30 seconds and se
 
 ✅ Status: New LONG position opened
 ⏰ Time: 14:25:30
+
+📱 Use /positions to view all positions
 ```
 
 **🎯 Position Closed Notifications**
@@ -483,10 +943,50 @@ The bot automatically monitors your orders and positions every 30 seconds and se
 
 ✅ Status: Position fully closed
 ⏰ Time: 16:45:22
+
+📊 Use /stats to view updated performance
+```
+
+**📉 Partial Position Closed**
+```
+📉 Position Partially Closed
+
+📊 Partial Close Details:
+• Token: BTC
+• Direction: LONG
+• Closed Size: 0.001 contracts
+• Entry Price: $45,230.50
+• Exit Price: $46,150.00
+
+🟢 Partial P&L:
+• P&L: $0.92 (+2.04%)
+
+✅ Status: Partial position closed
+⏰ Time: 15:30:15
+
+📈 Use /positions to view remaining position
+```
+
+**🔄 External Trade Detection**
+```
+🔄 External Trade Detected
+
+📊 Trade Details:
+• Token: ETH
+• Side: BUY
+• Amount: 0.015 ETH
+• Price: $3,200.00
+• Value: $48.00
+
+🟢 Source: Direct Platform Trade
+⏰ Time: 14:35:20
+
+📈 Note: This trade was executed outside the Telegram bot
+📊 Stats have been automatically updated
 ```
 
 ### `/monitoring`
-Check the status of order monitoring system.
+Check the status of all monitoring systems.
 
 **Example:**
 ```
@@ -495,19 +995,120 @@ Check the status of order monitoring system.
 
 **Response:**
 ```
-🔄 Order Monitoring Status
+🔄 System Monitoring Status
 
-📊 Current Status:
+📊 Order Monitoring:
 • Active: ✅ Yes
 • Check Interval: 30 seconds
 • Orders Tracked: 3
 • Positions Tracked: 2
 
+🔔 Price Alarms:
+• Active Alarms: 5
+• Triggered Today: 2
+• Tokens Monitored: 3
+• Next Alarm ID: 6
+
+🔄 External Trade Monitoring:
+• Last Check: 2024-12-15 14:25:30
+• Auto Stats Update: ✅ Enabled
+• External Notifications: ✅ Enabled
+
+🛡️ Risk Management:
+• Automatic Stop Loss: ❌ Disabled
+• Stop Loss Threshold: 5.0%
+• Position Monitoring: ❌ Inactive
+
 📈 Notifications:
-• 🚀 Position Opened
-• 📈 Position Increased
-• 📉 Position Partially Closed
-• 🎯 Position Closed (with P&L)
+• 🚀 Position Opened/Increased
+• 📉 Position Partially/Fully Closed
+• 🎯 P&L Calculations
+• 🔔 Price Alarm Triggers
+• 🔄 External Trade Detection
+• 🛑 Automatic Stop Loss Triggers
+
+⏰ Last Check: 14:25:30
+
+💡 Monitoring Features:
+• Real-time order fill detection
+• Automatic P&L calculation
+• Position change tracking
+• Price alarm monitoring
+• External trade monitoring
+• Auto stats synchronization
+• Instant Telegram notifications
+
+📋 Active Alarms by Token:
+• BTC: 2 alarms
+• ETH: 2 alarms
+• SOL: 1 alarm
+```
+
+## 🗂️ System Management
+
+### `/logs [cleanup] [days (optional)]`
+View log file statistics and manage log cleanup.
+
+**Usage:**
+```
+/logs                    # Show log statistics
+/logs cleanup            # Clean logs older than 30 days (default)
+/logs cleanup <DAYS>     # Clean logs older than specified days
+```
+
+**Examples:**
+```
+/logs               # View log stats
+/logs cleanup       # Clean old logs (30 days)
+/logs cleanup 7     # Clean logs older than 7 days
+```
+
+**Log Statistics:**
+```
+📊 System Logging Status
+
+📁 Current Log Files:
+• Main Log: trading_bot_20241215.log (2.5 MB)
+• Error Log: bot_errors.log (0.8 MB)
+• Archive Files: 5 files (12.3 MB total)
+
+📈 Log Activity (Last 24h):
+• Total Entries: 2,450
+• Info: 2,180 (89%)
+• Warning: 195 (8%)
+• Error: 75 (3%)
+
+💾 Disk Usage:
+• Current Logs: 3.3 MB
+• Archive Logs: 12.3 MB
+• Total Usage: 15.6 MB
+
+📈 Log Configuration:
+• Log Level: INFO
+• Heartbeat Interval: 30s
+• Bot Uptime: 2024-12-15 14:25:30
+
+💡 Log Management:
+• /logs cleanup - Clean old logs (30 days)
+• /logs cleanup 7 - Clean logs older than 7 days
+• Log rotation happens automatically
+• Old backups are removed automatically
+
+🔧 Configuration:
+• Rotation Type: SIZE
+• Max Size: 10MB (size rotation)
+• Backup Count: 5
+```
+
+**Log Cleanup:**
+```
+/logs cleanup 7
+```
+
+**Response:**
+```
+🧹 Cleaning up log files older than 7 days...
+✅ Log cleanup completed!
 ```
 
 ## 💡 Pro Tips
@@ -516,7 +1117,9 @@ Check the status of order monitoring system.
 - Start small and test with small amounts first
 - Use confirmations and always review orders
 - Monitor positions regularly with `/positions`
-- Track performance with `/stats`
+- Track performance with `/stats` and `/performance`
+- Set up price alerts with `/alarm` for key levels
+- Review daily/weekly performance with `/daily` and `/weekly`
 
 ### **⚡ Quick Trading**
 ```bash
@@ -533,15 +1136,35 @@ Check the status of order monitoring system.
 /long BTC 100        # Open long
 /sl BTC 42000        # Stop loss 5% below
 /tp BTC 50000        # Take profit 10% above
+/alarm BTC 41000     # Emergency alert
+```
+
+### **📊 Performance Tracking**
+```bash
+/stats            # Overall performance
+/performance      # Token rankings
+/daily            # Daily breakdown
+/weekly           # Weekly trends
+/monthly          # Monthly analysis
+/performance BTC  # Detailed BTC stats
+```
+
+### **🔔 Alert Management**
+```bash
+/alarm BTC 50000     # Set upside alert
+/alarm BTC 40000     # Set downside alert
+/alarm               # Check all alarms
+/alarm BTC           # Check BTC alarms
+/alarm 3             # Remove alarm ID 3
 ```
 
 ### **📊 Monitoring**
 ```bash
 /balance          # Check account
-/stats            # Review performance
 /positions        # Monitor open trades
-/monitoring       # Check order monitoring status
+/monitoring       # Check system status
 /orders           # All open orders
+/logs             # System health
 ```
 
 ## ⚠️ Important Notes
@@ -551,25 +1174,45 @@ Check the status of order monitoring system.
 - **Auto-notifications** for order fills
 - **Real-time monitoring** every 30 seconds
 - **Comprehensive logging** of all activities
+- **Price alerts** for key levels
+- **External trade detection** and sync
 
 ### **🔄 Order Monitoring**
 - **30-second intervals** for order fill detection
 - **Automatic P&L calculation** for closed positions
 - **Position change tracking** (opens, closes, increases)
 - **Instant Telegram notifications** for all fills
+- **External trade monitoring** and sync
+
+### **📈 Performance Analytics**
+- **Token-level performance tracking** with rankings
+- **Period-based analysis** (daily/weekly/monthly)
+- **Comprehensive statistics** with risk metrics
+- **Real-time P&L calculations** with percentages
+- **Trade history** and pattern analysis
+
+### **🔔 Alert System**
+- **Price alerts** with automatic monitoring
+- **Customizable thresholds** for any token
+- **Direction-based triggers** (above/below)
+- **Automatic removal** after trigger
+- **Multi-token support** with unlimited alerts
 
 ### **📱 Mobile Optimized**
 - **One-tap buttons** for quick actions
 - **Clean formatting** for mobile screens
 - **Instant notifications** for trade results
 - **Real-time order fill alerts**
+- **Comprehensive emoji indicators**
 
 ## 🚀 Getting Started
 
-1. **Configure**: Set up your `.env` file
+1. **Configure**: Set up your `.env` file with API keys
 2. **Test**: Start with `/balance` and `/price`
 3. **Trade**: Try `/long BTC 10` for a small market order
 4. **Monitor**: Use `/monitoring` to check auto-notifications
-5. **Track**: Use `/positions` and `/stats`
+5. **Track**: Use `/positions`, `/stats`, and `/performance`
+6. **Alerts**: Set up `/alarm BTC 50000` for price notifications
+7. **Analyze**: Review `/daily`, `/weekly` performance
 
 **Happy trading! 📱💰**

+ 338 - 7
src/telegram_bot.py

@@ -119,9 +119,13 @@ Tap the buttons below for instant access to key functions.
 • /coo BTC - Cancel all open orders for BTC
 
 <b>📈 Statistics & Analytics:</b>
-/stats - Full trading statistics
-/performance - Performance metrics
-/risk - Risk analysis
+• /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
+• /trades - Recent trade history
 
 <b>🔔 Price Alerts:</b>
 • /alarm - List all alarms
@@ -401,22 +405,40 @@ For support, contact your bot administrator.
             
             if open_positions:
                 total_unrealized = 0
+                total_position_value = 0
+                
                 for position in open_positions:
                     symbol = position.get('symbol', 'Unknown')
                     contracts = float(position.get('contracts', 0))
                     unrealized_pnl = float(position.get('unrealizedPnl', 0))
                     entry_price = float(position.get('entryPx', 0))
                     
+                    # Calculate position value and P&L percentage
+                    position_value = abs(contracts) * entry_price
+                    pnl_percentage = (unrealized_pnl / position_value * 100) if position_value > 0 else 0
+                    
                     pnl_emoji = "🟢" if unrealized_pnl >= 0 else "🔴"
                     
-                    positions_text += f"📊 <b>{symbol}</b>\n"
-                    positions_text += f"   📏 Size: {contracts} contracts\n"
+                    # Extract token name for cleaner display
+                    token = symbol.split('/')[0] if '/' in symbol else symbol
+                    position_type = "LONG" if contracts > 0 else "SHORT"
+                    
+                    positions_text += f"📊 <b>{token}</b> ({position_type})\n"
+                    positions_text += f"   📏 Size: {abs(contracts):.6f} {token}\n"
                     positions_text += f"   💰 Entry: ${entry_price:,.2f}\n"
-                    positions_text += f"   {pnl_emoji} PnL: ${unrealized_pnl:,.2f}\n\n"
+                    positions_text += f"   💵 Value: ${position_value:,.2f}\n"
+                    positions_text += f"   {pnl_emoji} P&L: ${unrealized_pnl:,.2f} ({pnl_percentage:+.2f}%)\n\n"
                     
                     total_unrealized += unrealized_pnl
+                    total_position_value += position_value
                 
-                positions_text += f"💼 <b>Total Unrealized P&L:</b> ${total_unrealized:,.2f}"
+                # Calculate overall P&L percentage
+                total_pnl_percentage = (total_unrealized / total_position_value * 100) if total_position_value > 0 else 0
+                total_pnl_emoji = "🟢" if total_unrealized >= 0 else "🔴"
+                
+                positions_text += f"💼 <b>Total Portfolio:</b>\n"
+                positions_text += f"   💵 Total Value: ${total_position_value:,.2f}\n"
+                positions_text += f"   {total_pnl_emoji} Total P&L: ${total_unrealized:,.2f} ({total_pnl_percentage:+.2f}%)"
             else:
                 positions_text += "📭 <b>No open positions currently</b>\n\n"
                 positions_text += "🚀 Ready to start trading!\n"
@@ -1069,6 +1091,10 @@ For support, contact your bot administrator.
         self.application.add_handler(CommandHandler("monitoring", self.monitoring_command))
         self.application.add_handler(CommandHandler("alarm", self.alarm_command))
         self.application.add_handler(CommandHandler("logs", self.logs_command))
+        self.application.add_handler(CommandHandler("performance", self.performance_command))
+        self.application.add_handler(CommandHandler("daily", self.daily_command))
+        self.application.add_handler(CommandHandler("weekly", self.weekly_command))
+        self.application.add_handler(CommandHandler("monthly", self.monthly_command))
         
         # Callback query handler for inline keyboards
         self.application.add_handler(CallbackQueryHandler(self.button_callback))
@@ -2599,6 +2625,311 @@ Will trigger when {token} price moves {alarm['direction']} ${target_price:,.2f}
             await update.message.reply_text(error_message)
             logger.error(f"Error in logs command: {e}")
 
+    async def performance_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+        """Handle the /performance command to show token performance ranking or detailed stats."""
+        if not self.is_authorized(update.effective_chat.id):
+            await update.message.reply_text("❌ Unauthorized access.")
+            return
+        
+        try:
+            # Check if specific token is requested
+            if context.args and len(context.args) >= 1:
+                # Detailed performance for specific token
+                token = context.args[0].upper()
+                await self._show_token_performance(update, token)
+            else:
+                # Show token performance ranking
+                await self._show_performance_ranking(update)
+                
+        except Exception as e:
+            error_message = f"❌ Error processing performance command: {str(e)}"
+            await update.message.reply_text(error_message)
+            logger.error(f"Error in performance command: {e}")
+
+    async def _show_performance_ranking(self, update: Update):
+        """Show token performance ranking (compressed view)."""
+        token_performance = self.stats.get_token_performance()
+        
+        if not token_performance:
+            await update.message.reply_text(
+                "📊 <b>Token Performance</b>\n\n"
+                "📭 No trading data available yet.\n\n"
+                "💡 Performance tracking starts after your first completed trades.\n"
+                "Use /long or /short to start trading!",
+                parse_mode='HTML'
+            )
+            return
+        
+        # Sort tokens by total P&L (best to worst)
+        sorted_tokens = sorted(
+            token_performance.items(),
+            key=lambda x: x[1]['total_pnl'],
+            reverse=True
+        )
+        
+        performance_text = "🏆 <b>Token Performance Ranking</b>\n\n"
+        
+        # Add ranking with emojis
+        for i, (token, stats) in enumerate(sorted_tokens, 1):
+            # Ranking emoji
+            if i == 1:
+                rank_emoji = "🥇"
+            elif i == 2:
+                rank_emoji = "🥈"
+            elif i == 3:
+                rank_emoji = "🥉"
+            else:
+                rank_emoji = f"#{i}"
+            
+            # P&L emoji
+            pnl_emoji = "🟢" if stats['total_pnl'] >= 0 else "🔴"
+            
+            # Format the line
+            performance_text += f"{rank_emoji} <b>{token}</b>\n"
+            performance_text += f"   {pnl_emoji} P&L: ${stats['total_pnl']:,.2f} ({stats['pnl_percentage']:+.1f}%)\n"
+            performance_text += f"   📊 Trades: {stats['completed_trades']}"
+            
+            # Add win rate if there are completed trades
+            if stats['completed_trades'] > 0:
+                performance_text += f" | Win: {stats['win_rate']:.0f}%"
+            
+            performance_text += "\n\n"
+        
+        # Add summary
+        total_pnl = sum(stats['total_pnl'] for stats in token_performance.values())
+        total_trades = sum(stats['completed_trades'] for stats in token_performance.values())
+        total_pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
+        
+        performance_text += f"💼 <b>Portfolio Summary:</b>\n"
+        performance_text += f"   {total_pnl_emoji} Total P&L: ${total_pnl:,.2f}\n"
+        performance_text += f"   📈 Tokens Traded: {len(token_performance)}\n"
+        performance_text += f"   🔄 Completed Trades: {total_trades}\n\n"
+        
+        performance_text += f"💡 <b>Usage:</b> <code>/performance BTC</code> for detailed {Config.DEFAULT_TRADING_TOKEN} stats"
+        
+        await update.message.reply_text(performance_text.strip(), parse_mode='HTML')
+
+    async def _show_token_performance(self, update: Update, token: str):
+        """Show detailed performance for a specific token."""
+        token_stats = self.stats.get_token_detailed_stats(token)
+        
+        # Check if token has any data
+        if token_stats.get('total_trades', 0) == 0:
+            await update.message.reply_text(
+                f"📊 <b>{token} Performance</b>\n\n"
+                f"📭 No trading history found for {token}.\n\n"
+                f"💡 Start trading {token} with:\n"
+                f"• <code>/long {token} 100</code>\n"
+                f"• <code>/short {token} 100</code>\n\n"
+                f"🔄 Use <code>/performance</code> to see all token rankings.",
+                parse_mode='HTML'
+            )
+            return
+        
+        # Check if there's a message (no completed trades)
+        if 'message' in token_stats and token_stats.get('completed_trades', 0) == 0:
+            await update.message.reply_text(
+                f"📊 <b>{token} Performance</b>\n\n"
+                f"{token_stats['message']}\n\n"
+                f"📈 <b>Current Activity:</b>\n"
+                f"• Total Trades: {token_stats['total_trades']}\n"
+                f"• Buy Orders: {token_stats.get('buy_trades', 0)}\n"
+                f"• Sell Orders: {token_stats.get('sell_trades', 0)}\n"
+                f"• Volume: ${token_stats.get('total_volume', 0):,.2f}\n\n"
+                f"💡 Complete some trades to see P&L statistics!\n"
+                f"🔄 Use <code>/performance</code> to see all token rankings.",
+                parse_mode='HTML'
+            )
+            return
+        
+        # Detailed stats display
+        pnl_emoji = "🟢" if token_stats['total_pnl'] >= 0 else "🔴"
+        
+        performance_text = f"""
+📊 <b>{token} Detailed Performance</b>
+
+💰 <b>P&L Summary:</b>
+• {pnl_emoji} Total P&L: ${token_stats['total_pnl']:,.2f} ({token_stats['pnl_percentage']:+.2f}%)
+• 💵 Total Volume: ${token_stats['completed_volume']:,.2f}
+• 📈 Expectancy: ${token_stats['expectancy']:,.2f}
+
+📊 <b>Trading Activity:</b>
+• Total Trades: {token_stats['total_trades']}
+• Completed: {token_stats['completed_trades']}
+• Buy Orders: {token_stats['buy_trades']}
+• Sell Orders: {token_stats['sell_trades']}
+
+🏆 <b>Performance Metrics:</b>
+• Win Rate: {token_stats['win_rate']:.1f}%
+• Profit Factor: {token_stats['profit_factor']:.2f}
+• Wins: {token_stats['total_wins']} | Losses: {token_stats['total_losses']}
+
+💡 <b>Best/Worst:</b>
+• Largest Win: ${token_stats['largest_win']:,.2f}
+• Largest Loss: ${token_stats['largest_loss']:,.2f}
+• Avg Win: ${token_stats['avg_win']:,.2f}
+• Avg Loss: ${token_stats['avg_loss']:,.2f}
+        """
+        
+        # Add recent trades if available
+        if token_stats.get('recent_trades'):
+            performance_text += f"\n🔄 <b>Recent Trades:</b>\n"
+            for trade in token_stats['recent_trades'][-3:]:  # Last 3 trades
+                trade_time = datetime.fromisoformat(trade['timestamp']).strftime('%m/%d %H:%M')
+                side_emoji = "🟢" if trade['side'] == 'buy' else "🔴"
+                pnl_display = f" | P&L: ${trade.get('pnl', 0):.2f}" if trade.get('pnl', 0) != 0 else ""
+                
+                performance_text += f"• {side_emoji} {trade['side'].upper()} ${trade['value']:,.0f} @ {trade_time}{pnl_display}\n"
+        
+        performance_text += f"\n🔄 Use <code>/performance</code> to see all token rankings"
+        
+        await update.message.reply_text(performance_text.strip(), parse_mode='HTML')
+
+    async def daily_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+        """Handle the /daily command to show daily performance stats."""
+        if not self.is_authorized(update.effective_chat.id):
+            await update.message.reply_text("❌ Unauthorized access.")
+            return
+        
+        try:
+            daily_stats = self.stats.get_daily_stats(10)
+            
+            if not daily_stats:
+                await update.message.reply_text(
+                    "📅 <b>Daily Performance</b>\n\n"
+                    "📭 No daily performance data available yet.\n\n"
+                    "💡 Daily stats are calculated from completed trades.\n"
+                    "Start trading to see daily performance!",
+                    parse_mode='HTML'
+                )
+                return
+            
+            daily_text = "📅 <b>Daily Performance (Last 10 Days)</b>\n\n"
+            
+            total_pnl = 0
+            total_trades = 0
+            
+            for day_stats in daily_stats:
+                pnl_emoji = "🟢" if day_stats['pnl'] >= 0 else "🔴"
+                
+                daily_text += f"📊 <b>{day_stats['date_formatted']}</b>\n"
+                daily_text += f"   {pnl_emoji} P&L: ${day_stats['pnl']:,.2f} ({day_stats['pnl_pct']:+.1f}%)\n"
+                daily_text += f"   🔄 Trades: {day_stats['trades']}\n\n"
+                
+                total_pnl += day_stats['pnl']
+                total_trades += day_stats['trades']
+            
+            # Add summary
+            total_pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
+            daily_text += f"💼 <b>10-Day Summary:</b>\n"
+            daily_text += f"   {total_pnl_emoji} Total P&L: ${total_pnl:,.2f}\n"
+            daily_text += f"   🔄 Total Trades: {total_trades}\n"
+            daily_text += f"   📊 Avg per Day: ${total_pnl/len(daily_stats):,.2f}"
+            
+            await update.message.reply_text(daily_text.strip(), parse_mode='HTML')
+            
+        except Exception as e:
+            error_message = f"❌ Error processing daily command: {str(e)}"
+            await update.message.reply_text(error_message)
+            logger.error(f"Error in daily command: {e}")
+
+    async def weekly_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+        """Handle the /weekly command to show weekly performance stats."""
+        if not self.is_authorized(update.effective_chat.id):
+            await update.message.reply_text("❌ Unauthorized access.")
+            return
+        
+        try:
+            weekly_stats = self.stats.get_weekly_stats(10)
+            
+            if not weekly_stats:
+                await update.message.reply_text(
+                    "📊 <b>Weekly Performance</b>\n\n"
+                    "📭 No weekly performance data available yet.\n\n"
+                    "💡 Weekly stats are calculated from completed trades.\n"
+                    "Start trading to see weekly performance!",
+                    parse_mode='HTML'
+                )
+                return
+            
+            weekly_text = "📊 <b>Weekly Performance (Last 10 Weeks)</b>\n\n"
+            
+            total_pnl = 0
+            total_trades = 0
+            
+            for week_stats in weekly_stats:
+                pnl_emoji = "🟢" if week_stats['pnl'] >= 0 else "🔴"
+                
+                weekly_text += f"📈 <b>{week_stats['week_formatted']}</b>\n"
+                weekly_text += f"   {pnl_emoji} P&L: ${week_stats['pnl']:,.2f} ({week_stats['pnl_pct']:+.1f}%)\n"
+                weekly_text += f"   🔄 Trades: {week_stats['trades']}\n\n"
+                
+                total_pnl += week_stats['pnl']
+                total_trades += week_stats['trades']
+            
+            # Add summary
+            total_pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
+            weekly_text += f"💼 <b>10-Week Summary:</b>\n"
+            weekly_text += f"   {total_pnl_emoji} Total P&L: ${total_pnl:,.2f}\n"
+            weekly_text += f"   🔄 Total Trades: {total_trades}\n"
+            weekly_text += f"   📊 Avg per Week: ${total_pnl/len(weekly_stats):,.2f}"
+            
+            await update.message.reply_text(weekly_text.strip(), parse_mode='HTML')
+            
+        except Exception as e:
+            error_message = f"❌ Error processing weekly command: {str(e)}"
+            await update.message.reply_text(error_message)
+            logger.error(f"Error in weekly command: {e}")
+
+    async def monthly_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
+        """Handle the /monthly command to show monthly performance stats."""
+        if not self.is_authorized(update.effective_chat.id):
+            await update.message.reply_text("❌ Unauthorized access.")
+            return
+        
+        try:
+            monthly_stats = self.stats.get_monthly_stats(10)
+            
+            if not monthly_stats:
+                await update.message.reply_text(
+                    "📆 <b>Monthly Performance</b>\n\n"
+                    "📭 No monthly performance data available yet.\n\n"
+                    "💡 Monthly stats are calculated from completed trades.\n"
+                    "Start trading to see monthly performance!",
+                    parse_mode='HTML'
+                )
+                return
+            
+            monthly_text = "📆 <b>Monthly Performance (Last 10 Months)</b>\n\n"
+            
+            total_pnl = 0
+            total_trades = 0
+            
+            for month_stats in monthly_stats:
+                pnl_emoji = "🟢" if month_stats['pnl'] >= 0 else "🔴"
+                
+                monthly_text += f"📅 <b>{month_stats['month_formatted']}</b>\n"
+                monthly_text += f"   {pnl_emoji} P&L: ${month_stats['pnl']:,.2f} ({month_stats['pnl_pct']:+.1f}%)\n"
+                monthly_text += f"   🔄 Trades: {month_stats['trades']}\n\n"
+                
+                total_pnl += month_stats['pnl']
+                total_trades += month_stats['trades']
+            
+            # Add summary
+            total_pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
+            monthly_text += f"💼 <b>10-Month Summary:</b>\n"
+            monthly_text += f"   {total_pnl_emoji} Total P&L: ${total_pnl:,.2f}\n"
+            monthly_text += f"   🔄 Total Trades: {total_trades}\n"
+            monthly_text += f"   📊 Avg per Month: ${total_pnl/len(monthly_stats):,.2f}"
+            
+            await update.message.reply_text(monthly_text.strip(), parse_mode='HTML')
+            
+        except Exception as e:
+            error_message = f"❌ Error processing monthly command: {str(e)}"
+            await update.message.reply_text(error_message)
+            logger.error(f"Error in monthly command: {e}")
+
+
 async def main_async():
     """Async main entry point for the Telegram bot."""
     try:

+ 323 - 2
src/trading_stats.py

@@ -59,7 +59,10 @@ class TradingStats:
             'trades': [],
             'daily_balances': [],
             'last_update': datetime.now().isoformat(),
-            'manual_trades_only': True  # Flag to indicate manual trading
+            'manual_trades_only': True,  # Flag to indicate manual trading
+            'daily_stats': {},    # Daily aggregate stats {date: {trades: N, pnl: X, pnl_pct: Y}}
+            'weekly_stats': {},   # Weekly aggregate stats {week: {trades: N, pnl: X, pnl_pct: Y}}
+            'monthly_stats': {}   # Monthly aggregate stats {month: {trades: N, pnl: X, pnl_pct: Y}}
         }
         self._save_stats()
     
@@ -108,6 +111,11 @@ class TradingStats:
         
         self.data['trades'].append(trade)
         self.data['last_update'] = datetime.now().isoformat()
+        
+        # Update period stats if this is a sell order (position close)
+        if side.lower() == 'sell':
+            self._update_period_stats()
+        
         self._save_stats()
         
         logger.info(f"Recorded trade: {side} {amount} {symbol} @ ${price:.2f}")
@@ -425,4 +433,317 @@ class TradingStats:
     
     def get_recent_trades(self, limit: int = 10) -> List[Dict[str, Any]]:
         """Get recent trades."""
-        return self.data['trades'][-limit:] if self.data['trades'] else [] 
+        return self.data['trades'][-limit:] if self.data['trades'] else []
+
+    def get_token_performance(self) -> Dict[str, Dict[str, Any]]:
+        """Get performance statistics grouped by token."""
+        trades_with_pnl = self.calculate_trade_pnl()
+        
+        # Group trades by token
+        token_trades = {}
+        
+        for trade in trades_with_pnl:
+            symbol = trade['symbol']
+            token = symbol.split('/')[0] if '/' in symbol else symbol
+            
+            if token not in token_trades:
+                token_trades[token] = []
+            token_trades[token].append(trade)
+        
+        # Calculate performance for each token
+        token_performance = {}
+        
+        for token, trades in token_trades.items():
+            completed_trades = [t for t in trades if t.get('pnl', 0) != 0]
+            
+            if not completed_trades:
+                # Only opening trades, no P&L yet
+                total_trades = len(trades)
+                buy_trades = len([t for t in trades if t['side'] == 'buy'])
+                sell_trades = len([t for t in trades if t['side'] == 'sell'])
+                
+                token_performance[token] = {
+                    'total_pnl': 0.0,
+                    'pnl_percentage': 0.0,
+                    'total_trades': total_trades,
+                    'completed_trades': 0,
+                    'buy_trades': buy_trades,
+                    'sell_trades': sell_trades,
+                    'win_rate': 0.0,
+                    'avg_win': 0.0,
+                    'avg_loss': 0.0,
+                    'largest_win': 0.0,
+                    'largest_loss': 0.0,
+                    'total_volume': sum(t['value'] for t in trades),
+                    'profit_factor': 0.0,
+                    'total_wins': 0,
+                    'total_losses': 0
+                }
+                continue
+            
+            # Calculate metrics for completed trades
+            total_pnl = sum(t['pnl'] for t in completed_trades)
+            total_volume = sum(t['value'] for t in completed_trades)
+            pnl_percentage = (total_pnl / total_volume * 100) if total_volume > 0 else 0.0
+            
+            # Win/loss analysis
+            wins = [t['pnl'] for t in completed_trades if t['pnl'] > 0]
+            losses = [abs(t['pnl']) for t in completed_trades if t['pnl'] < 0]
+            
+            total_wins = len(wins)
+            total_losses = len(losses)
+            total_completed = total_wins + total_losses
+            
+            win_rate = (total_wins / total_completed * 100) if total_completed > 0 else 0
+            avg_win = sum(wins) / total_wins if wins else 0
+            avg_loss = sum(losses) / total_losses if losses else 0
+            largest_win = max(wins) if wins else 0
+            largest_loss = max(losses) if losses else 0
+            
+            total_profit = sum(wins) if wins else 0
+            total_loss_amount = sum(losses) if losses else 0
+            profit_factor = (total_profit / total_loss_amount) if total_loss_amount > 0 else float('inf') if total_profit > 0 else 0
+            
+            token_performance[token] = {
+                'total_pnl': total_pnl,
+                'pnl_percentage': pnl_percentage,
+                'total_trades': len(trades),
+                'completed_trades': total_completed,
+                'buy_trades': len([t for t in trades if t['side'] == 'buy']),
+                'sell_trades': len([t for t in trades if t['side'] == 'sell']),
+                'win_rate': win_rate,
+                'avg_win': avg_win,
+                'avg_loss': avg_loss,
+                'largest_win': largest_win,
+                'largest_loss': largest_loss,
+                'total_volume': total_volume,
+                'profit_factor': profit_factor,
+                'total_wins': total_wins,
+                'total_losses': total_losses
+            }
+        
+        return token_performance
+
+    def get_token_detailed_stats(self, token: str) -> Dict[str, Any]:
+        """Get detailed statistics for a specific token."""
+        trades_with_pnl = self.calculate_trade_pnl()
+        
+        # Filter trades for this token
+        token_trades = []
+        for trade in trades_with_pnl:
+            symbol = trade['symbol']
+            trade_token = symbol.split('/')[0] if '/' in symbol else symbol
+            if trade_token.upper() == token.upper():
+                token_trades.append(trade)
+        
+        if not token_trades:
+            return {
+                'token': token.upper(),
+                'total_trades': 0,
+                'total_pnl': 0.0,
+                'win_rate': 0.0,
+                'message': f"No trading history found for {token.upper()}"
+            }
+        
+        completed_trades = [t for t in token_trades if t.get('pnl', 0) != 0]
+        
+        # Basic trade info
+        total_trades = len(token_trades)
+        buy_trades = len([t for t in token_trades if t['side'] == 'buy'])
+        sell_trades = len([t for t in token_trades if t['side'] == 'sell'])
+        total_volume = sum(t['value'] for t in token_trades)
+        
+        if not completed_trades:
+            return {
+                'token': token.upper(),
+                'total_trades': total_trades,
+                'buy_trades': buy_trades,
+                'sell_trades': sell_trades,
+                'total_volume': total_volume,
+                'completed_trades': 0,
+                'total_pnl': 0.0,
+                'pnl_percentage': 0.0,
+                'win_rate': 0.0,
+                'message': f"{token.upper()} has open positions but no completed trades yet"
+            }
+        
+        # Performance calculations
+        total_pnl = sum(t['pnl'] for t in completed_trades)
+        completed_volume = sum(t['value'] for t in completed_trades)
+        pnl_percentage = (total_pnl / completed_volume * 100) if completed_volume > 0 else 0.0
+        
+        # Win/loss analysis
+        wins = [t['pnl'] for t in completed_trades if t['pnl'] > 0]
+        losses = [abs(t['pnl']) for t in completed_trades if t['pnl'] < 0]
+        
+        total_wins = len(wins)
+        total_losses = len(losses)
+        completed_count = total_wins + total_losses
+        
+        win_rate = (total_wins / completed_count * 100) if completed_count > 0 else 0
+        avg_win = sum(wins) / total_wins if wins else 0
+        avg_loss = sum(losses) / total_losses if losses else 0
+        largest_win = max(wins) if wins else 0
+        largest_loss = max(losses) if losses else 0
+        
+        total_profit = sum(wins) if wins else 0
+        total_loss_amount = sum(losses) if losses else 0
+        profit_factor = (total_profit / total_loss_amount) if total_loss_amount > 0 else float('inf') if total_profit > 0 else 0
+        expectancy = avg_win * (win_rate/100) - avg_loss * ((100-win_rate)/100)
+        
+        # Recent trades
+        recent_trades = token_trades[-5:]  # Last 5 trades
+        
+        return {
+            'token': token.upper(),
+            'total_trades': total_trades,
+            'completed_trades': completed_count,
+            'buy_trades': buy_trades,
+            'sell_trades': sell_trades,
+            'total_volume': total_volume,
+            'completed_volume': completed_volume,
+            'total_pnl': total_pnl,
+            'pnl_percentage': pnl_percentage,
+            'win_rate': win_rate,
+            'profit_factor': profit_factor,
+            'avg_win': avg_win,
+            'avg_loss': avg_loss,
+            'largest_win': largest_win,
+            'largest_loss': largest_loss,
+            'expectancy': expectancy,
+            'total_wins': total_wins,
+            'total_losses': total_losses,
+            'recent_trades': recent_trades
+        }
+
+    def _update_period_stats(self):
+        """Update daily, weekly, and monthly stats."""
+        # Recalculate all period stats from completed trades
+        trades_with_pnl = self.calculate_trade_pnl()
+        completed_trades = [t for t in trades_with_pnl if t.get('pnl', 0) != 0]
+        
+        # Reset period stats
+        self.data['daily_stats'] = {}
+        self.data['weekly_stats'] = {}
+        self.data['monthly_stats'] = {}
+        
+        # Group completed trades by periods and calculate stats
+        for trade in completed_trades:
+            timestamp = trade['timestamp']
+            pnl = trade['pnl']
+            value = trade['value']
+            
+            try:
+                trade_date = datetime.fromisoformat(timestamp)
+                
+                # Daily stats
+                day_key = trade_date.strftime('%Y-%m-%d')
+                if day_key not in self.data['daily_stats']:
+                    self.data['daily_stats'][day_key] = {'trades': 0, 'pnl': 0.0, 'volume': 0.0}
+                
+                self.data['daily_stats'][day_key]['trades'] += 1
+                self.data['daily_stats'][day_key]['pnl'] += pnl
+                self.data['daily_stats'][day_key]['volume'] += value
+                
+                # Weekly stats (ISO week)
+                week_key = trade_date.strftime('%Y-W%U')
+                if week_key not in self.data['weekly_stats']:
+                    self.data['weekly_stats'][week_key] = {'trades': 0, 'pnl': 0.0, 'volume': 0.0}
+                
+                self.data['weekly_stats'][week_key]['trades'] += 1
+                self.data['weekly_stats'][week_key]['pnl'] += pnl
+                self.data['weekly_stats'][week_key]['volume'] += value
+                
+                # Monthly stats
+                month_key = trade_date.strftime('%Y-%m')
+                if month_key not in self.data['monthly_stats']:
+                    self.data['monthly_stats'][month_key] = {'trades': 0, 'pnl': 0.0, 'volume': 0.0}
+                
+                self.data['monthly_stats'][month_key]['trades'] += 1
+                self.data['monthly_stats'][month_key]['pnl'] += pnl
+                self.data['monthly_stats'][month_key]['volume'] += value
+                
+            except (ValueError, TypeError):
+                # Skip trades with invalid timestamps
+                continue
+        
+        # Calculate percentages for all periods
+        for period_data in [self.data['daily_stats'], self.data['weekly_stats'], self.data['monthly_stats']]:
+            for period_key, stats in period_data.items():
+                if stats['volume'] > 0:
+                    stats['pnl_pct'] = (stats['pnl'] / stats['volume']) * 100
+                else:
+                    stats['pnl_pct'] = 0.0
+
+    def get_daily_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
+        """Get daily performance stats for the last N days."""
+        # Ensure period stats are up to date
+        self._update_period_stats()
+        
+        # Get sorted daily stats (most recent first)
+        daily_stats = []
+        for date_str, stats in sorted(self.data['daily_stats'].items(), reverse=True):
+            try:
+                date_obj = datetime.strptime(date_str, '%Y-%m-%d')
+                daily_stats.append({
+                    'date': date_str,
+                    'date_formatted': date_obj.strftime('%m/%d'),
+                    'trades': stats['trades'],
+                    'pnl': stats['pnl'],
+                    'pnl_pct': stats['pnl_pct'],
+                    'volume': stats['volume']
+                })
+            except ValueError:
+                continue
+        
+        return daily_stats[:limit]
+
+    def get_weekly_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
+        """Get weekly performance stats for the last N weeks."""
+        # Ensure period stats are up to date
+        self._update_period_stats()
+        
+        # Get sorted weekly stats (most recent first)
+        weekly_stats = []
+        for week_str, stats in sorted(self.data['weekly_stats'].items(), reverse=True):
+            try:
+                # Parse week format YYYY-WXX
+                year, week_num = week_str.split('-W')
+                week_start = datetime.strptime(f"{year}-W{week_num.zfill(2)}-1", "%Y-W%U-%w")
+                week_end = week_start + timedelta(days=6)
+                
+                weekly_stats.append({
+                    'week': week_str,
+                    'week_formatted': f"{week_start.strftime('%m/%d')}-{week_end.strftime('%m/%d')}",
+                    'trades': stats['trades'],
+                    'pnl': stats['pnl'],
+                    'pnl_pct': stats['pnl_pct'],
+                    'volume': stats['volume']
+                })
+            except (ValueError, IndexError):
+                continue
+        
+        return weekly_stats[:limit]
+
+    def get_monthly_stats(self, limit: int = 10) -> List[Dict[str, Any]]:
+        """Get monthly performance stats for the last N months."""
+        # Ensure period stats are up to date
+        self._update_period_stats()
+        
+        # Get sorted monthly stats (most recent first)
+        monthly_stats = []
+        for month_str, stats in sorted(self.data['monthly_stats'].items(), reverse=True):
+            try:
+                month_obj = datetime.strptime(month_str, '%Y-%m')
+                monthly_stats.append({
+                    'month': month_str,
+                    'month_formatted': month_obj.strftime('%b %Y'),
+                    'trades': stats['trades'],
+                    'pnl': stats['pnl'],
+                    'pnl_pct': stats['pnl_pct'],
+                    'volume': stats['volume']
+                })
+            except ValueError:
+                continue
+        
+        return monthly_stats[:limit] 

+ 0 - 703
telegram_bot.py

@@ -1,703 +0,0 @@
-#!/usr/bin/env python3
-"""
-Telegram Bot for Hyperliquid Trading
-
-This module provides a Telegram interface for manual Hyperliquid trading
-with comprehensive statistics tracking and phone-friendly controls.
-"""
-
-import logging
-import asyncio
-import re
-from datetime import datetime
-from typing import Optional, Dict, Any
-from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
-from telegram.ext import Application, CommandHandler, CallbackQueryHandler, ContextTypes, MessageHandler, filters
-from hyperliquid_client import HyperliquidClient
-from trading_stats import TradingStats
-from config import Config
-
-# Set up logging
-logging.basicConfig(
-    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
-    level=getattr(logging, Config.LOG_LEVEL)
-)
-logger = logging.getLogger(__name__)
-
-class TelegramTradingBot:
-    """Telegram bot for manual trading with comprehensive statistics."""
-    
-    def __init__(self):
-        """Initialize the Telegram trading bot."""
-        self.client = HyperliquidClient(use_testnet=Config.HYPERLIQUID_TESTNET)
-        self.stats = TradingStats()
-        self.authorized_chat_id = Config.TELEGRAM_CHAT_ID
-        self.application = None
-        
-        # Initialize stats with current balance
-        self._initialize_stats()
-        
-    def _initialize_stats(self):
-        """Initialize stats with current balance."""
-        try:
-            balance = self.client.get_balance()
-            if balance and balance.get('total'):
-                # Get USDC balance as the main balance
-                usdc_balance = float(balance['total'].get('USDC', 0))
-                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)
-    
-    async def send_message(self, text: str, parse_mode: str = 'HTML') -> None:
-        """Send a message to the authorized chat."""
-        if self.application and self.authorized_chat_id:
-            try:
-                await self.application.bot.send_message(
-                    chat_id=self.authorized_chat_id,
-                    text=text,
-                    parse_mode=parse_mode
-                )
-            except Exception as e:
-                logger.error(f"Failed to send message: {e}")
-    
-    async def start_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /start command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        welcome_text = """
-🤖 <b>Hyperliquid Manual Trading Bot</b>
-
-Welcome to your personal trading assistant! Control your Hyperliquid account directly from your phone.
-
-<b>📱 Quick Actions:</b>
-Tap the buttons below for instant access to key functions.
-
-<b>💼 Account Commands:</b>
-/balance - Account balance
-/positions - Open positions
-/orders - Open orders
-/stats - Trading statistics
-
-<b>📊 Market Commands:</b>
-/market - Market data
-/price - Current price
-
-<b>🔄 Trading Commands:</b>
-/buy [amount] [price] - Buy order
-/sell [amount] [price] - Sell order
-/trades - Recent trades
-/cancel [order_id] - Cancel order
-
-<b>📈 Statistics:</b>
-/stats - Full trading statistics
-/performance - Performance metrics
-/risk - Risk analysis
-
-Type /help for detailed command information.
-        """
-        
-        keyboard = [
-            [
-                InlineKeyboardButton("💰 Balance", callback_data="balance"),
-                InlineKeyboardButton("📊 Stats", callback_data="stats")
-            ],
-            [
-                InlineKeyboardButton("📈 Positions", callback_data="positions"),
-                InlineKeyboardButton("📋 Orders", callback_data="orders")
-            ],
-            [
-                InlineKeyboardButton("💵 Price", callback_data="price"),
-                InlineKeyboardButton("📊 Market", callback_data="market")
-            ],
-            [
-                InlineKeyboardButton("🔄 Recent Trades", callback_data="trades"),
-                InlineKeyboardButton("⚙️ Help", callback_data="help")
-            ]
-        ]
-        reply_markup = InlineKeyboardMarkup(keyboard)
-        
-        await update.message.reply_text(welcome_text, parse_mode='HTML', reply_markup=reply_markup)
-    
-    async def help_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /help command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        help_text = """
-🔧 <b>Hyperliquid Trading Bot - Complete Guide</b>
-
-<b>💼 Account Management:</b>
-• /balance - Show account balance
-• /positions - Show open positions  
-• /orders - Show open orders
-
-<b>📊 Market Data:</b>
-• /market - Detailed market data
-• /price - Quick price check
-
-<b>🔄 Manual Trading:</b>
-• /buy 0.001 50000 - Buy 0.001 BTC at $50,000
-• /sell 0.001 55000 - Sell 0.001 BTC at $55,000
-• /cancel ABC123 - Cancel order with ID ABC123
-
-<b>📈 Statistics & Analytics:</b>
-• /stats - Complete trading statistics
-• /performance - Win rate, profit factor, etc.
-• /risk - Sharpe ratio, drawdown, VaR
-• /trades - Recent trade history
-
-<b>⚙️ Configuration:</b>
-• Symbol: {symbol}
-• Default Amount: {amount}
-• Network: {network}
-
-<b>🛡️ Safety Features:</b>
-• All trades logged automatically
-• Comprehensive performance tracking
-• Real-time balance monitoring
-• Risk metrics calculation
-
-<b>📱 Mobile Optimized:</b>
-• Quick action buttons
-• Instant notifications
-• Clean, readable layout
-• One-tap commands
-
-For support, contact your bot administrator.
-        """.format(
-            symbol=Config.DEFAULT_TRADING_SYMBOL,
-            amount=Config.DEFAULT_TRADE_AMOUNT,
-            network="Testnet" if Config.HYPERLIQUID_TESTNET else "Mainnet"
-        )
-        
-        await update.message.reply_text(help_text, parse_mode='HTML')
-    
-    async def stats_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /stats command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        # Get current balance for stats
-        balance = self.client.get_balance()
-        current_balance = 0
-        if balance and balance.get('total'):
-            current_balance = float(balance['total'].get('USDC', 0))
-        
-        stats_message = self.stats.format_stats_message(current_balance)
-        await update.message.reply_text(stats_message, parse_mode='HTML')
-    
-    async def buy_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /buy command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        try:
-            if len(context.args) < 2:
-                await update.message.reply_text(
-                    "❌ Usage: /buy [amount] [price]\n"
-                    f"Example: /buy {Config.DEFAULT_TRADE_AMOUNT} 50000"
-                )
-                return
-            
-            amount = float(context.args[0])
-            price = float(context.args[1])
-            symbol = Config.DEFAULT_TRADING_SYMBOL
-            
-            # Confirmation message
-            confirmation_text = f"""
-🟢 <b>Buy Order Confirmation</b>
-
-📊 <b>Order Details:</b>
-• Symbol: {symbol}
-• Side: BUY
-• Amount: {amount}
-• Price: ${price:,.2f}
-• Total Value: ${amount * price:,.2f}
-
-⚠️ <b>Are you sure you want to place this order?</b>
-
-This will attempt to buy {amount} {symbol} at ${price:,.2f} per unit.
-            """
-            
-            keyboard = [
-                [
-                    InlineKeyboardButton("✅ Confirm Buy", callback_data=f"confirm_buy_{amount}_{price}"),
-                    InlineKeyboardButton("❌ Cancel", callback_data="cancel_order")
-                ]
-            ]
-            reply_markup = InlineKeyboardMarkup(keyboard)
-            
-            await update.message.reply_text(confirmation_text, parse_mode='HTML', reply_markup=reply_markup)
-            
-        except ValueError:
-            await update.message.reply_text("❌ Invalid amount or price. Please use numbers only.")
-        except Exception as e:
-            await update.message.reply_text(f"❌ Error processing buy command: {e}")
-    
-    async def sell_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /sell command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        try:
-            if len(context.args) < 2:
-                await update.message.reply_text(
-                    "❌ Usage: /sell [amount] [price]\n"
-                    f"Example: /sell {Config.DEFAULT_TRADE_AMOUNT} 55000"
-                )
-                return
-            
-            amount = float(context.args[0])
-            price = float(context.args[1])
-            symbol = Config.DEFAULT_TRADING_SYMBOL
-            
-            # Confirmation message
-            confirmation_text = f"""
-🔴 <b>Sell Order Confirmation</b>
-
-📊 <b>Order Details:</b>
-• Symbol: {symbol}
-• Side: SELL
-• Amount: {amount}
-• Price: ${price:,.2f}
-• Total Value: ${amount * price:,.2f}
-
-⚠️ <b>Are you sure you want to place this order?</b>
-
-This will attempt to sell {amount} {symbol} at ${price:,.2f} per unit.
-            """
-            
-            keyboard = [
-                [
-                    InlineKeyboardButton("✅ Confirm Sell", callback_data=f"confirm_sell_{amount}_{price}"),
-                    InlineKeyboardButton("❌ Cancel", callback_data="cancel_order")
-                ]
-            ]
-            reply_markup = InlineKeyboardMarkup(keyboard)
-            
-            await update.message.reply_text(confirmation_text, parse_mode='HTML', reply_markup=reply_markup)
-            
-        except ValueError:
-            await update.message.reply_text("❌ Invalid amount or price. Please use numbers only.")
-        except Exception as e:
-            await update.message.reply_text(f"❌ Error processing sell command: {e}")
-    
-    async def trades_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /trades command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        recent_trades = self.stats.get_recent_trades(10)
-        
-        if not recent_trades:
-            await update.message.reply_text("📝 No trades recorded yet.")
-            return
-        
-        trades_text = "🔄 <b>Recent Trades</b>\n\n"
-        
-        for trade in reversed(recent_trades[-5:]):  # Show last 5 trades
-            timestamp = datetime.fromisoformat(trade['timestamp']).strftime('%m/%d %H:%M')
-            side_emoji = "🟢" if trade['side'] == 'buy' else "🔴"
-            
-            trades_text += f"{side_emoji} <b>{trade['side'].upper()}</b> {trade['amount']} {trade['symbol']}\n"
-            trades_text += f"   💰 ${trade['price']:,.2f} | 💵 ${trade['value']:,.2f}\n"
-            trades_text += f"   📅 {timestamp}\n\n"
-        
-        await update.message.reply_text(trades_text, parse_mode='HTML')
-    
-    async def balance_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /balance command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        balance = self.client.get_balance()
-        if balance:
-            balance_text = "💰 <b>Account Balance</b>\n\n"
-            total_balance = balance.get('total', {})
-            
-            if total_balance:
-                total_value = 0
-                for asset, amount in total_balance.items():
-                    if float(amount) > 0:
-                        balance_text += f"💵 <b>{asset}:</b> {amount}\n"
-                        if asset == 'USDC':
-                            total_value += float(amount)
-                
-                balance_text += f"\n💼 <b>Total Value:</b> ${total_value:,.2f}"
-                
-                # Add stats summary
-                basic_stats = self.stats.get_basic_stats()
-                if basic_stats['initial_balance'] > 0:
-                    pnl = total_value - basic_stats['initial_balance']
-                    pnl_percent = (pnl / basic_stats['initial_balance']) * 100
-                    
-                    balance_text += f"\n📊 <b>P&L:</b> ${pnl:,.2f} ({pnl_percent:+.2f}%)"
-            else:
-                balance_text += "No balance data available"
-        else:
-            balance_text = "❌ Could not fetch balance data"
-        
-        await update.message.reply_text(balance_text, parse_mode='HTML')
-    
-    async def positions_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /positions command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        positions = self.client.get_positions()
-        if positions:
-            positions_text = "📈 <b>Open Positions</b>\n\n"
-            
-            open_positions = [p for p in positions if float(p.get('contracts', 0)) != 0]
-            
-            if open_positions:
-                total_unrealized = 0
-                for position in open_positions:
-                    symbol = position.get('symbol', 'Unknown')
-                    contracts = float(position.get('contracts', 0))
-                    unrealized_pnl = float(position.get('unrealizedPnl', 0))
-                    entry_price = float(position.get('entryPx', 0))
-                    
-                    pnl_emoji = "🟢" if unrealized_pnl >= 0 else "🔴"
-                    
-                    positions_text += f"📊 <b>{symbol}</b>\n"
-                    positions_text += f"   📏 Size: {contracts} contracts\n"
-                    positions_text += f"   💰 Entry: ${entry_price:,.2f}\n"
-                    positions_text += f"   {pnl_emoji} PnL: ${unrealized_pnl:,.2f}\n\n"
-                    
-                    total_unrealized += unrealized_pnl
-                
-                positions_text += f"💼 <b>Total Unrealized P&L:</b> ${total_unrealized:,.2f}"
-            else:
-                positions_text += "No open positions"
-        else:
-            positions_text = "❌ Could not fetch positions data"
-        
-        await update.message.reply_text(positions_text, parse_mode='HTML')
-    
-    async def orders_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /orders command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        orders = self.client.get_open_orders()
-        if orders:
-            orders_text = "📋 <b>Open Orders</b>\n\n"
-            
-            if orders and len(orders) > 0:
-                for order in orders:
-                    symbol = order.get('symbol', 'Unknown')
-                    side = order.get('side', 'Unknown')
-                    amount = order.get('amount', 0)
-                    price = order.get('price', 0)
-                    order_id = order.get('id', 'Unknown')
-                    
-                    side_emoji = "🟢" if side.lower() == 'buy' else "🔴"
-                    
-                    orders_text += f"{side_emoji} <b>{symbol}</b>\n"
-                    orders_text += f"   📊 {side.upper()} {amount} @ ${price:,.2f}\n"
-                    orders_text += f"   💵 Value: ${float(amount) * float(price):,.2f}\n"
-                    orders_text += f"   🔑 ID: <code>{order_id}</code>\n\n"
-            else:
-                orders_text += "No open orders"
-        else:
-            orders_text = "❌ Could not fetch orders data"
-        
-        await update.message.reply_text(orders_text, parse_mode='HTML')
-    
-    async def market_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /market command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        symbol = Config.DEFAULT_TRADING_SYMBOL
-        market_data = self.client.get_market_data(symbol)
-        
-        if market_data:
-            ticker = market_data['ticker']
-            orderbook = market_data['orderbook']
-            
-            # Calculate 24h change
-            current_price = float(ticker.get('last', 0))
-            high_24h = float(ticker.get('high', 0))
-            low_24h = float(ticker.get('low', 0))
-            
-            market_text = f"📊 <b>Market Data - {symbol}</b>\n\n"
-            market_text += f"💵 <b>Current Price:</b> ${current_price:,.2f}\n"
-            market_text += f"📈 <b>24h High:</b> ${high_24h:,.2f}\n"
-            market_text += f"📉 <b>24h Low:</b> ${low_24h:,.2f}\n"
-            market_text += f"📊 <b>24h Volume:</b> {ticker.get('baseVolume', 'N/A')}\n\n"
-            
-            if orderbook.get('bids') and orderbook.get('asks'):
-                best_bid = float(orderbook['bids'][0][0]) if orderbook['bids'] else 0
-                best_ask = float(orderbook['asks'][0][0]) if orderbook['asks'] else 0
-                spread = best_ask - best_bid
-                spread_percent = (spread / best_ask * 100) if best_ask > 0 else 0
-                
-                market_text += f"🟢 <b>Best Bid:</b> ${best_bid:,.2f}\n"
-                market_text += f"🔴 <b>Best Ask:</b> ${best_ask:,.2f}\n"
-                market_text += f"📏 <b>Spread:</b> ${spread:.2f} ({spread_percent:.3f}%)\n"
-        else:
-            market_text = "❌ Could not fetch market data"
-        
-        await update.message.reply_text(market_text, parse_mode='HTML')
-    
-    async def price_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle the /price command."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        symbol = Config.DEFAULT_TRADING_SYMBOL
-        market_data = self.client.get_market_data(symbol)
-        
-        if market_data:
-            price = float(market_data['ticker'].get('last', 0))
-            price_text = f"💵 <b>{symbol}</b>: ${price:,.2f}"
-            
-            # Add timestamp
-            timestamp = datetime.now().strftime('%H:%M:%S')
-            price_text += f"\n⏰ <i>Updated: {timestamp}</i>"
-        else:
-            price_text = f"❌ Could not fetch price for {symbol}"
-        
-        await update.message.reply_text(price_text, parse_mode='HTML')
-    
-    async def button_callback(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle inline keyboard button presses."""
-        query = update.callback_query
-        await query.answer()
-        
-        if not self.is_authorized(query.message.chat_id):
-            await query.edit_message_text("❌ Unauthorized access.")
-            return
-        
-        callback_data = query.data
-        
-        # Handle trading confirmations
-        if callback_data.startswith('confirm_buy_'):
-            parts = callback_data.split('_')
-            amount = float(parts[2])
-            price = float(parts[3])
-            await self._execute_buy_order(query, amount, price)
-            return
-            
-        elif callback_data.startswith('confirm_sell_'):
-            parts = callback_data.split('_')
-            amount = float(parts[2])
-            price = float(parts[3])
-            await self._execute_sell_order(query, amount, price)
-            return
-            
-        elif callback_data == 'cancel_order':
-            await query.edit_message_text("❌ Order cancelled.")
-            return
-        
-        # Create a fake update object for reusing command handlers
-        fake_update = Update(
-            update_id=update.update_id,
-            message=query.message,
-            callback_query=query
-        )
-        
-        # Handle regular button callbacks
-        if callback_data == "balance":
-            await self.balance_command(fake_update, context)
-        elif callback_data == "stats":
-            await self.stats_command(fake_update, context)
-        elif callback_data == "positions":
-            await self.positions_command(fake_update, context)
-        elif callback_data == "orders":
-            await self.orders_command(fake_update, context)
-        elif callback_data == "market":
-            await self.market_command(fake_update, context)
-        elif callback_data == "price":
-            await self.price_command(fake_update, context)
-        elif callback_data == "trades":
-            await self.trades_command(fake_update, context)
-        elif callback_data == "help":
-            await self.help_command(fake_update, context)
-    
-    async def _execute_buy_order(self, query, amount: float, price: float):
-        """Execute a buy order."""
-        symbol = Config.DEFAULT_TRADING_SYMBOL
-        
-        try:
-            await query.edit_message_text("⏳ Placing buy order...")
-            
-            # Place the order
-            order = self.client.place_limit_order(symbol, 'buy', amount, price)
-            
-            if order:
-                # Record the trade in stats
-                order_id = order.get('id', 'N/A')
-                self.stats.record_trade(symbol, 'buy', amount, price, order_id)
-                
-                success_message = f"""
-✅ <b>Buy Order Placed Successfully!</b>
-
-📊 <b>Order Details:</b>
-• Symbol: {symbol}
-• Side: BUY
-• Amount: {amount}
-• Price: ${price:,.2f}
-• Order ID: <code>{order_id}</code>
-• Total Value: ${amount * price:,.2f}
-
-The order has been submitted to Hyperliquid.
-                """
-                
-                await query.edit_message_text(success_message, parse_mode='HTML')
-                logger.info(f"Buy order placed: {amount} {symbol} @ ${price}")
-            else:
-                await query.edit_message_text("❌ Failed to place buy order. Please try again.")
-                
-        except Exception as e:
-            error_message = f"❌ Error placing buy order: {str(e)}"
-            await query.edit_message_text(error_message)
-            logger.error(f"Error placing buy order: {e}")
-    
-    async def _execute_sell_order(self, query, amount: float, price: float):
-        """Execute a sell order."""
-        symbol = Config.DEFAULT_TRADING_SYMBOL
-        
-        try:
-            await query.edit_message_text("⏳ Placing sell order...")
-            
-            # Place the order
-            order = self.client.place_limit_order(symbol, 'sell', amount, price)
-            
-            if order:
-                # Record the trade in stats
-                order_id = order.get('id', 'N/A')
-                self.stats.record_trade(symbol, 'sell', amount, price, order_id)
-                
-                success_message = f"""
-✅ <b>Sell Order Placed Successfully!</b>
-
-📊 <b>Order Details:</b>
-• Symbol: {symbol}
-• Side: SELL
-• Amount: {amount}
-• Price: ${price:,.2f}
-• Order ID: <code>{order_id}</code>
-• Total Value: ${amount * price:,.2f}
-
-The order has been submitted to Hyperliquid.
-                """
-                
-                await query.edit_message_text(success_message, parse_mode='HTML')
-                logger.info(f"Sell order placed: {amount} {symbol} @ ${price}")
-            else:
-                await query.edit_message_text("❌ Failed to place sell order. Please try again.")
-                
-        except Exception as e:
-            error_message = f"❌ Error placing sell order: {str(e)}"
-            await query.edit_message_text(error_message)
-            logger.error(f"Error placing sell order: {e}")
-    
-    async def unknown_command(self, update: Update, context: ContextTypes.DEFAULT_TYPE) -> None:
-        """Handle unknown commands."""
-        if not self.is_authorized(update.effective_chat.id):
-            await update.message.reply_text("❌ Unauthorized access.")
-            return
-        
-        await update.message.reply_text(
-            "❓ Unknown command. Use /help to see available commands or tap the buttons in /start."
-        )
-    
-    def setup_handlers(self):
-        """Set up command handlers for the bot."""
-        if not self.application:
-            return
-        
-        # Command handlers
-        self.application.add_handler(CommandHandler("start", self.start_command))
-        self.application.add_handler(CommandHandler("help", self.help_command))
-        self.application.add_handler(CommandHandler("balance", self.balance_command))
-        self.application.add_handler(CommandHandler("positions", self.positions_command))
-        self.application.add_handler(CommandHandler("orders", self.orders_command))
-        self.application.add_handler(CommandHandler("market", self.market_command))
-        self.application.add_handler(CommandHandler("price", self.price_command))
-        self.application.add_handler(CommandHandler("stats", self.stats_command))
-        self.application.add_handler(CommandHandler("trades", self.trades_command))
-        self.application.add_handler(CommandHandler("buy", self.buy_command))
-        self.application.add_handler(CommandHandler("sell", self.sell_command))
-        
-        # Callback query handler for inline keyboards
-        self.application.add_handler(CallbackQueryHandler(self.button_callback))
-        
-        # Handle unknown commands
-        self.application.add_handler(MessageHandler(filters.COMMAND, self.unknown_command))
-    
-    async def run(self):
-        """Run the Telegram bot."""
-        if not Config.TELEGRAM_BOT_TOKEN:
-            logger.error("❌ TELEGRAM_BOT_TOKEN not configured")
-            return
-        
-        if not Config.TELEGRAM_CHAT_ID:
-            logger.error("❌ TELEGRAM_CHAT_ID not configured")
-            return
-        
-        # Create application
-        self.application = Application.builder().token(Config.TELEGRAM_BOT_TOKEN).build()
-        
-        # Set up handlers
-        self.setup_handlers()
-        
-        logger.info("🚀 Starting Telegram trading bot...")
-        
-        # Send startup notification
-        await self.send_message(
-            "🤖 <b>Manual Trading Bot Started</b>\n\n"
-            f"✅ Connected to Hyperliquid {'Testnet' if Config.HYPERLIQUID_TESTNET else 'Mainnet'}\n"
-            f"📊 Default Symbol: {Config.DEFAULT_TRADING_SYMBOL}\n"
-            f"📱 Manual trading ready!\n"
-            f"⏰ Started at: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"
-            "Use /start for quick actions or /help for all commands."
-        )
-        
-        # Start the bot
-        await self.application.run_polling()
-
-
-def main():
-    """Main entry point for the Telegram bot."""
-    try:
-        # Validate configuration
-        if not Config.validate():
-            logger.error("❌ Configuration validation failed!")
-            return
-        
-        if not Config.TELEGRAM_ENABLED:
-            logger.error("❌ Telegram is not enabled in configuration")
-            return
-        
-        # Create and run the bot
-        bot = TelegramTradingBot()
-        asyncio.run(bot.run())
-        
-    except KeyboardInterrupt:
-        logger.info("👋 Bot stopped by user")
-    except Exception as e:
-        logger.error(f"❌ Unexpected error: {e}")
-
-
-if __name__ == "__main__":
-    main() 

+ 0 - 0
demo_stats.py → tests/demo_stats.py


+ 0 - 0
test_bot_fixes.py → tests/test_bot_fixes.py


+ 0 - 0
test_heartbeat_config.py → tests/test_heartbeat_config.py


+ 0 - 0
test_logging_system.py → tests/test_logging_system.py


+ 210 - 0
tests/test_performance_command.py

@@ -0,0 +1,210 @@
+#!/usr/bin/env python3
+"""
+Test script to demonstrate the new /performance command functionality.
+"""
+
+def demo_performance_ranking():
+    """Demo what the performance ranking will look like."""
+    print("🏆 Token Performance Ranking Demo")
+    print("=" * 50)
+    
+    # Mock token performance data (sorted by P&L)
+    token_performance = {
+        'BTC': {
+            'total_pnl': 150.75,
+            'pnl_percentage': 5.2,
+            'completed_trades': 8,
+            'win_rate': 75.0
+        },
+        'ETH': {
+            'total_pnl': 45.30,
+            'pnl_percentage': 3.1,
+            'completed_trades': 5,
+            'win_rate': 60.0
+        },
+        'SOL': {
+            'total_pnl': -25.40,
+            'pnl_percentage': -2.8,
+            'completed_trades': 3,
+            'win_rate': 33.3
+        }
+    }
+    
+    sorted_tokens = sorted(
+        token_performance.items(),
+        key=lambda x: x[1]['total_pnl'],
+        reverse=True
+    )
+    
+    print("🏆 Token Performance Ranking\n")
+    
+    for i, (token, stats) in enumerate(sorted_tokens, 1):
+        # Ranking emoji
+        if i == 1:
+            rank_emoji = "🥇"
+        elif i == 2:
+            rank_emoji = "🥈"
+        elif i == 3:
+            rank_emoji = "🥉"
+        else:
+            rank_emoji = f"#{i}"
+        
+        # P&L emoji
+        pnl_emoji = "🟢" if stats['total_pnl'] >= 0 else "🔴"
+        
+        print(f"{rank_emoji} {token}")
+        print(f"   {pnl_emoji} P&L: ${stats['total_pnl']:,.2f} ({stats['pnl_percentage']:+.1f}%)")
+        print(f"   📊 Trades: {stats['completed_trades']} | Win: {stats['win_rate']:.0f}%")
+        print()
+    
+    # Summary
+    total_pnl = sum(stats['total_pnl'] for stats in token_performance.values())
+    total_trades = sum(stats['completed_trades'] for stats in token_performance.values())
+    total_pnl_emoji = "🟢" if total_pnl >= 0 else "🔴"
+    
+    print("💼 Portfolio Summary:")
+    print(f"   {total_pnl_emoji} Total P&L: ${total_pnl:,.2f}")
+    print(f"   📈 Tokens Traded: {len(token_performance)}")
+    print(f"   🔄 Completed Trades: {total_trades}")
+    print()
+    print("💡 Usage: /performance BTC for detailed BTC stats")
+
+def demo_detailed_performance():
+    """Demo what detailed token performance will look like."""
+    print("\n📊 BTC Detailed Performance Demo")
+    print("=" * 50)
+    
+    # Mock detailed BTC stats
+    token_stats = {
+        'token': 'BTC',
+        'total_pnl': 150.75,
+        'pnl_percentage': 5.2,
+        'completed_volume': 2900.00,
+        'expectancy': 18.84,
+        'total_trades': 12,
+        'completed_trades': 8,
+        'buy_trades': 6,
+        'sell_trades': 6,
+        'win_rate': 75.0,
+        'profit_factor': 3.2,
+        'total_wins': 6,
+        'total_losses': 2,
+        'largest_win': 85.50,
+        'largest_loss': 32.20,
+        'avg_win': 42.15,
+        'avg_loss': 28.75,
+        'recent_trades': [
+            {
+                'side': 'buy',
+                'value': 500,
+                'timestamp': '2023-12-01T10:30:00',
+                'pnl': 0
+            },
+            {
+                'side': 'sell',
+                'value': 500,
+                'timestamp': '2023-12-01T14:15:00',
+                'pnl': 45.20
+            },
+            {
+                'side': 'buy',
+                'value': 300,
+                'timestamp': '2023-12-01T16:45:00',
+                'pnl': 0
+            }
+        ]
+    }
+    
+    pnl_emoji = "🟢" if token_stats['total_pnl'] >= 0 else "🔴"
+    
+    print(f"📊 {token_stats['token']} Detailed Performance\n")
+    
+    print("💰 P&L Summary:")
+    print(f"• {pnl_emoji} Total P&L: ${token_stats['total_pnl']:,.2f} ({token_stats['pnl_percentage']:+.2f}%)")
+    print(f"• 💵 Total Volume: ${token_stats['completed_volume']:,.2f}")
+    print(f"• 📈 Expectancy: ${token_stats['expectancy']:,.2f}")
+    print()
+    
+    print("📊 Trading Activity:")
+    print(f"• Total Trades: {token_stats['total_trades']}")
+    print(f"• Completed: {token_stats['completed_trades']}")
+    print(f"• Buy Orders: {token_stats['buy_trades']}")
+    print(f"• Sell Orders: {token_stats['sell_trades']}")
+    print()
+    
+    print("🏆 Performance Metrics:")
+    print(f"• Win Rate: {token_stats['win_rate']:.1f}%")
+    print(f"• Profit Factor: {token_stats['profit_factor']:.2f}")
+    print(f"• Wins: {token_stats['total_wins']} | Losses: {token_stats['total_losses']}")
+    print()
+    
+    print("💡 Best/Worst:")
+    print(f"• Largest Win: ${token_stats['largest_win']:,.2f}")
+    print(f"• Largest Loss: ${token_stats['largest_loss']:,.2f}")
+    print(f"• Avg Win: ${token_stats['avg_win']:,.2f}")
+    print(f"• Avg Loss: ${token_stats['avg_loss']:,.2f}")
+    print()
+    
+    print("🔄 Recent Trades:")
+    for trade in token_stats['recent_trades'][-3:]:
+        side_emoji = "🟢" if trade['side'] == 'buy' else "🔴"
+        pnl_display = f" | P&L: ${trade['pnl']:.2f}" if trade['pnl'] != 0 else ""
+        print(f"• {side_emoji} {trade['side'].upper()} ${trade['value']:,.0f} @ 12/01 10:30{pnl_display}")
+    print()
+    print("🔄 Use /performance to see all token rankings")
+
+def demo_no_data_scenarios():
+    """Demo what happens when there's no trading data."""
+    print("\n📭 No Data Scenarios Demo")
+    print("=" * 50)
+    
+    print("1. No trading data at all:")
+    print("📊 Token Performance\n")
+    print("📭 No trading data available yet.\n")
+    print("💡 Performance tracking starts after your first completed trades.")
+    print("Use /long or /short to start trading!")
+    print()
+    
+    print("2. No trading history for specific token:")
+    print("📊 SOL Performance\n")
+    print("📭 No trading history found for SOL.\n")
+    print("💡 Start trading SOL with:")
+    print("• /long SOL 100")
+    print("• /short SOL 100")
+    print()
+    print("🔄 Use /performance to see all token rankings.")
+    print()
+    
+    print("3. Open positions but no completed trades:")
+    print("📊 ETH Performance\n")
+    print("ETH has open positions but no completed trades yet\n")
+    print("📈 Current Activity:")
+    print("• Total Trades: 3")
+    print("• Buy Orders: 2")
+    print("• Sell Orders: 1")
+    print("• Volume: $1,500.00")
+    print()
+    print("💡 Complete some trades to see P&L statistics!")
+    print("🔄 Use /performance to see all token rankings.")
+
+if __name__ == "__main__":
+    print("🚀 Performance Command Demo")
+    print("=" * 60)
+    
+    demo_performance_ranking()
+    demo_detailed_performance() 
+    demo_no_data_scenarios()
+    
+    print("\n" + "=" * 60)
+    print("✅ Key Features:")
+    print("• Token performance ranking (best to worst P&L)")
+    print("• Detailed stats for specific tokens")
+    print("• Win rate, profit factor, expectancy calculations")
+    print("• Recent trade history included")
+    print("• Mobile-friendly compressed and detailed views")
+    print("• Handles cases with no data gracefully")
+    print("• Easy navigation between ranking and details")
+    print("\n💡 Usage:")
+    print("• /performance - Show all token rankings")
+    print("• /performance BTC - Show detailed BTC stats")
+    print("• /performance ETH - Show detailed ETH stats") 

+ 1 - 0
tests/test_period_commands.py

@@ -0,0 +1 @@
+ 

+ 111 - 0
tests/test_positions_display.py

@@ -0,0 +1,111 @@
+#!/usr/bin/env python3
+"""
+Test script to demonstrate the enhanced positions display with P&L percentages.
+"""
+
+def demo_positions_display():
+    """Demo what the enhanced positions message will look like."""
+    print("📈 Enhanced Positions Display Demo")
+    print("=" * 50)
+    
+    # Mock position data
+    positions = [
+        {
+            'symbol': 'BTC/USDC:USDC',
+            'contracts': 0.05,  # Long position
+            'entryPx': 45000,
+            'unrealizedPnl': 1250
+        },
+        {
+            'symbol': 'ETH/USDC:USDC', 
+            'contracts': -2.0,  # Short position
+            'entryPx': 3000,
+            'unrealizedPnl': -150
+        },
+        {
+            'symbol': 'SOL/USDC:USDC',
+            'contracts': 10.0,  # Long position
+            'entryPx': 100,
+            'unrealizedPnl': 75
+        }
+    ]
+    
+    print("📈 <b>Open Positions</b>\n")
+    
+    total_unrealized = 0
+    total_position_value = 0
+    
+    for position in positions:
+        symbol = position['symbol']
+        contracts = float(position['contracts'])
+        unrealized_pnl = float(position['unrealizedPnl'])
+        entry_price = float(position['entryPx'])
+        
+        # Calculate position value and P&L percentage
+        position_value = abs(contracts) * entry_price
+        pnl_percentage = (unrealized_pnl / position_value * 100) if position_value > 0 else 0
+        
+        pnl_emoji = "🟢" if unrealized_pnl >= 0 else "🔴"
+        
+        # Extract token name for cleaner display
+        token = symbol.split('/')[0] if '/' in symbol else symbol
+        position_type = "LONG" if contracts > 0 else "SHORT"
+        
+        print(f"📊 {token} ({position_type})")
+        print(f"   📏 Size: {abs(contracts):.6f} {token}")
+        print(f"   💰 Entry: ${entry_price:,.2f}")
+        print(f"   💵 Value: ${position_value:,.2f}")
+        print(f"   {pnl_emoji} P&L: ${unrealized_pnl:,.2f} ({pnl_percentage:+.2f}%)")
+        print()
+        
+        total_unrealized += unrealized_pnl
+        total_position_value += position_value
+    
+    # Calculate overall P&L percentage
+    total_pnl_percentage = (total_unrealized / total_position_value * 100) if total_position_value > 0 else 0
+    total_pnl_emoji = "🟢" if total_unrealized >= 0 else "🔴"
+    
+    print(f"💼 Total Portfolio:")
+    print(f"   💵 Total Value: ${total_position_value:,.2f}")
+    print(f"   {total_pnl_emoji} Total P&L: ${total_unrealized:,.2f} ({total_pnl_percentage:+.2f}%)")
+
+def demo_comparison():
+    """Show before vs after comparison."""
+    print("\n📊 Before vs After Comparison")
+    print("=" * 50)
+    
+    print("BEFORE (old format):")
+    print("📊 BTC/USDC:USDC")
+    print("   📏 Size: 0.05 contracts")
+    print("   💰 Entry: $45,000.00")
+    print("   🟢 PnL: $1,250.00")
+    print()
+    print("💼 Total Unrealized P&L: $1,175.00")
+    
+    print("\nAFTER (enhanced format):")
+    print("📊 BTC (LONG)")
+    print("   📏 Size: 0.050000 BTC")
+    print("   💰 Entry: $45,000.00")
+    print("   💵 Value: $2,250.00")
+    print("   🟢 P&L: $1,250.00 (+55.56%)")
+    print()
+    print("💼 Total Portfolio:")
+    print("   💵 Total Value: $8,250.00")
+    print("   🟢 Total P&L: $1,175.00 (+14.24%)")
+
+if __name__ == "__main__":
+    print("🚀 Enhanced Positions Display Test")
+    print("=" * 60)
+    
+    demo_positions_display()
+    demo_comparison()
+    
+    print("\n" + "=" * 60)
+    print("✅ Enhanced features:")
+    print("• Shows position direction (LONG/SHORT)")
+    print("• Displays token names instead of full symbols")
+    print("• Shows position size in token units")
+    print("• Adds position value for context")
+    print("• P&L shown as both $ and % for easy assessment")
+    print("• Total portfolio value and P&L percentage")
+    print("• Clean, mobile-friendly formatting") 

+ 0 - 0
test_stop_loss_config.py → tests/test_stop_loss_config.py