有效投资边界的python实现

马科维茨有效投资投资边界的基本思想是通过对资产组合当中不同资产的配置情况进行调整,达到在既定风险水平下的收益最大化,或者既定收益水平下的风险最小化。

from datetime import date
import pandas_datareader.data as web
import matplotlib.pyplot as plt
import numpy as np 
import seaborn as sns
import warnings
warnings.filterwarnings("ignore")
%matplotlib inline

#获取股票数据
tickers = {
    'AAPL':'苹果',
    'AMZN':'亚马逊',
    'GOOGL':'谷歌',
    'BABA':'阿里巴巴'

}
data_source = 'stooq'#定义数据源的参数

start = date(2016,1,1)#起始时间

end = date(2017,12,31)#结束时间

stock_data = web.DataReader(list(tickers), data_source,start,end)["Close"]

stock_data.rename(columns=tickers,inplace=True)

stock_data=stock_data.iloc[::-1]
stock_data.head()

#画出收盘价走势图
sns.set_style("whitegrid")#横坐标有标线,纵坐标没有标线,背景白色
sns.set_style("darkgrid") #默认,横纵坐标都有标线,组成一个一个格子,背景稍微深色
sns.set_style("dark")#背景稍微深色,没有标线线
sns.set_style("white")#背景白色,没有标线线
sns.set_style("ticks")#xy轴都有非常短的小刻度
sns.despine(offset=30,left=True)#去掉上边和右边的轴线,offset=30表示距离轴线(x轴)的距离,left=True表示左边的轴保留


sns.set(font='SimHei',rc={'figure.figsize':(10,6)})# 图片大小和中文字体设置
# 图形展示

# name=input("股票名字")
(stock_data/stock_data.iloc[0]).plot()

计算收益率和风险

收益率

R_t=\frac{p_t-p_{t-1}}{p_t}=\frac{p_t}{P_{t-1}}-1

对数收益率

r=ln\frac{p_t}{p_{t-1}}

年化收益率

r\_annual=exp^{\sum^n_{i=1}\ r_i\times250}-1

R=stock_data/stock_data.shift(1)-1
R.head()

log_r=np.log(stock_data/stock_data.shift(1))
log_r.head()

r_annual=np.exp(log_r.mean()*250)-1
r_annual

风险

std = np.sqrt(log_r.var() * 250)#假设协方差为0
std

投资组合的收益和风险

def gen_weights(n):
    w=np.random.rand(n)
    return w /sum(w)

n=len(list(tickers))
w=gen_weights(n)
list(zip(r_annual.index,w))

投资组合的收益

\mu_p=\sum_{i=1}^nw_i\mu_i

#投资组合收益
def port_ret(w):
    return np.sum(w*r_annual)
port_ret(w)

投资组合的风险

\sigma^2=\sum^n_{i=1}\sum^n_{j=1}w_iw_jcov(r_i,r_j)

#投资组合的风险
def port_std(w):
    return np.sqrt((w.dot(log_r.cov()*250).dot(w.T)))
port_std(w)
#若干投资组合的收益和风险

def gen_ports(times):
    for _ in range(times):#生成不同的组合
        w=gen_weights(n)#每次生成不同的权重
        yield (port_std(w),port_ret(w),w)#计算风险和期望收益 以及组合的权重情况

import pandas as pd 
df=pd.DataFrame(gen_ports(25000),columns=["std","ret","w"])
df.head()

引入夏普比率

Sharpe\_Ratio=\frac{r_p-r_f}{\sigma_p}

假设无风险利率为0.03,画出投资有效边界

df['sharpe'] = (df['ret'] - 0.015) / df['std']#定义夏普比率
fig, ax = plt.subplots()
df.plot.scatter('std', 'ret', c='sharpe',s=30, alpha=0.3, cmap='cool',marker='o', ax=ax)
plt.style.use('ggplot')
plt.rcParams['axes.unicode_minus'] = False# 显示负号

list(zip(r_annual.index, df.loc[df.sharpe.idxmax()].w))

import scipy.optimize as opt
frontier=pd.DataFrame(columns=['std','ret'])

for std in np.linspace(0.16,0.25):
    res=opt.minimize(lambda x:-port_ret(x),
                x0=((1/n),)*n,
                method='SLSQP',
                bounds=((0,1),)*n,
                constraints=[
                   {"fun":lambda x:port_std(x)-std,"type":"eq"},
                   {"fun":lambda x:(np.sum(x)-1),"type":"eq"}
                ])
    if res.success:
        frontier=frontier.append({"std":std,"ret":-res.fun},ignore_index=True)
frontier.plot('std','ret',lw=3,c='blue',ax=ax)

fig

计算最优资产配置情况

res=opt.minimize(lambda x:-((port_ret(x)-0.03)/port_std(x)),
                x0=((1/n),)*n,
                method='SLSQP',
                bounds=((0,1),)*n,
                constraints={"fun":lambda x:(np.sum(x)-1), "type":"eq"})

