from enhanced_trading_core import EnhancedTradingCore
from quantum_strategy import QuantumStrategy
from quantum_optimizer import QuantumOptimizer
from quantum_analytics import QuantumAnalytics
from quantum_metrics import QuantumMetrics
import asyncio
import logging

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("QuantumTrading")

class QuantumTradingIntegration:
    def __init__(self):
        # Initialize core components
        self.trader = EnhancedTradingCore()
        self.strategy = QuantumStrategy()
        self.optimizer = QuantumOptimizer()
        self.analytics = QuantumAnalytics(self.trader)
        self.metrics = QuantumMetrics()
        
        logger.info("[LAUNCH] Quantum Trading Integration Initialized")

    async def execute_quantum_trade(self, token_address: str):
        """Main trading execution flow"""
        try:
            # 1. Get market data
            market_data = await self.analytics.get_market_data(token_address)
            
            # 2. Get strategy signals
            signals = await self.strategy.analyze_market(market_data)
            
            # 3. If signal is strong enough, optimize and execute
            if signals['confidence'] > 0.8:
                # Optimize trade parameters
                trade_setup = await self.optimizer.execute_optimized_trade(
                    token_address=token_address,
                    signal_strength=signals['confidence']
                )
                
                if trade_setup:
                    # Execute through proven method
                    result = await self.trader.execute_trade(
                        output_mint=token_address,
                        amount_in=trade_setup['amount_lamports']
                    )
                    
                    # Update metrics
                    if result.success:
                        self.metrics.add_trade({
                            'timestamp': result.timestamp,
                            'token': token_address,
                            'size': trade_setup['size'],
                            'price_impact': result.price_impact,
                            'execution_time': result.execution_time_us,
                            'signature': result.signature
                        })
                    
                    return result
                    
        except Exception as e:
            logger.error(f"[ERROR] Trade execution error: {e}")
            return None

    async def run(self):
        """Main trading loop"""
        try:
            while True:
                # Your token address here
                token_address = "EPjFWdd5AufqSSqeM2qN1xzybapC8G4wEGGkZwyTDt1v"  # USDC
                await self.execute_quantum_trade(token_address)
                await asyncio.sleep(1)  # Adjust timing as needed
                
        except KeyboardInterrupt:
            logger.info("[SYSTEM] Shutting down...")
        except Exception as e:
            logger.error(f"[ERROR] Fatal error: {e}")

    def is_trading(self):
        """Check if trading is active"""
        return True

# Test the integration
async def test_integration():
    integration = QuantumTradingIntegration()
    await integration.run()

if __name__ == "__main__":
    asyncio.run(test_integration())import asyncio
import numpy as np
from dataclasses import dataclass
from datetime import datetime, timedelta
from typing import Dict, List, Optional
import logging
import torch
from concurrent.futures import ThreadPoolExecutor
from collections import deque
import json
import yaml

