Un exemple d'implémentation standard en Python pour l'optimisation d'un portefeuille d'investissement à l'aide de la méthode Markowitz. Il existe de nombreuses implémentations de cette méthode. Y compris Python. Implémenté à nouveau (voir lien sur GitHub ).
Sources
Prenons une théorie à partir de ces sources:
Meilleur portefeuille d'investissement grâce à la simulation de Monte Carlo en Python
Théorie du portefeuille Markowitz (Wikipedia)
Téléchargement de données sur les devis
Nous utilisons les données du service Yahoo.Finance
! pip install yfinance
import yfinance as yf
Nous prenons plusieurs parts du marché américain au cours des 3 derniers mois.
data = yf.download(['AAPL','GE','BAC','AMD','PLUG','F'],period='3mo')
Taux de clôture
Nous utiliserons les taux de clôture quotidiens dans nos calculs
closeData = data.Close
closeData
Graphiques de cours
import matplotlib.pyplot as plt
for name in closeData.columns:
closeData[name].plot()
plt.grid()
plt.title(name)
plt.show()
Changer de cours
Ensuite, vous avez besoin de modifications relatives par rapport à la veille.
dCloseData = closeData.pct_change()
dCloseData
Graphiques des changements de taux relatifs
for name in dCloseData.columns:
dCloseData[name].plot()
plt.title(name)
plt.grid()
plt.show()
Rendement moyen
Rendement quotidien moyen de chaque action pour calculer le rendement du portefeuille.
dohMean = dCloseData.mean()
dohMean
Covariance
Pour calculer le risque du portefeuille, une matrice de covariance est nécessaire.
cov = dCloseData.cov()
cov
Portfolio aléatoire
Nous générerons des portefeuilles aléatoires. En eux, la somme des actions est égale à 1 (un).
import numpy as np
cnt = len(dCloseData.columns)
def randPortf():
res = np.exp(np.random.randn(cnt))
res = res / res.sum()
return res
r = randPortf()
print(r)
print(r.sum())
[0.07519908 0.07594622 0.20932539 0.40973202 0.1234458 0.10635148]
1.0
Rendement du portefeuille
Le rendement du portefeuille est calculé comme la somme des parts des rendements de chaque action du portefeuille.
def dohPortf(r):
return np.matmul(dohMean.values,r)
r = randPortf()
print(r)
d = dohPortf(r)
print(d)
[0.0789135 0.13031559 0.25977124 0.21157419 0.13506695 0.18435853]
0.006588795350151513
Risque de portefeuille¶
Nous calculons le risque du portefeuille au moyen de produits matriciels d'actions du portefeuille et de matrices de covariance.
def riskPortf(r):
return np.sqrt(np.matmul(np.matmul(r,cov.values),r))
r = randPortf()
print(r)
rs = riskPortf(r)
print(rs)
[0.10999361 0.13739338 0.20412889 0.13648828 0.24021123 0.17178461]
0.02483674110724784
Nuage de portefeuille
Générons un ensemble de portefeuilles et affichons le résultat sur un graphique risque-rendement. Trouvons les paramètres du portefeuille optimal pour le risque minimum et le ratio de Sharpe maximum. Comparons avec les données du portefeuille moyen.
risk = np.zeros(N)
doh = np.zeros(N)
portf = np.zeros((N,cnt))
for n in range(N):
r = randPortf()
portf[n,:] = r
risk[n] = riskPortf(r)
doh[n] = dohPortf(r)
plt.figure(figsize=(10,8))
plt.scatter(risk*100,doh*100,c='y',marker='.')
plt.xlabel(', %')
plt.ylabel(', %')
plt.title(" ")
min_risk = np.argmin(risk)
plt.scatter([(risk[min_risk])*100],[(doh[min_risk])*100],c='r',marker='*',label=' ')
maxSharpKoef = np.argmax(doh/risk)
plt.scatter([risk[maxSharpKoef]*100],[doh[maxSharpKoef]*100],c='g',marker='o',label=' - ')
r_mean = np.ones(cnt)/cnt
risk_mean = riskPortf(r_mean)
doh_mean = dohPortf(r_mean)
plt.scatter([risk_mean*100],[doh_mean*100],c='b',marker='x',label=' ')
plt.legend()
plt.show()
Affiche les données des portefeuilles trouvés.
import pandas as pd
print('---------- ----------')
print()
print(" = %1.2f%%" % (float(risk[min_risk])*100.))
print(" = %1.2f%%" % (float(doh[min_risk])*100.))
print()
print(pd.DataFrame([portf[min_risk]*100],columns=dCloseData.columns,index=[', %']).T)
print()
print('---------- ----------')
print()
print(" = %1.2f%%" % (float(risk[maxSharpKoef])*100.))
print(" = %1.2f%%" % (float(doh[maxSharpKoef])*100.))
print()
print(pd.DataFrame([portf[maxSharpKoef]*100],columns=dCloseData.columns,index=[', %']).T)
print()
print('---------- ----------')
print()
print(" = %1.2f%%" % (float(risk_mean)*100.))
print(" = %1.2f%%" % (float(doh_mean)*100.))
print()
print(pd.DataFrame([r_mean*100],columns=dCloseData.columns,index=[', %']).T)
print()
---------- ----------
= 1.80%
= 0.59%
, %
AAPL 53.890706
AMD 12.793389
BAC 4.117541
F 16.547201
GE 10.945462
PLUG 1.705701
---------- ----------
= 2.17%
= 0.88%
, %
AAPL 59.257114
AMD 8.317192
BAC 2.049882
F 8.689935
GE 4.772159
PLUG 16.913719
---------- ----------
= 2.33%
= 0.68%
, %
AAPL 16.666667
AMD 16.666667
BAC 16.666667
F 16.666667
GE 16.666667
PLUG 16.666667
conclusions
Nous avons repris la méthode classique de calcul des parts d'un portefeuille d'investissement. Nous avons obtenu des résultats très précis.
L'optimisation du portefeuille par la méthode de Markowitz suppose la préservation des paramètres dans le futur (corrélations entre les instruments individuels et leur niveau de rentabilité). Mais ce n'est pas garanti. Ceci doit être vérifié dans les travaux suivants.
Il est clair qu'il ne faut pas s'attendre à un résultat positif du test ci-dessus. Mais alors vous pouvez chercher comment modifier la méthode de Markowitz pour obtenir un revenu plus garanti à l'avenir. Voici un sujet pour une autre étude.