res.x.round(3)
array([0.29 , 0.255, 0.   , 0.455])最优资产组合的配置为29%的苹果股票,25.5%的亚马逊股票,45.5%的阿里巴巴股票
ax.scatter(port_std(res.x),port_ret(res.x),marker="*",c="black",s=300)
fig

 绘制资本市场线

ax.plot((0,.27),(.03,-res.fun*.27+.03))
fig

         在上图的所示资本市场线上,星号左边表示将资本用于投资一部分无风险资产,和一部分风险资产组合,而在星号处代表将所有的资本都用于投资风险资产组合星号右边意味着借入无风险资产并投资于风险资产组合,可以在相同的风险水平下获得更高的收益。

  • 2
    点赞
  • 37
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
实现马科维茨有效边界图,需要以下步骤: 1. 安装必要的Python库,如numpy、pandas、matplotlib等。 2. 创建一个投资组合的收益率和波动率数据集。可以使用历史数据或模拟数据。 3. 计算投资组合的预期收益率、预期波动率和协方差矩阵。 4. 使用numpy中的linspace函数生成各个预期收益率水平下的最小方差投资组合的权重组合。 5. 计算每个最小方差投资组合的预期收益率和波动率。 6. 使用matplotlib中的scatter函数绘制最小方差投资组合的预期收益率和波动率散点图。 7. 使用scipy.optimize库中的minimize函数计算每个预期收益率水平下的最优投资组合。 8. 计算每个最优投资组合的预期收益率和波动率。 9. 使用matplotlib中的plot函数绘制最优投资组合的有效边界。 下面是示例代码: ```python import numpy as np import pandas as pd import matplotlib.pyplot as plt from scipy.optimize import minimize # 创建数据集 returns = np.random.normal(0.05, 0.1, 100) volatility = np.random.normal(0.1, 0.05, 100) data = pd.DataFrame({'returns': returns, 'volatility': volatility}) # 计算预期收益率、预期波动率和协方差矩阵 mu = data['returns'].mean() sigma = data['volatility'].std() cov_matrix = np.cov(data['returns'], data['volatility']) # 生成权重组合 num_portfolios = 1000 results = np.zeros((3 + len(data.columns), num_portfolios)) for i in range(num_portfolios): weights = np.random.random(len(data.columns)) weights /= np.sum(weights) portfolio_return = np.dot(weights, data['returns']) portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) results[0, i] = portfolio_return results[1, i] = portfolio_volatility results[2, i] = portfolio_return / portfolio_volatility for j in range(len(weights)): results[j+3, i] = weights[j] # 绘制最小方差投资组合散点图 min_volatility_idx = np.argmin(results[1]) min_volatility_return = results[0, min_volatility_idx] min_volatility_volatility = results[1, min_volatility_idx] plt.scatter(results[1,:], results[0,:], c=results[2,:], cmap='YlOrRd', alpha=0.5) plt.scatter(min_volatility_volatility, min_volatility_return, c='b', marker='*', s=500) plt.xlabel('Volatility') plt.ylabel('Returns') plt.colorbar() # 计算最优投资组合 def objective(weights): portfolio_return = np.dot(weights, data['returns']) portfolio_volatility = np.sqrt(np.dot(weights.T, np.dot(cov_matrix, weights))) return -portfolio_return / portfolio_volatility constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}) bounds = [(0, 1)] * len(data.columns) initial_weights = np.ones(len(data.columns)) / len(data.columns) optimal_weights = minimize(objective, initial_weights, method='SLSQP', bounds=bounds, constraints=constraints) optimal_weights = optimal_weights.x # 计算最优投资组合的预期收益率和波动率 optimal_return = np.dot(optimal_weights, data['returns']) optimal_volatility = np.sqrt(np.dot(optimal_weights.T, np.dot(cov_matrix, optimal_weights))) # 绘制最优投资组合的有效边界 frontier_returns = [] frontier_volatilities = [] for r in np.linspace(min(results[0,:]), max(results[0,:]), num=100): constraints = ({'type': 'eq', 'fun': lambda x: np.sum(x) - 1}, {'type': 'eq', 'fun': lambda x, r=r: np.dot(x, data['returns']) - r}) bounds = [(0, 1)] * len(data.columns) initial_weights = np.ones(len(data.columns)) / len(data.columns) optimal_weights = minimize(objective, initial_weights, method='SLSQP', bounds=bounds, constraints=constraints) optimal_weights = optimal_weights.x frontier_returns.append(r) frontier_volatilities.append(np.sqrt(np.dot(optimal_weights.T, np.dot(cov_matrix, optimal_weights)))) plt.plot(frontier_volatilities, frontier_returns, 'g--', linewidth=2) plt.show() ``` 此代码将生成一个包含最小方差投资组合散点图和有效边界图的matplotlib图形。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值