You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

计算两股票投资组合有效前沿时出现直线的问题求助

有效前沿呈现直线的问题排查

问题背景

学校作业要求基于亚马逊(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()

可能的问题点及排查步骤

  1. 两只股票呈完全正相关
    有效前沿呈直线的唯一理论场景是两只资产完全正相关(correlation=1),此时组合标准差是权重的线性函数,收益-标准差曲线会变成直线。

    • 排查方式:打印correlation的值,如果接近1,说明数据存在异常——要么是误将同一只股票的数据赋值给了两只股票,要么是原始股价数据本身有错误(比如其中一只股票的股价完全复制了另一只)。
  2. 收益率数据处理异常
    代码中直接用pct_change()覆盖原始股价数据,若原始数据存在缺失、格式错误或重复值,会导致收益率数据异常,间接引发直线问题。

    • 排查方式:处理完收益率后,打印df[["AMZN", "PFIZER"]].head()和df[["AMZN", "PFIZER"]].describe(),检查数据是否符合预期(比如是否有大量重复值、NaN占比是否过高)。
  3. 循环步长不符合作业要求
    作业要求构建20个组合(步长0.05),但代码中用了np.arange(0, 1.00, 0.001),步长过小,虽不影响曲线形状,但不符合作业要求,建议改为np.arange(0, 1.05, 0.05)(包含1.0的权重)。

  4. 注释与实际代码不符
    注释标注“Get the mean log returns”,但实际代码计算的是算术平均收益率。若作业要求用对数收益率,需修改为:

    return_amzn = np.log(1 + df["AMZN"]).mean()
    return_pfizer = np.log(1 + df["PFIZER"]).mean()
    

    注:这不会导致有效前沿变直线,但需符合作业要求。

内容的提问来源于stack exchange,提问作者ES100

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.31 22:55:18