import numpy as np import pandas as pd from typing import Dict, List, Optional import logging from datetime import datetime, timedelta import requests from textblob import TextBlob import tweepy from newsapi import NewsApiClient import yfinance as yf from concurrent.futures import ThreadPoolExecutor import json import os logger = logging.getLogger(__name__) class SentimentAnalyzer: def __init__(self, config: Dict): self.config = config self.news_api = NewsApiClient(api_key=config['news_api_key']) self.twitter_auth = tweepy.OAuthHandler( config['twitter_api_key'], config['twitter_api_secret'] ) self.twitter_auth.set_access_token( config['twitter_access_token'], config['twitter_access_token_secret'] ) self.twitter_api = tweepy.API(self.twitter_auth) # Initialize sentiment cache self.sentiment_cache = {} self.cache_duration = timedelta(hours=1) def analyze_text(self, text: str) -> float: """ Analyze sentiment of a single text using TextBlob """ try: analysis = TextBlob(text) # Normalize sentiment score to [-1, 1] return analysis.sentiment.polarity except Exception as e: logger.error(f"Error analyzing text: {str(e)}") return 0.0 def get_news_sentiment(self, symbol: str) -> Optional[float]: """ Get sentiment from news articles """ try: # Check cache first cache_key = f"news_{symbol}" if cache_key in self.sentiment_cache: cached_data = self.sentiment_cache[cache_key] if datetime.now() - cached_data['timestamp'] < self.cache_duration: return cached_data['sentiment'] # Get news articles news = self.news_api.get_everything( q=symbol, language='en', from_param=(datetime.now() - timedelta(days=1)).strftime('%Y-%m-%d'), sort_by='relevancy' ) if not news['articles']: return None # Analyze sentiment of each article sentiments = [] for article in news['articles']: title_sentiment = self.analyze_text(article['title']) if article['description']: desc_sentiment = self.analyze_text(article['description']) sentiments.append((title_sentiment + desc_sentiment) / 2) else: sentiments.append(title_sentiment) # Calculate weighted average sentiment avg_sentiment = np.mean(sentiments) # Cache the result self.sentiment_cache[cache_key] = { 'sentiment': avg_sentiment, 'timestamp': datetime.now() } return avg_sentiment except Exception as e: logger.error(f"Error getting news sentiment: {str(e)}") return None def get_twitter_sentiment(self, symbol: str) -> Optional[float]: """ Get sentiment from Twitter """ try: # Check cache first cache_key = f"twitter_{symbol}" if cache_key in self.sentiment_cache: cached_data = self.sentiment_cache[cache_key] if datetime.now() - cached_data['timestamp'] < self.cache_duration: return cached_data['sentiment'] # Get tweets tweets = self.twitter_api.search_tweets( q=f"${symbol}", lang="en", count=100 ) if not tweets: return None # Analyze sentiment of each tweet sentiments = [] for tweet in tweets: sentiment = self.analyze_text(tweet.text) sentiments.append(sentiment) # Calculate weighted average sentiment avg_sentiment = np.mean(sentiments) # Cache the result self.sentiment_cache[cache_key] = { 'sentiment': avg_sentiment, 'timestamp': datetime.now() } return avg_sentiment except Exception as e: logger.error(f"Error getting Twitter sentiment: {str(e)}") return None def get_market_sentiment(self, symbol: str) -> Optional[float]: """ Get market sentiment indicators """ try: # Check cache first cache_key = f"market_{symbol}" if cache_key in self.sentiment_cache: cached_data = self.sentiment_cache[cache_key] if datetime.now() - cached_data['timestamp'] < self.cache_duration: return cached_data['sentiment'] # Get market data ticker = yf.Ticker(symbol) info = ticker.info # Calculate various sentiment indicators sentiment_indicators = [] # RSI sentiment if 'RSI' in info: rsi = info['RSI'] rsi_sentiment = (rsi - 50) / 50 # Normalize to [-1, 1] sentiment_indicators.append(rsi_sentiment) # Volume sentiment if 'volume' in info and 'averageVolume' in info: volume_ratio = info['volume'] / info['averageVolume'] volume_sentiment = (volume_ratio - 1) / volume_ratio # Normalize to [-1, 1] sentiment_indicators.append(volume_sentiment) # Price momentum sentiment if 'regularMarketChangePercent' in info: momentum_sentiment = info['regularMarketChangePercent'] / 100 sentiment_indicators.append(momentum_sentiment) if not sentiment_indicators: return None # Calculate weighted average sentiment avg_sentiment = np.mean(sentiment_indicators) # Cache the result self.sentiment_cache[cache_key] = { 'sentiment': avg_sentiment, 'timestamp': datetime.now() } return avg_sentiment except Exception as e: logger.error(f"Error getting market sentiment: {str(e)}") return None def get_combined_sentiment(self, symbol: str) -> Optional[float]: """ Get combined sentiment from all sources """ try: # Check cache first cache_key = f"combined_{symbol}" if cache_key in self.sentiment_cache: cached_data = self.sentiment_cache[cache_key] if datetime.now() - cached_data['timestamp'] < self.cache_duration: return cached_data['sentiment'] # Get sentiment from all sources sentiments = [] weights = [] # News sentiment news_sentiment = self.get_news_sentiment(symbol) if news_sentiment is not None: sentiments.append(news_sentiment) weights.append(self.config['sentiment_weights']['news']) # Twitter sentiment twitter_sentiment = self.get_twitter_sentiment(symbol) if twitter_sentiment is not None: sentiments.append(twitter_sentiment) weights.append(self.config['sentiment_weights']['twitter']) # Market sentiment market_sentiment = self.get_market_sentiment(symbol) if market_sentiment is not None: sentiments.append(market_sentiment) weights.append(self.config['sentiment_weights']['market']) if not sentiments: return None # Calculate weighted average sentiment avg_sentiment = np.average(sentiments, weights=weights) # Cache the result self.sentiment_cache[cache_key] = { 'sentiment': avg_sentiment, 'timestamp': datetime.now() } return avg_sentiment except Exception as e: logger.error(f"Error getting combined sentiment: {str(e)}") return None def clear_cache(self): """ Clear the sentiment cache """ self.sentiment_cache.clear() def get_sentiment_signal(self, symbol: str) -> int: """ Convert sentiment to trading signal """ sentiment = self.get_combined_sentiment(symbol) if sentiment is None: return 0 # Define sentiment thresholds positive_threshold = self.config['sentiment_thresholds']['positive'] negative_threshold = self.config['sentiment_thresholds']['negative'] if sentiment > positive_threshold: return 1 # Buy signal elif sentiment < negative_threshold: return -1 # Sell signal else: return 0 # Neutral signal import pandas as pd import plotly.graph_objects as go from plotly.subplots import make_subplots from typing import Dict, List import json import os def plot_backtest_results(results_file: str, save_path: str = None): """ Create interactive plots for backtest results """ # Load results with open(results_file, 'r') as f: results = json.load(f) # Convert data to DataFrames trades_df = pd.DataFrame(results['trades']) equity_df = pd.DataFrame(results['equity_curve']) # Create figure with secondary y-axis fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.03, subplot_titles=('Price and Trades', 'Equity Curve'), row_heights=[0.7, 0.3] ) # Add price line fig.add_trace( go.Scatter( x=trades_df['timestamp'], y=trades_df['price'], name='Price', line=dict(color='blue') ), row=1, col=1 ) # Add buy trades buy_trades = trades_df[trades_df['action'] == 'buy'] fig.add_trace( go.Scatter( x=buy_trades['timestamp'], y=buy_trades['price'], mode='markers', name='Buy', marker=dict(color='green', size=10) ), row=1, col=1 ) # Add sell trades sell_trades = trades_df[trades_df['action'] == 'sell'] fig.add_trace( go.Scatter( x=sell_trades['timestamp'], y=sell_trades['price'], mode='markers', name='Sell', marker=dict(color='red', size=10) ), row=1, col=1 ) # Add equity curve fig.add_trace( go.Scatter( x=equity_df['timestamp'], y=equity_df['equity'], name='Equity', line=dict(color='purple') ), row=2, col=1 ) # Update layout fig.update_layout( title='Backtest Results', xaxis_title='Date', yaxis_title='Price', yaxis2_title='Equity', showlegend=True, height=800 ) # Save plot if path is provided if save_path: fig.write_html(save_path) print(f"Plot saved to {save_path}") return fig def plot_performance_metrics(results_files: List[str], save_path: str = None): """ Create comparison plot of performance metrics across different scenarios """ metrics_data = [] for file in results_files: with open(file, 'r') as f: results = json.load(f) metrics = results['performance_metrics'] # Extract scenario name from filename scenario_name = os.path.basename(file).replace('backtest_results_', '').replace('.json', '') metrics_data.append({ 'Scenario': scenario_name, 'Total Return': metrics['total_return'], 'Annual Return': metrics['annual_return'], 'Sharpe Ratio': metrics['sharpe_ratio'], 'Max Drawdown': metrics['max_drawdown'], 'Win Rate': metrics['win_rate'] }) # Create DataFrame df = pd.DataFrame(metrics_data) # Create figure fig = go.Figure() # Add bars for each metric metrics = ['Total Return', 'Annual Return', 'Sharpe Ratio', 'Max Drawdown', 'Win Rate'] for metric in metrics: fig.add_trace( go.Bar( name=metric, x=df['Scenario'], y=df[metric] ) ) # Update layout fig.update_layout( title='Performance Metrics Comparison', xaxis_title='Scenario', yaxis_title='Value', barmode='group', height=600 ) # Save plot if path is provided if save_path: fig.write_html(save_path) print(f"Plot saved to {save_path}") return fig def main(): # Example usage results_dir = 'backtest_results' results_files = [ os.path.join(results_dir, f) for f in os.listdir(results_dir) if f.startswith('backtest_results_') and f.endswith('.json') ] # Create plots for each scenario for file in results_files: scenario_name = os.path.basename(file).replace('.json', '') plot_path = os.path.join(results_dir, f'{scenario_name}_plot.html') plot_backtest_results(file, plot_path) # Create comparison plot comparison_path = os.path.join(results_dir, 'performance_comparison.html') plot_performance_metrics(results_files, comparison_path) if __name__ == "__main__": main() import os import sys from datetime import datetime, timedelta import logging from src.backtesting import Backtester # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('backtest.log'), logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger(__name__) def run_backtest_scenarios(): # Load configuration config_path = os.path.join(os.path.dirname(__file__), 'config', 'config.json') # Create backtester backtester = Backtester(config_path) # Define test scenarios scenarios = [ { 'name': 'BTC/USDT 1h - Last 30 days', 'symbol': 'BTC/USDT', 'timeframe': '1h', 'days': 30 }, { 'name': 'ETH/USDT 4h - Last 60 days', 'symbol': 'ETH/USDT', 'timeframe': '4h', 'days': 60 }, { 'name': 'BTC/USDT 1d - Last 90 days', 'symbol': 'BTC/USDT', 'timeframe': '1d', 'days': 90 } ] # Run each scenario for scenario in scenarios: logger.info(f"\nRunning scenario: {scenario['name']}") # Calculate date range end_date = datetime.now() start_date = end_date - timedelta(days=scenario['days']) # Run backtest results = backtester.run_backtest( symbol=scenario['symbol'], timeframe=scenario['timeframe'], start_date=start_date, end_date=end_date, initial_capital=50.0 ) if results: # Print performance metrics metrics = results['performance_metrics'] print(f"\nResults for {scenario['name']}:") print(f"Total Trades: {metrics['total_trades']}") print(f"Win Rate: {metrics['win_rate']:.2%}") print(f"Total Return: {metrics['total_return']:.2%}") print(f"Annual Return: {metrics['annual_return']:.2%}") print(f"Sharpe Ratio: {metrics['sharpe_ratio']:.2f}") print(f"Max Drawdown: {metrics['max_drawdown']:.2%}") # Save results filename = f"backtest_results_{scenario['symbol'].replace('/', '_')}_{scenario['timeframe']}.json" backtester.save_results(filename) logger.info(f"Results saved to {filename}") else: logger.error(f"Backtest failed for scenario: {scenario['name']}") if __name__ == "__main__": run_backtest_scenarios() import pandas as pd import numpy as np from datetime import datetime, timedelta import logging from typing import Dict, List, Optional import ccxt from concurrent.futures import ThreadPoolExecutor import json import os from .trading_strategy import TradingStrategy from .config import load_config logger = logging.getLogger(__name__) class Backtester: def __init__(self, config_path: str): # Load configuration self.config = load_config(config_path) # Initialize exchange self.exchange = self._initialize_exchange() # Initialize trading strategy self.strategy = TradingStrategy(self.config) # Initialize results storage self.results = { 'trades': [], 'equity_curve': [], 'performance_metrics': {} } def _initialize_exchange(self) -> ccxt.Exchange: """Initialize the cryptocurrency exchange""" try: exchange_class = getattr(ccxt, self.config['exchange']['name']) exchange = exchange_class({ 'apiKey': self.config['exchange']['api_key'], 'secret': self.config['exchange']['api_secret'], 'enableRateLimit': True }) # Test connection exchange.load_markets() logger.info(f"Successfully connected to {self.config['exchange']['name']}") return exchange except Exception as e: logger.error(f"Error initializing exchange: {str(e)}") raise def fetch_historical_data(self, symbol: str, timeframe: str, start_date: datetime, end_date: datetime) -> pd.DataFrame: """Fetch historical market data""" try: # Convert dates to timestamps start_timestamp = int(start_date.timestamp() * 1000) end_timestamp = int(end_date.timestamp() * 1000) # Fetch OHLCV data ohlcv = self.exchange.fetch_ohlcv( symbol, timeframe=timeframe, since=start_timestamp, limit=1000 # Maximum limit per request ) # Convert to DataFrame df = pd.DataFrame( ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'] ) # Convert timestamp to datetime df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') df.set_index('timestamp', inplace=True) return df except Exception as e: logger.error(f"Error fetching historical data for {symbol}: {str(e)}") return None def run_backtest(self, symbol: str, timeframe: str, start_date: datetime, end_date: datetime, initial_capital: float = 50.0) -> Dict: """Run backtest for a given period""" try: logger.info(f"Starting backtest for {symbol} from {start_date} to {end_date}") # Fetch historical data df = self.fetch_historical_data(symbol, timeframe, start_date, end_date) if df is None: raise ValueError("Failed to fetch historical data") # Initialize variables current_capital = initial_capital position = 0 entry_price = 0 trades = [] equity_curve = [] # Iterate through data for i in range(len(df)): current_data = df.iloc[:i+1] current_price = current_data['close'].iloc[-1] # Generate trading signal signal = self.strategy.analyze_market(symbol, current_data) if signal: # Execute trade if conditions are met if signal.action == 'buy' and position <= 0: position = 1 entry_price = current_price trades.append({ 'timestamp': current_data.index[-1], 'action': 'buy', 'price': current_price, 'position_size': signal.position_size }) elif signal.action == 'sell' and position >= 0: position = -1 entry_price = current_price trades.append({ 'timestamp': current_data.index[-1], 'action': 'sell', 'price': current_price, 'position_size': signal.position_size }) # Update position PnL if position != 0: pnl = position * (current_price - entry_price) * signal.position_size current_capital += pnl # Record equity equity_curve.append({ 'timestamp': current_data.index[-1], 'equity': current_capital }) # Calculate performance metrics self.results['trades'] = trades self.results['equity_curve'] = equity_curve self.results['performance_metrics'] = self._calculate_performance_metrics(trades) return self.results except Exception as e: logger.error(f"Error running backtest: {str(e)}") return None def _calculate_performance_metrics(self, trades: List[Dict]) -> Dict: """Calculate performance metrics from trades""" if not trades: return {} # Convert trades to DataFrame df = pd.DataFrame(trades) # Calculate basic metrics total_trades = len(df) winning_trades = len(df[df['action'] == 'buy']) losing_trades = len(df[df['action'] == 'sell']) win_rate = winning_trades / total_trades if total_trades > 0 else 0 # Calculate returns returns = df['price'].pct_change() total_return = (1 + returns).prod() - 1 annual_return = (1 + total_return) ** (252 / len(df)) - 1 # Calculate risk metrics volatility = returns.std() * np.sqrt(252) sharpe_ratio = annual_return / volatility if volatility > 0 else 0 # Calculate drawdown cumulative_returns = (1 + returns).cumprod() rolling_max = cumulative_returns.expanding().max() drawdowns = (cumulative_returns - rolling_max) / rolling_max max_drawdown = drawdowns.min() return { 'total_trades': total_trades, 'winning_trades': winning_trades, 'losing_trades': losing_trades, 'win_rate': win_rate, 'total_return': total_return, 'annual_return': annual_return, 'volatility': volatility, 'sharpe_ratio': sharpe_ratio, 'max_drawdown': max_drawdown } def save_results(self, filepath: str): """Save backtest results to file""" try: with open(filepath, 'w') as f: json.dump(self.results, f, default=str) logger.info(f"Backtest results saved to {filepath}") return True except Exception as e: logger.error(f"Error saving results: {str(e)}") return False def load_results(self, filepath: str): """Load backtest results from file""" try: with open(filepath, 'r') as f: self.results = json.load(f) logger.info(f"Backtest results loaded from {filepath}") return True except Exception as e: logger.error(f"Error loading results: {str(e)}") return False def main(): # Load configuration config_path = os.path.join(os.path.dirname(__file__), '..', 'config', 'config.json') # Create backtester backtester = Backtester(config_path) # Define backtest parameters symbol = "BTC/USDT" timeframe = "1h" start_date = datetime.now() - timedelta(days=30) end_date = datetime.now() initial_capital = 50.0 # Run backtest results = backtester.run_backtest( symbol=symbol, timeframe=timeframe, start_date=start_date, end_date=end_date, initial_capital=initial_capital ) if results: # Print performance metrics metrics = results['performance_metrics'] print("\nBacktest Results:") print(f"Total Trades: {metrics['total_trades']}") print(f"Win Rate: {metrics['win_rate']:.2%}") print(f"Total Return: {metrics['total_return']:.2%}") print(f"Annual Return: {metrics['annual_return']:.2%}") print(f"Sharpe Ratio: {metrics['sharpe_ratio']:.2f}") print(f"Max Drawdown: {metrics['max_drawdown']:.2%}") # Save results backtester.save_results('backtest_results.json') else: print("Backtest failed to complete") if __name__ == "__main__": main() # Core dependencies numpy==1.24.3 pandas==2.0.3 scipy==1.10.1 scikit-learn==1.3.0 # Deep Learning torch==2.0.1 tensorflow==2.13.0 keras==2.13.1 transformers==4.31.0 # Reinforcement Learning gym==0.26.2 stable-baselines3==2.0.0 # Trading & Financial ccxt==4.0.0 ta==0.10.2 yfinance==0.2.28 pandas-ta==0.3.14b0 # Data Processing & Analysis statsmodels==0.14.0 pyfolio==0.9.2 empyrical==0.5.5 # Sentiment Analysis textblob==0.17.1 vaderSentiment==3.3.2 newsapi-python==0.2.7 tweepy==4.14.0 praw==7.7.1 # Web Dashboard dash==2.11.1 dash-bootstrap-components==1.4.1 plotly==5.15.0 # System Monitoring psutil==5.9.5 py-cpuinfo==9.0.0 # Code Analysis pylint==2.17.5 astroid==2.15.6 radon==6.0.1 # Utilities python-dotenv==1.0.0 requests==2.31.0 websockets==11.0.3 aiohttp==3.8.5 schedule==1.2.0 # Testing pytest==7.4.0 pytest-asyncio==0.21.1 pytest-cov==4.1.0 # Documentation sphinx==7.1.2 sphinx-rtd-theme==1.2.2 # Development Tools black==23.7.0 isort==5.12.0 mypy==1.5.1 pre-commit==3.3.3 { "system": { "name": "Quantum Edge System", "version": "1.0.0", "log_level": "INFO", "dashboard_port": 8050 }, "trading": { "exchange": { "name": "binance", "testnet": true, "api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET" }, "markets": ["BTC/USD", "ETH/USD", "SOL/USD", "ADA/USD"], "timeframes": ["1m", "5m", "15m", "1h", "4h", "1d"], "default_leverage": 1.0, "position_types": ["long", "short"], "order_types": ["market", "limit", "stop_loss", "take_profit"] }, "ml_model": { "default_type": "lstm", "lstm": { "layers": [64, 32], "dropout": 0.2, "learning_rate": 0.001, "batch_size": 32, "epochs": 100, "validation_split": 0.2, "sequence_length": 60 }, "reinforcement": { "model_type": "ppo", "policy_network": [64, 64], "value_network": [64, 32], "learning_rate": 0.0003, "gamma": 0.99, "gae_lambda": 0.95, "clip_ratio": 0.2, "train_iterations": 80 }, "features": { "price": ["open", "high", "low", "close"], "volume": ["volume", "taker_buy_volume"], "technical": [ "rsi", "macd", "bollinger_bands", "moving_averages", "momentum", "volatility" ] } }, "risk_management": { "position_sizing": { "max_position_size": 0.1, "max_leverage": 3.0, "min_position_size": 0.01 }, "risk_limits": { "max_drawdown": 0.2, "var_limit": 0.05, "min_sharpe": 1.0, "max_correlation": 0.7 }, "stop_loss": { "default_percentage": 0.02, "trailing_stop": true, "activation_percentage": 0.01 }, "take_profit": { "default_percentage": 0.03, "trailing_take_profit": true, "activation_percentage": 0.015 }, "exposure_limits": { "max_total_exposure": 1.0, "max_single_market": 0.3, "max_correlated_exposure": 0.5 } }, "sentiment_analysis": { "providers": { "news": { "api_key": "YOUR_NEWS_API_KEY", "sources": ["reuters", "bloomberg", "coindesk"], "update_interval": 300 }, "social": { "twitter_api_key": "YOUR_TWITTER_API_KEY", "twitter_api_secret": "YOUR_TWITTER_API_SECRET", "reddit_client_id": "YOUR_REDDIT_CLIENT_ID", "reddit_client_secret": "YOUR_REDDIT_CLIENT_SECRET", "update_interval": 60 } }, "analysis": { "sentiment_window": 3600, "min_confidence": 0.6, "impact_threshold": 0.3, "correlation_threshold": 0.5 } }, "optimization": { "system": { "cpu_threshold": 80, "memory_threshold": 80, "network_latency_threshold": 1000, "optimization_interval": 3600 }, "trading": { "min_win_rate": 0.55, "min_profit_factor": 1.5, "max_drawdown": 0.2, "optimization_lookback": 1000 }, "ml_model": { "min_accuracy": 0.6, "min_sharpe": 1.0, "max_drawdown": 0.15, "retraining_interval": 86400 } }, "monitoring": { "metrics_update_interval": 60, "health_check_interval": 300, "alert_thresholds": { "cpu_usage": 90, "memory_usage": 90, "api_latency": 2000, "error_rate": 0.01 }, "performance_thresholds": { "min_daily_profit": -0.02, "max_daily_loss": -0.05, "min_win_rate": 0.5, "min_profit_factor": 1.2 } } } import logging import threading import queue import json import os from typing import Dict, List, Optional, Any, Tuple from dataclasses import dataclass from datetime import datetime import time import numpy as np import pandas as pd from concurrent.futures import ThreadPoolExecutor, as_completed from functools import wraps import traceback import signal import sys from .trading_system import TradingSystem, create_trading_system from .code_guardian import CodeGuardian, create_guardian from .system_monitor import SystemMonitor from .dashboard import create_dashboard from .risk_management import RiskManager, RiskMetrics from .sentiment_analysis import SentimentAnalyzer from .machine_learning_model import MachineLearningModel from .trading_environment import TradingEnvironment # Configure logging with rotation logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.handlers.RotatingFileHandler( 'logs/quantum_edge_system.log', maxBytes=10*1024*1024, # 10MB backupCount=5 ), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) def retry_on_failure(max_retries: int = 3, delay: float = 1.0): """Decorator for retrying failed operations""" def decorator(func): @wraps(func) def wrapper(*args, **kwargs): last_exception = None for attempt in range(max_retries): try: return func(*args, **kwargs) except Exception as e: last_exception = e logger.warning(f"Attempt {attempt + 1}/{max_retries} failed: {str(e)}") if attempt < max_retries - 1: time.sleep(delay * (attempt + 1)) # Exponential backoff logger.error(f"All {max_retries} attempts failed. Last error: {str(last_exception)}") raise last_exception return wrapper return decorator @dataclass class SystemHealth: """System health metrics""" cpu_usage: float memory_usage: float network_latency: float disk_usage: float error_rate: float last_check: datetime @dataclass class QuantumBotInstance: """Represents a Quantum Edge trading bot instance""" bot_id: str trading_system: TradingSystem ml_model: MachineLearningModel risk_manager: RiskManager sentiment_analyzer: SentimentAnalyzer trading_env: TradingEnvironment config: Dict status: str last_update: datetime performance_metrics: Dict message_queue: queue.Queue health_metrics: SystemHealth error_count: int recovery_attempts: int last_error: Optional[Exception] = None class QuantumEdgeSystem: def __init__(self, project_root: str, config_path: str): """Initialize the Quantum Edge System""" self.project_root = project_root self.load_config(config_path) self.bots: Dict[str, QuantumBotInstance] = {} self.code_guardian = create_guardian(project_root) self.system_monitor = SystemMonitor(project_root) self.message_queue = queue.Queue() self.running = True self.thread_pool = ThreadPoolExecutor(max_workers=10) self.error_threshold = self.config['monitoring']['alert_thresholds']['error_rate'] self.recovery_threshold = 3 # Initialize system components self._init_system_components() self._start_management_threads() self._init_dashboard() self._setup_signal_handlers() def _setup_signal_handlers(self): """Setup signal handlers for graceful shutdown""" signal.signal(signal.SIGINT, self._handle_shutdown) signal.signal(signal.SIGTERM, self._handle_shutdown) def _handle_shutdown(self, signum, frame): """Handle system shutdown signals""" logger.info(f"Received shutdown signal {signum}") self.stop() @retry_on_failure(max_retries=3, delay=2.0) def load_config(self, config_path: str): """Load system configuration with retry""" try: with open(config_path, 'r') as f: self.config = json.load(f) self.validate_config() except Exception as e: logger.error(f"Error loading config: {str(e)}") raise def validate_config(self): """Validate system configuration with detailed checks""" required_sections = ['trading', 'ml_model', 'risk_management', 'sentiment_analysis'] for section in required_sections: if section not in self.config: raise ValueError(f"Missing required config section: {section}") # Validate section-specific requirements if section == 'trading': self._validate_trading_config() elif section == 'ml_model': self._validate_ml_config() elif section == 'risk_management': self._validate_risk_config() elif section == 'sentiment_analysis': self._validate_sentiment_config() def _validate_trading_config(self): """Validate trading configuration""" trading_config = self.config['trading'] required_fields = ['exchange', 'markets', 'timeframes'] for field in required_fields: if field not in trading_config: raise ValueError(f"Missing required trading config field: {field}") if not trading_config['markets']: raise ValueError("No trading markets specified") if not trading_config['timeframes']: raise ValueError("No timeframes specified") def _validate_ml_config(self): """Validate ML configuration""" ml_config = self.config['ml_model'] if 'default_type' not in ml_config: raise ValueError("ML model default type not specified") if ml_config['default_type'] not in ['lstm', 'reinforcement']: raise ValueError(f"Invalid ML model type: {ml_config['default_type']}") def _validate_risk_config(self): """Validate risk management configuration""" risk_config = self.config['risk_management'] required_sections = ['position_sizing', 'risk_limits', 'stop_loss'] for section in required_sections: if section not in risk_config: raise ValueError(f"Missing required risk config section: {section}") def _validate_sentiment_config(self): """Validate sentiment analysis configuration""" sentiment_config = self.config['sentiment_analysis'] if 'providers' not in sentiment_config: raise ValueError("Sentiment analysis providers not specified") def _init_system_components(self): """Initialize system-wide components with error handling""" try: self.global_risk_manager = RiskManager(self.config['risk_management']) self.global_sentiment_analyzer = SentimentAnalyzer(self.config['sentiment_analysis']) self.performance_tracker = self._init_performance_tracker() self.health_metrics = SystemHealth( cpu_usage=0.0, memory_usage=0.0, network_latency=0.0, disk_usage=0.0, error_rate=0.0, last_check=datetime.now() ) except Exception as e: logger.error(f"Error initializing system components: {str(e)}") raise def _init_performance_tracker(self): """Initialize system-wide performance tracking with enhanced metrics""" return { 'system_metrics': {}, 'bot_metrics': {}, 'risk_metrics': {}, 'sentiment_metrics': {}, 'ml_metrics': {}, 'error_metrics': { 'total_errors': 0, 'error_types': {}, 'recovery_success_rate': 1.0 }, 'performance_metrics': { 'average_latency': 0.0, 'throughput': 0.0, 'resource_utilization': {} } } def _start_management_threads(self): """Start system management threads with enhanced monitoring""" self.threads = { 'monitor': threading.Thread(target=self._monitor_system), 'message_handler': threading.Thread(target=self._handle_messages), 'code_repair': threading.Thread(target=self._continuous_code_repair), 'performance_tracker': threading.Thread(target=self._track_performance), 'risk_monitor': threading.Thread(target=self._monitor_risk), 'sentiment_monitor': threading.Thread(target=self._monitor_sentiment), 'health_checker': threading.Thread(target=self._check_system_health) } for thread_name, thread in self.threads.items(): thread.daemon = True thread.name = f"quantum_edge_{thread_name}" thread.start() logger.info(f"Started thread: {thread_name}") def _check_system_health(self): """Continuously check system health""" while self.running: try: health_metrics = { 'cpu_usage': self.system_monitor.get_cpu_usage(), 'memory_usage': self.system_monitor.get_memory_usage(), 'network_latency': self.system_monitor.get_network_latency(), 'disk_usage': self.system_monitor.get_disk_usage(), 'error_rate': self._calculate_error_rate() } self.health_metrics = SystemHealth( **health_metrics, last_check=datetime.now() ) if self._is_system_unhealthy(): self._handle_system_health_issue() time.sleep(60) except Exception as e: logger.error(f"Error checking system health: {str(e)}") time.sleep(300) def _calculate_error_rate(self) -> float: """Calculate system-wide error rate""" total_errors = sum(bot.error_count for bot in self.bots.values()) total_operations = sum(bot.performance_metrics.get('total_operations', 0) for bot in self.bots.values()) return total_errors / total_operations if total_operations > 0 else 0.0 def _is_system_unhealthy(self) -> bool: """Determine if system is unhealthy""" thresholds = self.config['monitoring']['alert_thresholds'] return ( self.health_metrics.cpu_usage > thresholds['cpu_usage'] or self.health_metrics.memory_usage > thresholds['memory_usage'] or self.health_metrics.network_latency > thresholds['api_latency'] or self.health_metrics.error_rate > thresholds['error_rate'] ) def _handle_system_health_issue(self): """Handle system health issues""" logger.warning("System health issues detected") # Reduce system load self._optimize_system_performance() # Notify all bots self.broadcast_message({ 'type': 'system_alert', 'action': 'reduce_load', 'timestamp': datetime.now().isoformat() }) # Log health metrics logger.warning(f"Current health metrics: {self.health_metrics}") @retry_on_failure(max_retries=3, delay=2.0) def create_quantum_bot(self, config: Dict) -> str: """Create a new Quantum Edge bot instance with enhanced error handling""" try: bot_id = f"quantum_bot_{len(self.bots) + 1}" # Create bot-specific config bot_config = self._create_bot_config(config) config_path = os.path.join(self.project_root, 'config', f'{bot_id}_config.json') # Save config with retry self._save_bot_config(config_path, bot_config) # Initialize bot components with parallel execution components = self._initialize_bot_components(bot_config) # Create bot instance with health monitoring bot = QuantumBotInstance( bot_id=bot_id, trading_system=components['trading_system'], ml_model=components['ml_model'], risk_manager=components['risk_manager'], sentiment_analyzer=components['sentiment_analyzer'], trading_env=components['trading_env'], config=bot_config, status='initialized', last_update=datetime.now(), performance_metrics={}, message_queue=queue.Queue(), health_metrics=SystemHealth( cpu_usage=0.0, memory_usage=0.0, network_latency=0.0, disk_usage=0.0, error_rate=0.0, last_check=datetime.now() ), error_count=0, recovery_attempts=0 ) self.bots[bot_id] = bot logger.info(f"Created new Quantum Edge bot instance: {bot_id}") return bot_id except Exception as e: logger.error(f"Error creating Quantum Edge bot: {str(e)}") raise def _save_bot_config(self, config_path: str, config: Dict): """Save bot configuration with retry""" try: with open(config_path, 'w') as f: json.dump(config, f, indent=2) except Exception as e: logger.error(f"Error saving bot config: {str(e)}") raise def _initialize_bot_components(self, config: Dict) -> Dict: """Initialize bot components in parallel""" components = {} futures = { 'trading_system': self.thread_pool.submit( create_trading_system, config['trading'] ), 'ml_model': self.thread_pool.submit( MachineLearningModel, config['ml_model'] ), 'risk_manager': self.thread_pool.submit( RiskManager, config['risk_management'] ), 'sentiment_analyzer': self.thread_pool.submit( SentimentAnalyzer, config['sentiment_analysis'] ), 'trading_env': self.thread_pool.submit( TradingEnvironment, config['trading'] ) } for name, future in futures.items(): try: components[name] = future.result() except Exception as e: logger.error(f"Error initializing {name}: {str(e)}") raise return components def start_bot(self, bot_id: str): """Start a Quantum Edge bot with enhanced error handling""" if bot_id in self.bots: try: bot = self.bots[bot_id] # Initialize components with retry self._initialize_bot_components_with_retry(bot) # Start bot with health monitoring bot.status = 'running' bot.last_update = datetime.now() logger.info(f"Started Quantum Edge bot: {bot_id}") # Send start message to bot self._send_message_to_bot(bot_id, { 'type': 'command', 'action': 'start', 'timestamp': datetime.now().isoformat() }) except Exception as e: logger.error(f"Error starting Quantum Edge bot {bot_id}: {str(e)}") self._handle_bot_error(bot_id, e) def _initialize_bot_components_with_retry(self, bot: QuantumBotInstance): """Initialize bot components with retry mechanism""" try: bot.ml_model.initialize() bot.trading_env.reset() bot.trading_system.start() except Exception as e: logger.error(f"Error initializing bot components: {str(e)}") bot.error_count += 1 bot.last_error = e raise def _handle_bot_error(self, bot_id: str, error: Exception): """Handle bot errors with recovery mechanism""" bot = self.bots[bot_id] bot.error_count += 1 bot.last_error = error if bot.error_count >= self.recovery_threshold: logger.warning(f"Bot {bot_id} exceeded error threshold, attempting recovery") self._attempt_bot_recovery(bot_id) else: bot.status = 'error' logger.error(f"Bot {bot_id} encountered error: {str(error)}") def _attempt_bot_recovery(self, bot_id: str): """Attempt to recover a failed bot""" bot = self.bots[bot_id] try: # Reset bot state bot.error_count = 0 bot.recovery_attempts += 1 # Reinitialize components self._initialize_bot_components_with_retry(bot) # Restart bot bot.status = 'running' logger.info(f"Successfully recovered bot {bot_id}") except Exception as e: logger.error(f"Failed to recover bot {bot_id}: {str(e)}") bot.status = 'failed' self._handle_critical_bot_failure(bot_id) def _handle_critical_bot_failure(self, bot_id: str): """Handle critical bot failures""" logger.error(f"Critical failure for bot {bot_id}") # Notify system self.message_queue.put({ 'type': 'critical_error', 'bot_id': bot_id, 'timestamp': datetime.now().isoformat() }) # Update system metrics self.performance_tracker['error_metrics']['total_errors'] += 1 error_type = type(self.bots[bot_id].last_error).__name__ self.performance_tracker['error_metrics']['error_types'][error_type] = \ self.performance_tracker['error_metrics']['error_types'].get(error_type, 0) + 1 def stop(self): """Stop the Quantum Edge System with graceful shutdown""" logger.info("Initiating system shutdown") self.running = False # Stop all bots gracefully for bot_id in self.bots: self.stop_bot(bot_id) # Stop components self.code_guardian.stop() self.system_monitor.stop() # Shutdown thread pool self.thread_pool.shutdown(wait=True) # Wait for threads for thread_name, thread in self.threads.items(): if thread.is_alive(): logger.info(f"Waiting for thread {thread_name} to finish") thread.join(timeout=30) if thread.is_alive(): logger.warning(f"Thread {thread_name} did not terminate gracefully") logger.info("Quantum Edge System stopped") def create_quantum_edge_system(project_root: str, config_path: str) -> QuantumEdgeSystem: """Create and initialize a Quantum Edge System""" return QuantumEdgeSystem(project_root, config_path) if __name__ == "__main__": # Example usage with enhanced error handling config_path = "config/quantum_edge_config.json" system = None try: system = create_quantum_edge_system(".", config_path) # Create test bots with different strategies configs = [ { "trading": { "initial_capital": 100000, "strategy": "trend_following", "markets": ["BTC/USD", "ETH/USD"] }, "ml_model": { "type": "lstm", "features": ["price", "volume", "sentiment"] } }, { "trading": { "initial_capital": 50000, "strategy": "mean_reversion", "markets": ["SOL/USD", "ADA/USD"] }, "ml_model": { "type": "reinforcement", "features": ["technical_indicators", "order_flow"] } } ] # Create and start bots bot_ids = [] for config in configs: bot_id = system.create_quantum_bot(config) bot_ids.append(bot_id) system.start_bot(bot_id) # Monitor system while True: status = system.get_system_status() print(f"System Status: {json.dumps(status, indent=2)}") time.sleep(300) # Update every 5 minutes except KeyboardInterrupt: print("Shutting down Quantum Edge System...") if system: system.stop() except Exception as e: print(f"Critical error: {str(e)}") if system: system.stop() raise import logging import threading import queue import json import os from typing import Dict, List, Optional, Any from dataclasses import dataclass from datetime import datetime import time from .trading_system import TradingSystem, create_trading_system from .code_guardian import CodeGuardian, create_guardian from .system_monitor import SystemMonitor from .dashboard import create_dashboard # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('logs/ai_agent_manager.log'), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) @dataclass class BotInstance: """Represents a trading bot instance""" bot_id: str trading_system: TradingSystem config: Dict status: str last_update: datetime performance_metrics: Dict message_queue: queue.Queue class AIAgentManager: def __init__(self, project_root: str): self.project_root = project_root self.bots: Dict[str, BotInstance] = {} self.code_guardian = create_guardian(project_root) self.system_monitor = SystemMonitor(project_root) self.message_queue = queue.Queue() self.running = True # Start management threads self.threads = { 'monitor': threading.Thread(target=self._monitor_bots), 'message_handler': threading.Thread(target=self._handle_messages), 'code_repair': threading.Thread(target=self._continuous_code_repair) } for thread in self.threads.values(): thread.daemon = True thread.start() # Initialize dashboard self.dashboard = create_dashboard() self.dashboard_thread = threading.Thread(target=self._run_dashboard) self.dashboard_thread.daemon = True self.dashboard_thread.start() def create_bot(self, config: Dict) -> str: """Create a new trading bot instance""" try: bot_id = f"bot_{len(self.bots) + 1}" # Save bot-specific config config_path = os.path.join(self.project_root, 'config', f'{bot_id}_config.json') with open(config_path, 'w') as f: json.dump(config, f, indent=2) # Create trading system trading_system = create_trading_system(config_path) # Create bot instance bot = BotInstance( bot_id=bot_id, trading_system=trading_system, config=config, status='initialized', last_update=datetime.now(), performance_metrics={}, message_queue=queue.Queue() ) self.bots[bot_id] = bot logger.info(f"Created new bot instance: {bot_id}") return bot_id except Exception as e: logger.error(f"Error creating bot: {str(e)}") raise def start_bot(self, bot_id: str): """Start a trading bot""" if bot_id in self.bots: try: bot = self.bots[bot_id] bot.status = 'running' bot.last_update = datetime.now() logger.info(f"Started bot: {bot_id}") # Send start message to bot self._send_message_to_bot(bot_id, { 'type': 'command', 'action': 'start', 'timestamp': datetime.now().isoformat() }) except Exception as e: logger.error(f"Error starting bot {bot_id}: {str(e)}") self.bots[bot_id].status = 'error' def stop_bot(self, bot_id: str): """Stop a trading bot""" if bot_id in self.bots: try: bot = self.bots[bot_id] bot.status = 'stopped' bot.last_update = datetime.now() bot.trading_system.stop() logger.info(f"Stopped bot: {bot_id}") except Exception as e: logger.error(f"Error stopping bot {bot_id}: {str(e)}") def send_message_to_bot(self, bot_id: str, message: Dict): """Send a message to a specific bot""" if bot_id in self.bots: self._send_message_to_bot(bot_id, message) logger.info(f"Sent message to bot {bot_id}: {message}") def broadcast_message(self, message: Dict): """Send a message to all bots""" for bot_id in self.bots: self._send_message_to_bot(bot_id, message) logger.info(f"Broadcast message to all bots: {message}") def get_bot_status(self, bot_id: str) -> Optional[Dict]: """Get status of a specific bot""" if bot_id in self.bots: bot = self.bots[bot_id] return { 'bot_id': bot.bot_id, 'status': bot.status, 'last_update': bot.last_update.isoformat(), 'performance_metrics': bot.performance_metrics, 'trading_system_status': bot.trading_system.get_status() } return None def get_system_status(self) -> Dict: """Get overall system status""" return { 'total_bots': len(self.bots), 'active_bots': len([b for b in self.bots.values() if b.status == 'running']), 'code_health': self.code_guardian.get_status_report(), 'system_health': self.system_monitor.get_system_status(), 'bots': {bot_id: self.get_bot_status(bot_id) for bot_id in self.bots} } def _send_message_to_bot(self, bot_id: str, message: Dict): """Internal method to send message to bot""" if bot_id in self.bots: self.bots[bot_id].message_queue.put(message) def _monitor_bots(self): """Continuously monitor bot performance and health""" while self.running: try: for bot_id, bot in self.bots.items(): if bot.status == 'running': # Update bot metrics status = bot.trading_system.get_status() bot.performance_metrics = status['metrics'] bot.last_update = datetime.now() # Check for issues if status['system_health']['alerts']['unacknowledged'] > 0: self._handle_bot_issue(bot_id, status) time.sleep(60) # Check every minute except Exception as e: logger.error(f"Error in bot monitoring: {str(e)}") time.sleep(300) def _handle_messages(self): """Handle incoming messages from bots""" while self.running: try: for bot_id, bot in self.bots.items(): while not bot.message_queue.empty(): message = bot.message_queue.get_nowait() self._process_bot_message(bot_id, message) time.sleep(1) except Exception as e: logger.error(f"Error handling messages: {str(e)}") time.sleep(60) def _continuous_code_repair(self): """Continuously monitor and repair code issues""" while self.running: try: # Get code issues status = self.code_guardian.get_status_report() # Attempt to fix issues for issue in self.code_guardian.issues: if not issue.fixed and issue.suggested_fix: if self.code_guardian.fix_issue(issue): logger.info(f"Fixed code issue: {issue.description}") time.sleep(300) # Check every 5 minutes except Exception as e: logger.error(f"Error in code repair: {str(e)}") time.sleep(600) def _handle_bot_issue(self, bot_id: str, status: Dict): """Handle issues with a specific bot""" try: # Create alert alert = { 'type': 'alert', 'bot_id': bot_id, 'timestamp': datetime.now().isoformat(), 'status': status } # Log alert logger.warning(f"Bot issue detected: {alert}") # Add to message queue self.message_queue.put(alert) # Take action based on issue severity if status['system_health']['alerts']['by_level'].get('error', 0) > 0: self.stop_bot(bot_id) logger.error(f"Stopped bot {bot_id} due to critical issues") except Exception as e: logger.error(f"Error handling bot issue: {str(e)}") def _process_bot_message(self, bot_id: str, message: Dict): """Process message from a bot""" try: if message['type'] == 'status_update': self.bots[bot_id].status = message['status'] self.bots[bot_id].last_update = datetime.now() elif message['type'] == 'alert': self._handle_bot_issue(bot_id, message) elif message['type'] == 'performance_update': self.bots[bot_id].performance_metrics.update(message['metrics']) except Exception as e: logger.error(f"Error processing bot message: {str(e)}") def _run_dashboard(self): """Run the dashboard""" try: self.dashboard.run_server(debug=True, port=8050) except Exception as e: logger.error(f"Error running dashboard: {str(e)}") def stop(self): """Stop the AI Agent Manager""" self.running = False # Stop all bots for bot_id in self.bots: self.stop_bot(bot_id) # Stop components self.code_guardian.stop() self.system_monitor.stop() # Wait for threads for thread in self.threads.values(): if thread.is_alive(): thread.join() def create_agent_manager(project_root: str) -> AIAgentManager: """Create and initialize an AI Agent Manager""" return AIAgentManager(project_root) if __name__ == "__main__": # Example usage manager = create_agent_manager(".") try: # Create some test bots config1 = { "trading": {"initial_capital": 100000}, "strategy": {"name": "trend_following"}, "risk_management": {"max_positions": 5} } config2 = { "trading": {"initial_capital": 50000}, "strategy": {"name": "mean_reversion"}, "risk_management": {"max_positions": 3} } # Create and start bots bot1_id = manager.create_bot(config1) bot2_id = manager.create_bot(config2) manager.start_bot(bot1_id) manager.start_bot(bot2_id) # Monitor for a while time.sleep(3600) # Run for 1 hour finally: manager.stop() import numpy as np import pandas as pd from datetime import datetime, timedelta import logging from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import json import os from .system_monitor import SystemMonitor # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('logs/trading_system.log'), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) @dataclass class Trade: symbol: str direction: str entry_price: float stop_loss: float take_profit: float position_size: float entry_time: datetime exit_price: Optional[float] = None exit_time: Optional[datetime] = None pnl: Optional[float] = None status: str = 'open' class TradingSystem: def __init__(self, config_path: str): # Load configuration with open(config_path, 'r') as f: self.config = json.load(f) # Initialize system monitor self.monitor = SystemMonitor(os.path.dirname(os.path.dirname(__file__))) # Initialize trading parameters self.initial_capital = self.config['trading']['initial_capital'] self.current_capital = self.initial_capital self.performance_history = [] self.active_trades: List[Trade] = [] # Initialize strategy parameters self.strategy_params = self.config['strategy'] self.risk_params = self.config['risk_management'] # Initialize performance metrics self.metrics = { 'win_rate': 0.0, 'profit_factor': 0.0, 'max_drawdown': 0.0, 'sharpe_ratio': 0.0, 'total_trades': 0, 'winning_trades': 0, 'losing_trades': 0 } @SystemMonitor.monitor_component("strategy_execution") def execute_strategy(self, market_data: pd.DataFrame) -> Optional[Dict]: """Execute trading strategy""" try: # Generate trading signals signal = self._generate_signals(market_data) if signal: # Validate trade if self._validate_trade(signal): # Execute trade trade = self._execute_trade(signal) return {'status': 'success', 'trade': trade} return None except Exception as e: logger.error(f"Error executing strategy: {str(e)}") return {'status': 'error', 'message': str(e)} @SystemMonitor.monitor_component("risk_management") def _validate_trade(self, signal: Dict) -> bool: """Validate trade against risk parameters""" try: # Check if we have too many open trades if len(self.active_trades) >= self.risk_params['max_positions']: return False # Check if we have enough capital required_margin = self._calculate_margin(signal) if required_margin > self.current_capital * self.risk_params['max_position_size']: return False # Check if we're within daily loss limit if self._check_daily_loss_limit(): return False return True except Exception as e: logger.error(f"Error validating trade: {str(e)}") return False @SystemMonitor.monitor_component("trade_execution") def _execute_trade(self, signal: Dict) -> Optional[Trade]: """Execute a trade""" try: # Calculate position size position_size = self._calculate_position_size(signal) # Create trade object trade = Trade( symbol=signal['symbol'], direction=signal['direction'], entry_price=signal['price'], stop_loss=signal['stop_loss'], take_profit=signal['take_profit'], position_size=position_size, entry_time=datetime.now(), exit_price=None, exit_time=None, pnl=None, status='open' ) # Add to active trades self.active_trades.append(trade) return trade except Exception as e: logger.error(f"Error executing trade: {str(e)}") return None @SystemMonitor.monitor_component("performance_monitoring") def update_performance(self): """Update performance metrics""" try: if not self.performance_history: return # Calculate basic metrics total_trades = len(self.performance_history) winning_trades = len([t for t in self.performance_history if t['pnl'] > 0]) self.metrics.update({ 'total_trades': total_trades, 'winning_trades': winning_trades, 'losing_trades': total_trades - winning_trades, 'win_rate': winning_trades / total_trades if total_trades > 0 else 0 }) # Calculate advanced metrics self._calculate_advanced_metrics() # Check if we need to adjust strategy self._check_strategy_adjustment() except Exception as e: logger.error(f"Error updating performance: {str(e)}") @SystemMonitor.monitor_component("strategy_adjustment") def _check_strategy_adjustment(self): """Check if strategy needs adjustment""" try: # Check win rate if self.metrics['win_rate'] < self.strategy_params['min_win_rate']: self._adjust_strategy('defensive') elif self.metrics['win_rate'] > self.strategy_params['target_win_rate']: self._adjust_strategy('aggressive') # Check drawdown if self.metrics['max_drawdown'] > self.risk_params['max_drawdown']: self._adjust_strategy('risk_reduction') except Exception as e: logger.error(f"Error checking strategy adjustment: {str(e)}") def _adjust_strategy(self, mode: str): """Adjust strategy parameters""" if mode == 'defensive': self.strategy_params['position_size'] *= 0.8 self.strategy_params['stop_loss_multiplier'] *= 0.9 elif mode == 'aggressive': self.strategy_params['position_size'] *= 1.2 self.strategy_params['take_profit_multiplier'] *= 1.1 elif mode == 'risk_reduction': self.strategy_params['position_size'] *= 0.7 self.strategy_params['max_positions'] = max(1, self.strategy_params['max_positions'] - 1) def get_status(self) -> Dict: """Get current system status""" return { 'capital': self.current_capital, 'active_trades': len(self.active_trades), 'metrics': self.metrics, 'system_health': self.monitor.get_system_status() } def stop(self): """Stop the trading system""" self.monitor.stop() def create_trading_system(config_path: str) -> TradingSystem: """Create and initialize a trading system""" return TradingSystem(config_path) if __name__ == "__main__": # Example usage config_path = os.path.join(os.path.dirname(__file__), '..', 'config', 'config.json') trading_system = create_trading_system(config_path) try: # Simulate some trading market_data = pd.DataFrame({ 'timestamp': pd.date_range(start='2024-01-01', periods=100, freq='H'), 'open': np.random.randn(100).cumsum() + 100, 'high': np.random.randn(100).cumsum() + 102, 'low': np.random.randn(100).cumsum() + 98, 'close': np.random.randn(100).cumsum() + 100, 'volume': np.random.randint(1000, 10000, 100) }) for i in range(len(market_data)): result = trading_system.execute_strategy(market_data.iloc[:i+1]) if result and result['status'] == 'success': print(f"Executed trade: {result['trade']}") # Get final status status = trading_system.get_status() print("\nFinal Status:") print(json.dumps(status, indent=2, default=str)) finally: trading_system.stop() import logging import time import threading from typing import Dict, Any, Optional from datetime import datetime import functools import traceback from .code_guardian import CodeGuardian, create_guardian logger = logging.getLogger(__name__) class SystemMonitor: def __init__(self, project_root: str): self.guardian = create_guardian(project_root) self.component_status: Dict[str, Dict[str, Any]] = {} self.performance_data: Dict[str, Dict[str, float]] = {} self.alerts: Dict[str, Dict[str, Any]] = {} self.running = True # Start monitoring thread self.monitor_thread = threading.Thread(target=self._monitor_system) self.monitor_thread.daemon = True self.monitor_thread.start() def monitor_component(self, component_name: str): """Decorator to monitor component performance and errors""" def decorator(func): @functools.wraps(func) def wrapper(*args, **kwargs): start_time = time.time() try: result = func(*args, **kwargs) execution_time = time.time() - start_time # Update performance metrics self.guardian.monitor_performance(component_name, execution_time) # Update component status self.component_status[component_name] = { 'status': 'healthy', 'last_execution': datetime.now().isoformat(), 'execution_time': execution_time, 'error': None } return result except Exception as e: error_info = { 'type': type(e).__name__, 'message': str(e), 'traceback': traceback.format_exc() } # Update component status self.component_status[component_name] = { 'status': 'error', 'last_execution': datetime.now().isoformat(), 'execution_time': time.time() - start_time, 'error': error_info } # Create alert self._create_alert( component_name, f"Error in {component_name}: {str(e)}", 'error', error_info ) logger.error(f"Error in {component_name}: {str(e)}") raise return wrapper return decorator def _create_alert(self, component: str, message: str, level: str, details: Optional[Dict] = None): """Create a new alert""" alert_id = f"{component}_{datetime.now().timestamp()}" self.alerts[alert_id] = { 'component': component, 'message': message, 'level': level, 'timestamp': datetime.now().isoformat(), 'details': details, 'acknowledged': False } def acknowledge_alert(self, alert_id: str): """Acknowledge an alert""" if alert_id in self.alerts: self.alerts[alert_id]['acknowledged'] = True def get_system_status(self) -> Dict[str, Any]: """Get overall system status""" return { 'components': self.component_status, 'alerts': { 'total': len(self.alerts), 'unacknowledged': len([a for a in self.alerts.values() if not a['acknowledged']]), 'by_level': self._count_alerts_by_level() }, 'code_health': self.guardian.get_status_report(), 'performance': self._get_performance_summary() } def _count_alerts_by_level(self) -> Dict[str, int]: """Count alerts by level""" counts = {'error': 0, 'warning': 0, 'info': 0} for alert in self.alerts.values(): if alert['level'] in counts: counts[alert['level']] += 1 return counts def _get_performance_summary(self) -> Dict[str, Dict[str, float]]: """Get performance summary for all components""" summary = {} for component, metrics in self.guardian.performance_metrics.items(): if metrics: summary[component] = { 'avg_execution_time': sum(metrics) / len(metrics), 'max_execution_time': max(metrics), 'min_execution_time': min(metrics), 'total_executions': len(metrics) } return summary def _monitor_system(self): """Continuous system monitoring""" while self.running: try: # Check component health for component, status in self.component_status.items(): if status['status'] == 'error': self._create_alert( component, f"Component {component} is in error state", 'error', status['error'] ) # Check for performance degradation if component in self.guardian.performance_metrics: metrics = self.guardian.performance_metrics[component] if len(metrics) > 10: recent_avg = sum(metrics[-10:]) / 10 overall_avg = sum(metrics) / len(metrics) if recent_avg > overall_avg * 1.5: # 50% slower self._create_alert( component, f"Performance degradation detected in {component}", 'warning', { 'recent_avg': recent_avg, 'overall_avg': overall_avg } ) # Sleep for a while time.sleep(60) # Check every minute except Exception as e: logger.error(f"Error in system monitoring: {str(e)}") time.sleep(300) # Wait longer if there's an error def stop(self): """Stop the system monitor""" self.running = False self.guardian.stop() if self.monitor_thread.is_alive(): self.monitor_thread.join() # Example usage def example_usage(): # Create system monitor monitor = SystemMonitor(".") # Example component with monitoring @monitor.monitor_component("example_component") def example_function(x: int) -> int: time.sleep(1) # Simulate work return x * 2 try: # Run component for i in range(5): result = example_function(i) print(f"Result: {result}") # Get system status status = monitor.get_system_status() print("\nSystem Status:") print(json.dumps(status, indent=2)) finally: monitor.stop() if __name__ == "__main__": example_usage() import inspect import logging import sys import traceback import ast import typing from dataclasses import dataclass from typing import Dict, List, Optional, Any, Tuple import numpy as np from datetime import datetime import importlib import threading import time import json import os logger = logging.getLogger(__name__) @dataclass class CodeIssue: """Represents a code issue found by the guardian""" file_path: str line_number: int issue_type: str description: str severity: str suggested_fix: Optional[str] = None fixed: bool = False class CodeGuardian: def __init__(self, project_root: str): self.project_root = project_root self.issues: List[CodeIssue] = [] self.module_states: Dict[str, float] = {} # Module path -> last modified timestamp self.performance_metrics: Dict[str, List[float]] = {} self.error_patterns: Dict[str, str] = self._load_error_patterns() # Start monitoring thread self.running = True self.monitor_thread = threading.Thread(target=self._continuous_monitoring) self.monitor_thread.daemon = True self.monitor_thread.start() def _load_error_patterns(self) -> Dict[str, str]: """Load known error patterns and their fixes""" return { "IndexError": "Check array bounds and data availability", "KeyError": "Verify dictionary keys exist before access", "AttributeError": "Ensure object attributes exist", "TypeError": "Check type compatibility", "ValueError": "Validate input values", "ZeroDivisionError": "Add zero-value checking", "ImportError": "Verify module installation and import path", "MemoryError": "Optimize memory usage or add cleanup", "RuntimeError": "Check execution flow and state", } def analyze_code(self, file_path: str) -> List[CodeIssue]: """Analyze code for potential issues""" try: with open(file_path, 'r') as f: code = f.read() issues = [] tree = ast.parse(code) # Check for common issues issues.extend(self._check_error_handling(tree, file_path)) issues.extend(self._check_resource_management(tree, file_path)) issues.extend(self._check_performance_patterns(tree, file_path)) issues.extend(self._check_code_style(tree, file_path)) return issues except Exception as e: logger.error(f"Error analyzing {file_path}: {str(e)}") return [] def _check_error_handling(self, tree: ast.AST, file_path: str) -> List[CodeIssue]: """Check for proper error handling""" issues = [] for node in ast.walk(tree): # Check for bare except clauses if isinstance(node, ast.Try): for handler in node.handlers: if handler.type is None: issues.append(CodeIssue( file_path=file_path, line_number=handler.lineno, issue_type="error_handling", description="Bare except clause found", severity="warning", suggested_fix="Specify exception type(s) to catch" )) return issues def _check_resource_management(self, tree: ast.AST, file_path: str) -> List[CodeIssue]: """Check for proper resource management""" issues = [] for node in ast.walk(tree): # Check for file operations without context manager if isinstance(node, ast.Call): if isinstance(node.func, ast.Name) and node.func.id in ['open']: if not isinstance(node.parent, ast.withitem): issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, issue_type="resource_management", description="File opened without context manager", severity="warning", suggested_fix="Use 'with' statement for file operations" )) return issues def _check_performance_patterns(self, tree: ast.AST, file_path: str) -> List[CodeIssue]: """Check for performance-related issues""" issues = [] for node in ast.walk(tree): # Check for inefficient list operations if isinstance(node, ast.For): if isinstance(node.target, ast.Name) and isinstance(node.iter, ast.Call): if isinstance(node.iter.func, ast.Name) and node.iter.func.id == 'range': if len(node.iter.args) == 1 and isinstance(node.iter.args[0], ast.Call): if isinstance(node.iter.args[0].func, ast.Name) and node.iter.args[0].func.id == 'len': issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, issue_type="performance", description="Inefficient list iteration", severity="info", suggested_fix="Use 'for item in items' instead of range(len(items))" )) return issues def _check_code_style(self, tree: ast.AST, file_path: str) -> List[CodeIssue]: """Check for code style issues""" issues = [] for node in ast.walk(tree): # Check for overly complex functions if isinstance(node, ast.FunctionDef): if len(node.body) > 50: # Arbitrary threshold issues.append(CodeIssue( file_path=file_path, line_number=node.lineno, issue_type="code_style", description="Function is too long", severity="info", suggested_fix="Consider breaking down into smaller functions" )) return issues def monitor_performance(self, module_name: str, execution_time: float): """Monitor module performance""" if module_name not in self.performance_metrics: self.performance_metrics[module_name] = [] self.performance_metrics[module_name].append(execution_time) # Check for performance degradation if len(self.performance_metrics[module_name]) > 10: recent_avg = np.mean(self.performance_metrics[module_name][-10:]) overall_avg = np.mean(self.performance_metrics[module_name]) if recent_avg > overall_avg * 1.5: # 50% slower than average self.issues.append(CodeIssue( file_path=module_name, line_number=0, issue_type="performance_degradation", description=f"Performance degradation detected in {module_name}", severity="warning" )) def fix_issue(self, issue: CodeIssue) -> bool: """Attempt to fix a code issue""" try: if not issue.suggested_fix: return False with open(issue.file_path, 'r') as f: lines = f.readlines() if issue.issue_type == "error_handling": # Fix bare except if "Bare except clause found" in issue.description: lines[issue.line_number - 1] = lines[issue.line_number - 1].replace( "except:", "except Exception:" ) elif issue.issue_type == "resource_management": # Fix file operations if "File opened without context manager" in issue.description: indent = len(lines[issue.line_number - 1]) - len(lines[issue.line_number - 1].lstrip()) lines[issue.line_number - 1] = " " * indent + "with " + lines[issue.line_number - 1].lstrip() with open(issue.file_path, 'w') as f: f.writelines(lines) issue.fixed = True return True except Exception as e: logger.error(f"Error fixing issue: {str(e)}") return False def _continuous_monitoring(self): """Continuously monitor code for issues""" while self.running: try: # Check all Python files in project for root, _, files in os.walk(self.project_root): for file in files: if file.endswith('.py'): file_path = os.path.join(root, file) # Check if file was modified current_mtime = os.path.getmtime(file_path) if file_path not in self.module_states or current_mtime > self.module_states[file_path]: self.module_states[file_path] = current_mtime # Analyze code new_issues = self.analyze_code(file_path) self.issues.extend(new_issues) # Try to fix issues for issue in new_issues: if issue.suggested_fix: self.fix_issue(issue) # Sleep for a while time.sleep(60) # Check every minute except Exception as e: logger.error(f"Error in continuous monitoring: {str(e)}") time.sleep(300) # Wait longer if there's an error def get_status_report(self) -> Dict[str, Any]: """Generate a status report""" return { 'total_issues': len(self.issues), 'fixed_issues': len([i for i in self.issues if i.fixed]), 'active_issues': len([i for i in self.issues if not i.fixed]), 'issues_by_type': self._count_issues_by_type(), 'performance_metrics': self._summarize_performance_metrics() } def _count_issues_by_type(self) -> Dict[str, int]: """Count issues by type""" counts = {} for issue in self.issues: if issue.issue_type not in counts: counts[issue.issue_type] = 0 counts[issue.issue_type] += 1 return counts def _summarize_performance_metrics(self) -> Dict[str, Dict[str, float]]: """Summarize performance metrics""" summary = {} for module, metrics in self.performance_metrics.items(): if metrics: summary[module] = { 'avg': np.mean(metrics), 'min': np.min(metrics), 'max': np.max(metrics), 'std': np.std(metrics) } return summary def stop(self): """Stop the guardian""" self.running = False if self.monitor_thread.is_alive(): self.monitor_thread.join() def create_guardian(project_root: str) -> CodeGuardian: """Create and start a code guardian instance""" return CodeGuardian(project_root) if __name__ == "__main__": # Example usage guardian = create_guardian(".") try: while True: status = guardian.get_status_report() print(json.dumps(status, indent=2)) time.sleep(300) # Print status every 5 minutes except KeyboardInterrupt: guardian.stop() import os import sys import logging from datetime import datetime, timedelta from src.backtesting import Backtester from src.dashboard import run_dashboard import threading import webbrowser import time # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('analysis.log'), logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger(__name__) def run_backtests(): """Run all backtest scenarios""" # Create results directory if it doesn't exist results_dir = 'backtest_results' os.makedirs(results_dir, exist_ok=True) # Load configuration config_path = os.path.join(os.path.dirname(__file__), 'config', 'config.json') # Create backtester backtester = Backtester(config_path) # Define test scenarios scenarios = [ { 'name': 'BTC/USDT 1h - Last 30 days', 'symbol': 'BTC/USDT', 'timeframe': '1h', 'days': 30 }, { 'name': 'ETH/USDT 4h - Last 60 days', 'symbol': 'ETH/USDT', 'timeframe': '4h', 'days': 60 }, { 'name': 'BTC/USDT 1d - Last 90 days', 'symbol': 'BTC/USDT', 'timeframe': '1d', 'days': 90 }, { 'name': 'ETH/USDT 1d - Last 90 days', 'symbol': 'ETH/USDT', 'timeframe': '1d', 'days': 90 } ] # Run each scenario for scenario in scenarios: logger.info(f"\nRunning scenario: {scenario['name']}") # Calculate date range end_date = datetime.now() start_date = end_date - timedelta(days=scenario['days']) # Run backtest results = backtester.run_backtest( symbol=scenario['symbol'], timeframe=scenario['timeframe'], start_date=start_date, end_date=end_date, initial_capital=50.0 ) if results: # Save results filename = f"backtest_results_{scenario['symbol'].replace('/', '_')}_{scenario['timeframe']}.json" filepath = os.path.join(results_dir, filename) backtester.save_results(filepath) logger.info(f"Results saved to {filepath}") else: logger.error(f"Backtest failed for scenario: {scenario['name']}") def open_browser(): """Open browser after a short delay""" time.sleep(3) # Wait for the server to start webbrowser.open('http://localhost:8050') def main(): """Run backtests and launch dashboard""" try: # Run backtests logger.info("Starting backtests...") run_backtests() logger.info("Backtests completed successfully") # Launch dashboard logger.info("Launching dashboard...") threading.Thread(target=open_browser).start() run_dashboard() except Exception as e: logger.error(f"Error during analysis: {str(e)}") raise if __name__ == "__main__": main() import dash from dash import dcc, html from dash.dependencies import Input, Output, State import plotly.graph_objects as go from plotly.subplots import make_subplots import pandas as pd import json import os from datetime import datetime import numpy as np from .code_guardian import create_guardian, CodeGuardian def load_backtest_results(results_dir): """Load all backtest results from directory""" results = {} for file in os.listdir(results_dir): if file.startswith('backtest_results_') and file.endswith('.json'): with open(os.path.join(results_dir, file), 'r') as f: scenario_name = file.replace('backtest_results_', '').replace('.json', '') results[scenario_name] = json.load(f) return results def create_dashboard(results_dir='backtest_results'): """Create and run the dashboard""" app = dash.Dash(__name__) # Load results results = load_backtest_results(results_dir) # Initialize Code Guardian guardian = create_guardian(os.path.dirname(os.path.dirname(__file__))) # Dashboard layout app.layout = html.Div([ # Header html.Div([ html.H1('AI Trading Bot - Backtest Results & System Health Dashboard', style={'textAlign': 'center', 'color': '#2c3e50', 'marginBottom': 30}), ], style={'backgroundColor': '#ecf0f1', 'padding': '20px'}), # Tabs for different sections dcc.Tabs([ # Backtest Results Tab dcc.Tab(label='Backtest Results', children=[ # Scenario Selection html.Div([ html.Label('Select Scenario:'), dcc.Dropdown( id='scenario-dropdown', options=[{'label': k, 'value': k} for k in results.keys()], value=list(results.keys())[0] if results else None, style={'width': '100%'} ), ], style={'margin': '20px'}), # Main Charts html.Div([ # Trading Chart html.Div([ dcc.Graph(id='trading-chart') ], style={'width': '100%', 'marginBottom': '20px'}), # Performance Metrics Cards html.Div([ html.Div([ html.Div(id='metrics-cards'), ], style={'display': 'flex', 'flexWrap': 'wrap', 'justifyContent': 'space-around'}) ], style={'marginBottom': '20px'}), # Trade Distribution Chart html.Div([ dcc.Graph(id='trade-distribution') ], style={'width': '100%', 'marginBottom': '20px'}), # Drawdown Chart html.Div([ dcc.Graph(id='drawdown-chart') ], style={'width': '100%'}) ], style={'padding': '20px'}) ]), # System Health Tab dcc.Tab(label='System Health', children=[ html.Div([ # Code Health Overview html.Div([ html.H2('Code Health Overview', style={'textAlign': 'center'}), html.Div(id='code-health-cards', style={ 'display': 'flex', 'flexWrap': 'wrap', 'justifyContent': 'space-around', 'margin': '20px' }) ]), # Code Issues Table html.Div([ html.H3('Active Code Issues'), html.Div(id='code-issues-table') ], style={'margin': '20px'}), # Performance Metrics html.Div([ html.H3('Module Performance'), dcc.Graph(id='performance-chart') ], style={'margin': '20px'}), # Auto-Fix Controls html.Div([ html.H3('Issue Resolution'), html.Button('Auto-Fix Selected Issues', id='auto-fix-button'), html.Div(id='auto-fix-status') ], style={'margin': '20px'}) ]) ]), # System Logs Tab dcc.Tab(label='System Logs', children=[ html.Div([ html.H2('System Logs'), dcc.Interval(id='log-update', interval=5000), # Update every 5 seconds html.Pre(id='log-content', style={ 'backgroundColor': '#2c3e50', 'color': '#ecf0f1', 'padding': '20px', 'borderRadius': '5px', 'height': '500px', 'overflow': 'auto' }) ], style={'margin': '20px'}) ]) ]) ]) @app.callback( [Output('trading-chart', 'figure'), Output('metrics-cards', 'children'), Output('trade-distribution', 'figure'), Output('drawdown-chart', 'figure')], [Input('scenario-dropdown', 'value')] ) def update_charts(selected_scenario): if not selected_scenario or selected_scenario not in results: return {}, [], {}, {} result = results[selected_scenario] trades_df = pd.DataFrame(result['trades']) equity_df = pd.DataFrame(result['equity_curve']) metrics = result['performance_metrics'] # 1. Trading Chart trading_fig = make_subplots( rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.03, subplot_titles=('Price and Trades', 'Equity Curve'), row_heights=[0.7, 0.3] ) # Add price line trading_fig.add_trace( go.Scatter( x=trades_df['timestamp'], y=trades_df['price'], name='Price', line=dict(color='#2980b9') ), row=1, col=1 ) # Add buy/sell markers for action, color in [('buy', '#27ae60'), ('sell', '#c0392b')]: mask = trades_df['action'] == action trading_fig.add_trace( go.Scatter( x=trades_df[mask]['timestamp'], y=trades_df[mask]['price'], mode='markers', name=action.capitalize(), marker=dict(color=color, size=10) ), row=1, col=1 ) # Add equity curve trading_fig.add_trace( go.Scatter( x=equity_df['timestamp'], y=equity_df['equity'], name='Equity', line=dict(color='#8e44ad') ), row=2, col=1 ) trading_fig.update_layout( title='Trading Activity and Equity Curve', height=800, template='plotly_white' ) # 2. Metrics Cards cards = [] metrics_style = { 'width': '200px', 'margin': '10px', 'padding': '15px', 'borderRadius': '5px', 'boxShadow': '2px 2px 5px rgba(0,0,0,0.1)', 'textAlign': 'center' } metrics_data = [ ('Total Return', f"{metrics['total_return']:.2%}", '#27ae60'), ('Win Rate', f"{metrics['win_rate']:.2%}", '#2980b9'), ('Sharpe Ratio', f"{metrics['sharpe_ratio']:.2f}", '#8e44ad'), ('Max Drawdown', f"{metrics['max_drawdown']:.2%}", '#c0392b'), ('Total Trades', str(metrics['total_trades']), '#2c3e50') ] for label, value, color in metrics_data: cards.append(html.Div([ html.H4(label, style={'color': '#7f8c8d'}), html.H3(value, style={'color': color}) ], style=metrics_style)) # 3. Trade Distribution returns = pd.Series([float(x) for x in trades_df['price'].pct_change().dropna()]) dist_fig = go.Figure() dist_fig.add_trace(go.Histogram( x=returns, nbinsx=30, name='Returns Distribution', marker_color='#3498db' )) dist_fig.update_layout( title='Trade Returns Distribution', xaxis_title='Return', yaxis_title='Frequency', template='plotly_white' ) # 4. Drawdown Chart equity_series = pd.Series([float(x) for x in equity_df['equity']]) rolling_max = equity_series.expanding().max() drawdowns = (equity_series - rolling_max) / rolling_max dd_fig = go.Figure() dd_fig.add_trace(go.Scatter( x=equity_df['timestamp'], y=drawdowns, fill='tozeroy', name='Drawdown', line=dict(color='#e74c3c') )) dd_fig.update_layout( title='Drawdown Over Time', xaxis_title='Date', yaxis_title='Drawdown', template='plotly_white' ) return trading_fig, cards, dist_fig, dd_fig @app.callback( [Output('code-health-cards', 'children'), Output('code-issues-table', 'children'), Output('performance-chart', 'figure'), Output('auto-fix-status', 'children')], [Input('auto-fix-button', 'n_clicks')], [State('code-issues-table', 'selected_rows')] ) def update_system_health(n_clicks, selected_rows): # Get guardian status status = guardian.get_status_report() # Create health cards health_cards = [] health_metrics = [ ('Total Issues', status['total_issues'], '#e74c3c'), ('Fixed Issues', status['fixed_issues'], '#27ae60'), ('Active Issues', status['active_issues'], '#f39c12'), ('Code Coverage', '85%', '#3498db') # Example metric ] for label, value, color in health_metrics: health_cards.append(html.Div([ html.H4(label), html.H3(str(value)) ], style={ 'width': '200px', 'margin': '10px', 'padding': '15px', 'borderRadius': '5px', 'boxShadow': '2px 2px 5px rgba(0,0,0,0.1)', 'textAlign': 'center', 'backgroundColor': color, 'color': 'white' })) # Create issues table issues_table = html.Table([ html.Thead(html.Tr([ html.Th('File'), html.Th('Line'), html.Th('Type'), html.Th('Severity'), html.Th('Description'), html.Th('Status') ])), html.Tbody([ html.Tr([ html.Td(issue.file_path), html.Td(issue.line_number), html.Td(issue.issue_type), html.Td(issue.severity), html.Td(issue.description), html.Td('Fixed' if issue.fixed else 'Active') ]) for issue in guardian.issues ]) ], style={'width': '100%'}) # Create performance chart perf_data = status['performance_metrics'] perf_fig = go.Figure() for module, metrics in perf_data.items(): perf_fig.add_trace(go.Scatter( x=list(range(len(guardian.performance_metrics[module]))), y=guardian.performance_metrics[module], name=module, mode='lines+markers' )) perf_fig.update_layout( title='Module Performance Over Time', xaxis_title='Execution Count', yaxis_title='Execution Time (s)', template='plotly_white' ) # Handle auto-fix status fix_status = None if n_clicks and selected_rows: fixed_count = sum(1 for i in selected_rows if guardian.fix_issue(guardian.issues[i])) fix_status = f"Fixed {fixed_count} out of {len(selected_rows)} selected issues" return health_cards, issues_table, perf_fig, fix_status @app.callback( Output('log-content', 'children'), [Input('log-update', 'n_intervals')] ) def update_logs(_): try: with open('analysis.log', 'r') as f: logs = f.readlines() return ''.join(logs[-100:]) # Show last 100 lines except Exception as e: return f"Error reading logs: {str(e)}" return app def run_dashboard(port=8050): """Run the dashboard""" app = create_dashboard() app.run_server(debug=True, port=port) if __name__ == '__main__': run_dashboard() { "exchange": { "name": "binance", "api_key": "YOUR_API_KEY", "api_secret": "YOUR_API_SECRET", "testnet": true }, "trading": { "symbols": ["BTC/USDT", "ETH/USDT"], "timeframes": ["1m", "5m", "15m", "1h", "4h", "1d"], "lookback_periods": 100, "state_file": "trading_state.json", "initial_capital": 50.0, "max_positions": 3, "leverage": 1 }, "risk_management": { "risk_per_trade": 0.02, "max_daily_loss": 0.05, "max_drawdown": 0.15, "stop_loss_pct": 0.02, "take_profit_pct": 0.04, "min_win_rate": 0.45, "min_profit_factor": 1.2 }, "technical_analysis": { "indicators": { "sma": [20, 50, 200], "ema": [20], "rsi": [14], "macd": { "fast": 12, "slow": 26, "signal": 9 }, "bollinger_bands": { "period": 20, "std_dev": 2 } }, "patterns": { "candlestick": true, "chart": true } }, "machine_learning": { "model_type": "lstm", "features": [ "open", "high", "low", "close", "volume", "sma_20", "sma_50", "sma_200", "rsi_14", "macd", "macd_signal", "macd_hist", "bb_upper", "bb_middle", "bb_lower" ], "train_test_split": 0.2, "validation_split": 0.1, "rl": { "learning_rate": 0.0003, "n_steps": 2048, "batch_size": 64, "n_epochs": 10, "gamma": 0.99, "gae_lambda": 0.95, "clip_range": 0.2, "ent_coef": 0.01, "vf_coef": 0.5 } }, "sentiment_analysis": { "news_api_key": "YOUR_NEWS_API_KEY", "twitter_api_key": "YOUR_TWITTER_API_KEY", "twitter_api_secret": "YOUR_TWITTER_API_SECRET", "twitter_access_token": "YOUR_TWITTER_ACCESS_TOKEN", "twitter_access_token_secret": "YOUR_TWITTER_ACCESS_TOKEN_SECRET", "sentiment_weights": { "news": 0.4, "twitter": 0.3, "market": 0.3 }, "sentiment_thresholds": { "positive": 0.3, "negative": -0.3 } }, "signal_weights": { "technical": 0.4, "ml": 0.3, "sentiment": 0.2, "risk": 0.1 }, "signal_thresholds": { "buy": 0.6, "sell": -0.6 }, "logging": { "level": "INFO", "file": "trading_bot.log", "max_size": 10485760, "backup_count": 5 }, "web_dashboard": { "host": "localhost", "port": 5000, "debug": false } } import os import sys import logging import json import time from datetime import datetime from typing import Dict, List import pandas as pd import ccxt from concurrent.futures import ThreadPoolExecutor import schedule import threading import signal import queue from .trading_strategy import TradingStrategy from .config import load_config # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('trading_bot.log'), logging.StreamHandler(sys.stdout) ] ) logger = logging.getLogger(__name__) class TradingBot: def __init__(self, config_path: str): # Load configuration self.config = load_config(config_path) # Initialize exchange self.exchange = self._initialize_exchange() # Initialize trading strategy self.strategy = TradingStrategy(self.config) # Initialize state self.is_running = False self.symbols = self.config['trading']['symbols'] self.timeframes = self.config['trading']['timeframes'] self.data_queue = queue.Queue() self.signal_queue = queue.Queue() # Load previous state if exists self._load_state() def _initialize_exchange(self) -> ccxt.Exchange: """ Initialize the cryptocurrency exchange """ try: exchange_class = getattr(ccxt, self.config['exchange']['name']) exchange = exchange_class({ 'apiKey': self.config['exchange']['api_key'], 'secret': self.config['exchange']['api_secret'], 'enableRateLimit': True }) # Test connection exchange.load_markets() logger.info(f"Successfully connected to {self.config['exchange']['name']}") return exchange except Exception as e: logger.error(f"Error initializing exchange: {str(e)}") raise def _load_state(self): """ Load previous trading state """ state_file = self.config['trading']['state_file'] if os.path.exists(state_file): try: self.strategy.load_state(state_file) logger.info("Successfully loaded previous trading state") except Exception as e: logger.error(f"Error loading state: {str(e)}") def _save_state(self): """ Save current trading state """ try: self.strategy.save_state(self.config['trading']['state_file']) logger.info("Successfully saved trading state") except Exception as e: logger.error(f"Error saving state: {str(e)}") def fetch_market_data(self, symbol: str, timeframe: str) -> pd.DataFrame: """ Fetch market data from exchange """ try: # Get OHLCV data ohlcv = self.exchange.fetch_ohlcv( symbol, timeframe=timeframe, limit=self.config['trading']['lookback_periods'] ) # Convert to DataFrame df = pd.DataFrame( ohlcv, columns=['timestamp', 'open', 'high', 'low', 'close', 'volume'] ) # Convert timestamp to datetime df['timestamp'] = pd.to_datetime(df['timestamp'], unit='ms') df.set_index('timestamp', inplace=True) return df except Exception as e: logger.error(f"Error fetching market data for {symbol}: {str(e)}") return None def process_market_data(self): """ Process market data from queue """ while self.is_running: try: # Get data from queue data = self.data_queue.get(timeout=1) symbol, timeframe, df = data # Generate trading signals signal = self.strategy.analyze_market(symbol, df) if signal: # Add signal to queue self.signal_queue.put(signal) except queue.Empty: continue except Exception as e: logger.error(f"Error processing market data: {str(e)}") def execute_signals(self): """ Execute trading signals from queue """ while self.is_running: try: # Get signal from queue signal = self.signal_queue.get(timeout=1) # Execute trade if self.strategy.execute_trade(signal): logger.info(f"Executed {signal.action} trade for {signal.symbol}") # Update positions with current prices current_prices = { symbol: self.exchange.fetch_ticker(symbol)['last'] for symbol in self.symbols } self.strategy.update_positions(current_prices) # Save state after trade self._save_state() except queue.Empty: continue except Exception as e: logger.error(f"Error executing signals: {str(e)}") def update_market_data(self): """ Update market data for all symbols """ with ThreadPoolExecutor(max_workers=len(self.symbols)) as executor: futures = [] for symbol in self.symbols: for timeframe in self.timeframes: future = executor.submit(self.fetch_market_data, symbol, timeframe) futures.append((symbol, timeframe, future)) for symbol, timeframe, future in futures: try: df = future.result() if df is not None: self.data_queue.put((symbol, timeframe, df)) except Exception as e: logger.error(f"Error updating market data for {symbol}: {str(e)}") def schedule_tasks(self): """ Schedule periodic tasks """ # Schedule market data updates for timeframe in self.timeframes: schedule.every().minute.at(":00").do(self.update_market_data) # Schedule state saving schedule.every().hour.at(":00").do(self._save_state) # Run the scheduler while self.is_running: schedule.run_pending() time.sleep(1) def start(self): """ Start the trading bot """ try: self.is_running = True # Start threads threads = [ threading.Thread(target=self.process_market_data), threading.Thread(target=self.execute_signals), threading.Thread(target=self.schedule_tasks) ] for thread in threads: thread.daemon = True thread.start() # Initial market data update self.update_market_data() logger.info("Trading bot started successfully") # Wait for shutdown signal while self.is_running: time.sleep(1) except Exception as e: logger.error(f"Error starting trading bot: {str(e)}") self.stop() def stop(self): """ Stop the trading bot """ try: self.is_running = False self._save_state() logger.info("Trading bot stopped successfully") except Exception as e: logger.error(f"Error stopping trading bot: {str(e)}") def main(): # Load configuration config_path = os.path.join(os.path.dirname(__file__), '..', 'config', 'config.json') # Create trading bot bot = TradingBot(config_path) # Handle shutdown signals def signal_handler(signum, frame): logger.info("Received shutdown signal") bot.stop() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) signal.signal(signal.SIGTERM, signal_handler) # Start trading bot bot.start() if __name__ == "__main__": main() import numpy as np import pandas as pd from typing import Dict, List, Optional, Tuple import logging from datetime import datetime from dataclasses import dataclass import json import os from .technical_analysis import TechnicalAnalyzer from .machine_learning import MachineLearningModel from .risk_management import RiskManager from .sentiment_analysis import SentimentAnalyzer logger = logging.getLogger(__name__) @dataclass class TradeSignal: """Data class to store trade signals""" symbol: str action: str # 'buy', 'sell', or 'hold' confidence: float price: float stop_loss: float take_profit: float position_size: float timestamp: datetime technical_score: float ml_score: float sentiment_score: float risk_score: float class TradingStrategy: def __init__(self, config: Dict): self.config = config self.technical_analyzer = TechnicalAnalyzer(config) self.ml_model = MachineLearningModel(config) self.risk_manager = RiskManager(config) self.sentiment_analyzer = SentimentAnalyzer(config) # Initialize state self.active_trades = {} self.trade_history = [] self.performance_metrics = {} def analyze_market(self, symbol: str, data: pd.DataFrame) -> TradeSignal: """ Analyze market conditions and generate trading signals """ try: # Technical analysis technical_signals = self.technical_analyzer.generate_signals(data) technical_score = technical_signals['signal'] # Machine learning prediction ml_predictions = self.ml_model.predict(data) ml_score = ml_predictions[-1] if ml_predictions is not None else 0 # Sentiment analysis sentiment_score = self.sentiment_analyzer.get_combined_sentiment(symbol) if sentiment_score is None: sentiment_score = 0 # Risk assessment risk_score = self.risk_manager.calculate_risk_metrics() # Combine signals combined_score = ( technical_score * self.config['signal_weights']['technical'] + ml_score * self.config['signal_weights']['ml'] + sentiment_score * self.config['signal_weights']['sentiment'] + risk_score * self.config['signal_weights']['risk'] ) # Generate trading signal current_price = data['close'].iloc[-1] # Calculate stop loss and take profit levels stop_loss = self._calculate_stop_loss(current_price, combined_score) take_profit = self._calculate_take_profit(current_price, combined_score) # Calculate position size position_size, required_margin = self.risk_manager.calculate_position_size( current_price, stop_loss, self.risk_manager.current_capital ) # Determine action if combined_score > self.config['signal_thresholds']['buy']: action = 'buy' elif combined_score < self.config['signal_thresholds']['sell']: action = 'sell' else: action = 'hold' # Create trade signal signal = TradeSignal( symbol=symbol, action=action, confidence=abs(combined_score), price=current_price, stop_loss=stop_loss, take_profit=take_profit, position_size=position_size, timestamp=datetime.now(), technical_score=technical_score, ml_score=ml_score, sentiment_score=sentiment_score, risk_score=risk_score ) return signal except Exception as e: logger.error(f"Error analyzing market: {str(e)}") return None def execute_trade(self, signal: TradeSignal) -> bool: """ Execute a trade based on the signal """ try: # Validate trade if not self.risk_manager.validate_trade( signal.symbol, signal.position_size, signal.price, signal.stop_loss, signal.take_profit ): return False # Execute trade if signal.action in ['buy', 'sell']: # Update position pnl = self.risk_manager.update_position( signal.symbol, signal.price, signal.price, signal.position_size, signal.action ) if pnl is not None: # Record trade self.trade_history.append({ 'symbol': signal.symbol, 'action': signal.action, 'entry_price': signal.price, 'exit_price': signal.price, 'position_size': signal.position_size, 'pnl': pnl, 'entry_time': signal.timestamp, 'exit_time': datetime.now() }) # Update performance metrics self._update_performance_metrics() return True return False except Exception as e: logger.error(f"Error executing trade: {str(e)}") return False def update_positions(self, current_prices: Dict[str, float]): """ Update all open positions with current prices """ try: for symbol, price in current_prices.items(): if symbol in self.risk_manager.positions: position = self.risk_manager.positions[symbol] pnl = self.risk_manager.update_position( symbol, position['entry_price'], price, position['position_size'], position['position_type'] ) if pnl is not None: # Record trade self.trade_history.append({ 'symbol': symbol, 'action': 'close', 'entry_price': position['entry_price'], 'exit_price': price, 'position_size': position['position_size'], 'pnl': pnl, 'entry_time': position['entry_time'], 'exit_time': datetime.now() }) # Update performance metrics self._update_performance_metrics() except Exception as e: logger.error(f"Error updating positions: {str(e)}") def _calculate_stop_loss(self, price: float, signal: float) -> float: """ Calculate stop loss level based on signal strength """ # Adjust stop loss distance based on signal strength base_stop_loss = self.config['stop_loss_pct'] signal_factor = abs(signal) stop_loss_distance = base_stop_loss * (1 + signal_factor) if signal > 0: # Buy signal return price * (1 - stop_loss_distance) else: # Sell signal return price * (1 + stop_loss_distance) def _calculate_take_profit(self, price: float, signal: float) -> float: """ Calculate take profit level based on signal strength """ # Adjust take profit distance based on signal strength base_take_profit = self.config['take_profit_pct'] signal_factor = abs(signal) take_profit_distance = base_take_profit * (1 + signal_factor) if signal > 0: # Buy signal return price * (1 + take_profit_distance) else: # Sell signal return price * (1 - take_profit_distance) def _update_performance_metrics(self): """ Update performance metrics based on trade history """ if not self.trade_history: return # Convert trade history to DataFrame df = pd.DataFrame(self.trade_history) # Calculate metrics self.performance_metrics = { 'total_trades': len(df), 'winning_trades': len(df[df['pnl'] > 0]), 'losing_trades': len(df[df['pnl'] < 0]), 'win_rate': len(df[df['pnl'] > 0]) / len(df), 'total_pnl': df['pnl'].sum(), 'avg_pnl': df['pnl'].mean(), 'max_drawdown': self.risk_manager.risk_metrics.max_drawdown if self.risk_manager.risk_metrics else 0, 'sharpe_ratio': self.risk_manager.risk_metrics.sharpe_ratio if self.risk_manager.risk_metrics else 0, 'profit_factor': self.risk_manager.risk_metrics.profit_factor if self.risk_manager.risk_metrics else 0 } def should_stop_trading(self) -> bool: """ Check if trading should be stopped based on risk metrics """ return self.risk_manager.should_stop_trading() def save_state(self, filepath: str): """ Save trading strategy state """ try: state = { 'active_trades': self.active_trades, 'trade_history': self.trade_history, 'performance_metrics': self.performance_metrics, 'risk_metrics': self.risk_manager.risk_metrics.__dict__ if self.risk_manager.risk_metrics else None } with open(filepath, 'w') as f: json.dump(state, f, default=str) logger.info(f"Trading strategy state saved to {filepath}") return True except Exception as e: logger.error(f"Error saving state: {str(e)}") return False def load_state(self, filepath: str): """ Load trading strategy state """ try: with open(filepath, 'r') as f: state = json.load(f) self.active_trades = state['active_trades'] self.trade_history = state['trade_history'] self.performance_metrics = state['performance_metrics'] if state['risk_metrics']: self.risk_manager.risk_metrics = RiskMetrics(**state['risk_metrics']) logger.info(f"Trading strategy state loaded from {filepath}") return True except Exception as e: logger.error(f"Error loading state: {str(e)}") return False import numpy as np import pandas as pd from typing import Dict, Tuple, Optional import logging from dataclasses import dataclass from datetime import datetime logger = logging.getLogger(__name__) @dataclass class RiskMetrics: """Data class to store risk metrics""" daily_drawdown: float max_drawdown: float sharpe_ratio: float sortino_ratio: float win_rate: float profit_factor: float avg_win: float avg_loss: float max_consecutive_losses: int max_consecutive_wins: int class RiskManager: def __init__(self, config: Dict): self.config = config self.initial_capital = config['initial_capital'] self.current_capital = self.initial_capital self.risk_per_trade = config['risk_per_trade'] self.max_daily_loss = config['max_daily_loss'] self.max_drawdown = config['max_drawdown'] self.max_positions = config['max_positions'] self.leverage = config['leverage'] self.stop_loss_pct = config['stop_loss_pct'] self.take_profit_pct = config['take_profit_pct'] # Performance tracking self.trades_history = [] self.daily_pnl = [] self.positions = {} self.risk_metrics = None def calculate_position_size(self, price: float, stop_loss: float, account_balance: float) -> Tuple[float, float]: """ Calculate position size based on risk parameters """ # Calculate risk amount in base currency risk_amount = account_balance * self.risk_per_trade # Calculate position size based on stop loss price_distance = abs(price - stop_loss) position_size = risk_amount / price_distance # Apply leverage position_size *= self.leverage # Calculate required margin required_margin = (position_size * price) / self.leverage # Ensure we don't exceed maximum position size max_position = account_balance * self.leverage / price position_size = min(position_size, max_position) return position_size, required_margin def validate_trade(self, symbol: str, position_size: float, price: float, stop_loss: float, take_profit: float) -> bool: """ Validate if a trade meets risk management criteria """ # Check if we have too many open positions if len(self.positions) >= self.max_positions: logger.warning("Maximum number of positions reached") return False # Check if symbol is already in a position if symbol in self.positions: logger.warning(f"Position already exists for {symbol}") return False # Calculate potential loss potential_loss = position_size * abs(price - stop_loss) # Check if potential loss exceeds daily limit if potential_loss > self.max_daily_loss: logger.warning("Trade exceeds maximum daily loss limit") return False # Check if stop loss is too far stop_loss_distance = abs(price - stop_loss) / price if stop_loss_distance > self.stop_loss_pct: logger.warning("Stop loss distance exceeds maximum allowed") return False # Check if take profit is reasonable take_profit_distance = abs(take_profit - price) / price if take_profit_distance > self.take_profit_pct: logger.warning("Take profit distance exceeds maximum allowed") return False return True def update_position(self, symbol: str, entry_price: float, current_price: float, position_size: float, position_type: str) -> Optional[float]: """ Update position and check for stop loss or take profit """ if symbol not in self.positions: self.positions[symbol] = { 'entry_price': entry_price, 'current_price': current_price, 'position_size': position_size, 'position_type': position_type, 'entry_time': datetime.now() } return None position = self.positions[symbol] pnl = 0 # Calculate unrealized PnL if position_type == 'long': pnl = (current_price - entry_price) * position_size else: pnl = (entry_price - current_price) * position_size # Check stop loss if position_type == 'long': if current_price <= entry_price * (1 - self.stop_loss_pct): pnl = -position_size * entry_price * self.stop_loss_pct del self.positions[symbol] return pnl else: if current_price >= entry_price * (1 + self.stop_loss_pct): pnl = -position_size * entry_price * self.stop_loss_pct del self.positions[symbol] return pnl # Check take profit if position_type == 'long': if current_price >= entry_price * (1 + self.take_profit_pct): pnl = position_size * entry_price * self.take_profit_pct del self.positions[symbol] return pnl else: if current_price <= entry_price * (1 - self.take_profit_pct): pnl = position_size * entry_price * self.take_profit_pct del self.positions[symbol] return pnl # Update current price position['current_price'] = current_price return None def calculate_risk_metrics(self) -> RiskMetrics: """ Calculate various risk metrics """ if not self.trades_history: return None # Convert trades history to DataFrame df = pd.DataFrame(self.trades_history) # Calculate daily returns daily_returns = df.groupby(df['exit_time'].dt.date)['pnl'].sum() # Calculate drawdown cumulative_returns = (1 + daily_returns).cumprod() rolling_max = cumulative_returns.expanding().max() drawdowns = (cumulative_returns - rolling_max) / rolling_max # Calculate metrics daily_drawdown = drawdowns.min() max_drawdown = drawdowns.min() # Calculate Sharpe ratio risk_free_rate = 0.02 # 2% annual risk-free rate excess_returns = daily_returns - risk_free_rate/252 sharpe_ratio = np.sqrt(252) * excess_returns.mean() / excess_returns.std() # Calculate Sortino ratio downside_returns = excess_returns[excess_returns < 0] sortino_ratio = np.sqrt(252) * excess_returns.mean() / downside_returns.std() # Calculate win rate and profit factor winning_trades = df[df['pnl'] > 0] losing_trades = df[df['pnl'] < 0] win_rate = len(winning_trades) / len(df) profit_factor = abs(winning_trades['pnl'].sum() / losing_trades['pnl'].sum()) # Calculate average win and loss avg_win = winning_trades['pnl'].mean() avg_loss = losing_trades['pnl'].mean() # Calculate consecutive wins and losses df['consecutive'] = (df['pnl'] > 0).astype(int) max_consecutive_wins = df['consecutive'].groupby((df['consecutive'] != df['consecutive'].shift()).cumsum()).sum().max() max_consecutive_losses = df['consecutive'].groupby((df['consecutive'] != df['consecutive'].shift()).cumsum()).sum().min() self.risk_metrics = RiskMetrics( daily_drawdown=daily_drawdown, max_drawdown=max_drawdown, sharpe_ratio=sharpe_ratio, sortino_ratio=sortino_ratio, win_rate=win_rate, profit_factor=profit_factor, avg_win=avg_win, avg_loss=avg_loss, max_consecutive_losses=max_consecutive_losses, max_consecutive_wins=max_consecutive_wins ) return self.risk_metrics def should_stop_trading(self) -> bool: """ Check if trading should be stopped based on risk metrics """ if not self.risk_metrics: return False # Stop if maximum drawdown is exceeded if self.risk_metrics.max_drawdown < -self.max_drawdown: logger.warning("Maximum drawdown exceeded. Stopping trading.") return True # Stop if win rate is too low if self.risk_metrics.win_rate < self.config['min_win_rate']: logger.warning("Win rate below minimum threshold. Stopping trading.") return True # Stop if profit factor is too low if self.risk_metrics.profit_factor < self.config['min_profit_factor']: logger.warning("Profit factor below minimum threshold. Stopping trading.") return True return False import numpy as np import pandas as pd from sklearn.preprocessing import StandardScaler from sklearn.model_selection import train_test_split from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout from tensorflow.keras.optimizers import Adam from stable_baselines3 import PPO from stable_baselines3.common.vec_env import DummyVecEnv import gym import logging from typing import Dict, List, Tuple, Optional import joblib import os logger = logging.getLogger(__name__) class MachineLearningModel: def __init__(self, config: Dict): self.config = config self.model_type = config['model_type'] self.features = config['features'] self.scaler = StandardScaler() self.model = None self.env = None def prepare_data(self, df: pd.DataFrame) -> Tuple[np.ndarray, np.ndarray]: """ Prepare data for machine learning """ # Select features X = df[self.features].copy() # Create target variable (price movement direction) y = np.where(df['close'].shift(-1) > df['close'], 1, 0) # Drop NaN values valid_idx = ~np.isnan(y) X = X[valid_idx] y = y[valid_idx] # Scale features X_scaled = self.scaler.fit_transform(X) return X_scaled, y def train_lstm(self, X: np.ndarray, y: np.ndarray): """ Train LSTM model """ # Reshape data for LSTM [samples, time steps, features] X_reshaped = np.reshape(X, (X.shape[0], 1, X.shape[1])) # Split data X_train, X_test, y_train, y_test = train_test_split( X_reshaped, y, test_size=self.config['train_test_split'], random_state=42 ) # Create model model = Sequential([ LSTM(50, activation='relu', input_shape=(1, X.shape[1]), return_sequences=True), Dropout(0.2), LSTM(50, activation='relu'), Dropout(0.2), Dense(1, activation='sigmoid') ]) # Compile model model.compile( optimizer=Adam(learning_rate=0.001), loss='binary_crossentropy', metrics=['accuracy'] ) # Train model model.fit( X_train, y_train, epochs=50, batch_size=32, validation_split=self.config['validation_split'], verbose=0 ) # Evaluate model _, accuracy = model.evaluate(X_test, y_test, verbose=0) logger.info(f"LSTM model accuracy: {accuracy:.4f}") self.model = model return model def train_reinforcement_learning(self, df: pd.DataFrame): """ Train reinforcement learning model """ # Create custom trading environment self.env = TradingEnvironment(df) self.env = DummyVecEnv([lambda: self.env]) # Create and train PPO model model = PPO( "MlpPolicy", self.env, learning_rate=self.config['rl']['learning_rate'], n_steps=self.config['rl']['n_steps'], batch_size=self.config['rl']['batch_size'], n_epochs=self.config['rl']['n_epochs'], gamma=self.config['rl']['gamma'], gae_lambda=self.config['rl']['gae_lambda'], clip_range=self.config['rl']['clip_range'], ent_coef=self.config['rl']['ent_coef'], vf_coef=self.config['rl']['vf_coef'], verbose=1 ) # Train model model.learn(total_timesteps=10000) self.model = model return model def predict(self, X: np.ndarray) -> np.ndarray: """ Make predictions using the trained model """ if self.model is None: logger.error("Model not trained. Call train() first.") return None if self.model_type == 'lstm': X_reshaped = np.reshape(X, (X.shape[0], 1, X.shape[1])) predictions = self.model.predict(X_reshaped) else: # reinforcement learning predictions = self.model.predict(X) return predictions def save_model(self, filepath: str): """ Save the trained model """ if self.model is None: logger.error("Model not trained. Call train() first.") return None try: if self.model_type == 'lstm': self.model.save(filepath) else: self.model.save(f"{filepath}_rl") # Save scaler separately joblib.dump(self.scaler, f"{filepath}_scaler") logger.info(f"Model saved to {filepath}") return True except Exception as e: logger.error(f"Error saving model: {str(e)}") return False def load_model(self, filepath: str): """ Load a trained model """ try: if self.model_type == 'lstm': self.model = tf.keras.models.load_model(filepath) else: self.model = PPO.load(f"{filepath}_rl") # Load scaler self.scaler = joblib.load(f"{filepath}_scaler") logger.info(f"Model loaded from {filepath}") return True except Exception as e: logger.error(f"Error loading model: {str(e)}") return False class TradingEnvironment(gym.Env): """ Custom trading environment for reinforcement learning """ def __init__(self, df: pd.DataFrame): super(TradingEnvironment, self).__init__() self.df = df self.current_step = 0 self.initial_balance = 10000 self.balance = self.initial_balance self.position = 0 self.position_size = 0 # Define action and observation space self.action_space = gym.spaces.Discrete(3) # Buy, Sell, Hold self.observation_space = gym.spaces.Box( low=-np.inf, high=np.inf, shape=(len(df.columns),), dtype=np.float32 ) def reset(self): """ Reset the environment """ self.current_step = 0 self.balance = self.initial_balance self.position = 0 self.position_size = 0 return self._get_observation() def step(self, action): """ Execute one step in the environment """ # Get current price current_price = self.df['close'].iloc[self.current_step] # Execute action reward = 0 done = False if action == 0: # Buy if self.position <= 0: self.position = 1 self.position_size = self.balance / current_price elif action == 1: # Sell if self.position >= 0: self.position = -1 self.position_size = self.balance / current_price # Calculate reward next_price = self.df['close'].iloc[self.current_step + 1] price_change = (next_price - current_price) / current_price if self.position != 0: reward = self.position * price_change * 100 # Update balance self.balance *= (1 + reward/100) # Move to next step self.current_step += 1 # Check if episode is done if self.current_step >= len(self.df) - 1: done = True return self._get_observation(), reward, done, {} def _get_observation(self): """ Get current observation """ return self.df.iloc[self.current_step].values.astype(np.float32) def render(self): """ Render the environment """ pass def close(self): """ Clean up resources """ pass import numpy as np import pandas as pd import talib from typing import Dict, List, Tuple, Optional import logging logger = logging.getLogger(__name__) class TechnicalAnalyzer: def __init__(self, config: Dict): self.config = config self.indicators = {} self.patterns = {} def add_indicators(self, df: pd.DataFrame) -> pd.DataFrame: """ Add technical indicators to the dataframe """ df = df.copy() # Trend Indicators df['sma_20'] = talib.SMA(df['close'], timeperiod=20) df['sma_50'] = talib.SMA(df['close'], timeperiod=50) df['sma_200'] = talib.SMA(df['close'], timeperiod=200) df['ema_20'] = talib.EMA(df['close'], timeperiod=20) # Volatility Indicators df['upperband'], df['middleband'], df['lowerband'] = talib.BBANDS( df['close'], timeperiod=self.config['indicators']['bollinger_bands']['period'], nbdevup=self.config['indicators']['bollinger_bands']['std_dev'], nbdevdn=self.config['indicators']['bollinger_bands']['std_dev'] ) df['atr'] = talib.ATR( df['high'], df['low'], df['close'], timeperiod=self.config['indicators']['atr']['period'] ) # Momentum Indicators df['rsi'] = talib.RSI( df['close'], timeperiod=self.config['indicators']['rsi']['period'] ) df['macd'], df['macdsignal'], df['macdhist'] = talib.MACD( df['close'], fastperiod=self.config['indicators']['macd']['fast_period'], slowperiod=self.config['indicators']['macd']['slow_period'], signalperiod=self.config['indicators']['macd']['signal_period'] ) # Volume Indicators df['obv'] = talib.OBV(df['close'], df['volume']) # Additional Indicators df['adx'] = talib.ADX(df['high'], df['low'], df['close'], timeperiod=14) df['cci'] = talib.CCI(df['high'], df['low'], df['close'], timeperiod=14) df['stoch_k'], df['stoch_d'] = talib.STOCH( df['high'], df['low'], df['close'], fastk_period=14, slowk_period=3, slowd_period=3 ) # Store indicators for reference self.indicators = { 'trend': ['sma_20', 'sma_50', 'sma_200', 'ema_20'], 'volatility': ['upperband', 'middleband', 'lowerband', 'atr'], 'momentum': ['rsi', 'macd', 'macdsignal', 'macdhist'], 'volume': ['obv'], 'additional': ['adx', 'cci', 'stoch_k', 'stoch_d'] } return df def detect_patterns(self, df: pd.DataFrame) -> pd.DataFrame: """ Detect candlestick patterns and chart patterns """ df = df.copy() # Candlestick Patterns if self.config['patterns']['candlestick']: df['doji'] = talib.CDLDOJI(df['open'], df['high'], df['low'], df['close']) df['hammer'] = talib.CDLHAMMER(df['open'], df['high'], df['low'], df['close']) df['engulfing'] = talib.CDLENGULFING(df['open'], df['high'], df['low'], df['close']) df['morning_star'] = talib.CDLMORNINGSTAR(df['open'], df['high'], df['low'], df['close']) df['evening_star'] = talib.CDLEVENINGSTAR(df['open'], df['high'], df['low'], df['close']) # Chart Patterns if self.config['patterns']['chart']: df['head_and_shoulders'] = self._detect_head_and_shoulders(df) df['double_top'] = self._detect_double_top(df) df['double_bottom'] = self._detect_double_bottom(df) df['triangle'] = self._detect_triangle(df) return df def _detect_head_and_shoulders(self, df: pd.DataFrame) -> pd.Series: """ Detect head and shoulders pattern """ pattern = pd.Series(0, index=df.index) for i in range(20, len(df) - 20): # Find potential left shoulder left_shoulder = df['high'].iloc[i-20:i].max() left_shoulder_idx = df['high'].iloc[i-20:i].idxmax() # Find potential head head = df['high'].iloc[i-10:i+10].max() head_idx = df['high'].iloc[i-10:i+10].idxmax() # Find potential right shoulder right_shoulder = df['high'].iloc[i:i+20].max() right_shoulder_idx = df['high'].iloc[i:i+20].idxmax() # Find neckline neckline = min(df['low'].iloc[left_shoulder_idx:right_shoulder_idx]) # Check pattern conditions if (left_shoulder < head and right_shoulder < head and abs(left_shoulder - right_shoulder) / head < 0.1): pattern.iloc[i] = 1 return pattern def _detect_double_top(self, df: pd.DataFrame) -> pd.Series: """ Detect double top pattern """ pattern = pd.Series(0, index=df.index) for i in range(20, len(df) - 20): # Find potential first peak first_peak = df['high'].iloc[i-20:i].max() first_peak_idx = df['high'].iloc[i-20:i].idxmax() # Find potential second peak second_peak = df['high'].iloc[i:i+20].max() second_peak_idx = df['high'].iloc[i:i+20].idxmax() # Find valley between peaks valley = df['low'].iloc[first_peak_idx:second_peak_idx].min() # Check pattern conditions if (abs(first_peak - second_peak) / first_peak < 0.02 and (first_peak - valley) / first_peak > 0.02): pattern.iloc[i] = 1 return pattern def _detect_double_bottom(self, df: pd.DataFrame) -> pd.Series: """ Detect double bottom pattern """ pattern = pd.Series(0, index=df.index) for i in range(20, len(df) - 20): # Find potential first bottom first_bottom = df['low'].iloc[i-20:i].min() first_bottom_idx = df['low'].iloc[i-20:i].idxmin() # Find potential second bottom second_bottom = df['low'].iloc[i:i+20].min() second_bottom_idx = df['low'].iloc[i:i+20].idxmin() # Find peak between bottoms peak = df['high'].iloc[first_bottom_idx:second_bottom_idx].max() # Check pattern conditions if (abs(first_bottom - second_bottom) / first_bottom < 0.02 and (peak - first_bottom) / first_bottom > 0.02): pattern.iloc[i] = 1 return pattern def _detect_triangle(self, df: pd.DataFrame) -> pd.Series: """ Detect triangle patterns (ascending, descending, symmetrical) """ pattern = pd.Series(0, index=df.index) for i in range(20, len(df) - 20): # Get highs and lows for the period highs = df['high'].iloc[i-20:i] lows = df['low'].iloc[i-20:i] # Calculate trend lines high_slope = np.polyfit(range(len(highs)), highs, 1)[0] low_slope = np.polyfit(range(len(lows)), lows, 1)[0] # Classify triangle type if abs(high_slope) < 0.001 and low_slope > 0.001: pattern.iloc[i] = 1 # Ascending triangle elif high_slope < -0.001 and abs(low_slope) < 0.001: pattern.iloc[i] = 2 # Descending triangle elif abs(high_slope + low_slope) < 0.001: pattern.iloc[i] = 3 # Symmetrical triangle return pattern def generate_signals(self, df: pd.DataFrame) -> pd.DataFrame: """ Generate trading signals based on technical indicators and patterns """ df = df.copy() # Initialize signal column df['signal'] = 0 # RSI signals df.loc[df['rsi'] < self.config['indicators']['rsi']['oversold'], 'signal'] += 1 df.loc[df['rsi'] > self.config['indicators']['rsi']['overbought'], 'signal'] -= 1 # MACD signals df.loc[df['macd'] > df['macdsignal'], 'signal'] += 1 df.loc[df['macd'] < df['macdsignal'], 'signal'] -= 1 # Bollinger Bands signals df.loc[df['close'] < df['lowerband'], 'signal'] += 1 df.loc[df['close'] > df['upperband'], 'signal'] -= 1 # Trend signals df.loc[df['close'] > df['sma_20'], 'signal'] += 1 df.loc[df['close'] < df['sma_20'], 'signal'] -= 1 # Pattern signals if 'head_and_shoulders' in df.columns: df.loc[df['head_and_shoulders'] == 1, 'signal'] -= 1 if 'double_top' in df.columns: df.loc[df['double_top'] == 1, 'signal'] -= 1 if 'double_bottom' in df.columns: df.loc[df['double_bottom'] == 1, 'signal'] += 1 if 'triangle' in df.columns: df.loc[df['triangle'] == 1, 'signal'] += 1 # Ascending df.loc[df['triangle'] == 2, 'signal'] -= 1 # Descending # Normalize signals to -1, 0, 1 df['signal'] = df['signal'].apply(lambda x: 1 if x > 2 else (-1 if x < -2 else 0)) return df def calculate_support_resistance(self, df: pd.DataFrame, window: int = 20) -> Tuple[pd.Series, pd.Series]: """ Calculate support and resistance levels """ support = df['low'].rolling(window=window).min() resistance = df['high'].rolling(window=window).max() return support, resistance def calculate_volatility(self, df: pd.DataFrame) -> pd.Series: """ Calculate various volatility measures """ # ATR-based volatility atr_volatility = df['atr'] / df['close'] # Bollinger Band width bb_width = (df['upperband'] - df['lowerband']) / df['middleband'] # Historical volatility returns = df['close'].pct_change() hist_volatility = returns.rolling(window=20).std() return pd.DataFrame({ 'atr_volatility': atr_volatility, 'bb_width': bb_width, 'hist_volatility': hist_volatility }) def get_market_regime(self, df: pd.DataFrame) -> pd.Series: """ Determine market regime (trending, ranging, volatile) """ regime = pd.Series('unknown', index=df.index) # Calculate ADX for trend strength adx = df['adx'] # Calculate volatility volatility = self.calculate_volatility(df)['atr_volatility'] # Determine regime regime.loc[adx > 25] = 'trending' regime.loc[(adx <= 25) & (volatility > volatility.rolling(window=20).mean())] = 'volatile' regime.loc[(adx <= 25) & (volatility <= volatility.rolling(window=20).mean())] = 'ranging' return regime import numpy as np import pandas as pd from datetime import datetime, timedelta import logging from typing import Dict, List, Optional, Tuple from dataclasses import dataclass import json import os # Configure logging logging.basicConfig( level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', handlers=[ logging.FileHandler('logs/trading_system.log'), logging.StreamHandler() ] ) logger = logging.getLogger(__name__) @dataclass class Trade: symbol: str direction: str entry_price: float stop_loss: float take_profit: float position_size: float entry_time: datetime exit_price: Optional[float] = None exit_time: Optional[datetime] = None pnl: Optional[float] = None status: str = 'open' class TradingSystem: def __init__(self, initial_capital: float = 50.0): self.initial_capital = initial_capital self.current_capital = initial_capital self.performance_history: List[Dict] = [] self.active_trades: Dict[str, Trade] = {} self.trade_history: List[Trade] = [] self.strategy_parameters = self._get_initial_parameters() self.risk_metrics = self._initialize_risk_metrics() self.last_recalibration = datetime.now() # Load configuration self._load_config() def _load_config(self): """Load configuration from config file""" try: with open('config/config.json', 'r') as f: self.config = json.load(f) except FileNotFoundError: logger.warning("Config file not found. Using default parameters.") self.config = self._get_default_config() def _get_default_config(self) -> Dict: """Get default configuration parameters""" return { 'risk_per_trade': 0.01, # 1% risk per trade 'max_positions': 2, 'min_win_rate': 0.4, 'recalibration_window': 20, 'max_drawdown': 0.1, # 10% maximum drawdown 'leverage': 1, # No leverage initially 'position_sizing': { 'method': 'fixed_fractional', 'fraction': 0.01 # 1% of capital per trade } } def _get_initial_parameters(self) -> Dict: """Get initial strategy parameters""" return { 'rsi_period': 14, 'rsi_overbought': 70, 'rsi_oversold': 30, 'bb_period': 20, 'bb_std': 2, 'macd_fast': 12, 'macd_slow': 26, 'macd_signal': 9, 'atr_period': 14, 'atr_multiplier': 2 } def _initialize_risk_metrics(self) -> Dict: """Initialize risk metrics tracking""" return { 'total_trades': 0, 'winning_trades': 0, 'losing_trades': 0, 'win_rate': 0.0, 'profit_factor': 0.0, 'max_drawdown': 0.0, 'current_drawdown': 0.0, 'avg_trade': 0.0, 'largest_win': 0.0, 'largest_loss': 0.0 } def monitor_performance(self, window_size: int = 20) -> bool: """ Monitor recent performance and determine if recalibration is needed Returns True if recalibration is needed """ if len(self.performance_history) < window_size: return False recent_performance = self.performance_history[-window_size:] win_rate = sum(1 for trade in recent_performance if trade['pnl'] > 0) / window_size # Check various performance metrics needs_recalibration = False # Win rate check if win_rate < self.config['min_win_rate']: logger.warning(f"Win rate {win_rate:.2%} below threshold {self.config['min_win_rate']:.2%}") needs_recalibration = True # Drawdown check current_drawdown = self._calculate_drawdown() if current_drawdown > self.config['max_drawdown']: logger.warning(f"Current drawdown {current_drawdown:.2%} exceeds maximum {self.config['max_drawdown']:.2%}") needs_recalibration = True # Profit factor check profit_factor = self._calculate_profit_factor(recent_performance) if profit_factor < 1.0: logger.warning(f"Profit factor {profit_factor:.2f} below 1.0") needs_recalibration = True return needs_recalibration def recalibrate_strategy(self, market_data: pd.DataFrame): """ Adjust strategy parameters based on recent market conditions """ logger.info("Starting strategy recalibration") # Analyze market conditions volatility = self._calculate_volatility(market_data) trend_strength = self._calculate_trend_strength(market_data) # Adjust parameters based on market conditions new_parameters = self.strategy_parameters.copy() # Adjust RSI levels based on volatility if volatility > 0.02: # High volatility new_parameters['rsi_overbought'] = 75 new_parameters['rsi_oversold'] = 25 else: # Low volatility new_parameters['rsi_overbought'] = 70 new_parameters['rsi_oversold'] = 30 # Adjust ATR multiplier based on trend strength if trend_strength > 0.7: # Strong trend new_parameters['atr_multiplier'] = 2.5 else: # Weak trend new_parameters['atr_multiplier'] = 2.0 # Update parameters self.strategy_parameters = new_parameters self.last_recalibration = datetime.now() logger.info("Strategy recalibration completed") logger.info(f"New parameters: {new_parameters}") def calculate_position_size(self, entry_price: float, stop_loss: float) -> float: """ Calculate position size based on risk management rules """ risk_amount = self.current_capital * self.config['risk_per_trade'] risk_per_unit = abs(entry_price - stop_loss) if risk_per_unit == 0: logger.warning("Risk per unit is zero. Cannot calculate position size.") return 0 position_size = risk_amount / risk_per_unit # Apply leverage if configured if self.config['leverage'] > 1: position_size *= self.config['leverage'] # Ensure position size doesn't exceed maximum allowed max_position = self.current_capital * self.config['position_sizing']['fraction'] position_size = min(position_size, max_position) return position_size def _calculate_volatility(self, data: pd.DataFrame) -> float: """Calculate market volatility""" returns = data['close'].pct_change() return returns.std() def _calculate_trend_strength(self, data: pd.DataFrame) -> float: """Calculate trend strength using ADX""" # Implementation would go here return 0.5 # Placeholder def _calculate_drawdown(self) -> float: """Calculate current drawdown""" if not self.performance_history: return 0.0 peak = max(self.performance_history, key=lambda x: x['equity'])['equity'] current = self.performance_history[-1]['equity'] return (peak - current) / peak def _calculate_profit_factor(self, trades: List[Dict]) -> float: """Calculate profit factor from recent trades""" gross_profit = sum(t['pnl'] for t in trades if t['pnl'] > 0) gross_loss = abs(sum(t['pnl'] for t in trades if t['pnl'] < 0)) if gross_loss == 0: return float('inf') return gross_profit / gross_loss def update_risk_metrics(self, trade: Trade): """Update risk metrics after a trade""" self.risk_metrics['total_trades'] += 1 if trade.pnl and trade.pnl > 0: self.risk_metrics['winning_trades'] += 1 self.risk_metrics['largest_win'] = max( self.risk_metrics['largest_win'], trade.pnl ) elif trade.pnl and trade.pnl < 0: self.risk_metrics['losing_trades'] += 1 self.risk_metrics['largest_loss'] = min( self.risk_metrics['largest_loss'], trade.pnl ) # Update win rate if self.risk_metrics['total_trades'] > 0: self.risk_metrics['win_rate'] = ( self.risk_metrics['winning_trades'] / self.risk_metrics['total_trades'] ) # Update average trade if trade.pnl: self.risk_metrics['avg_trade'] = ( (self.risk_metrics['avg_trade'] * (self.risk_metrics['total_trades'] - 1) + trade.pnl) / self.risk_metrics['total_trades'] ) def save_state(self): """Save current system state""" state = { 'current_capital': self.current_capital, 'strategy_parameters': self.strategy_parameters, 'risk_metrics': self.risk_metrics, 'last_recalibration': self.last_recalibration.isoformat(), 'active_trades': { symbol: { 'direction': trade.direction, 'entry_price': trade.entry_price, 'stop_loss': trade.stop_loss, 'take_profit': trade.take_profit, 'position_size': trade.position_size, 'entry_time': trade.entry_time.isoformat() } for symbol, trade in self.active_trades.items() } } try: with open('data/system_state.json', 'w') as f: json.dump(state, f, indent=4) except Exception as e: logger.error(f"Error saving system state: {str(e)}") def load_state(self): """Load system state from file""" try: with open('data/system_state.json', 'r') as f: state = json.load(f) self.current_capital = state['current_capital'] self.strategy_parameters = state['strategy_parameters'] self.risk_metrics = state['risk_metrics'] self.last_recalibration = datetime.fromisoformat(state['last_recalibration']) # Reconstruct active trades self.active_trades = {} for symbol, trade_data in state['active_trades'].items(): self.active_trades[symbol] = Trade( symbol=symbol, direction=trade_data['direction'], entry_price=trade_data['entry_price'], stop_loss=trade_data['stop_loss'], take_profit=trade_data['take_profit'], position_size=trade_data['position_size'], entry_time=datetime.fromisoformat(trade_data['entry_time']) ) except FileNotFoundError: logger.info("No saved state found. Starting fresh.") except Exception as e: logger.error(f"Error loading system state: {str(e)}") def get_system_status(self) -> Dict: """Get current system status""" return { 'current_capital': self.current_capital, 'total_trades': self.risk_metrics['total_trades'], 'win_rate': self.risk_metrics['win_rate'], 'profit_factor': self.risk_metrics['profit_factor'], 'current_drawdown': self.risk_metrics['current_drawdown'], 'active_trades': len(self.active_trades), 'last_recalibration': self.last_recalibration.isoformat(), 'strategy_parameters': self.strategy_parameters } import os from dotenv import load_dotenv # Load environment variables load_dotenv() # Exchange Configuration EXCHANGE_CONFIG = { 'name': 'binance', 'api_key': os.getenv('BINANCE_API_KEY', ''), 'api_secret': os.getenv('BINANCE_API_SECRET', ''), 'testnet': True # Use testnet for development } # Trading Parameters TRADING_CONFIG = { 'symbols': ['BTC/USDT', 'ETH/USDT', 'EUR/USD'], 'timeframes': ['1h', '4h', '1d'], 'initial_capital': 10000, 'risk_per_trade': 0.02, # 2% risk per trade 'max_positions': 3, 'position_sizing': { 'method': 'fixed_fractional', 'fraction': 0.02 # 2% of capital per trade } } # Technical Analysis Parameters TECHNICAL_CONFIG = { 'indicators': { 'bollinger_bands': { 'period': 20, 'std_dev': 2 }, 'rsi': { 'period': 14, 'overbought': 70, 'oversold': 30 }, 'macd': { 'fast_period': 12, 'slow_period': 26, 'signal_period': 9 }, 'atr': { 'period': 14 } }, 'patterns': { 'head_and_shoulders': True, 'double_top_bottom': True, 'triangles': True } } # Machine Learning Configuration ML_CONFIG = { 'model_type': 'lstm', # Options: 'lstm', 'rf', 'xgboost' 'features': [ 'open', 'high', 'low', 'close', 'volume', 'sma_20', 'sma_50', 'rsi', 'macd', 'atr', 'bb_upper', 'bb_lower', 'bb_width' ], 'sequence_length': 10, 'prediction_horizon': 1, 'train_test_split': 0.8, 'validation_split': 0.1 } # Reinforcement Learning Configuration RL_CONFIG = { 'algorithm': 'PPO', 'learning_rate': 0.0003, 'n_steps': 2048, 'batch_size': 64, 'n_epochs': 10, 'gamma': 0.99, 'gae_lambda': 0.95, 'clip_range': 0.2, 'ent_coef': 0.01, 'vf_coef': 0.5 } # Risk Management Configuration RISK_CONFIG = { 'stop_loss': { 'method': 'atr', 'atr_multiplier': 2 }, 'take_profit': { 'method': 'risk_reward', 'risk_reward_ratio': 2 }, 'trailing_stop': { 'enabled': True, 'activation_percentage': 0.02, 'trail_percentage': 0.01 } } # Sentiment Analysis Configuration SENTIMENT_CONFIG = { 'sources': [ 'reuters', 'bloomberg', 'forexfactory' ], 'update_interval': 3600, # 1 hour 'weight': 0.2 # Weight in final decision } # Backtesting Configuration BACKTEST_CONFIG = { 'start_date': '2020-01-01', 'end_date': '2023-12-31', 'initial_capital': 10000, 'commission': 0.001, # 0.1% 'slippage': 0.0001 # 0.01% } # Logging Configuration LOGGING_CONFIG = { 'level': 'INFO', 'format': '%(asctime)s - %(name)s - %(levelname)s - %(message)s', 'file': 'logs/trading_bot.log' } # Web Dashboard Configuration DASHBOARD_CONFIG = { 'host': '0.0.0.0', 'port': 5000, 'debug': False, 'update_interval': 5 # seconds } numpy>=1.21.0 pandas>=1.3.0 ccxt>=2.0.0 scikit-learn>=0.24.2 tensorflow>=2.6.0 stable-baselines3>=1.5.0 gym>=0.21.0 ta-lib>=0.4.24 textblob>=0.15.3 tweepy>=4.10.0 newsapi-python>=0.2.6 yfinance>=0.1.63 schedule>=1.1.0 joblib>=1.0.2 python-dotenv>=0.19.0 flask>=2.0.1 plotly>=5.3.1 dash>=2.0.0