Explorar o código

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 hai 5 días
pai
achega
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
 /sl BTC 9000 # Set stop loss at $9,000
 /tp BTC 11000 # Set take profit at $11,000
 /tp BTC 11000 # Set take profit at $11,000
 /monitoring  # Check order monitoring status
 /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
 /help        # Full command reference
 ```
 ```
 
 
@@ -53,7 +56,7 @@ Show your current account balance and P&L summary with detailed breakdown of ava
 ```
 ```
 
 
 ### `/positions`
 ### `/positions`
-Display all open positions with unrealized P&L.
+Display all open positions with unrealized P&L and percentages.
 
 
 **Example:**
 **Example:**
 ```
 ```
@@ -64,12 +67,21 @@ Display all open positions with unrealized P&L.
 ```
 ```
 📈 Open Positions
 📈 Open Positions
 
 
-📊 BTC/USDC:USDC
-   📏 Size: 0.001 contracts
+📊 BTC (LONG)
+   📏 Size: 0.001000 BTC
    💰 Entry: $45,230.50
    💰 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)]`
 ### `/orders [token (optional)]`
@@ -224,9 +236,197 @@ Complete trading statistics and performance metrics.
 • Max Drawdown: 8.5%
 • Max Drawdown: 8.5%
 • Volatility: 12.3%
 • Volatility: 12.3%
 • VaR (95%): 3.2%
 • 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
 ## 🚀 Perps Trading
 
 
@@ -393,6 +593,8 @@ Close an open position using market order.
 • Order Type: Market Order
 • Order Type: Market Order
 
 
 ⚠️ Are you sure you want to close this LONG position?
 ⚠️ 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
 ## 🛡️ Risk Management
@@ -419,6 +621,29 @@ Set a stop loss order to limit downside risk.
 3. Places limit order at stop loss price
 3. Places limit order at stop loss price
 4. Order executes automatically when price is reached
 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]`
 ### `/tp [token] [price]`
 Set a take profit order to secure gains.
 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
 /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
 ## 📊 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.
 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`
 ### `/trades`
 Recent trade history.
 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
 ## 🔄 Order Monitoring & Notifications
 
 
 The bot automatically monitors your orders and positions every 30 seconds and sends real-time notifications when orders are filled.
 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
 ✅ Status: New LONG position opened
 ⏰ Time: 14:25:30
 ⏰ Time: 14:25:30
+
+📱 Use /positions to view all positions
 ```
 ```
 
 
 **🎯 Position Closed Notifications**
 **🎯 Position Closed Notifications**
@@ -483,10 +943,50 @@ The bot automatically monitors your orders and positions every 30 seconds and se
 
 
 ✅ Status: Position fully closed
 ✅ Status: Position fully closed
 ⏰ Time: 16:45:22
 ⏰ 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`
 ### `/monitoring`
-Check the status of order monitoring system.
+Check the status of all monitoring systems.
 
 
 **Example:**
 **Example:**
 ```
 ```
@@ -495,19 +995,120 @@ Check the status of order monitoring system.
 
 
 **Response:**
 **Response:**
 ```
 ```
-🔄 Order Monitoring Status
+🔄 System Monitoring Status
 
 
-📊 Current Status:
+📊 Order Monitoring:
 • Active: ✅ Yes
 • Active: ✅ Yes
 • Check Interval: 30 seconds
 • Check Interval: 30 seconds
 • Orders Tracked: 3
 • Orders Tracked: 3
 • Positions Tracked: 2
 • 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:
 📈 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
 ## 💡 Pro Tips
@@ -516,7 +1117,9 @@ Check the status of order monitoring system.
 - Start small and test with small amounts first
 - Start small and test with small amounts first
 - Use confirmations and always review orders
 - Use confirmations and always review orders
 - Monitor positions regularly with `/positions`
 - 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**
 ### **⚡ Quick Trading**
 ```bash
 ```bash
@@ -533,15 +1136,35 @@ Check the status of order monitoring system.
 /long BTC 100        # Open long
 /long BTC 100        # Open long
 /sl BTC 42000        # Stop loss 5% below
 /sl BTC 42000        # Stop loss 5% below
 /tp BTC 50000        # Take profit 10% above
 /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**
 ### **📊 Monitoring**
 ```bash
 ```bash
 /balance          # Check account
 /balance          # Check account
-/stats            # Review performance
 /positions        # Monitor open trades
 /positions        # Monitor open trades
