Advertisement
palmux

Simulazione portafoglio

Nov 16th, 2024 (edited)
35
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 4.91 KB | Cryptocurrency | 0 0
  1. import yfinance as yf
  2. import numpy as np
  3. import matplotlib.pyplot as plt
  4.  
  5. class PortfolioOptimizer:
  6.     def __init__(self, tickers, start_date, end_date, num_portfolios=10000):
  7.         """
  8.        Inizializza l'ottimizzatore di portafoglio.
  9.        
  10.        :param tickers: Lista di ticker azionari.
  11.        :param start_date: Data di inizio per i dati storici.
  12.        :param end_date: Data di fine per i dati storici.
  13.        :param num_portfolios: Numero di portafogli da simulare.
  14.        """
  15.         self.tickers = tickers
  16.         self.start_date = start_date
  17.         self.end_date = end_date
  18.         self.num_portfolios = num_portfolios
  19.         self.data = None
  20.         self.returns = None
  21.         self.results = None
  22.         self.weights_record = []
  23.  
  24.     def fetch_data(self):
  25.         """Scarica i dati storici dei prezzi e calcola i rendimenti."""
  26.         self.data = yf.download(self.tickers, start=self.start_date, end=self.end_date)['Adj Close']
  27.         self.returns = self.data.pct_change(fill_method=None).dropna()
  28.  
  29.     def simulate_portfolios(self):
  30.         """Simula portafogli casuali e calcola rendimento, volatilità e Sharpe Ratio."""
  31.         num_assets = len(self.tickers)
  32.         self.results = np.zeros((3, self.num_portfolios))
  33.  
  34.         for i in range(self.num_portfolios):
  35.             weights = np.random.random(num_assets)
  36.             weights /= np.sum(weights)
  37.             self.weights_record.append(weights)
  38.  
  39.             # Rendimento atteso annualizzato
  40.             portfolio_return = np.sum(weights * self.returns.mean()) * 252
  41.             # Volatilità annualizzata
  42.             portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(self.returns.cov() * 252, weights)))
  43.             # Sharpe Ratio
  44.             sharpe_ratio = portfolio_return / portfolio_volatility
  45.  
  46.             self.results[0, i] = portfolio_return
  47.             self.results[1, i] = portfolio_volatility
  48.             self.results[2, i] = sharpe_ratio
  49.  
  50.     def get_optimal_portfolios(self):
  51.         """
  52.        Trova il portafoglio con il miglior Sharpe Ratio e quello con la minore volatilità.
  53.        
  54.        :return: Indici e pesi ottimali.
  55.        """
  56.         max_sharpe_idx = np.argmax(self.results[2])
  57.         min_volatility_idx = np.argmin(self.results[1])
  58.  
  59.         return {
  60.             "max_sharpe_idx": max_sharpe_idx,
  61.             "min_volatility_idx": min_volatility_idx,
  62.             "best_weights": self.weights_record[max_sharpe_idx],
  63.             "min_volatility_weights": self.weights_record[min_volatility_idx],
  64.         }
  65.  
  66.     def plot_results(self, optimal_portfolios):
  67.         """Visualizza i risultati della simulazione."""
  68.         plt.figure(figsize=(10, 6))
  69.         plt.scatter(self.results[1, :], self.results[0, :], c=self.results[2, :], cmap='YlGnBu', marker='o')
  70.         plt.colorbar(label='Sharpe Ratio')
  71.         plt.scatter(
  72.             self.results[1, optimal_portfolios["max_sharpe_idx"]],
  73.             self.results[0, optimal_portfolios["max_sharpe_idx"]],
  74.             marker='*',
  75.             color='r',
  76.             s=500,
  77.             label='Miglior Sharpe Ratio',
  78.         )
  79.         plt.scatter(
  80.             self.results[1, optimal_portfolios["min_volatility_idx"]],
  81.             self.results[0, optimal_portfolios["min_volatility_idx"]],
  82.             marker='*',
  83.             color='g',
  84.             s=500,
  85.             label='Minima Volatilità',
  86.         )
  87.         plt.title('Simulazione di Portafogli')
  88.         plt.xlabel('Volatilità')
  89.         plt.ylabel('Rendimento Atteso')
  90.         plt.legend()
  91.         plt.show()
  92.  
  93.     def print_optimal_portfolios(self, optimal_portfolios):
  94.         """Stampa i dettagli dei portafogli ottimali."""
  95.         max_sharpe_idx = optimal_portfolios["max_sharpe_idx"]
  96.         min_volatility_idx = optimal_portfolios["min_volatility_idx"]
  97.  
  98.         print("Portafoglio con miglior Sharpe Ratio:")
  99.         print(f"Rendimento atteso: {self.results[0, max_sharpe_idx]:.2f}")
  100.         print(f"Volatilità: {self.results[1, max_sharpe_idx]:.2f}")
  101.         print("Pesi:")
  102.         for ticker, weight in zip(self.tickers, optimal_portfolios["best_weights"]):
  103.             print(f"{ticker}: {weight:.2%}")
  104.  
  105.         print("\nPortafoglio con minima volatilità:")
  106.         print(f"Rendimento atteso: {self.results[0, min_volatility_idx]:.2f}")
  107.         print(f"Volatilità: {self.results[1, min_volatility_idx]:.2f}")
  108.         print("Pesi:")
  109.         for ticker, weight in zip(self.tickers, optimal_portfolios["min_volatility_weights"]):
  110.             print(f"{ticker}: {weight:.2%}")
  111.  
  112.  
  113. # Esempio di utilizzo
  114. tickers = ['NVDA', 'KO', 'TSLA', 'ENI.MI', 'META', 'BC.MI']
  115. optimizer = PortfolioOptimizer(tickers, start_date="2023-05-01", end_date="2023-11-01")
  116.  
  117. # Passaggi
  118. optimizer.fetch_data()
  119. optimizer.simulate_portfolios()
  120. optimal_portfolios = optimizer.get_optimal_portfolios()
  121. optimizer.plot_results(optimal_portfolios)
  122. optimizer.print_optimal_portfolios(optimal_portfolios)
  123.  
  124.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement