Optimisation de portefeuille avec Python et PyPortfolioOpt

Théorie du portefeuille de Markowitz

La théorie du portefeuille de Markowitz (ci-après dénommée PTM) (théorie du portefeuille moderne) est une méthodologie de formation d'un portefeuille d'investissement, développée par Harry Markowitz, visant le choix optimal des actifs, en fonction du rapport rendement/risque requis. Les idées qu'il a formulées dans les années 1950 constituent la base de la théorie moderne du portefeuille.





Les principales dispositions de la théorie du portefeuille ont été formulées par Garry Markowitz lorsqu'il préparait sa thèse de doctorat en 1950-1951.





La naissance de la théorie du portefeuille de Markowitz est considérée comme l'article « Sélection de portefeuille » publié dans le Financial Journal en 1952. Dans ce document, il a d'abord proposé un modèle mathématique pour la formation d'un portefeuille optimal et a présenté des méthodes pour construire des portefeuilles sous certaines conditions. Le principal mérite de Markowitz a été de proposer une formalisation probabiliste des notions de « rentabilité » et de « risque », qui a permis de traduire le problème du choix du portefeuille optimal dans un langage mathématique formel. Il convient de noter que pendant les années de création de la théorie, Markowitz a travaillé chez RAND Corp., avec l'un des fondateurs de l'optimisation linéaire et non linéaire, George Danzig, et il a lui-même participé à la résolution de ces problèmes. Par conséquent, ma propre théorie, après la formalisation nécessaire, va bien dans le sens indiqué.





Markowitz améliore constamment sa théorie et publie en 1959 la première monographie dédiée « Sélection de portefeuille : diversification efficace des investissements ».





Base du modèle

1.  Rendement attendu du portefeuille





Le rendement attendu du portefeuille dépendra du rendement attendu de chacun des actifs qui le composent. Cette approche vous permet de réduire le risque grâce à la diversification et en même temps de maximiser le revenu de l'investisseur, puisque les pertes sur un investissement seront compensées par les revenus sur les autres.





Le rendement attendu d'un portefeuille est le rendement total attendu des titres qui le composent, pondéré par leur part dans le portefeuille.





E (R_ {p}) = \ sum_ {i = 1} ^ nw_ {i} E (R_ {i})

2. Écart de portefeuille





— , , . , , , , .





\ sigma_ {p} ^ {2} = \ sum_ {i} ^ {} \ omega_ {i} ^ {2} \ sigma_ {i} ^ {2} + \ sum_ {i} ^ {} \ sum_ {j \ neq i} ^ {} \ omega_ {i} ^ {} \ omega_ {j} ^ {} \ sigma_ {i} ^ {} \ sigma_ {j} ^ {} \ rho_ {ij}

3. (Sharpe Ratio)





\ frac {R_ {p} - R_ {f}} {\ sigma_ {p}}

4.  (The Efficient Frontier)





:





(. Efficient frontier) — , . , , , . 1952 .





«», ( ). , , . () , .





, , , ( ) . , .





Python





:





import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import pandas_datareader as web
from matplotlib.ticker import FuncFormatter
      
      



PyPortfolioOpt. , .





!pip install PyPortfolioOpt
      
      



:





from pypfopt.efficient_frontier import EfficientFrontier 
from pypfopt import risk_models 
from pypfopt import expected_returns
from pypfopt.cla import CLA
import pypfopt.plotting as pplt
from matplotlib.ticker import FuncFormatter
      
      







, . yahoo.





, — .





nullin_df = pd.DataFrame(df_stocks,columns=tickers)
print(nullin_df.isnull().sum())
      
      







. .





# 
mu = expected_returns.mean_historical_return(df_stocks) 
# 
Sigma = risk_models.sample_cov(df_stocks)
#  
ef = EfficientFrontier(mu, Sigma, weight_bounds=(0,1)) #weight bounds in negative allows shorting of stocks
sharpe_pfolio=ef.max_sharpe() #May use add objective to ensure minimum zero weighting to individual stocks
sharpe_pwt=ef.clean_weights()
print(sharpe_pwt)

OrderedDict([('AFLT.ME', 0.0), ('DSKY.ME', 0.22606), ('GMKN.ME', 0.48796), ('IRAO.ME', 0.0), ('LKOH.ME', 0.0), ('MTSS.ME', 0.02953), ('NKNC.ME', 0.25645), ('SBER.ME', 0.0)])
      
      



, weight_bounds=(0,1) weight_bounds=(-1,1), .





.





ef.portfolio_performance(verbose=True)

Expected annual return: 37.1%
Annual volatility: 20.7%
Sharpe Ratio: 1.70
(0.37123023494063007, 0.20717177784552962, 1.695357536597058)
      
      



, :





ef1 = EfficientFrontier(mu, Sigma, weight_bounds=(0,1)) 
minvol=ef1.min_volatility()
minvol_pwt=ef1.clean_weights()
print(minvol_pwt)

OrderedDict([('AFLT.ME', 0.02876), ('DSKY.ME', 0.24503), ('GMKN.ME', 0.10403), ('IRAO.ME', 0.0938), ('LKOH.ME', 0.01168), ('MTSS.ME', 0.41967), ('NKNC.ME', 0.09704), ('SBER.ME', 0.0)])

ef1.portfolio_performance(verbose=True, risk_free_rate = 0.27)

Expected annual return: 24.0%
Annual volatility: 16.9%
Sharpe Ratio: -0.18(0.239915644698749, 0.16885732511472468, -0.17816434839774456)
      
      







.





100 000 .





cl_obj = CLA(mu, Sigma)
ax = pplt.plot_efficient_frontier(cl_obj, showfig = False)
ax.xaxis.set_major_formatter(FuncFormatter(lambda x, _: '{:.0%}'.format(x)))
ax.yaxis.set_major_formatter(FuncFormatter(lambda y, _: '{:.0%}'.format(y)))
      
      



:





latest_prices = get_latest_prices(df_stocks)
allocation_minv, rem_minv = DiscreteAllocation(minvol_pwt, latest_prices, total_portfolio_value=100000).lp_portfolio() 
print(allocation_minv)
print("         - {:.2f} ".format(rem_minv))
print()

{'AFLT.ME': 41, 'DSKY.ME': 181, 'IRAO.ME': 1765, 'LKOH.ME': 1, 'MTSS.ME': 127, 'NKNC.ME': 107}
         - 6152.03 
      
      



:





latest_prices1 = get_latest_prices(df_stocks)
allocation_shp, rem_shp = DiscreteAllocation(sharpe_pwt, latest_prices1, total_portfolio_value=100000).lp_portfolio() 
print(allocation_shp)
print("          {:.2f} ".format(rem_shp))

{'DSKY.ME': 167, 'GMKN.ME': 2, 'MTSS.ME': 9, 'NKNC.ME': 283} 
          1319.05 
      
      



167 , 2 , 9 283 . 1319 .





, , .








All Articles