from enhanced_trading_core import EnhancedTradingCore
from quantum_analytics import QuantumAnalytics
from quantum_optimizer import QuantumOptimizer
from quantum_strategy import QuantumStrategy
from quantum_metrics import QuantumMetrics

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.FileHandler('trading_execution.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger("QuantumTrader")

@dataclass
class TradeSetup:
    token_address: str
    entry_price: float
    size: float
    stop_loss: float
    take_profit: float
    risk_amount: float
    expected_profit: float
    confidence: float
    timestamp: datetime

@dataclass
class TradingState:
    in_position: bool = False
    position_size: float = 0.0
    entry_price: float = 0.0
    current_profit: float = 0.0
    total_profit: float = 0.0
    trades_won: int = 0
    total_trades: int = 0
    peak_balance: float = 0.0
    max_drawdown: float = 0.0

class QuantumTradingBot:
    def __init__(self, config_path: str = 'config.yaml'):
        self.load_config(config_path)
        self.setup_components()
        self.state = TradingState()
        self.trade_history = deque(maxlen=1000)
        self.last_trade_time = None
        self.min_trade_interval = 0.5
        
        self.performance_metrics = {
            'win_rate': 0.0,
            'profit_factor': 0.0,
            'sharpe_ratio': 0.0,
            'max_drawdown': 0.0
        }
        
        logger.info("Quantum Trading Bot Initialized")

    def load_config(self, config_path: str):
        try:
            with open(config_path, 'r') as f:
                self.config = yaml.safe_load(f)
            logger.info("Configuration loaded")
        except Exception as e:
            logger.error(f"Config load failed: {e}")
            self.load_default_config()

    def load_default_config(self):
        self.config = {
            'max_position_size': 5.0,
            'risk_per_trade': 0.02,
            'min_profit_target': 0.015,
            'max_slippage': 0.005,
            'emergency_stop_loss': 0.05,
            'trading': {
                'execution_enabled': True,
                'max_retries': 3,
                'priority_fee': 15000
            },
            'helius_rpc': "https://marga-e56m84-fast-mainnet.helius-rpc.com",
            'helius_ws': "wss://marga-e56m84-fast-mainnet.helius-rpc.com",
            'backup_rpc': "https://mainnet.helius-rpc.xyz/?api-key=1ea5843b-9daa-4926-a97a-be021922da2f"
        }

    def setup_components(self):
        try:
            self.trader = EnhancedTradingCore()
            self.analytics = QuantumAnalytics(self.trader)
            self.optimizer = QuantumOptimizer()
            self.strategy = QuantumStrategy()
            self.metrics = QuantumMetrics()
            self.device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
            
            logger.info(f"Using device: {self.device}")
        except Exception as e:
            logger.error(f"Setup error: {e}")
            raise

    async def run(self):
        logger.info("Starting trading bot...")
        
        try:
            while True:
                await self.trading_cycle()
                await asyncio.sleep(1)
        except Exception as e:
            logger.error(f"Fatal error: {e}")
            await self.emergency_shutdown()

    async def trading_cycle(self):
        try:
            market_data = await self.analytics.get_market_data()
            signals = await self.strategy.analyze_market(market_data)
            await self.update_state(market_data)
            
            if self.state.in_position:
                await self.manage_position(market_data, signals)
            else:
                await self.look_for_entry(market_data, signals)
                
            self.update_performance_metrics()
            
        except Exception as e:
            logger.error(f"Cycle error: {e}")

    async def update_state(self, market_data: Dict):
        try:
            balance = await self.trader.get_balance()
            
            if balance > self.state.peak_balance:
                self.state.peak_balance = balance
            elif balance < self.state.peak_balance:
                drawdown = (self.state.peak_balance - balance) / self.state.peak_balance
                self.state.max_drawdown = max(self.state.max_drawdown, drawdown)
                
            if self.state.in_position:
                self.state.current_profit = (
                    market_data['price'] - self.state.entry_price
                ) * self.state.position_size
                
        except Exception as e:
            logger.error(f"State update error: {e}")

    async def look_for_entry(self, market_data: Dict, signals: Dict):
        if not self.should_enter(signals):
            return

        try:
            setup = await self.optimizer.optimize_trade(
                market_data, 
                signals['confidence']
            )
            
            if setup and self.validate_trade(setup):
                await self.execute_entry(setup)
                
        except Exception as e:
            logger.error(f"Entry analysis error: {e}")

    def should_enter(self, signals: Dict) -> bool:
        try:
            return (
                signals['confidence'] > 0.8 and
                not self.state.in_position and
                signals['signal'] in ['BUY', 'SELL']
            )
        except Exception as e:
            logger.error(f"Entry validation error: {e}")
            return False

    async def execute_entry(self, setup: TradeSetup):
        try:
            amount_lamports = int(setup.size * 1e9)
            
            result = await self.trader.execute_trade(
                output_mint=setup.token_address,
                amount_in=amount_lamports,
                max_price_impact=self.config.get('max_price_impact', 0.01)
            )
            
            if result.success:
                self.state.in_position = True
                self.state.position_size = setup.size
                self.state.entry_price = setup.entry_price
                self.log_trade('ENTRY', setup, result)
                
                logger.info(f"Entered position: {setup.size} @ ${setup.entry_price}")
                logger.info(f"Transaction: {result.signature}")
            else:
                logger.error(f"Entry failed: {result.error}")
                
        except Exception as e:
            logger.error(f"Entry execution error: {e}")

    async def manage_position(self, market_data: Dict, signals: Dict):
        try:
            if self.should_exit(market_data, signals):
                await self.execute_exit(market_data)
        except Exception as e:
            logger.error(f"Position management error: {e}")

    def should_exit(self, market_data: Dict, signals: Dict) -> bool:
        try:
            current_price = market_data['price']
            
            # Stop loss check
            stop_loss_hit = (
                current_price < self.state.entry_price * 
                (1 - self.config['emergency_stop_loss'])
            )
            
            # Take profit check
            take_profit_hit = (
                self.state.current_profit > 
                self.state.position_size * self.config['min_profit_target']
            )
            
            # Signal based exit
            signal_exit = (
                signals['signal'] == 'SELL' and 
                signals['confidence'] > 0.8
            )
            
            return stop_loss_hit or take_profit_hit or signal_exit
            
        except Exception as e:
            logger.error(f"Exit validation error: {e}")
            return False

    async def execute_exit(self, market_data: Dict):
        try:
            amount_lamports = int(self.state.position_size * 1e9)
            
            result = await self.trader.execute_trade(
                output_mint=market_data['token_address'],
                amount_in=amount_lamports
            )
            
            if result.success:
                profit = (
                    market_data['price'] - self.state.entry_price
                ) * self.state.position_size
                
                self.state.total_profit += profit
                if profit > 0:
                    self.state.trades_won += 1
                self.state.total_trades += 1
                
                self.state.in_position = False
                self.state.position_size = 0
                self.state.current_profit = 0
                
                self.log_trade('EXIT', None, result)
                
                logger.info(f"Exited position with profit: ${profit:.2f}")
                logger.info(f"Transaction: {result.signature}")
            else:
                logger.error(f"Exit failed: {result.error}")
                
        except Exception as e:
            logger.error(f"Exit execution error: {e}")
            await self.emergency_exit()

    async def emergency_exit(self):
        if self.state.in_position:
            try:
                logger.warning("Emergency exit initiated")
                market_data = await self.analytics.get_market_data()
                await self.execute_exit(market_data)
            except Exception as e:
                logger.error(f"Emergency exit failed: {e}")

    def validate_trade(self, setup: TradeSetup) -> bool:
        try:
            return (
                setup.size > 0 and
                setup.size <= self.config['max_position_size'] and
                setup.confidence >= 0.8 and
                setup.risk_amount <= self.config['risk_per_trade']
            )
        except Exception as e:
            logger.error(f"Trade validation error: {e}")
            return False

    def log_trade(self, trade_type: str, setup: Optional[TradeSetup], result: Dict):
        trade = {
            'timestamp': datetime.now(),
            'type': trade_type,
            'signature': result.signature,
            'size': self.state.position_size,
            'price_impact': result.price_impact,
            'execution_time': result.execution_time_us / 1_000_000,
            'profit': self.state.current_profit
        }
        self.trade_history.append(trade)
        self.metrics.add_trade(trade)

    def calculate_profit_factor(self) -> float:
        winning_trades = [t['profit'] for t in self.trade_history if t['profit'] > 0]
        losing_trades = [abs(t['profit']) for t in self.trade_history if t['profit'] < 0]
        
        if not losing_trades:
            return 0.0
            
        return sum(winning_trades) / sum(losing_trades)

    def calculate_sharpe_ratio(self) -> float:
        if len(self.trade_history) < 2:
            return 0.0
            
        profits = [t['profit'] for t in self.trade_history]
        return np.mean(profits) / (np.std(profits) + 1e-10)

    def update_performance_metrics(self):
        if self.state.total_trades == 0:
            return
            
        self.performance_metrics.update({
            'win_rate': self.state.trades_won / self.state.total_trades,
            'profit_factor': self.calculate_profit_factor(),
            'sharpe_ratio': self.calculate_sharpe_ratio(),
            'max_drawdown': self.state.max_drawdown
        })

    async def emergency_shutdown(self):
        logger.warning("Emergency shutdown initiated")
        
        try:
            await self.emergency_exit()
            self.save_state()
            
            logger.info("Final Performance:")
            logger.info(f"Total Profit: ${self.state.total_profit:.2f}")
            logger.info(f"Win Rate: {self.performance_metrics['win_rate']:.1%}")
            logger.info(f"Max Drawdown: {self.state.max_drawdown:.1%}")
            
        except Exception as e:
            logger.error(f"Shutdown error: {e}")
        finally:
            logger.info("Trading bot shutdown complete")

    def save_state(self):
        try:
            state = {
                'performance_metrics': self.performance_metrics,
                'trading_state': self.state.__dict__,
                'timestamp': datetime.now().isoformat()
            }
            
            with open('trading_state.json', 'w') as f:
                json.dump(state, f, default=str)
                
        except Exception as e:
            logger.error(f"State save error: {e}")

    def get_status(self) -> Dict:
        return {
            'in_position': self.state.in_position,
            'position_size': self.state.position_size,
            'current_profit': self.state.current_profit,
            'total_profit': self.state.total_profit,
            'trades_won': self.state.trades_won,
            'total_trades': self.state.total_trades,
            'performance': self.performance_metrics,
            'timestamp': datetime.now().isoformat()
        }

async def main():
    bot = QuantumTradingBot()
    try:
        await bot.run()
    except KeyboardInterrupt:
        logger.info("Bot stopped by user")
        await bot.emergency_shutdown()
    except Exception as e:
        logger.error(f"Bot error: {e}")
        await bot.emergency_shutdown()

if __name__ == "__main__":
    asyncio.run(main())from PyQt6.QtCore import QThread, pyqtSignal
import asyncio
from typing import Optional, Dict, Callable
import logging
import os
from datetime import datetime

# Configure logging
if not os.path.exists('logs'):
    os.makedirs('logs')

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.FileHandler(f'logs/thread_manager_{datetime.now().strftime("%Y%m%d")}.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger("TradingThread")

class AsyncTradingThread(QThread):
    """Properly handles async trading operations"""
    update_signal = pyqtSignal(dict)
    error_signal = pyqtSignal(str)
    completed_signal = pyqtSignal()
    status_signal = pyqtSignal(str)

    def __init__(self, async_function: Callable, *args, **kwargs):
        super().__init__()
        self.async_function = async_function
        self.args = args
        self.kwargs = kwargs
        self.loop: Optional[asyncio.AbstractEventLoop] = None
        self._is_running = True
        logger.info(f"Initialized AsyncTradingThread for {async_function.__name__}")

    def run(self):
        try:
            self.loop = asyncio.new_event_loop()
            asyncio.set_event_loop(self.loop)
            self.loop.run_until_complete(self._run_trading())
        except Exception as e:
            error_msg = f"Trading thread error: {str(e)}"
            logger.error(error_msg)
            self.error_signal.emit(error_msg)
        finally:
            if self.loop:
                self.loop.close()
            self.completed_signal.emit()

    async def _run_trading(self):
        try:
            self.status_signal.emit("Starting trading operation...")
            result = await self.async_function(*self.args, **self.kwargs)
            if result:
                self.update_signal.emit(result)
            logger.info(f"Trading operation completed: {self.async_function.__name__}")
        except Exception as e:
            error_msg = f"Trading operation error: {str(e)}"
            logger.error(error_msg)
            self.error_signal.emit(error_msg)
            raise

    def stop(self):
        """Gracefully stop the trading thread"""
        logger.info("Stopping trading thread...")
        self._is_running = False
        if self.loop and self.loop.is_running():
            self.loop.stop()
        self.wait()
        logger.info("Trading thread stopped")

class MonitorThread(QThread):
    """Monitors trading system health"""
    update_signal = pyqtSignal(dict)
    error_signal = pyqtSignal(str)
    status_signal = pyqtSignal(str)

    def __init__(self, trading_bot, update_interval: float = 1.0):
        super().__init__()
        self.bot = trading_bot
        self.update_interval = update_interval
        self._is_running = True
        logger.info("Initialized MonitorThread")

    def run(self):
        logger.info("Starting monitor thread")
        while self._is_running:
            try:
                if hasattr(self.bot, 'state'):
                    status = {
                        'balance': self.bot.state.position_size,
                        'in_position': self.bot.state.in_position,
                        'current_profit': self.bot.state.current_profit,
                        'total_profit': self.bot.state.total_profit,
                        'trades_won': self.bot.state.trades_won,
                        'total_trades': self.bot.state.total_trades,
                        'performance': self.bot.performance_metrics if hasattr(self.bot, 'performance_metrics') else {},
                        'timestamp': datetime.now().isoformat()
                    }
                    self.update_signal.emit(status)
                    self.status_signal.emit("Monitoring active")
                self.msleep(int(self.update_interval * 1000))
            except Exception as e:
                error_msg = f"Monitor error: {str(e)}"
                logger.error(error_msg)
                self.error_signal.emit(error_msg)
                self.msleep(5000)

    def stop(self):
        """Gracefully stop the monitor thread"""
        logger.info("Stopping monitor thread...")
        self._is_running = False
        self.wait()
        logger.info("Monitor thread stopped")

class EmergencyThread(QThread):
    """Handles emergency operations"""
    completed_signal = pyqtSignal(bool)
    error_signal = pyqtSignal(str)
    status_signal = pyqtSignal(str)

    def __init__(self, trading_bot):
        super().__init__()
        self.bot = trading_bot
        logger.info("Initialized EmergencyThread")

    def run(self):
        try:
            logger.warning("Running emergency shutdown...")
            self.status_signal.emit("Emergency shutdown in progress...")
            
            loop = asyncio.new_event_loop()
            asyncio.set_event_loop(loop)
            
            loop.run_until_complete(self.bot.emergency_shutdown())
            loop.close()
            
            logger.info("Emergency shutdown completed successfully")
            self.completed_signal.emit(True)
            self.status_signal.emit("Emergency shutdown completed")
            
        except Exception as e:
            error_msg = f"Emergency shutdown error: {str(e)}"
            logger.error(error_msg)
            self.error_signal.emit(error_msg)
            self.completed_signal.emit(False)
 import numpy as np
import pandas as pd
from typing import Dict, List, Optional, Tuple
import logging
from datetime import datetime
import ta
from dataclasses import dataclass
from pathlib import Path

# Ensure log directory exists
log_dir = Path("logs")
log_dir.mkdir(exist_ok=True)

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.FileHandler('logs/strategy.log'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger("QuantumStrategy")

@dataclass
class StrategyResult:
    signal: str          # BUY, SELL, HOLD
    confidence: float    # 0.0 to 1.0
    entry_price: float
    stop_loss: float
    take_profit: float
    metadata: Dict

class QuantumStrategy:
    def __init__(self):
        self.strategies = {
            'momentum': self.momentum_strategy,     # Weight: 30%
            'liquidity': self.liquidity_strategy,   # Weight: 25%
            'breakout': self.breakout_strategy,     # Weight: 25%
            'mean_reversion': self.mean_reversion,  # Weight: 20%
        }
        
        self.weights = {
            'momentum': 0.30,
            'liquidity': 0.25,
            'breakout': 0.25,
            'mean_reversion': 0.20
        }
        
        self.strategy_performance = {
            name: {'wins': 0, 'losses': 0, 'profit': 0.0}
            for name in self.strategies.keys()
        }
        
        logger.info("Quantum Strategy System Initialized")

    async def momentum_strategy(self, data: Dict) -> StrategyResult:
        try:
            # Ensure data has required fields and convert to proper format
            prices = pd.Series(data.get('price_history', []), dtype=float)
            volume = pd.Series(data.get('volume_history', []), dtype=float)
            
            if len(prices) < 15:  # Need minimum data points
                return self.create_neutral_result(data)
                
            # Calculate indicators with proper error handling
            try:
                rsi = ta.momentum.RSIIndicator(prices, window=min(14, len(prices))).rsi()
                macd = ta.trend.MACD(prices)
                macd_line = macd.macd()
                signal_line = macd.macd_signal()
                
                if len(volume) >= len(prices):
                    obv = ta.volume.OnBalanceVolumeIndicator(prices, volume).on_balance_volume()
                else:
                    obv = pd.Series([0] * len(prices))
            except Exception as e:
                logger.error(f"Indicator calculation error: {e}")
                return self.create_neutral_result(data)
            
            signals = []
            
            # RSI Signals
            if not pd.isna(rsi.iloc[-1]):
                if rsi.iloc[-1] < 30 and prices.iloc[-1] > prices.iloc[-2]:
                    signals.append(1)
                elif rsi.iloc[-1] > 70 and prices.iloc[-1] < prices.iloc[-2]:
                    signals.append(-1)
            
            # MACD Signals
            if not pd.isna(macd_line.iloc[-1]) and not pd.isna(signal_line.iloc[-1]):
                if macd_line.iloc[-1] > signal_line.iloc[-1] and macd_line.iloc[-2] <= signal_line.iloc[-2]:
                    signals.append(1)
                elif macd_line.iloc[-1] < signal_line.iloc[-1] and macd_line.iloc[-2] >= signal_line.iloc[-2]:
                    signals.append(-1)
            
            # Volume Confirmation
            if not pd.isna(obv.iloc[-1]):
                if obv.iloc[-1] > obv.iloc[-2] and prices.iloc[-1] > prices.iloc[-2]:
                    signals.append(1)
                elif obv.iloc[-1] < obv.iloc[-2] and prices.iloc[-1] < prices.iloc[-2]:
                    signals.append(-1)
            
            signal_strength = np.mean(signals) if signals else 0
            
            return self.create_strategy_result(
                signal_strength,
                prices.iloc[-1],
                {
                    'rsi': float(rsi.iloc[-1]) if not pd.isna(rsi.iloc[-1]) else 50.0,
                    'macd': float(macd_line.iloc[-1]) if not pd.isna(macd_line.iloc[-1]) else 0.0,
                    'obv': float(obv.iloc[-1]) if not pd.isna(obv.iloc[-1]) else 0.0
                }
            )
            
        except Exception as e:
            logger.error(f"Momentum strategy error: {e}")
            return self.create_neutral_result(data)

    async def liquidity_strategy(self, data: Dict) -> StrategyResult:
        try:
            metrics = data.get('metrics', {})
            current_price = metrics.get('price', 0)
            if not current_price:
                return self.create_neutral_result(data)
                
            orderbook = data.get('orderbook', {'bids': [], 'asks': []})
            if not orderbook['bids'] or not orderbook['asks']:
                return self.create_neutral_result(data)
            
            # Calculate liquidity metrics safely
            bid_liquidity = sum(
                float(bid.get('size', 0)) * float(bid.get('price', 0)) 
                for bid in orderbook['bids'][:10]
            )
            ask_liquidity = sum(
                float(ask.get('size', 0)) * float(ask.get('price', 0)) 
                for ask in orderbook['asks'][:10]
            )
            
            total_liquidity = bid_liquidity + ask_liquidity
            if total_liquidity == 0:
                return self.create_neutral_result(data)
                
            imbalance = (bid_liquidity - ask_liquidity) / total_liquidity
            confidence = min(abs(imbalance) * 2, 1.0)
            
            return self.create_strategy_result(
                imbalance,
                current_price,
                {
                    'bid_liquidity': bid_liquidity,
                    'ask_liquidity': ask_liquidity,
                    'imbalance': imbalance,
                    'total_liquidity': total_liquidity
                },
                confidence=confidence
            )
            
        except Exception as e:
            logger.error(f"Liquidity strategy error: {e}")
            return self.create_neutral_result(data)

    async def breakout_strategy(self, data: Dict) -> StrategyResult:
        try:
            # Convert price data to pandas Series with proper dtype
            prices = pd.Series(data.get('price_history', []), dtype=float)
            volume = pd.Series(data.get('volume_history', []), dtype=float)
            high_prices = pd.Series(data.get('high_history', []), dtype=float)
            low_prices = pd.Series(data.get('low_history', []), dtype=float)
            
            if len(prices) < 20:  # Need enough data for BB calculation
                return self.create_neutral_result(data)
            
            try:
                # Calculate Bollinger Bands
                bb_indicator = ta.volatility.BollingerBands(prices)
                upper = bb_indicator.bollinger_hband()
                middle = bb_indicator.bollinger_mavg()
                lower = bb_indicator.bollinger_lband()
                
                # Calculate ATR if we have high/low data
                if len(high_prices) >= len(prices) and len(low_prices) >= len(prices):
                    atr = ta.volatility.AverageTrueRange(
                        high_prices, low_prices, prices
                    ).average_true_range()
                else:
                    atr = pd.Series([prices.std()])
                
                # Volume confirmation
                volume_sma = volume.rolling(window=20).mean()
                volume_surge = volume.iloc[-1] > volume_sma.iloc[-1] * 1.5 if not pd.isna(volume_sma.iloc[-1]) else False
                
            except Exception as e:
                logger.error(f"Indicator calculation error: {e}")
                return self.create_neutral_result(data)
            
            signal = 0
            confidence = 0
            
            # Check for breakout conditions
            if not pd.isna(upper.iloc[-1]) and not pd.isna(lower.iloc[-1]):
                if prices.iloc[-1] > upper.iloc[-1] and prices.iloc[-2] <= upper.iloc[-2] and volume_surge:
                    signal = 1
                    confidence = (prices.iloc[-1] - upper.iloc[-1]) / upper.iloc[-1]
                elif prices.iloc[-1] < lower.iloc[-1] and prices.iloc[-2] >= lower.iloc[-2] and volume_surge:
                    signal = -1
                    confidence = (lower.iloc[-1] - prices.iloc[-1]) / lower.iloc[-1]
            
            return self.create_strategy_result(
                signal,
                prices.iloc[-1],
                {
                    'bb_width': float((upper.iloc[-1] - lower.iloc[-1]) / middle.iloc[-1]) if not pd.isna(middle.iloc[-1]) else 0.0,
                    'atr': float(atr.iloc[-1]) if not pd.isna(atr.iloc[-1]) else 0.0,
                    'volume_surge': volume_surge
                },
                confidence=min(confidence * 2, 1.0)
            )
            
        except Exception as e:
            logger.error(f"Breakout strategy error: {e}")
            return self.create_neutral_result(data)

    async def mean_reversion(self, data: Dict) -> StrategyResult:
        try:
            prices = pd.Series(data.get('price_history', []), dtype=float)
            
            if len(prices) < 20:
                return self.create_neutral_result(data)
            
            try:
                # Calculate indicators
                sma = ta.trend.SMAIndicator(prices, window=20).sma_indicator()
                std = prices.rolling(window=20).std()
                upper_band = sma + (2 * std)
                lower_band = sma - (2 * std)
                rsi = ta.momentum.RSIIndicator(prices).rsi()
                
            except Exception as e:
                logger.error(f"Indicator calculation error: {e}")
                return self.create_neutral_result(data)
            
            signal = 0
            confidence = 0
            
            # Check for mean reversion conditions
            if not pd.isna(lower_band.iloc[-1]) and not pd.isna(upper_band.iloc[-1]) and not pd.isna(rsi.iloc[-1]):
                if prices.iloc[-1] < lower_band.iloc[-1] and rsi.iloc[-1] < 30:
                    signal = 1
                    confidence = (lower_band.iloc[-1] - prices.iloc[-1]) / lower_band.iloc[-1]
                elif prices.iloc[-1] > upper_band.iloc[-1] and rsi.iloc[-1] > 70:
                    signal = -1
                    confidence = (prices.iloc[-1] - upper_band.iloc[-1]) / upper_band.iloc[-1]
            
            return self.create_strategy_result(
                signal,
                prices.iloc[-1],
                {
                    'sma': float(sma.iloc[-1]) if not pd.isna(sma.iloc[-1]) else prices.iloc[-1],
                    'std': float(std.iloc[-1]) if not pd.isna(std.iloc[-1]) else 0.0,
                    'rsi': float(rsi.iloc[-1]) if not pd.isna(rsi.iloc[-1]) else 50.0
                },
                confidence=min(confidence * 2, 1.0)
            )
            
        except Exception as e:
            logger.error(f"Mean reversion strategy error: {e}")
            return self.create_neutral_result(data)

    def create_strategy_result(
        self, 
        signal_strength: float,
        current_price: float,
        metadata: Dict,
        confidence: Optional[float] = None
    ) -> StrategyResult:
        try:
            if confidence is None:
                confidence = abs(signal_strength)
                
            if abs(signal_strength) < 0.2:
                signal = "HOLD"
            else:
                signal = "BUY" if signal_strength > 0 else "SELL"
                
            volatility = metadata.get('atr', current_price * 0.02)
            stop_distance = max(volatility * 2, current_price * 0.01)
            
            if signal == "BUY":
                stop_loss = current_price - stop_distance
                take_profit = current_price + (stop_distance * 2)
            elif signal == "SELL":
                stop_loss = current_price + stop_distance
                take_profit = current_price - (stop_distance * 2)
            else:
                stop_loss = take_profit = current_price
                
            return StrategyResult(
                signal=signal,
                confidence=confidence,
                entry_price=current_price,
                stop_loss=stop_loss,
                take_profit=take_profit,
                metadata=metadata
            )
            
        except Exception as e:
            logger.error(f"Strategy result creation error: {e}")
            return self.create_neutral_result({'price': current_price})

    def create_neutral_result(self, data: Dict) -> StrategyResult:
        """Create a neutral trading signal with safe defaults"""
        current_price = float(data.get('price', 0))
        return StrategyResult(
            signal="HOLD",
            confidence=0.0,
            entry_price=current_price,
            stop_loss=current_price,
            take_profit=current_price,
            metadata={}
        )

    async def analyze_market(self, data: Dict) -> Dict:
        try:
            signals = {}
            weighted_signal = 0
            total_weight = 0
            
            # Enhance market data with additional metrics
            enhanced_data = {
                **data,
                'volatility': self.calculate_volatility(data),
                'market_depth': self.calculate_market_depth(data)
            }
            
            # Get signals from each strategy
            for name, strategy in self.strategies.items():
                try:
                    result = await strategy(enhanced_data)
                    signals[name] = result
                    
                    signal_value = 0
                    if result.signal == "BUY":
                        signal_value = 1
                    elif result.signal == "SELL":
                        signal_value = -1
                        
                    weight = self.weights[name]
                    weighted_signal += signal_value * weight * result.confidence
                    total_weight += weight
                    
                except Exception as e:
                    logger.error(f"Strategy {name} error: {e}")
                    continue
                    
            if total_weight == 0:
                return {
                    'signal': "HOLD",
                    'confidence': 0.0,
                     'strategies': signals,
                    'weighted_signal': 0.0,
                    'market_metrics': enhanced_data
                }
                
            # Calculate final signal
            final_signal = weighted_signal / total_weight
            
            # Determine final trading decision
            if abs(final_signal) < 0.3:
                signal = "HOLD"
                confidence = 0.0
            else:
                signal = "BUY" if final_signal > 0 else "SELL"
                confidence = abs(final_signal)
                
            return {
                'signal': signal,
                'confidence': confidence,
                'strategies': signals,
                'weighted_signal': final_signal,
                'market_metrics': {
                    'volatility': enhanced_data['volatility'],
                    'market_depth': enhanced_data['market_depth']
                }
            }
            
        except Exception as e:
            logger.error(f"Market analysis error: {e}")
            return {
                'signal': "HOLD",
                'confidence': 0.0,
                'strategies': {},
                'weighted_signal': 0.0,
                'market_metrics': {}
            }

    def calculate_volatility(self, data: Dict) -> float:
        """Calculate market volatility safely"""
        try:
            prices = data.get('price_history', [])
            if len(prices) < 2:
                return 0.0
            
            # Convert to numpy array and handle any potential string values
            prices = np.array(prices, dtype=float)
            if np.any(prices <= 0):
                return 0.0
                
            returns = np.diff(np.log(prices))
            return float(np.std(returns) * np.sqrt(len(returns)))
            
        except Exception as e:
            logger.error(f"Volatility calculation error: {e}")
            return 0.0

    def calculate_market_depth(self, data: Dict) -> float:
        """Calculate market depth safely"""
        try:
            orderbook = data.get('orderbook', {'bids': [], 'asks': []})
            bids = orderbook['bids'][:10]
            asks = orderbook['asks'][:10]
            
            # Calculate total liquidity safely
            bid_depth = sum(
                float(bid.get('size', 0)) * float(bid.get('price', 0)) 
                for bid in bids
            )
            ask_depth = sum(
                float(ask.get('size', 0)) * float(ask.get('price', 0)) 
                for ask in asks
            )
            
            return bid_depth + ask_depth
            
        except Exception as e:
            logger.error(f"Market depth calculation error: {e}")
            return 0.0

    async def update_performance(self, trade_result: Dict):
        """Update strategy performance metrics"""
        try:
            signal = trade_result.get('signal', '')
            profit = trade_result.get('profit', 0.0)
            
            # Update performance for strategies that matched the signal
            for strategy, result in trade_result.get('strategies', {}).items():
                if result.signal == signal:
                    perf = self.strategy_performance[strategy]
                    if profit > 0:
                        perf['wins'] += 1
                    else:
                        perf['losses'] += 1
                    perf['profit'] += profit
            
            # Adjust strategy weights based on performance
            await self.update_weights()
            
        except Exception as e:
            logger.error(f"Performance update error: {e}")

    async def update_weights(self):
        """Update strategy weights based on performance"""
        try:
            total_profit = sum(
                perf['profit'] 
                for perf in self.strategy_performance.values()
            )
            
            if total_profit <= 0:
                return
                
            # Calculate new weights based on performance
            new_weights = {}
            for name, perf in self.strategy_performance.items():
                profit_contribution = perf['profit'] / total_profit if total_profit > 0 else 0
                new_weights[name] = 0.1 + (profit_contribution * 0.9)  # Keep minimum 10% weight
                
            # Normalize weights
            total_weight = sum(new_weights.values())
            self.weights = {
                name: weight / total_weight 
                for name, weight in new_weights.items()
            }
            
            logger.info(f"Updated strategy weights: {self.weights}")
            
        except Exception as e:
            logger.error(f"Weight update error: {e}")

    def get_performance_metrics(self) -> Dict:
        """Get current performance metrics for all strategies"""
        try:
            metrics = {}
            for name, perf in self.strategy_performance.items():
                total_trades = perf['wins'] + perf['losses']
                win_rate = perf['wins'] / max(1, total_trades)
                
                metrics[name] = {
                    'win_rate': win_rate,
                    'profit': perf['profit'],
                    'weight': self.weights[name],
                    'trades': total_trades,
                    'wins': perf['wins'],
                    'losses': perf['losses']
                }
                
            return metrics
            
        except Exception as e:
            logger.error(f"Metrics calculation error: {e}")
            return {}

async def test_strategy():
    """Test strategy functionality"""
    try:
        strategy = QuantumStrategy()
        
        # Create test data with proper format
        test_data = {
            'price': 100.0,
            'price_history': [98.0 + i * 0.5 for i in range(100)],  # Upward trend
            'volume_history': [1000.0 + i * 10 for i in range(100)],
            'high_history': [99.0 + i * 0.5 for i in range(100)],
            'low_history': [97.0 + i * 0.5 for i in range(100)],
            'orderbook': {
                'bids': [{'price': 99.5 - i * 0.1, 'size': 100.0} for i in range(10)],
                'asks': [{'price': 100.5 + i * 0.1, 'size': 100.0} for i in range(10)]
            }
        }
        
        # Test market analysis
        result = await strategy.analyze_market(test_data)
        
        print("\n🚀 Strategy Test Results:")
        print(f"Signal: {result['signal']}")
        print(f"Confidence: {result['confidence']:.2f}")
        print("\n📊 Individual Strategy Results:")
        
        for name, strat_result in result['strategies'].items():
            print(f"\n{name}:")
            print(f"  Signal: {strat_result.signal}")
            print(f"  Confidence: {strat_result.confidence:.2f}")
            print(f"  Entry Price: {strat_result.entry_price:.2f}")
            print(f"  Stop Loss: {strat_result.stop_loss:.2f}")
            print(f"  Take Profit: {strat_result.take_profit:.2f}")
            
    except Exception as e:
        print(f"Strategy test error: {e}")
        raise

if __name__ == "__main__":
    import asyncio
    asyncio.run(test_strategy())import numpy as np
from typing import Dict, Optional
from dataclasses import dataclass
import logging
from datetime import datetime, timedelta
from enhanced_trading_core import EnhancedTradingCore

logging.basicConfig(
    level=logging.INFO,
    format='%(asctime)s [%(levelname)s] %(message)s',
    handlers=[
        logging.FileHandler('optimizer.log', encoding='utf-8'),
        logging.StreamHandler()
    ]
)
logger = logging.getLogger("QuantumOptimizer")

@dataclass
class OptimizedTrade:
    size: float
    entry_price: float
    stop_loss: float
    take_profit: float
    confidence: float
    expected_profit: float
    risk_ratio: float
    liquidity_score: float

class QuantumOptimizer:
    def __init__(self, max_position: float = 5.0):
        self.logger = logger
        self.logger.info("Quantum Optimizer initialized")
        self.max_position = max_position
        self.trader = EnhancedTradingCore()
        self.risk_history = []
        self.liquidity_cache = {}
        self.min_liquidity_threshold = 0.7
        
        # Market impact thresholds
        self.max_price_impact = 0.005  # 0.5%
        self.ideal_order_size = 0.1    # 10% of available liquidity

    async def execute_optimized_trade(self, token_address: str, signal_strength: float) -> Optional[Dict]:
        try:
            # Analyze liquidity first
            liquidity_score = await self.analyze_liquidity(token_address)
            if liquidity_score < self.min_liquidity_threshold:
                logger.warning(f"Insufficient liquidity: {liquidity_score}")
                return None

            # Calculate optimal size
            size = await self.calculate_optimal_size(token_address, liquidity_score)
            amount_lamports = int(size * 1e9)

            # Execute through core
            result = await self.trader.execute_trade(
                output_mint=token_address,
                amount_in=amount_lamports,
                max_price_impact=self.max_price_impact
            )

            if result.success:
                return {
                    'success': True,
                    'signature': result.signature,
                    'size': size,
                    'price_impact': result.price_impact,
                    'execution_time': result.execution_time_us / 1_000_000
                }
            else:
                logger.error(f"Trade execution failed: {result.error}")
                return None

        except Exception as e:
            logger.error(f"Optimization error: {str(e)}")
            return None

    async def analyze_liquidity(self, token_address: str) -> float:
        try:
            # Get market data from cache or fetch new
            if token_address in self.liquidity_cache:
                cache_time, data = self.liquidity_cache[token_address]
                if datetime.now() - cache_time < timedelta(minutes=5):
                    return data

            # Calculate liquidity metrics
            balance = await self.trader.get_balance()
            market_depth = await self.trader.get_market_depth()
            
            liquidity_score = min(1.0, market_depth / (balance * 10))
            
            # Cache result
            self.liquidity_cache[token_address] = (datetime.now(), liquidity_score)
            
            return liquidity_score

        except Exception as e:
            logger.error(f"Liquidity analysis error: {str(e)}")
            return 0.0

    async def calculate_optimal_size(self, token_address: str, liquidity_score: float) -> float:
        try:
            # Get current balance
            balance = await self.trader.get_balance()
            
            # Base position size (never more than 20% of balance)
            base_size = min(balance * 0.2, self.max_position)
            
            # Adjust for liquidity
            size = base_size * liquidity_score
            
            # Final safety check
            return min(size, balance * 0.99)  # Leave 1% for fees
            
        except Exception as e:
            logger.error(f"Size calculation error: {str(e)}")
            return 0.0

    async def optimize_entry_parameters(self, token_address: str, size: float) -> Dict:
        try:
            # Get current price
            market_data = await self.get_market_data(token_address)
            current_price = market_data['price']
            
            # Calculate optimal entry spread based on size
            entry_spread = self.calculate_optimal_spread(size, market_data)
            entry_price = current_price * (1 + entry_spread)
            
            # Dynamic stop loss and take profit
            volatility = market_data.get('volatility', 0.02)
            stop_distance = max(volatility * 2, 0.01)
            
            stop_loss = entry_price * (1 - stop_distance)
            take_profit = entry_price + (entry_price - stop_loss) * 2
            
            return {
                'entry_price': entry_price,
                'stop_loss': stop_loss,
                'take_profit': take_profit,
                'spread': entry_spread
            }
            
        except Exception as e:
            logger.error(f"Parameter optimization error: {str(e)}")
            return None

    def calculate_optimal_spread(self, size: float, market_data: Dict) -> float:
        try:
            orderbook = market_data['orderbook']
            
            # Calculate volume-weighted average spread
            total_volume = 0
            weighted_spread = 0
            
            for i in range(min(5, len(orderbook['asks']))):
                ask = orderbook['asks'][i]
                bid = orderbook['bids'][i]
                volume = (float(ask['size']) + float(bid['size'])) / 2
                spread = (float(ask['price']) - float(bid['price'])) / float(bid['price'])
                
                weighted_spread += spread * volume
                total_volume += volume
            
            if total_volume == 0:
                return 0.001  # Default 0.1% spread
                
            optimal_spread = weighted_spread / total_volume
            
            # Adjust for size
            size_factor = min(1.0, size / self.max_position)
            return optimal_spread * (1 + size_factor)
            
        except Exception as e:
            logger.error(f"Spread calculation error: {str(e)}")
            return 0.001

    def update_risk_metrics(self, trade_result: Dict):
        try:
            self.risk_history.append({
                'timestamp': datetime.now(),
                'size': trade_result['size'],
                'price_impact': trade_result['price_impact'],
                'success': trade_result['success']
            })
            
            # Keep only last 1000 trades
            if len(self.risk_history) > 1000:
                self.risk_history.pop(0)
                
            # Update risk thresholds based on history
            self.update_risk_thresholds()
            
        except Exception as e:
            logger.error(f"Risk metrics update error: {str(e)}")

    def update_risk_thresholds(self):
        try:
            recent_trades = self.risk_history[-100:]
            if not recent_trades:
                return
                
            # Calculate success rate by size
            sizes = np.array([t['size'] for t in recent_trades])
            impacts = np.array([t['price_impact'] for t in recent_trades])
            successes = np.array([t['success'] for t in recent_trades])
            
            # Update optimal size based on success rate
            size_quantiles = np.percentile(sizes, [25, 50, 75])
            success_rates = []
            
            for sq in size_quantiles:
                mask = sizes <= sq
                if np.any(mask):
                    success_rate = np.mean(successes[mask])
                    success_rates.append(success_rate)
            
            if success_rates:
                optimal_quantile = size_quantiles[np.argmax(success_rates)]
                self.max_position = min(self.max_position, optimal_quantile * 1.2)
            
            # Update price impact threshold
            self.max_price_impact = np.percentile(impacts[successes], 75) * 1.1
            
        except Exception as e:
            logger.error(f"Risk threshold update error: {str(e)}")

    async def get_market_data(self, token_address: str) -> Dict:
        try:
            return {
                'price': await self.trader.get_balance(),
                'orderbook': {'asks': [], 'bids': []},
                'volatility': 0.02
            }
        except Exception as e:
            logger.error(f"Market data error: {str(e)}")
            return {
                'price': 0,
                'orderbook': {'asks': [], 'bids': []},
                'volatility': 0.02
            }

    def get_optimization_metrics(self) -> Dict:
        try:
            return {
                'max_position': self.max_position,
                'max_price_impact': self.max_price_impact,
                'liquidity_threshold': self.min_liquidity_threshold,
                'risk_history_length': len(self.risk_history)
            }
        except Exception as e:
            logger.error(f"Metrics retrieval error: {str(e)}")
            return {}