Selaa lähdekoodia

Enhance Hyperliquid Account Analyzer with detailed single account deep dive analysis

- Introduced a new method to provide a comprehensive deep dive analysis for individual accounts, including live data fetching, performance metrics, trading patterns, and copy trading evaluations.
- Updated the existing analysis results method to handle single account scenarios, improving user insights and experience.
- Enhanced output formatting for better clarity and engagement during account evaluations.
Carles Sentis 4 päivää sitten
vanhempi
sitoutus
7c235388a6
2 muutettua tiedostoa jossa 193 lisäystä ja 4 poistoa
  1. 1 1
      trading_bot.py
  2. 192 3
      utils/hyperliquid_account_analyzer.py

+ 1 - 1
trading_bot.py

@@ -14,7 +14,7 @@ from datetime import datetime
 from pathlib import Path
 
 # Bot version
-BOT_VERSION = "3.0.346"
+BOT_VERSION = "3.0.347"
 
 # Add src directory to Python path
 sys.path.insert(0, str(Path(__file__).parent / "src"))

+ 192 - 3
utils/hyperliquid_account_analyzer.py

@@ -832,16 +832,205 @@ class HyperliquidAccountAnalyzer:
         
         return valid_results
 
-    def print_analysis_results(self, stats_list: List[AccountStats]):
+    async def print_single_account_deep_dive(self, stats: AccountStats):
+        """Print detailed deep dive analysis for a single account"""
+        print(f"\n🎯 ACCOUNT: {stats.address}")
+        print("="*100)
+        
+        # Fetch current live data
+        print("🔄 Fetching current account state...")
+        try:
+            current_state = await self.get_account_state(stats.address)
+            current_positions = self.parse_positions(current_state) if current_state else []
+            
+            # Get recent fills for more context
+            recent_fills = await self.get_user_fills(stats.address, limit=20)
+            recent_trades = self.parse_trades(recent_fills) if recent_fills else []
+            
+        except Exception as e:
+            print(f"⚠️ Could not fetch live data: {e}")
+            current_positions = []
+            recent_trades = []
+        
+        # Basic Account Information
+        print(f"\n📋 ACCOUNT OVERVIEW")
+        print(f"   📍 Address: {stats.address}")
+        print(f"   📅 Analysis Period: {stats.analysis_period_days} days")
+        if stats.last_trade_timestamp > 0:
+            from datetime import datetime
+            last_trade_date = datetime.fromtimestamp(stats.last_trade_timestamp / 1000)
+            print(f"   🕒 Last Trade: {last_trade_date.strftime('%Y-%m-%d %H:%M:%S')} UTC")
+        
+        # Current Positions (LIVE DATA)
+        print(f"\n📊 CURRENT POSITIONS ({len(current_positions)} active)")
+        if current_positions:
+            total_position_value = 0
+            total_unrealized_pnl = 0
+            
+            for pos in current_positions:
+                side_emoji = "📈" if pos.side == "long" else "📉"
+                pnl_emoji = "✅" if pos.unrealized_pnl >= 0 else "❌"
+                
+                print(f"   {side_emoji} {pos.coin} - {pos.side.upper()}")
+                print(f"      💰 Size: {pos.size:.6f} {pos.coin} @ ${pos.entry_price:.4f}")
+                print(f"      🏷️ Mark Price: ${pos.mark_price:.4f}")
+                print(f"      {pnl_emoji} Unrealized PnL: ${pos.unrealized_pnl:.2f}")
+                print(f"      ⚖️ Leverage: {pos.leverage:.1f}x")
+                print(f"      💳 Margin Used: ${pos.margin_used:.2f}")
+                
+                total_position_value += abs(pos.size * pos.mark_price)
+                total_unrealized_pnl += pos.unrealized_pnl
+                print()
+            
+            print(f"   📊 POSITION SUMMARY:")
+            print(f"      💼 Total Position Value: ${total_position_value:.2f}")
+            print(f"      📈 Total Unrealized PnL: ${total_unrealized_pnl:.2f}")
+            
+        else:
+            print("   💤 No active positions")
+        
+        # Performance Metrics
+        print(f"\n📈 PERFORMANCE ANALYSIS")
+        print(f"   💰 Total Realized PnL: ${stats.total_pnl:.2f}")
+        print(f"   📊 Win Rate: {stats.win_rate:.1%}")
+        print(f"   🎯 Total Trades: {stats.total_trades}")
+        print(f"   💵 Average Position Size: ${stats.avg_position_size:.2f}")
+        print(f"   ⏱️ Average Trade Duration: {stats.avg_trade_duration_hours:.1f} hours")
+        print(f"   📉 Maximum Drawdown: {stats.max_drawdown:.1%}")
+        print(f"   📉 Current Drawdown: {stats.current_drawdown:.1%}")
+        print(f"   🏆 Largest Win: ${stats.largest_win:.2f}")
+        print(f"   💔 Largest Loss: ${stats.largest_loss:.2f}")
+        print(f"   📊 Profit Factor: {stats.profit_factor:.2f}")
+        print(f"   🔗 Max Consecutive Losses: {stats.consecutive_losses_max}")
+        
+        # Trading Patterns
+        print(f"\n🎲 TRADING PATTERNS")
+        print(f"   🔄 Trading Frequency: {stats.trading_frequency_per_day:.1f} trades/day")
+        print(f"   ⚖️ Average Leverage: {stats.avg_leverage_used:.1f}x")
+        print(f"   📊 Max Leverage Used: {stats.max_leverage_used:.1f}x")
+        print(f"   🪙 Unique Tokens Traded: {stats.unique_tokens_traded}")
+        
+        # Trading style analysis
+        trading_type_display = {
+            "perps": "🔄 Perpetuals",
+            "spot": "💱 Spot Trading", 
+            "mixed": "🔀 Mixed (Spot + Perps)",
+            "unknown": "❓ Unknown"
+        }.get(stats.trading_type, f"❓ {stats.trading_type}")
+        print(f"   📈 Trading Type: {trading_type_display}")
+        print(f"   📊 Trading Style: {stats.trading_style}")
+        print(f"   📉 Short Percentage: {stats.short_percentage:.1f}%")
+        
+        # Buy/Sell ratio
+        if stats.buy_sell_ratio == float('inf'):
+            ratio_display = "∞ (only buys)"
+        elif stats.buy_sell_ratio == 0:
+            ratio_display = "0 (only sells)" 
+        else:
+            ratio_display = f"{stats.buy_sell_ratio:.2f}"
+        print(f"   ⚖️ Buy/Sell Ratio: {ratio_display}")
+        
+        # Top tokens
+        if stats.top_tokens:
+            print(f"   🏆 Top Traded Tokens: {', '.join(stats.top_tokens[:5])}")
+        
+        # Recent Trading Activity
+        if recent_trades:
+            print(f"\n🕒 RECENT TRADING ACTIVITY (last {len(recent_trades)} trades)")
+            for i, trade in enumerate(recent_trades[:10], 1):  # Show last 10 trades
+                from datetime import datetime
+                trade_time = datetime.fromtimestamp(trade.timestamp / 1000)
+                side_emoji = "🟢" if trade.side == "buy" else "🔴"
+                
+                print(f"   {i}. {side_emoji} {trade.side.upper()} {trade.size:.6f} {trade.coin}")
+                print(f"      💰 Price: ${trade.price:.4f} | Value: ${trade.size * trade.price:.2f}")
+                print(f"      🕒 Time: {trade_time.strftime('%m-%d %H:%M:%S')}")
+                if i < len(recent_trades[:10]):
+                    print()
+        
+        # Copy Trading Evaluation
+        print(f"\n🎯 COPY TRADING EVALUATION")
+        print(f"   ✅ Copyable: {'YES' if stats.is_copyable else 'NO'}")
+        print(f"   📝 Reason: {stats.copyability_reason}")
+        
+        # Detailed evaluation
+        evaluation = []
+        is_hft_pattern = stats.trading_frequency_per_day > 50
+        is_copyable = 1 <= stats.trading_frequency_per_day <= 20
+        
+        if is_hft_pattern:
+            evaluation.append("❌ HFT/Bot pattern detected")
+        elif stats.trading_frequency_per_day < 1:
+            evaluation.append("❌ Too inactive for copy trading")
+        elif is_copyable:
+            evaluation.append("✅ Human-like trading pattern")
+        
+        if stats.total_pnl > 0:
+            evaluation.append("✅ Profitable track record")
+        else:
+            evaluation.append("❌ Not profitable")
+        
+        if stats.max_drawdown < 0.15:
+            evaluation.append("✅ Good risk management")
+        elif stats.max_drawdown < 0.25:
+            evaluation.append("⚠️ Moderate risk")
+        else:
+            evaluation.append("❌ High risk (excessive drawdown)")
+        
+        if 2 <= stats.avg_trade_duration_hours <= 48:
+            evaluation.append("✅ Suitable trade duration")
+        elif stats.avg_trade_duration_hours < 2:
+            evaluation.append("⚠️ Very short trades (scalping)")
+        else:
+            evaluation.append("⚠️ Long hold times")
+        
+        print(f"\n   📊 Detailed Evaluation:")
+        for eval_point in evaluation:
+            print(f"      {eval_point}")
+        
+        # Copy Trading Recommendations
+        if stats.is_copyable and stats.total_pnl > 0:
+            print(f"\n💡 COPY TRADING RECOMMENDATIONS")
+            
+            if stats.max_drawdown < 0.1 and stats.win_rate > 0.6:
+                print(f"   📊 Suggested Portfolio Allocation: 15-25% (high confidence)")
+                print(f"   ⚖️ Max Leverage Limit: 8-10x")
+            elif stats.max_drawdown < 0.2 and stats.win_rate > 0.5:
+                print(f"   📊 Suggested Portfolio Allocation: 8-15% (moderate confidence)")
+                print(f"   ⚖️ Max Leverage Limit: 5-8x")
+            else:
+                print(f"   📊 Suggested Portfolio Allocation: 3-8% (low confidence)")
+                print(f"   ⚖️ Max Leverage Limit: 2-5x")
+            
+            print(f"   💰 Min Position Size: $25-50")
+            print(f"   🔄 Expected Activity: ~{stats.trading_frequency_per_day:.1f} trades/day")
+            print(f"   ⏱️ Avg Trade Duration: ~{stats.avg_trade_duration_hours:.1f} hours")
+            
+        else:
+            print(f"\n❌ NOT RECOMMENDED FOR COPY TRADING")
+            print(f"   Reason: {stats.copyability_reason}")
+
+    async def print_analysis_results(self, stats_list: List[AccountStats]):
         """Print comprehensive analysis results with relative scoring"""
         if not stats_list:
             print("❌ No valid analysis results to display")
             return
         
+        # Check if this is a single account deep dive
+        is_single_account = len(stats_list) == 1
+        
         print("\n" + "="*100)
-        print("📊 HYPERLIQUID ACCOUNT ANALYSIS RESULTS")
+        if is_single_account:
+            print("🔍 DEEP DIVE ACCOUNT ANALYSIS")
+        else:
+            print("📊 HYPERLIQUID ACCOUNT ANALYSIS RESULTS")
         print("="*100)
         
+        # Special handling for single account analysis
+        if is_single_account:
+            await self.print_single_account_deep_dive(stats_list[0])
+            return
+        
         # Calculate data ranges for relative scoring
         def get_data_ranges(stats_list):
             """Calculate min/max values for relative scoring"""
@@ -1458,7 +1647,7 @@ async def main():
             return
             
         results = await analyzer.analyze_multiple_accounts(addresses)
-        analyzer.print_analysis_results(results)
+        await analyzer.print_analysis_results(results)
 
 if __name__ == "__main__":
     asyncio.run(main())