# -*- coding: utf-8 -*- """ Created on Wed Sep 30 14:24:41 2020 @author: Gabriel """ import pandas as pd import numpy as np import matplotlib.pyplot as plt data = pd.read_csv('cac40_30.csv', sep=';') data.head() data.keys() #plot de l histogramme pour les cours %matplotlib inline _=data.hist(bins=30, figsize = (15,15)) #calcul des rendements avec le formule log ... indication utiliser "shift" cac40codes = data.columns[1:] returns=pd.DataFrame() for share in cac40codes: returns[share]=np.log(data[share]/data[share].shift(1)) #plot de l histogramme pour les rendements returns.hist(bins=30, figsize = (15,15)) n=30 # tirer au hasard n actions parmi ceux disponibles sans repetition (!) actifs = np.random.choice(cac40codes,n,replace=False) # calculer $M$ annuel et $\Sigma$, à savoir rdt moyenne et matrice covariances returns_jour=pd.DataFrame() for share in actifs: returns_jour[share]=np.log(data[share]/data[share].shift(1)) returns_an=pd.DataFrame() returns_an=returns_jour*250.0 # rdt/jour * jour/an = rdt/an rendements_an = np.array(returns_an.mean()) rendements_an =rendements_an[:,None]#vecteur des rdt moyens cov_an = np.array(returns_an.cov())#matrice Sigma inverse_cov = np.linalg.inv(cov_an) # inverse de Sigma = cov_an #np.max(np.abs(inverse_cov@cov_an-np.eye(n))) no_portef=1000 #tirer au hasard des portefeuilles sans produit sans risque # dessiner leur profil rdt (axe y) / risque (axe x) rendements_portef=[] volatilite_portef=[] for portefeuille in range(no_portef): poids = np.random.rand(n,1) poids = poids - np.mean(poids)+1.0/n#le vecteur $\Pi$ du cours #print(np.sum(poids)) rendement= np.float64(poids.T @ rendements_an) rendements_portef.append(rendement) volatilite=np.sqrt(np.float64(poids.T @ cov_an @ poids)) volatilite_portef.append(volatilite) #calculer a,b et faire figurer la frontiere efficience sur la figure vect_un=np.ones((n,1)) a = np.float64(vect_un.T @ inverse_cov @ vect_un) b = np.float64(vect_un.T @ inverse_cov @ rendements_an) print('a=',a,' b=',b) Mmoinsbsura=rendements_an-vect_un*b/a facteur = np.float64( Mmoinsbsura.T @ inverse_cov @ Mmoinsbsura) volatility_range=np.linspace(1/np.sqrt(a)+1.e-6,1.1*np.max(volatilite_portef)) rdt_optimal= b/a + np.sqrt(volatility_range**2-1.0/a)*np.sqrt(facteur) plt.figure(3) plt.xlabel('Volatilite') plt.ylabel('Rendement') plt.title('Perf. portef. no_portef='+np.str(no_portef)+' n(actifs)=' + np.str(n)) plt.plot(volatilite_portef,rendements_portef,'.b', volatility_range,rdt_optimal,'-r', volatility_range,-rdt_optimal,'-r') # question: comment ceci depend de l incertitude sur les M et Sigma ??