-/monitoring       # Check order monitoring status
+/monitoring       # Check system status
 /orders           # All open orders
 /orders           # All open orders
+/logs             # System health
 ```
 ```
 
 
 ## ⚠️ Important Notes
 ## ⚠️ Important Notes
@@ -551,25 +1174,45 @@ Check the status of order monitoring system.
 - **Auto-notifications** for order fills
 - **Auto-notifications** for order fills
 - **Real-time monitoring** every 30 seconds
 - **Real-time monitoring** every 30 seconds
 - **Comprehensive logging** of all activities
 - **Comprehensive logging** of all activities
+- **Price alerts** for key levels
+- **External trade detection** and sync
 
 
 ### **🔄 Order Monitoring**
 ### **🔄 Order Monitoring**
 - **30-second intervals** for order fill detection
 - **30-second intervals** for order fill detection
 - **Automatic P&L calculation** for closed positions
 - **Automatic P&L calculation** for closed positions
 - **Position change tracking** (opens, closes, increases)
 - **Position change tracking** (opens, closes, increases)
 - **Instant Telegram notifications** for all fills
 - **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**
 ### **📱 Mobile Optimized**
 - **One-tap buttons** for quick actions
 - **One-tap buttons** for quick actions
 - **Clean formatting** for mobile screens
 - **Clean formatting** for mobile screens
 - **Instant notifications** for trade results
 - **Instant notifications** for trade results
 - **Real-time order fill alerts**
 - **Real-time order fill alerts**
+- **Comprehensive emoji indicators**
 
 
 ## 🚀 Getting Started
 ## 🚀 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`
 2. **Test**: Start with `/balance` and `/price`
 3. **Trade**: Try `/long BTC 10` for a small market order
 3. **Trade**: Try `/long BTC 10` for a small market order
 4. **Monitor**: Use `/monitoring` to check auto-notifications
 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! 📱💰**
 **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
 • /coo BTC - Cancel all open orders for BTC
 
 
 <b>📈 Statistics & Analytics:</b>
 <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>
 <b>🔔 Price Alerts:</b>
 • /alarm - List all alarms
 • /alarm - List all alarms
@@ -401,22 +405,40 @@ For support, contact your bot administrator.
             
             
             if open_positions:
             if open_positions:
                 total_unrealized = 0
                 total_unrealized = 0
+                total_position_value = 0
+                
                 for position in open_positions:
                 for position in open_positions:
                     symbol = position.get('symbol', 'Unknown')
                     symbol = position.get('symbol', 'Unknown')
                     contracts = float(position.get('contracts', 0))
                     contracts = float(position.get('contracts', 0))
                     unrealized_pnl = float(position.get('unrealizedPnl', 0))
                     unrealized_pnl = float(position.get('unrealizedPnl', 0))
                     entry_price = float(position.get('entryPx', 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 "🔴"
                     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"   💰 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_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:
             else:
                 positions_text += "📭 <b>No open positions currently</b>\n\n"
                 positions_text += "📭 <b>No open positions currently</b>\n\n"
                 positions_text += "🚀 Ready to start trading!\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("monitoring", self.monitoring_command))
         self.application.add_handler(CommandHandler("alarm", self.alarm_command))
         self.application.add_handler(CommandHandler("alarm", self.alarm_command))
         self.application.add_handler(CommandHandler("logs", self.logs_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
         # Callback query handler for inline keyboards
         self.application.add_handler(CallbackQueryHandler(self.button_callback))
         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)
             await update.message.reply_text(error_message)
             logger.error(f"Error in logs command: {e}")
             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 def main_async():
     """Async main entry point for the Telegram bot."""
     """Async main entry point for the Telegram bot."""
     try:
     try:

+ 323 - 2
src/trading_stats.py

@@ -59,7 +59,10 @@ class TradingStats:
             'trades': [],
             'trades': [],
             'daily_balances': [],
             'daily_balances': [],
             'last_update': datetime.now().isoformat(),
             '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()
         self._save_stats()
     
     
@@ -108,6 +111,11 @@ class TradingStats:
         
         
         self.data['trades'].append(trade)
         self.data['trades'].append(trade)
         self.data['last_update'] = datetime.now().isoformat()
         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()
         self._save_stats()
         
         
         logger.info(f"Recorded trade: {side} {amount} {symbol} @ ${price:.2f}")
         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]]:
     def get_recent_trades(self, limit: int = 10) -> List[Dict[str, Any]]:
         """Get recent trades."""
         """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