Optimización de la cartera con Python y PyPortfolioOpt

Teoría de la cartera de Markowitz

La teoría de la cartera de Markowitz (en lo sucesivo, PTM) (teoría de la cartera moderna) es una metodología para la formación de una cartera de inversión, desarrollada por Harry Markowitz, dirigida a la elección óptima de activos, en función de la relación rentabilidad / riesgo requerida. Las ideas que formuló en la década de 1950 forman la base de la teoría moderna de la cartera.





Las principales disposiciones de la teoría de la cartera fueron formuladas por Garry Markowitz cuando estaba preparando su tesis doctoral en 1950-1951.





Se considera que el nacimiento de la teoría de la cartera de Markowitz es el artículo "Selección de cartera" publicado en el Financial Journal en 1952. En él, primero propuso un modelo matemático para la formación de una cartera óptima y presentó métodos para construir carteras bajo ciertas condiciones. El principal mérito de Markowitz fue proponer una formalización probabilística de los conceptos de "rentabilidad" y "riesgo", lo que permitió traducir el problema de la elección del portafolio óptimo a un lenguaje matemático formal. Cabe destacar que durante los años de la creación de la teoría, Markowitz trabajó en RAND Corp., junto con uno de los fundadores de la optimización lineal y no lineal, George Danzig, y él mismo participó en la solución de estos problemas. Por tanto, mi propia teoría, tras la necesaria formalización, encajó bien en la dirección indicada.





Markowitz está mejorando constantemente su teoría y en 1959 publica la primera monografía dedicada "Selección de cartera: diversificación efectiva de la inversión".





Base del modelo

1.  Rentabilidad esperada de la cartera





La rentabilidad esperada de la cartera dependerá de la rentabilidad esperada de cada uno de los activos incluidos en ella. Este enfoque le permite reducir el riesgo mediante la diversificación y, al mismo tiempo, maximizar los ingresos del inversor, ya que las pérdidas de una inversión se compensarán con los ingresos de otras.





El rendimiento esperado de una cartera es el rendimiento total esperado de los valores que la componen, ponderado por su participación en la cartera.





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

2. Variación de la cartera





— , , . , , , , .





\ 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