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

Matplotlib绘图仅返回Line2D对象无图形显示问题求助

问题解决:Matplotlib图形无法显示的修复

问题描述

定义efficient_frontier函数返回Matplotlib的axes对象,在该对象上添加新元素后执行绘图,仅输出<matplotlib.lines.Line2D at 0x273b82d3f50>,图形无法正常显示。环境为Python 3.11,已配置%matplotlib inline并导入matplotlib.pyplot。

核心错误分析

  1. 未定义标识符错误:代码中w_msr=erk.msr_weight(er, cov,rf)一行使用了未定义的erk前缀,实际应为直接调用自定义的msr_weight函数,该错误会导致代码中断,后续绘图逻辑无法执行。
  2. 函数注释与实际返回值不符:efficient_frontier函数注释标注返回DataFrame,但实际返回的是绘图的axes对象,虽不影响功能,但易造成混淆。

修正后的完整代码

import akshare as ak
import pandas as pd
import numpy as np
from scipy.optimize import minimize
%matplotlib inline
import matplotlib.pyplot as plt

def get_ind_returns(symbol_list,start_date,end_date):
    """
    使用akshare工具获取行业指数收益率
    参数:
        symbol_list: 行业名称列表
        start_date: 起始日期
        end_date: 结束日期
    返回:
        以行业指数为列的收益率DataFrame
    """
    stock_board_industry_index=ak.stock_board_industry_index_ths(symbol=symbol_list[0] , start_date=start_date, end_date=end_date)["日期"].to_frame()
    for i in range(len(symbol_list)):
        stock_board_industry_index_pct=ak.stock_board_industry_index_ths(symbol=symbol_list[i] , start_date=start_date, end_date=end_date)["收盘价"].pct_change()
        stock_board_industry_index.insert(i+1,symbol_list[i],stock_board_industry_index_pct,True)
    stock_board_industry_index.index=pd.to_datetime(stock_board_industry_index['日期'],format='%Y%m%d')
    stock_board_industry_index.drop("日期",axis=1,inplace=True)
    return stock_board_industry_index

def annualized_returns(returns,periods_per_year):
    """
    计算年化收益率
    参数:
        returns: 收益率序列
        periods_per_year: 每年的周期数(日频为365,月频为12)
    返回:
        年化收益率
    """
    compound_growth_rate=(1+returns).prod()
    n_of_periods=returns.shape[0]
    annualized_return=(compound_growth_rate**(periods_per_year/n_of_periods)-1)
    return annualized_return

def portfolio_return(weights,returns):
    """
    计算组合收益率
    参数:
        weights: 资产权重数组
        returns: 资产预期收益率数组
    返回:
        组合收益率
    """
    return weights.T @ returns

def portfolio_vol(weights,cov_matrix):
    """
    计算组合波动率
    参数:
        weights: 资产权重数组
        cov_matrix: 资产协方差矩阵
    返回:
        组合波动率
    """
    return (weights.T @ cov_matrix @ weights)**0.5

def minimize_vol_weight(target_return,er,cov):
    """
    给定目标收益率,求解最小波动率对应的资产权重
    参数:
        target_return: 目标组合收益率
        er: 资产预期收益率数组
        cov: 资产协方差矩阵
    返回:
        最小波动率对应的权重数组
    """
    n=er.shape[0]
    initial_guess=np.repeat(1/n,n)
    bounds=((0,1),)*n
    return_is_target={
        'type':'eq',
        'args':(er,),
        'fun':lambda weights,er:target_return-portfolio_return(weights, er)
        }
    weights_sum_to_1={
        'type':'eq',
        'fun':lambda weights:np.sum(weights)-1
        }
    minimize_result=minimize(portfolio_vol,initial_guess,args=(cov,)
                          ,method="SLSQP",bounds=bounds,
                          constraints=([return_is_target,weights_sum_to_1]),
                          options={'disp':False}
                          )
    return minimize_result.x

def optimal_weights(er,cov,n_points):
    """
    生成一系列目标收益率对应的最优权重列表
    参数:
        er: 资产预期收益率数组
        cov: 资产协方差矩阵
        n_points: 绘图的点数
    返回:
        各目标收益率对应的最优权重列表
    """
    target_returns=np.linspace(er.min(),er.max(),n_points)
    optimal_weights=[minimize_vol_weight(target_return, er, cov) for target_return in target_returns]
    return optimal_weights

def efficient_frontier(er,cov,n_points,style=".-"):
    """
    绘制多资产有效前沿,并返回绘图的axes对象
    参数:
        er: 资产预期收益率数组
        cov: 资产协方差矩阵
        n_points: 绘图的点数
        style: 绘图样式
    返回:
        绘图的Matplotlib axes对象
    """
    weights=optimal_weights(er,cov,n_points)
    rets=[portfolio_return(w ,er) for w in weights]
    vols=[portfolio_vol(w, cov) for w in weights]
    ef_df=pd.DataFrame({'Weights':weights,'R':rets,"Vol":vols})
    return ef_df.plot.line(x="Vol", y="R", style=style)

def msr_weight(er,cov,riskfree_rate):
    """
    求解最大夏普比率对应的资产权重
    参数:
        er: 资产预期收益率数组
        cov: 资产协方差矩阵
        riskfree_rate: 无风险收益率
    返回:
        最大夏普比率对应的权重数组
    """
    n=er.shape[0]
    initial_guess=np.repeat(1/n,n)
    bounds=((0,1),)*n
    weights_sum_to_1={
        'type':'eq',
        'fun':lambda weights:np.sum(weights)-1
        }
    negative_sharpe= lambda weights,riskfree_rate,er,cov: -(portfolio_return(weights, er)-riskfree_rate)/portfolio_vol(weights, cov)
    msr_result=minimize(negative_sharpe,initial_guess,args=(riskfree_rate,er,cov,)
                          ,method="SLSQP",bounds=bounds,
                          constraints=(weights_sum_to_1),
                          options={'disp':False}
                          )
    return msr_result.x

# 主逻辑
symbol_list=['半导体及元件','房地产开发','消费电子','油气开采及服务','银行']
ind=get_ind_returns(symbol_list, '20150101', '20240108')
er=annualized_returns(ind["2010":"2024"], 365)
cov=ind.cov()
rf=0.03
# 修正:直接调用自定义的msr_weight函数
w_msr=msr_weight(er, cov,rf)
ax=efficient_frontier(er, cov, 20)
ax.set_xlim(left=0)
r_msr=portfolio_return(w_msr,er)
vol_msr=portfolio_vol(w_msr, cov)
# 绘制资本市场线(CML)
cml_x=[0,vol_msr]
cml_y=[rf, r_msr]
ax.plot(cml_x,cml_y,color='green',marker='o',linestyle='dashed',linewidth=2,markersize=12)
plt.show()

其他注意事项

  • 确保akshare库已正确安装并能正常获取数据,若数据获取失败,需检查网络连接或akshare的版本兼容性。
  • 在Jupyter环境中,%matplotlib inline需放在导入matplotlib.pyplot之前执行,确保绘图能嵌入单元格显示。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.23 02:30:02