计算两股票投资组合有效前沿时出现直线的问题求助
有效前沿呈现直线的问题排查
问题背景
学校作业要求基于亚马逊(AMZN)和辉瑞(PFIZER)的股价数据,构建20个投资组合(权重从0%AMZN+100%PFIZER到100%AMZN+0%PFIZER,步长5%),计算每个组合的均值收益与标准差,并绘制有效前沿。但运行代码后,有效前沿始终显示为直线,无法定位错误。
代码片段
import pandas as pd import plotly.graph_objects as go import numpy as np # Read in the data df = pd.read_csv('../data.csv') ''' Plot Amazon and Pfizer stocks in the standard diagram with the mean return on the y- axis and the standard deviation of returns on the x-axis. Plot the potential combinations of stocks with a share in Amazon 0 <= wAmazon <= 1 and a share in Pfizer wPfizer = 1−wAmazon with a step size resolution of 0.05 in the same diagram (the efficient frontier). ''' #Calculate standard deviation for Amazon and Pfizer df["AMZN"] = df["AMZN"].pct_change() df["PFIZER"] = df["PFIZER"].pct_change() stdev_amzn = df["AMZN"].std() stdev_pfizer = df["PFIZER"].std() #Get the mean log returns for Amazon and Pfizer return_amzn = df["AMZN"].mean() return_pfizer = df["PFIZER"].mean() #Calc correlation between Amazon and Pfizer correlation = df["AMZN"].corr(df["PFIZER"]) talj = stdev_pfizer**2 - (stdev_amzn * stdev_pfizer * correlation) namn = stdev_amzn**2 + stdev_pfizer**2 - (2 * stdev_amzn * stdev_pfizer * correlation) print("Minimum variance portfolio: ", talj/namn) #Calculate portfolio return and standard deviation for different weights btwn 0 and 1 with increments of 0.05 returns = [] stdevs = [] for x in np.arange(0, 1.00, 0.001): w_amzn = x w_pfizer = 1 - x returns.append(return_amzn * w_amzn + return_pfizer * w_pfizer) stdevs.append(np.sqrt((stdev_amzn**2 * w_amzn**2) + (stdev_pfizer**2 * w_pfizer**2) + (2 * correlation * stdev_amzn * stdev_pfizer * w_amzn * w_pfizer))) #Plot the monthly return of each stock if x% of the portfolio is in amazon and 100% - x% is in pfizer on the y axis #and the standard deviation of returns on the x axis fig = go.Figure() fig.add_trace(go.Scatter(x=stdevs, y=returns, name='Efficient Frontier')) fig.update_layout(title='Efficient Frontier', xaxis_title='Standard Deviation', yaxis_title='Mean Return') fig.show()
可能的问题点及排查步骤
两只股票呈完全正相关
有效前沿呈直线的唯一理论场景是两只资产完全正相关(correlation=1),此时组合标准差是权重的线性函数,收益-标准差曲线会变成直线。- 排查方式:打印
correlation的值,如果接近1,说明数据存在异常——要么是误将同一只股票的数据赋值给了两只股票,要么是原始股价数据本身有错误(比如其中一只股票的股价完全复制了另一只)。
- 排查方式:打印
收益率数据处理异常
代码中直接用pct_change()覆盖原始股价数据,若原始数据存在缺失、格式错误或重复值,会导致收益率数据异常,间接引发直线问题。- 排查方式:处理完收益率后,打印
df[["AMZN", "PFIZER"]].head()和df[["AMZN", "PFIZER"]].describe(),检查数据是否符合预期(比如是否有大量重复值、NaN占比是否过高)。
- 排查方式:处理完收益率后,打印
循环步长不符合作业要求
作业要求构建20个组合(步长0.05),但代码中用了np.arange(0, 1.00, 0.001),步长过小,虽不影响曲线形状,但不符合作业要求,建议改为np.arange(0, 1.05, 0.05)(包含1.0的权重)。注释与实际代码不符
注释标注“Get the mean log returns”,但实际代码计算的是算术平均收益率。若作业要求用对数收益率,需修改为:return_amzn = np.log(1 + df["AMZN"]).mean() return_pfizer = np.log(1 + df["PFIZER"]).mean()注:这不会导致有效前沿变直线,但需符合作业要求。
内容的提问来源于stack exchange,提问作者ES100
相关产品推荐
相关产品推荐

