Python 中的马科维茨优化

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

我已经完成了马科维茨投资组合优化的 Python 实现。最小化函数将确保风险最小化,同时解决优化器基于股票列表生成一定百分比的回报。它还考虑到权重之和应等于 1。大多数时候我生成的结果是不可行的。可能是什么原因?

import pandas as pd
import numpy as np
from helper_functions.get_data import download_data
from scipy.optimize import minimize

def optimizer(tickers, start_date, end_date, required_return=0.02):

    df = download_data(tickers, start_date, end_date)
    
    # Calculate daily returns
    returns = df['Close'].pct_change()

    # Calculate mean returns and covariance
    mean_returns = returns.mean()
    cov_matrix = returns.cov()

    # Number of portfolio assets
    num_assets = len(mean_returns)

    # Initialize weights
    weights_initial = num_assets * [1. / num_assets,]

    # Constraints
    constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, 
                {'type': 'eq', 'fun': lambda x: np.sum(x*mean_returns) - required_return})

    # Bounds
    bounds = tuple((0,1) for asset in range(num_assets))

    # Objective function
    def objective(weights):
        return np.dot(weights.T, np.dot(cov_matrix, weights))

    # Optimize
    result = minimize(objective, weights_initial, method='SLSQP', bounds=bounds, constraints=constraints)

    # Return optimization results
    return result
python optimization scipy mathematical-optimization scipy-optimize
1个回答
0
投票

如上所述,将等式约束更改为不等式可以解决该问题。不必要地对浮点数施加等式约束绝不是一个好主意。投资者实际上寻求具有最低要求回报的投资组合(即回报大于或等于......)。

实施来了:

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

以下函数是(公共)Markowitz optimization Streamlit 应用程序的一部分: https://markowitz.streamlit.app 你可以在那里尝试一下。 源代码可在 Github 上获取:https://github.com/MarekOzana/streamlit_markowitz/blob/main/src/optimization.py

© www.soinside.com 2019 - 2024. All rights reserved.