在理想化的CAPM世界中,,残差的均值为0,且与市场组合的收益无关。import numpy as npimport pandas as pdimport statsmodels.api as smimport seaborn as snsfrom scipy import statsnp.random.seed(99)# --------参数设置————————————T = 1000 # 时间序列长度n_assets = 10 # 资产数量# 市场参数mu_M = 0.12 # 市场预期超额回报率(年化12%)sigma_M = 0.2 # 市场波动率r_f = 0.015 # 无风险利率(年化1.5%)# 生成市场超额回报(月度模拟简化)market_excess = np.random.normal(mu_M/12, sigma_M/np.sqrt(12), T)# 生成各资产的贝塔(均匀分布在0.5到1.5之间)true_betas = np.random.uniform(0.5, 1.5, n_assets)# 每个资产的残差标准差residual_errors = np.random.uniform(0.02, 0.05, n_assets)# 生成资产超额回报(严格满足CAPM:alpha=0)asset_excess = np.zeros((T, n_assets))for i in range(n_assets): eps = np.random.normal(0, residual_errors[i], T) asset_excess[:, i] = true_betas[i] * market_excess + eps# 转换为DataFramedf_assets = pd.DataFrame(asset_excess, columns=[f'Asset{i}' for i in range(n_assets)])df_market = pd.Series(market_excess, name='Market')print("======== 模拟数据概览 ==========")print(f"市场超额回报均值: {df_market.mean():.4f}")print(f"各资产真实贝塔: \n{true_betas}")print(f"各资产模拟超额回报均值:\n{df_assets.mean()}")
======== 模拟数据概览 ==========市场超额回报均值: 0.0134各资产真实贝塔: [0.75951176 1.40353203 1.3622242 1.05155768 0.65028921 0.79992067 0.57768957 1.30911331 0.59490048 1.43057719]各资产模拟超额回报均值:Asset0 0.010297Asset1 0.021223Asset2 0.019569Asset3 0.013892Asset4 0.008839Asset5 0.011843Asset6 0.008016Asset7 0.016315Asset8 0.010034Asset9 0.021307dtype: float64
以上,我们生成了一个完全满足CAPM的市场:所有资产的阿尔法都为0,收益只由贝塔和残差决定。这样,在随后的回归中,我们可以反推出贝塔,并检验估计的无偏性。# 根据上述公式定义求贝塔函数def beta_cov(asset_return, market_return): cov_matrix = np.cov(asset_return, market_return) beta = cov_matrix[0, 1] / cov_matrix[1, 1] return beta# 对第一项资产进行计算beta_0 = beta_cov(df_assets['Asset0'], df_market)print(f"协方差法估算的贝塔(Asset0): {beta_1:.4f}, 真实值: {true_betas[0]:.4f}.")
协方差法估算的贝塔(Asset0): 0.7813, 真实值: 0.7595.
def beta_ols(asset_excess, market_excess): # 添加常数项(估计alpha) X = sm.add_constant(market_excess) model = sm.OLS(asset_excess, X).fit() beta = model.params.iloc[1] # 斜率系数 alpha = model.params.iloc[0] # 截距系数 return beta, alpha, modelbeta_ols_est, alpha_ols_est, model = beta_ols(df_assets['Asset0'], df_market)print(f"OLS法估计的贝塔: {beta_ols_est:.4f} (真实值: {true_betas[0]:.4f})")print(f"OLS法估计的阿尔法: {alpha_ols_est:.4f} (真实值: 0)")print(f"R-squared: {model.rsquared:.4f}")
OLS法估计的贝塔: 0.7813 (真实值: 0.7595)OLS法估计的阿尔法: -0.0002 (真实值: 0)R-squared: 0.6364
可以看出,贝塔接近真实值,阿尔法接近0。R2说明市场因子解释了约60%的资产波动。betas_seris = df_assets.apply(lambda x: x.cov(df_market) / df_market.var(), axis=0)print("所有资产的贝塔估计: \n", list(betas_seris.round(4)))print("真实贝塔: \n", true_betas.round(4))
所有资产的贝塔估计: [0.7813, 1.4035, 1.3622, 1.0679, 0.6426, 0.8034, 0.6048, 1.2893, 0.5789, 1.4026]真实贝塔: [0.7595 1.4035 1.3622 1.0516 0.6503 0.7999 0.5777 1.3091 0.5949 1.4306]
plt.figure(figsize=(8, 6))plt.scatter(true_betas, betas_seris, s=50, alpha=0.7)plt.plot([0, 2], [0, 2], 'r--', label='45度线')plt.xlabel('真实贝塔')plt.ylabel('估计贝塔')plt.title('贝塔估计值与真实值的对比')plt.legend()plt.grid(True)plt.show()
如果数据生成满足CAPM且残差独立,估计点应围绕45o线分布,说明OLS给出了无偏的β估计。