Team Ai
Apppublic

Deepvest/ProfilingAI

sourceHugging Faceupdated 2y agoView on Hugging Face
0likes
strategy_optimizer.py230 linesDownload Raw Back to analysis
1# src/analysis/strategy_optimizer.py2 3import numpy as np4import pandas as pd5from typing import Dict, List, Tuple6from dataclasses import dataclass7import optuna8import matplotlib.pyplot as plt9import seaborn as sns10from concurrent.futures import ProcessPoolExecutor11from datetime import datetime, timedelta12 13from src.models.backtest_results import EnhancedBacktestResult14 15 16@dataclass17class OptimizationResult:18    """Résultats de l'optimisation de la stratégie"""19    best_params: Dict[str, float]20    performance_metrics: Dict[str, float]21    optimization_path: pd.DataFrame22    parameter_importance: Dict[str, float]23 24class StrategyOptimizer:25    """Optimiseur de stratégie utilisant Optuna"""26    27    def __init__(self, enhanced_backtest_engine, n_trials: int = 100):28        self.backtest_engine = enhanced_backtest_engine29        self.n_trials = n_trials30        self.study = None31        32    async def optimize_strategy(self,33                              symbols: List[str],34                              start_date: pd.Timestamp,35                              end_date: pd.Timestamp) -> OptimizationResult:36        """Optimise les paramètres de la stratégie"""37        38        # Création de l'étude Optuna39        self.study = optuna.create_study(40            direction="maximize",41            study_name="strategy_optimization",42            sampler=optuna.samplers.TPESampler(seed=42)43        )44        45        # Exécution de l'optimisation46        self.study.optimize(47            lambda trial: self._objective(trial, symbols, start_date, end_date),48            n_trials=self.n_trials,49            show_progress_bar=True50        )51        52        # Analyse des résultats53        optimization_results = self._analyze_optimization_results()54        55        # Visualisation des résultats56        self._plot_optimization_results()57        58        return optimization_results59    60    async def _objective(self, 61                  trial: optuna.Trial,62                  symbols: List[str],63                  start_date: pd.Timestamp,64                  end_date: pd.Timestamp) -> float:65        """Fonction objectif pour l'optimisation"""66        67        # Paramètres à optimiser68        params = {69            'technical_weight': trial.suggest_float('technical_weight', 0.2, 0.6),70            'alternative_weight': trial.suggest_float('alternative_weight', 0.1, 0.4),71            'social_weight': trial.suggest_float('social_weight', 0.1, 0.4),72            'signal_threshold': trial.suggest_float('signal_threshold', 0.3, 0.7),73            'position_size_factor': trial.suggest_float('position_size_factor', 0.5, 2.0),74            'stop_loss': trial.suggest_float('stop_loss', 0.02, 0.10),75            'take_profit': trial.suggest_float('take_profit', 0.03, 0.15)76        }77        78        # Exécution du backtest avec les paramètres actuels79        results = await self.backtest_engine.run_enhanced_backtest(80            symbols=symbols,81            start_date=start_date,82            end_date=end_date,83            strategy_params=params84        )85        86        # Calcul du score d'optimisation87        optimization_score = self._calculate_optimization_score(results)88        89        return optimization_score90    91    def _calculate_optimization_score(self, results: Dict) -> float:92        """Calcule le score pour l'optimisation"""93        # Extraction des métriques94        sharpe_ratio = results.performance_metrics['sharpe_ratio']95        max_drawdown = abs(results.performance_metrics['max_drawdown'])96        return_risk_ratio = results.performance_metrics['annual_return'] / max_drawdown97        98        # Combinaison pondérée des métriques99        score = (0.4 * sharpe_ratio + 100                0.3 * return_risk_ratio + 101                0.3 * (1 / (1 + max_drawdown)))102        103        return score104 105    def _analyze_optimization_results(self) -> OptimizationResult:106        """Analyse des résultats de l'optimisation"""107        # Meilleurs paramètres108        best_params = self.study.best_params109        110        # Chemin d'optimisation111        optimization_path = pd.DataFrame(112            [t.params for t in self.study.trials],113            index=[t.number for t in self.study.trials]114        )115        116        # Importance des paramètres117        parameter_importance = optuna.importance.get_param_importances(self.study)118        119        return OptimizationResult(120            best_params=best_params,121            performance_metrics=self.study.best_value,122            optimization_path=optimization_path,123            parameter_importance=parameter_importance124        )125 126    def _plot_optimization_results(self):127        """Visualisation des résultats d'optimisation"""128        # Configuration du style129        plt.style.use('seaborn')130        fig = plt.figure(figsize=(15, 10))131        132        # 1. Évolution de l'optimisation133        plt.subplot(221)134        optuna.visualization.matplotlib.plot_optimization_history(self.study)135        plt.title('Progression de l\'optimisation')136        137        # 2. Importance des paramètres138        plt.subplot(222)139        optuna.visualization.matplotlib.plot_param_importances(self.study)140        plt.title('Importance des paramètres')141        142        # 3. Corrélations entre paramètres143        plt.subplot(223)144        optuna.visualization.matplotlib.plot_parallel_coordinate(self.study)145        plt.title('Corrélations des paramètres')146        147        # 4. Distribution des meilleurs paramètres148        plt.subplot(224)149        data = pd.DataFrame(150            [t.params for t in self.study.trials],151            columns=self.study.best_params.keys()152        )153        sns.boxplot(data=data)154        plt.xticks(rotation=45)155        plt.title('Distribution des paramètres')156        157        plt.tight_layout()158        plt.show()159 160# Visualisation détaillée des résultats de backtest161class BacktestVisualizer:162    """Visualisation détaillée des résultats de backtest"""163    164    @staticmethod165    def create_performance_dashboard(results: EnhancedBacktestResult):166        """Création d'un dashboard de performance complet"""167        plt.style.use('seaborn')168        fig = plt.figure(figsize=(20, 12))169        170        # 1. Courbe de croissance du portefeuille171        plt.subplot(331)172        cumulative_returns = (1 + results.returns).cumprod()173        plt.plot(cumulative_returns.index, cumulative_returns.values)174        plt.title('Performance du portefeuille')175        176        # 2. Drawdowns177        plt.subplot(332)178        drawdowns = BacktestVisualizer._calculate_drawdowns(results.returns)179        plt.fill_between(drawdowns.index, drawdowns.values, 0, color='red', alpha=0.3)180        plt.title('Drawdowns')181        182        # 3. Distribution des rendements183        plt.subplot(333)184        sns.histplot(results.returns, kde=True)185        plt.title('Distribution des rendements')186        187        # 4. Heat map des positions188        plt.subplot(334)189        sns.heatmap(results.positions.T, cmap='RdYlGn', center=0)190        plt.title('Évolution des positions')191        192        # 5. Contribution par signal193        plt.subplot(335)194        signal_returns = BacktestVisualizer._calculate_signal_returns(results)195        sns.barplot(data=signal_returns)196        plt.title('Performance par type de signal')197        198        # 6. Métriques de risque199        plt.subplot(336)200        risk_metrics = pd.Series(results.risk_metrics)201        sns.barplot(x=risk_metrics.index, y=risk_metrics.values)202        plt.xticks(rotation=45)203        plt.title('Métriques de risque')204        205        # 7. Impact des données alternatives206        plt.subplot(337)207        alt_contribution = pd.Series(results.alternative_contribution)208        sns.barplot(x=alt_contribution.index, y=alt_contribution.values)209        plt.xticks(rotation=45)210        plt.title('Contribution des données alternatives')211        212        plt.tight_layout()213        plt.show()214 215    @staticmethod216    def _calculate_drawdowns(returns: pd.Series) -> pd.Series:217        """Calcul des drawdowns"""218        cumulative = (1 + returns).cumprod()219        running_max = cumulative.expanding().max()220        drawdowns = cumulative / running_max - 1221        return drawdowns222 223    @staticmethod224    def _calculate_signal_returns(results: EnhancedBacktestResult) -> pd.DataFrame:225        """Calcul des rendements par type de signal"""226        signal_returns = pd.DataFrame()227        for signal_type in results.signals['direction'].unique():228            mask = results.signals['direction'] == signal_type229            signal_returns[signal_type] = results.returns[mask].mean()230        return signal_returns