如何使用 Markowitz 获得正确的权重

问题描述 投票:0回答:1

我需要一些帮助。我正在尝试为具有相同资产的多个投资组合(不同权重)运行马科维茨模型。但我想要一个函数来寻找所有可能的投资组合的给定风险和/或回报并返回其权重。 我的代码:

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')

谢谢!

python data-science quantitative-finance
1个回答
0
投票

解决方案有很多。 如果您只想重用代码,那么您可以添加“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
© www.soinside.com 2019 - 2024. All rights reserved.