Last active
December 18, 2024 07:52
-
-
Save architectureman/0de2b6245d54e5dbd4b27ff2032fc468 to your computer and use it in GitHub Desktop.
Fix bug ticker smaller than risk-free rate
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| CONFIG = { | |
| 'MAX_PORTFOLIO_POINT_GENERATE_ATTEMPTS': 100, | |
| 'DEFAULT_RISK_FREE_RATE': 0.02, | |
| 'DEFAULT_LOOKBACK_DAYS': 365, | |
| 'MAX_TICKERS': 20 | |
| } | |
| #------------------------------------------------------------------------------------------------------------------------ | |
| def safely_fetch_stock_data( | |
| fetch_func: Callable[[List[str], Optional[datetime], Optional[datetime], Optional[str]], pd.DataFrame] | |
| ) -> Callable[[List[str], Optional[datetime], Optional[datetime], Optional[str]], pd.DataFrame]: | |
| """ | |
| Higher-order function for safe stock data retrieval. | |
| Wraps the original fetch function with validation and error handling. | |
| """ | |
| def wrapper( | |
| tickers: List[str], | |
| start_date: Optional[datetime] = None, | |
| end_date: Optional[datetime] = None, | |
| exchange: Optional[str] = None | |
| ) -> pd.DataFrame: | |
| if len(tickers) > CONFIG['MAX_TICKERS']: | |
| raise StockDataFetchError( | |
| f"Too many tickers. Maximum allowed: {CONFIG['MAX_TICKERS']}" | |
| ) | |
| try: | |
| return fetch_func(tickers, start_date, end_date, exchange) | |
| except Exception as e: | |
| logger.error(f"Stock data fetch error: {e}") | |
| raise StockDataFetchError(f"Failed to fetch stock data: {e}") | |
| return wrapper | |
| #------------------------------------------------------------------------------------------------------------------------ | |
| def optimize_portfolio( | |
| df: pd.DataFrame, | |
| initial_weights: Dict[str, float], | |
| constraints: Optional[Dict[str, Tuple[float, float]]] = None, | |
| risk_free_rate: float = CONFIG['DEFAULT_RISK_FREE_RATE'] # Default to 2% risk-free rate | |
| ) -> Dict: | |
| """ | |
| Perform robust portfolio optimization with enhanced error handling. | |
| Args: | |
| df: Price data DataFrame | |
| initial_weights: Initial portfolio weights | |
| constraints: Optional allocation constraints | |
| risk_free_rate: Risk-free rate for Sharpe ratio calculation | |
| Returns: | |
| Dictionary with optimized weights and metrics | |
| """ | |
| tickers = df.columns.tolist() | |
| try: | |
| # Validate input data | |
| if df.empty: | |
| logger.warning("Empty price data DataFrame") | |
| return { | |
| 'optimized_weights': initial_weights, | |
| 'metrics': compute_portfolio_metrics(df, initial_weights) | |
| } | |
| # Calculate returns with annualized method | |
| # Subtract risk-free rate to adjust expected returns | |
| mu = expected_returns.mean_historical_return(df, frequency=252) | |
| mu_adjusted = mu - risk_free_rate | |
| # Handle cases with zero or negative returns | |
| if (mu_adjusted <= 0).all(): | |
| logger.warning("All assets have returns below risk-free rate") | |
| return { | |
| 'optimized_weights': initial_weights, | |
| 'metrics': compute_portfolio_metrics(df, initial_weights) | |
| } | |
| # Use sample covariance with annual frequency | |
| S = risk_models.sample_cov(df, frequency=252) | |
| # Set default weight bounds | |
| weight_bounds = [(0, 1) for _ in range(len(tickers))] | |
| # Apply custom constraints if provided | |
| if constraints: | |
| for ticker, (min_val, max_val) in constraints.items(): | |
| if ticker in tickers: | |
| idx = tickers.index(ticker) | |
| weight_bounds[idx] = (min_val, max_val) | |
| # Create Efficient Frontier with adjusted returns | |
| ef = EfficientFrontier( | |
| mu_adjusted, # Use adjusted returns | |
| S, | |
| weight_bounds=weight_bounds | |
| ) | |
| try: | |
| # Attempt to maximize Sharpe ratio (now with adjusted returns) | |
| weights = ef.max_sharpe() | |
| except ValueError: | |
| # Fallback to equal weight portfolio if optimization fails | |
| logger.warning("Sharpe ratio optimization failed. Using equal weights.") | |
| equal_weights = dict(zip(tickers, [1/len(tickers)]*len(tickers))) | |
| return { | |
| 'optimized_weights': equal_weights, | |
| 'metrics': compute_portfolio_metrics(df, equal_weights) | |
| } | |
| # Clean and validate weights | |
| optimized_weights = ef.clean_weights() | |
| # Compute portfolio metrics | |
| optimized_metrics = compute_portfolio_metrics(df, optimized_weights) | |
| # Optional: Add risk-free rate to metrics if needed | |
| if 'risk_free_rate' not in optimized_metrics: | |
| optimized_metrics['risk_free_rate'] = risk_free_rate | |
| return { | |
| 'optimized_weights': optimized_weights, | |
| 'metrics': optimized_metrics | |
| } | |
| except Exception as e: | |
| logger.error(f"Portfolio optimization error: {e}") | |
| return { | |
| 'optimized_weights': initial_weights, | |
| 'metrics': compute_portfolio_metrics(df, initial_weights) | |
| } | |
| #------------------------------------------------------------------------------------------------------------------------ | |
| def generate_efficient_frontier( | |
| df: pd.DataFrame, | |
| num_portfolios: int = CONFIG['MAX_PORTFOLIO_POINT_GENERATE_ATTEMPTS'], | |
| risk_free_rate: float = CONFIG['DEFAULT_RISK_FREE_RATE'], | |
| constraints: Optional[Dict[str, Tuple[float, float]]] = None | |
| ) -> Dict[str, Union[List[Dict[str, float]], Dict[str, float]]]: | |
| try: | |
| # Expected returns and sample covariance | |
| mu = expected_returns.mean_historical_return(df) | |
| S = risk_models.sample_cov(df) | |
| # Set default weight bounds based on constraints | |
| tickers = df.columns.tolist() | |
| weight_bounds = [(0, 1) for _ in range(len(tickers))] | |
| # Apply custom constraints if provided | |
| if constraints: | |
| for ticker, (min_val, max_val) in constraints.items(): | |
| if ticker in tickers: | |
| idx = tickers.index(ticker) | |
| weight_bounds[idx] = (min_val, max_val) | |
| # Store frontier points | |
| frontier_points = [] | |
| # Variables to track optimal portfolios | |
| gmv_weights = None | |
| gmv_return, gmv_volatility = None, None | |
| # Calculate global minimum variance portfolio with constraints | |
| ef_min = EfficientFrontier(mu, S, weight_bounds=weight_bounds) | |
| ef_min.min_volatility() | |
| gmv_weights = ef_min.clean_weights() | |
| gmv_portfolio_performance = ef_min.portfolio_performance() | |
| gmv_return, gmv_volatility = gmv_portfolio_performance[0], gmv_portfolio_performance[1] | |
| # Calculate maximum Sharpe ratio portfolio with constraints | |
| ef_msr = EfficientFrontier(mu, S, weight_bounds=weight_bounds) | |
| ef_msr.max_sharpe(risk_free_rate=risk_free_rate) | |
| msr_weights = ef_msr.clean_weights() | |
| msr_portfolio_performance = ef_msr.portfolio_performance() | |
| msr_return = msr_portfolio_performance[0] | |
| msr_volatility = msr_portfolio_performance[1] | |
| msr_sharpe = msr_portfolio_performance[2] | |
| # Calculate the maximum return from individual assets | |
| max_return = mu.max() | |
| # Generate target returns within feasible range, extending beyond MSR | |
| target_returns = np.linspace(gmv_return, max_return, num_portfolios + 1) | |
| for target_return in target_returns: | |
| try: | |
| # Initialize EfficientFrontier object with constraints | |
| ef = EfficientFrontier(mu, S, weight_bounds=weight_bounds) | |
| # Optimize portfolio for target return | |
| ef.efficient_return(target_return) | |
| weights = ef.clean_weights() | |
| # Calculate portfolio performance | |
| portfolio_performance = ef.portfolio_performance() | |
| portfolio_return = portfolio_performance[0] | |
| portfolio_volatility = portfolio_performance[1] | |
| # Calculate Sharpe Ratio | |
| sharpe_ratio = (portfolio_return - risk_free_rate) / portfolio_volatility if portfolio_volatility > 0 else 0 | |
| # Add point to frontier | |
| frontier_points.append({ | |
| 'volatility': round(portfolio_volatility * 100, 4), | |
| 'return': round(portfolio_return * 100, 4), | |
| 'sharpe_ratio': round(sharpe_ratio, 4), | |
| 'weights': {ticker: round(float(weight), 4) | |
| for ticker, weight in weights.items()} | |
| }) | |
| except Exception as e: | |
| logger.warning(f"Skipping target return {target_return}: {str(e)}") | |
| continue | |
| # Sort points by volatility for smooth plotting | |
| # frontier_points.sort(key=lambda x: x['volatility']) | |
| # Prepare outputs | |
| return { | |
| "frontier_points": frontier_points, | |
| "global_minimum_variance": { | |
| "return": round(gmv_return * 100, 4), | |
| "volatility": round(gmv_volatility * 100, 4), | |
| "weights": {ticker: round(float(weight), 4) | |
| for ticker, weight in gmv_weights.items()} | |
| }, | |
| "maximum_sharpe_ratio": { | |
| "return": round(msr_return * 100, 4), | |
| "volatility": round(msr_volatility * 100, 4), | |
| "sharpe_ratio": round(msr_sharpe, 4), | |
| "weights": {ticker: round(float(weight), 4) | |
| for ticker, weight in msr_weights.items()} | |
| }, | |
| "minimum_volatility": { | |
| "return": round(gmv_return * 100, 4), | |
| "volatility": round(gmv_volatility * 100, 4), | |
| "sharpe_ratio": (gmv_return - risk_free_rate) / gmv_volatility if gmv_volatility > 0 else 0, | |
| "weights": {ticker: round(float(weight), 4) | |
| for ticker, weight in gmv_weights.items()} | |
| }, | |
| "capital_market_line": { | |
| "slope": round((msr_return * 100 - risk_free_rate * 100) / (msr_volatility * 100), 4), | |
| "risk_free_rate": risk_free_rate * 100, # Convert to percentage | |
| "start_point": { | |
| "x": 0, # volatility | |
| "y": risk_free_rate * 100 # return (converted to percentage) | |
| }, | |
| "end_point": { | |
| "x": round(msr_volatility * 100, 4), # volatility of maximum sharpe ratio portfolio | |
| "y": round(msr_return * 100, 4) # return of maximum sharpe ratio portfolio | |
| } | |
| } | |
| } | |
| except Exception as e: | |
| logger.error(f"Efficient Frontier generation error: {e}") | |
| return { | |
| "status": "error", | |
| "message": str(e) | |
| } | |
| #------------------------------------------------------------------------------------------------------------------------ | |
| def calculate_asset_correlations(df: pd.DataFrame) -> Dict[str, Dict[str, float]]: | |
| """ | |
| Calculates the correlation matrix between assets. | |
| Args: | |
| df: DataFrame containing asset price data. | |
| Returns: | |
| A dictionary representing the correlation matrix. | |
| """ | |
| correlations = df.corr().to_dict() | |
| # Convert to serializable format | |
| serializable_correlations = { | |
| outer_key: {inner_key: round(float(inner_val), 4) for inner_key, inner_val in outer_dict.items()} | |
| for outer_key, outer_dict in correlations.items() | |
| } | |
| return serializable_correlations | |
| #------------------------------------------------------------------------------------------------------------------------ | |
| def portfolio_manager( | |
| tickers: List[str], | |
| allocations: Optional[Dict[str, float]] = None, | |
| constraints: Optional[Dict[str, Tuple[float, float]]] = None, | |
| data_fetcher: Callable[[List[str], Optional[datetime], Optional[datetime]], pd.DataFrame] = default_yfinance_data_fetcher, | |
| start_date: Optional[datetime] = None, | |
| end_date: Optional[datetime] = None, | |
| exchange: Optional[str] = None | |
| ) -> Dict: | |
| """ | |
| Comprehensive portfolio management with JSON-serializable return. | |
| """ | |
| try: | |
| # Use function composition for input resolution | |
| resolved_allocations = ( | |
| lambda allocs: generate_weights(tickers, constraints) if allocs is None else allocs | |
| )(allocations) | |
| # Fetch data and compute metrics | |
| df = data_fetcher(tickers, start_date, end_date, exchange) | |
| # Compute initial metrics | |
| initial_metrics = compute_portfolio_metrics(df, resolved_allocations) | |
| # Optimize portfolio | |
| optimized_results = optimize_portfolio(df, allocations, constraints) | |
| # Generate Efficient Frontier data | |
| efficient_frontier_data = generate_efficient_frontier(df, constraints=constraints) | |
| # Optimization | |
| ef = EfficientFrontier( | |
| expected_returns.mean_historical_return(df), | |
| risk_models.sample_cov(df) | |
| ) | |
| ef.max_sharpe() | |
| optimized_weights = ef.clean_weights() | |
| optimized_metrics = compute_portfolio_metrics(df, optimized_weights) | |
| # Prepare detailed asset allocation comparison | |
| asset_allocation_changes = [] | |
| efficient_frontier_assets = [] | |
| for ticker in tickers: | |
| initial_pct = allocations.get(ticker, 0) * 100 | |
| optimized_pct = optimized_results['optimized_weights'].get(ticker, 0) * 100 | |
| change_pct = optimized_pct - initial_pct | |
| # Categorize change magnitude | |
| if abs(change_pct) <= 5: | |
| change_category = "minor" | |
| elif 5 < abs(change_pct) <= 15: | |
| change_category = "moderate" | |
| else: | |
| change_category = "significant" | |
| asset_allocation_changes.append({ | |
| "ticker": ticker, | |
| "initial_allocation": round(initial_pct, 2), | |
| "optimized_allocation": round(optimized_pct, 2), | |
| "allocation_change": round(change_pct, 2), | |
| "change_category": change_category | |
| }) | |
| # Expected return (annualized monthly arithmetic mean return) | |
| expected_return = expected_returns.mean_historical_return(df[[ticker]], frequency=12)[ticker] * 100 | |
| # Standard deviation | |
| standard_deviation = risk_models.sample_cov(df[[ticker]], frequency=12)[ticker][ticker]**0.5 * 100 | |
| # Sharpe ratio (using U.S. 3-Month Treasury Bill Rate as risk-free rate) | |
| sharpe_ratio = (expected_return - CONFIG['DEFAULT_RISK_FREE_RATE'] * 100) / standard_deviation if standard_deviation > 0 else 0 | |
| efficient_frontier_assets.append({ | |
| "ticker": ticker, | |
| "expected_return": round(expected_return, 2), | |
| "standard_deviation": round(standard_deviation, 2), | |
| "sharpe_ratio": round(sharpe_ratio, 3), # Adjusted to 3 decimal places | |
| "min_weight": 0.0, | |
| "max_weight": 100.0 # Assuming no constraints by default | |
| }) | |
| # Apply constraints to weight ranges if provided | |
| if constraints: | |
| for asset_data in efficient_frontier_assets: | |
| if asset_data["ticker"] in constraints: | |
| min_weight, max_weight = constraints[asset_data["ticker"]] | |
| asset_data["min_weight"] = min_weight * 100 | |
| asset_data["max_weight"] = max_weight * 100 | |
| # Prepare optimization insights | |
| is_improved = bool(optimized_results['metrics']['sharpe_ratio'] > initial_metrics['sharpe_ratio']) | |
| volatility_change = float(optimized_results['metrics']['volatility'] - initial_metrics['volatility']) | |
| # Calculate asset correlations | |
| asset_correlations = calculate_asset_correlations(df) | |
| # Modify result to include efficient frontier data | |
| result = { | |
| "status": "success", | |
| "portfolio_analysis": { | |
| "performance_metrics": { | |
| "initial": { | |
| "return": round(float(initial_metrics['return'] * 100), 2), | |
| "volatility": round(float(initial_metrics['volatility'] * 100), 2), | |
| "sharpe_ratio": round(float(initial_metrics['sharpe_ratio']), 4) | |
| }, | |
| "optimized": { | |
| "return": round(float(optimized_results['metrics']['return'] * 100), 2), | |
| "volatility": round(float(optimized_results['metrics']['volatility'] * 100), 2), | |
| "sharpe_ratio": round(float(optimized_results['metrics']['sharpe_ratio']), 4) | |
| }, | |
| "changes": { | |
| "return_change": round(float((optimized_results['metrics']['return'] - initial_metrics['return']) * 100), 2), | |
| "volatility_change": round(float((optimized_results['metrics']['volatility'] - initial_metrics['volatility']) * 100), 2), | |
| "sharpe_ratio_change": round(float(optimized_results['metrics']['sharpe_ratio'] - initial_metrics['sharpe_ratio']), 4) | |
| }, | |
| "asset_correlations": asset_correlations, | |
| "efficient_frontier_assets": efficient_frontier_assets | |
| }, | |
| "asset_allocation": { | |
| "initial_weights": {ticker: round(float(weight), 4) for ticker, weight in allocations.items()}, | |
| "optimized_weights": {ticker: round(float(weight), 4) for ticker, weight in optimized_results['optimized_weights'].items()}, | |
| "allocation_changes": asset_allocation_changes | |
| }, | |
| "optimization_insights": { | |
| "performance_improved": is_improved, | |
| "volatility_direction": "reduced" if volatility_change < 0 else "increased" if volatility_change > 0 else "stable", | |
| "volatility_change_magnitude": round(float(volatility_change * 100), 2), | |
| "recommendation": "Consider adopting optimized allocation" if is_improved else "Current allocation appears optimal" | |
| }, | |
| "efficient_frontier": efficient_frontier_data | |
| } | |
| } | |
| # Final conversion to ensure full JSON serializability | |
| return convert_to_serializable(result) | |
| except (StockDataFetchError, PortfolioOptimizationError) as e: | |
| logger.error(f"Portfolio management error: {e}") | |
| return { | |
| "status": "error", | |
| "message": str(e) | |
| } | |
| #------------------------------------------------------------------------------------------------------------------------ | |
| { | |
| "status": "success", | |
| "portfolio_analysis": { | |
| "performance_metrics": { | |
| "initial": { | |
| "return": 45.33, | |
| "volatility": 19.89, | |
| "sharpe_ratio": 2.1778 | |
| }, | |
| "optimized": { | |
| "return": 46.64, | |
| "volatility": 21.16, | |
| "sharpe_ratio": 2.1102 | |
| }, | |
| "changes": { | |
| "return_change": 1.32, | |
| "volatility_change": 1.26, | |
| "sharpe_ratio_change": -0.0676 | |
| }, | |
| "asset_correlations": { | |
| "AAPL": { | |
| "AAPL": 1.0, | |
| "GOOGL": 0.8048, | |
| "MSFT": 0.7902, | |
| "AMZN": 0.7236 | |
| }, | |
| "GOOGL": { | |
| "AAPL": 0.8048, | |
| "GOOGL": 1.0, | |
| "MSFT": 0.9381, | |
| "AMZN": 0.9481 | |
| }, | |
| "MSFT": { | |
| "AAPL": 0.7902, | |
| "GOOGL": 0.9381, | |
| "MSFT": 1.0, | |
| "AMZN": 0.9756 | |
| }, | |
| "AMZN": { | |
| "AAPL": 0.7236, | |
| "GOOGL": 0.9481, | |
| "MSFT": 0.9756, | |
| "AMZN": 1.0 | |
| } | |
| }, | |
| "efficient_frontier_assets": [ | |
| { | |
| "ticker": "AAPL", | |
| "expected_return": 1.78, | |
| "standard_deviation": 4.77, | |
| "sharpe_ratio": -0.047, | |
| "min_weight": 10.0, | |
| "max_weight": 40.0 | |
| }, | |
| { | |
| "ticker": "GOOGL", | |
| "expected_return": 1.83, | |
| "standard_deviation": 6.44, | |
| "sharpe_ratio": -0.026, | |
| "min_weight": 10.0, | |
| "max_weight": 30.0 | |
| }, | |
| { | |
| "ticker": "MSFT", | |
| "expected_return": 1.64, | |
| "standard_deviation": 5.06, | |
| "sharpe_ratio": -0.071, | |
| "min_weight": 0.0, | |
| "max_weight": 100.0 | |
| }, | |
| { | |
| "ticker": "AMZN", | |
| "expected_return": 2.1, | |
| "standard_deviation": 6.76, | |
| "sharpe_ratio": 0.015, | |
| "min_weight": 0.0, | |
| "max_weight": 100.0 | |
| } | |
| ] | |
| }, | |
| "asset_allocation": { | |
| "initial_weights": { | |
| "AAPL": 0.4444, | |
| "GOOGL": 0.2222, | |
| "MSFT": 0.2222, | |
| "AMZN": 0.1111 | |
| }, | |
| "optimized_weights": { | |
| "AAPL": 0.25, | |
| "GOOGL": 0.25, | |
| "MSFT": 0.25, | |
| "AMZN": 0.25 | |
| }, | |
| "allocation_changes": [ | |
| { | |
| "ticker": "AAPL", | |
| "initial_allocation": 44.44, | |
| "optimized_allocation": 25.0, | |
| "allocation_change": -19.44, | |
| "change_category": "significant" | |
| }, | |
| { | |
| "ticker": "GOOGL", | |
| "initial_allocation": 22.22, | |
| "optimized_allocation": 25.0, | |
| "allocation_change": 2.78, | |
| "change_category": "minor" | |
| }, | |
| { | |
| "ticker": "MSFT", | |
| "initial_allocation": 22.22, | |
| "optimized_allocation": 25.0, | |
| "allocation_change": 2.78, | |
| "change_category": "minor" | |
| }, | |
| { | |
| "ticker": "AMZN", | |
| "initial_allocation": 11.11, | |
| "optimized_allocation": 25.0, | |
| "allocation_change": 13.89, | |
| "change_category": "moderate" | |
| } | |
| ] | |
| }, | |
| "optimization_insights": { | |
| "performance_improved": false, | |
| "volatility_direction": "increased", | |
| "volatility_change_magnitude": 1.26, | |
| "recommendation": "Current allocation appears optimal" | |
| }, | |
| "efficient_frontier": { | |
| "frontier_points": [ | |
| { | |
| "volatility": 19.517, | |
| "return": 43.5759, | |
| "sharpe_ratio": 2.1302, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1042, | |
| "MSFT": 0.4496, | |
| "AMZN": 0.0462 | |
| } | |
| }, | |
| { | |
| "volatility": 19.518, | |
| "return": 43.6874, | |
| "sharpe_ratio": 2.1358, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1041, | |
| "MSFT": 0.4417, | |
| "AMZN": 0.0542 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5211, | |
| "return": 43.799, | |
| "sharpe_ratio": 2.1412, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1041, | |
| "MSFT": 0.4338, | |
| "AMZN": 0.0622 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5262, | |
| "return": 43.9105, | |
| "sharpe_ratio": 2.1464, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.104, | |
| "MSFT": 0.4259, | |
| "AMZN": 0.0702 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5333, | |
| "return": 44.022, | |
| "sharpe_ratio": 2.1513, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1039, | |
| "MSFT": 0.4179, | |
| "AMZN": 0.0782 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5424, | |
| "return": 44.1336, | |
| "sharpe_ratio": 2.156, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1038, | |
| "MSFT": 0.41, | |
| "AMZN": 0.0862 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5536, | |
| "return": 44.2451, | |
| "sharpe_ratio": 2.1605, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1037, | |
| "MSFT": 0.4021, | |
| "AMZN": 0.0942 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5667, | |
| "return": 44.3566, | |
| "sharpe_ratio": 2.1647, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1036, | |
| "MSFT": 0.3942, | |
| "AMZN": 0.1022 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5819, | |
| "return": 44.4682, | |
| "sharpe_ratio": 2.1687, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1035, | |
| "MSFT": 0.3863, | |
| "AMZN": 0.1102 | |
| } | |
| }, | |
| { | |
| "volatility": 19.5991, | |
| "return": 44.5797, | |
| "sharpe_ratio": 2.1725, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1034, | |
| "MSFT": 0.3784, | |
| "AMZN": 0.1182 | |
| } | |
| }, | |
| { | |
| "volatility": 19.6183, | |
| "return": 44.6913, | |
| "sharpe_ratio": 2.1761, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1033, | |
| "MSFT": 0.3704, | |
| "AMZN": 0.1262 | |
| } | |
| }, | |
| { | |
| "volatility": 19.6396, | |
| "return": 44.8028, | |
| "sharpe_ratio": 2.1794, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1032, | |
| "MSFT": 0.3625, | |
| "AMZN": 0.1342 | |
| } | |
| }, | |
| { | |
| "volatility": 19.6628, | |
| "return": 44.9143, | |
| "sharpe_ratio": 2.1825, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1032, | |
| "MSFT": 0.3546, | |
| "AMZN": 0.1422 | |
| } | |
| }, | |
| { | |
| "volatility": 19.688, | |
| "return": 45.0259, | |
| "sharpe_ratio": 2.1854, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1031, | |
| "MSFT": 0.3467, | |
| "AMZN": 0.1502 | |
| } | |
| }, | |
| { | |
| "volatility": 19.7151, | |
| "return": 45.1374, | |
| "sharpe_ratio": 2.188, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.103, | |
| "MSFT": 0.3388, | |
| "AMZN": 0.1582 | |
| } | |
| }, | |
| { | |
| "volatility": 19.7443, | |
| "return": 45.2489, | |
| "sharpe_ratio": 2.1905, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1029, | |
| "MSFT": 0.3309, | |
| "AMZN": 0.1663 | |
| } | |
| }, | |
| { | |
| "volatility": 19.7754, | |
| "return": 45.3605, | |
| "sharpe_ratio": 2.1926, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1028, | |
| "MSFT": 0.3229, | |
| "AMZN": 0.1743 | |
| } | |
| }, | |
| { | |
| "volatility": 19.8085, | |
| "return": 45.472, | |
| "sharpe_ratio": 2.1946, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1027, | |
| "MSFT": 0.315, | |
| "AMZN": 0.1823 | |
| } | |
| }, | |
| { | |
| "volatility": 19.8435, | |
| "return": 45.5835, | |
| "sharpe_ratio": 2.1964, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1026, | |
| "MSFT": 0.3071, | |
| "AMZN": 0.1903 | |
| } | |
| }, | |
| { | |
| "volatility": 19.8804, | |
| "return": 45.6951, | |
| "sharpe_ratio": 2.1979, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1025, | |
| "MSFT": 0.2992, | |
| "AMZN": 0.1983 | |
| } | |
| }, | |
| { | |
| "volatility": 19.9193, | |
| "return": 45.8066, | |
| "sharpe_ratio": 2.1992, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1024, | |
| "MSFT": 0.2913, | |
| "AMZN": 0.2063 | |
| } | |
| }, | |
| { | |
| "volatility": 19.96, | |
| "return": 45.9181, | |
| "sharpe_ratio": 2.2003, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1024, | |
| "MSFT": 0.2833, | |
| "AMZN": 0.2143 | |
| } | |
| }, | |
| { | |
| "volatility": 20.0027, | |
| "return": 46.0297, | |
| "sharpe_ratio": 2.2012, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1023, | |
| "MSFT": 0.2754, | |
| "AMZN": 0.2223 | |
| } | |
| }, | |
| { | |
| "volatility": 20.0473, | |
| "return": 46.1412, | |
| "sharpe_ratio": 2.2019, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1022, | |
| "MSFT": 0.2675, | |
| "AMZN": 0.2303 | |
| } | |
| }, | |
| { | |
| "volatility": 20.0937, | |
| "return": 46.2527, | |
| "sharpe_ratio": 2.2023, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1021, | |
| "MSFT": 0.2596, | |
| "AMZN": 0.2383 | |
| } | |
| }, | |
| { | |
| "volatility": 20.142, | |
| "return": 46.3643, | |
| "sharpe_ratio": 2.2026, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.102, | |
| "MSFT": 0.2517, | |
| "AMZN": 0.2463 | |
| } | |
| }, | |
| { | |
| "volatility": 20.1922, | |
| "return": 46.4758, | |
| "sharpe_ratio": 2.2026, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1019, | |
| "MSFT": 0.2438, | |
| "AMZN": 0.2543 | |
| } | |
| }, | |
| { | |
| "volatility": 20.2441, | |
| "return": 46.5873, | |
| "sharpe_ratio": 2.2025, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1018, | |
| "MSFT": 0.2359, | |
| "AMZN": 0.2623 | |
| } | |
| }, | |
| { | |
| "volatility": 20.2979, | |
| "return": 46.6989, | |
| "sharpe_ratio": 2.2021, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1017, | |
| "MSFT": 0.2279, | |
| "AMZN": 0.2703 | |
| } | |
| }, | |
| { | |
| "volatility": 20.3535, | |
| "return": 46.8104, | |
| "sharpe_ratio": 2.2016, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1017, | |
| "MSFT": 0.22, | |
| "AMZN": 0.2783 | |
| } | |
| }, | |
| { | |
| "volatility": 20.4109, | |
| "return": 46.9219, | |
| "sharpe_ratio": 2.2009, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1016, | |
| "MSFT": 0.2121, | |
| "AMZN": 0.2863 | |
| } | |
| }, | |
| { | |
| "volatility": 20.4701, | |
| "return": 47.0335, | |
| "sharpe_ratio": 2.2, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1015, | |
| "MSFT": 0.2042, | |
| "AMZN": 0.2943 | |
| } | |
| }, | |
| { | |
| "volatility": 20.5311, | |
| "return": 47.145, | |
| "sharpe_ratio": 2.1989, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1014, | |
| "MSFT": 0.1963, | |
| "AMZN": 0.3023 | |
| } | |
| }, | |
| { | |
| "volatility": 20.5937, | |
| "return": 47.2565, | |
| "sharpe_ratio": 2.1976, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1013, | |
| "MSFT": 0.1883, | |
| "AMZN": 0.3104 | |
| } | |
| }, | |
| { | |
| "volatility": 20.6582, | |
| "return": 47.3681, | |
| "sharpe_ratio": 2.1961, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1012, | |
| "MSFT": 0.1804, | |
| "AMZN": 0.3184 | |
| } | |
| }, | |
| { | |
| "volatility": 20.7243, | |
| "return": 47.4796, | |
| "sharpe_ratio": 2.1945, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1011, | |
| "MSFT": 0.1725, | |
| "AMZN": 0.3264 | |
| } | |
| }, | |
| { | |
| "volatility": 20.7921, | |
| "return": 47.5911, | |
| "sharpe_ratio": 2.1927, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.101, | |
| "MSFT": 0.1646, | |
| "AMZN": 0.3344 | |
| } | |
| }, | |
| { | |
| "volatility": 20.8616, | |
| "return": 47.7027, | |
| "sharpe_ratio": 2.1908, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1009, | |
| "MSFT": 0.1567, | |
| "AMZN": 0.3424 | |
| } | |
| }, | |
| { | |
| "volatility": 20.9328, | |
| "return": 47.8142, | |
| "sharpe_ratio": 2.1886, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1009, | |
| "MSFT": 0.1488, | |
| "AMZN": 0.3504 | |
| } | |
| }, | |
| { | |
| "volatility": 21.0056, | |
| "return": 47.9258, | |
| "sharpe_ratio": 2.1864, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1008, | |
| "MSFT": 0.1409, | |
| "AMZN": 0.3584 | |
| } | |
| }, | |
| { | |
| "volatility": 21.08, | |
| "return": 48.0373, | |
| "sharpe_ratio": 2.1839, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1007, | |
| "MSFT": 0.1329, | |
| "AMZN": 0.3664 | |
| } | |
| }, | |
| { | |
| "volatility": 21.1561, | |
| "return": 48.1488, | |
| "sharpe_ratio": 2.1813, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1006, | |
| "MSFT": 0.125, | |
| "AMZN": 0.3744 | |
| } | |
| }, | |
| { | |
| "volatility": 21.2338, | |
| "return": 48.2604, | |
| "sharpe_ratio": 2.1786, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1005, | |
| "MSFT": 0.1171, | |
| "AMZN": 0.3824 | |
| } | |
| }, | |
| { | |
| "volatility": 21.313, | |
| "return": 48.3719, | |
| "sharpe_ratio": 2.1758, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1004, | |
| "MSFT": 0.1092, | |
| "AMZN": 0.3904 | |
| } | |
| }, | |
| { | |
| "volatility": 21.3938, | |
| "return": 48.4834, | |
| "sharpe_ratio": 2.1728, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1003, | |
| "MSFT": 0.1013, | |
| "AMZN": 0.3984 | |
| } | |
| }, | |
| { | |
| "volatility": 21.4761, | |
| "return": 48.595, | |
| "sharpe_ratio": 2.1696, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1002, | |
| "MSFT": 0.0933, | |
| "AMZN": 0.4064 | |
| } | |
| }, | |
| { | |
| "volatility": 21.56, | |
| "return": 48.7065, | |
| "sharpe_ratio": 2.1664, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1002, | |
| "MSFT": 0.0854, | |
| "AMZN": 0.4144 | |
| } | |
| }, | |
| { | |
| "volatility": 21.6453, | |
| "return": 48.818, | |
| "sharpe_ratio": 2.163, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1001, | |
| "MSFT": 0.0775, | |
| "AMZN": 0.4224 | |
| } | |
| }, | |
| { | |
| "volatility": 21.7322, | |
| "return": 48.9296, | |
| "sharpe_ratio": 2.1594, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0696, | |
| "AMZN": 0.4304 | |
| } | |
| }, | |
| { | |
| "volatility": 21.8205, | |
| "return": 49.0411, | |
| "sharpe_ratio": 2.1558, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0616, | |
| "AMZN": 0.4384 | |
| } | |
| }, | |
| { | |
| "volatility": 21.9103, | |
| "return": 49.1526, | |
| "sharpe_ratio": 2.1521, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0536, | |
| "AMZN": 0.4464 | |
| } | |
| }, | |
| { | |
| "volatility": 22.0015, | |
| "return": 49.2642, | |
| "sharpe_ratio": 2.1482, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0457, | |
| "AMZN": 0.4543 | |
| } | |
| }, | |
| { | |
| "volatility": 22.0942, | |
| "return": 49.3757, | |
| "sharpe_ratio": 2.1443, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0377, | |
| "AMZN": 0.4623 | |
| } | |
| }, | |
| { | |
| "volatility": 22.1882, | |
| "return": 49.4872, | |
| "sharpe_ratio": 2.1402, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0297, | |
| "AMZN": 0.4703 | |
| } | |
| }, | |
| { | |
| "volatility": 22.2836, | |
| "return": 49.5988, | |
| "sharpe_ratio": 2.136, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0218, | |
| "AMZN": 0.4782 | |
| } | |
| }, | |
| { | |
| "volatility": 22.3804, | |
| "return": 49.7103, | |
| "sharpe_ratio": 2.1318, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0138, | |
| "AMZN": 0.4862 | |
| } | |
| }, | |
| { | |
| "volatility": 22.4785, | |
| "return": 49.8218, | |
| "sharpe_ratio": 2.1274, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0058, | |
| "AMZN": 0.4942 | |
| } | |
| }, | |
| { | |
| "volatility": 22.5894, | |
| "return": 49.9334, | |
| "sharpe_ratio": 2.1219, | |
| "weights": { | |
| "AAPL": 0.397, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.503 | |
| } | |
| }, | |
| { | |
| "volatility": 22.734, | |
| "return": 50.0449, | |
| "sharpe_ratio": 2.1133, | |
| "weights": { | |
| "AAPL": 0.3858, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5142 | |
| } | |
| }, | |
| { | |
| "volatility": 22.8827, | |
| "return": 50.1564, | |
| "sharpe_ratio": 2.1045, | |
| "weights": { | |
| "AAPL": 0.3746, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5254 | |
| } | |
| }, | |
| { | |
| "volatility": 23.0354, | |
| "return": 50.268, | |
| "sharpe_ratio": 2.0954, | |
| "weights": { | |
| "AAPL": 0.3634, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5366 | |
| } | |
| }, | |
| { | |
| "volatility": 23.1919, | |
| "return": 50.3795, | |
| "sharpe_ratio": 2.0861, | |
| "weights": { | |
| "AAPL": 0.3522, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5478 | |
| } | |
| }, | |
| { | |
| "volatility": 23.3522, | |
| "return": 50.491, | |
| "sharpe_ratio": 2.0765, | |
| "weights": { | |
| "AAPL": 0.341, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.559 | |
| } | |
| }, | |
| { | |
| "volatility": 23.5163, | |
| "return": 50.6026, | |
| "sharpe_ratio": 2.0668, | |
| "weights": { | |
| "AAPL": 0.3299, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5701 | |
| } | |
| }, | |
| { | |
| "volatility": 23.684, | |
| "return": 50.7141, | |
| "sharpe_ratio": 2.0568, | |
| "weights": { | |
| "AAPL": 0.3187, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5813 | |
| } | |
| }, | |
| { | |
| "volatility": 23.8553, | |
| "return": 50.8256, | |
| "sharpe_ratio": 2.0467, | |
| "weights": { | |
| "AAPL": 0.3075, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.5925 | |
| } | |
| }, | |
| { | |
| "volatility": 24.0301, | |
| "return": 50.9372, | |
| "sharpe_ratio": 2.0365, | |
| "weights": { | |
| "AAPL": 0.2963, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6037 | |
| } | |
| }, | |
| { | |
| "volatility": 24.2082, | |
| "return": 51.0487, | |
| "sharpe_ratio": 2.0261, | |
| "weights": { | |
| "AAPL": 0.2851, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6149 | |
| } | |
| }, | |
| { | |
| "volatility": 24.3898, | |
| "return": 51.1603, | |
| "sharpe_ratio": 2.0156, | |
| "weights": { | |
| "AAPL": 0.2739, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6261 | |
| } | |
| }, | |
| { | |
| "volatility": 24.5746, | |
| "return": 51.2718, | |
| "sharpe_ratio": 2.005, | |
| "weights": { | |
| "AAPL": 0.2627, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6373 | |
| } | |
| }, | |
| { | |
| "volatility": 24.7626, | |
| "return": 51.3833, | |
| "sharpe_ratio": 1.9943, | |
| "weights": { | |
| "AAPL": 0.2515, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6484 | |
| } | |
| }, | |
| { | |
| "volatility": 24.9537, | |
| "return": 51.4949, | |
| "sharpe_ratio": 1.9835, | |
| "weights": { | |
| "AAPL": 0.2404, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6596 | |
| } | |
| }, | |
| { | |
| "volatility": 25.1479, | |
| "return": 51.6064, | |
| "sharpe_ratio": 1.9726, | |
| "weights": { | |
| "AAPL": 0.2292, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6708 | |
| } | |
| }, | |
| { | |
| "volatility": 25.345, | |
| "return": 51.7179, | |
| "sharpe_ratio": 1.9616, | |
| "weights": { | |
| "AAPL": 0.218, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.682 | |
| } | |
| }, | |
| { | |
| "volatility": 25.5451, | |
| "return": 51.8295, | |
| "sharpe_ratio": 1.9506, | |
| "weights": { | |
| "AAPL": 0.2068, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.6932 | |
| } | |
| }, | |
| { | |
| "volatility": 25.748, | |
| "return": 51.941, | |
| "sharpe_ratio": 1.9396, | |
| "weights": { | |
| "AAPL": 0.1956, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7044 | |
| } | |
| }, | |
| { | |
| "volatility": 25.9537, | |
| "return": 52.0525, | |
| "sharpe_ratio": 1.9285, | |
| "weights": { | |
| "AAPL": 0.1844, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7156 | |
| } | |
| }, | |
| { | |
| "volatility": 26.1621, | |
| "return": 52.1641, | |
| "sharpe_ratio": 1.9174, | |
| "weights": { | |
| "AAPL": 0.1732, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7268 | |
| } | |
| }, | |
| { | |
| "volatility": 26.3732, | |
| "return": 52.2756, | |
| "sharpe_ratio": 1.9063, | |
| "weights": { | |
| "AAPL": 0.162, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7379 | |
| } | |
| }, | |
| { | |
| "volatility": 26.5868, | |
| "return": 52.3871, | |
| "sharpe_ratio": 1.8952, | |
| "weights": { | |
| "AAPL": 0.1509, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7491 | |
| } | |
| }, | |
| { | |
| "volatility": 26.803, | |
| "return": 52.4987, | |
| "sharpe_ratio": 1.8841, | |
| "weights": { | |
| "AAPL": 0.1397, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7603 | |
| } | |
| }, | |
| { | |
| "volatility": 27.0216, | |
| "return": 52.6102, | |
| "sharpe_ratio": 1.873, | |
| "weights": { | |
| "AAPL": 0.1285, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7715 | |
| } | |
| }, | |
| { | |
| "volatility": 27.2426, | |
| "return": 52.7217, | |
| "sharpe_ratio": 1.8619, | |
| "weights": { | |
| "AAPL": 0.1173, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7827 | |
| } | |
| }, | |
| { | |
| "volatility": 27.466, | |
| "return": 52.8333, | |
| "sharpe_ratio": 1.8508, | |
| "weights": { | |
| "AAPL": 0.1061, | |
| "GOOGL": 0.1, | |
| "MSFT": 0.0, | |
| "AMZN": 0.7939 | |
| } | |
| } | |
| ], | |
| "global_minimum_variance": { | |
| "return": 43.5759, | |
| "volatility": 19.517, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1042, | |
| "MSFT": 0.4496, | |
| "AMZN": 0.0462 | |
| } | |
| }, | |
| "maximum_sharpe_ratio": { | |
| "return": 46.4497, | |
| "volatility": 20.1803, | |
| "sharpe_ratio": 2.2026, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1019, | |
| "MSFT": 0.2456, | |
| "AMZN": 0.2524 | |
| } | |
| }, | |
| "minimum_volatility": { | |
| "return": 43.5759, | |
| "volatility": 19.517, | |
| "sharpe_ratio": 2.1302396723830648, | |
| "weights": { | |
| "AAPL": 0.4, | |
| "GOOGL": 0.1042, | |
| "MSFT": 0.4496, | |
| "AMZN": 0.0462 | |
| } | |
| }, | |
| "capital_market_line": { | |
| "slope": 2.2026, | |
| "risk_free_rate": 2.0, | |
| "start_point": { | |
| "x": 0, | |
| "y": 2.0 | |
| }, | |
| "end_point": { | |
| "x": 20.1803, | |
| "y": 46.4497 | |
| } | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment