我需要一些帮助。我正在尝试为具有相同资产的多个投资组合(不同权重)运行马科维茨模型。但我想要一个函数来寻找所有可能的投资组合的给定风险和/或回报并返回其权重。 我的代码:
returns_portfolio = []
risks_portfolio = []
for x in range(1000):
weights = np.random.random(number_of_assets)
weights /= np.sum(weights)
returns_portfolio.append(np.sum(weights * log_returns.mean()) * 250)
risks_portfolio.append(np.sqrt(np.dot(weights.T, np.dot(log_returns.cov() * 250, weights))))
returns_portfolio = np.array(returns_portfolio)
risks_portfolio = np.array(risks_portfolio)
returns_portfolio, risks_portfolio
portfolios = pd.DataFrame({'Returns' : returns_portfolio, 'Risks' : risks_portfolio})
portfolios.plot(x = 'Risks', y = 'Returns', kind = 'scatter')
谢谢!
解决方案有很多。 如果您只想重用代码,那么您可以添加“slope”列:
portfolios['slope'] = portfolios['Returns'] / portfolios['Risks']
然后,考虑到您对回报或风险的限制,最佳投资组合就是具有最大“斜率”的投资组合。
如果你想正确地做到这一点,你应该设置优化问题,例如最小化给定最小回报约束的风险并解决它,例如使用 scipy.optimize.minimize
作为示例,请查看(开源)Markowitz Optimization 应用程序的代码:https://markowitz.streamlit.app
import numpy as np
import scipy.optimize as sco
def find_min_var_portfolio(
exp_rets: np.array, cov: np.array, r_min: float = 0, w_max: float = 1
):
"""Find portfolio with minimum variance given constraint return
Solve the following optimization problem
min: w.T*COV*w
subjto: w.T * r_ann >= r_min
sum(w) = 1
0 <= w[i] <= w_max for every i
Parameters
==========
exp_rets: annualized expected returns
cov: covariance matrix
r_min: minimum portfolio return (constraint)
w_max: maximum individual weight (constraint)
Returns
=======
(w, r_opt, vol_opt)
w: portfolio weights
r_opt: return of optimal portfolio
vol_opt: volatility of optimal portfolio
"""
def calc_var(w, cov):
"""Calculate portfolio Variance"""
return np.dot(w.T, np.dot(cov, w))
n_assets = len(exp_rets)
constraints = [
# sum(w_i) = 1
{"type": "eq", "fun": lambda x: np.sum(x) - 1},
# sum(r_i * w_i >= r_min)
{"type": "ineq", "fun": lambda x: np.dot(x.T, exp_rets) - r_min},
]
bounds = tuple((0, w_max) for asset in range(n_assets)) # sequence of (min,max)
opts = sco.minimize(
# Objective Function
fun=calc_var,
# Initial guess
x0=n_assets * [1.0 / n_assets],
# Extra Arguments to objective function
args=(cov,),
method="SLSQP",
options={"ftol": 1e-7, "maxiter": 100},
bounds=bounds,
constraints=constraints,
)
w = opts["x"]
r_opt = np.dot(w, exp_rets)
vol_opt = np.sqrt(calc_var(w, cov))
return w, r_opt, vol_opt