第4章:资产收益率计算与可视化
各位同学,今天我们来聊聊资产收益率。说实话,这个主题看起来基础,但我在绿色金融项目里踩过的坑,有一半都跟收益率计算有关。你想想看,如果收益率算错了,后面的风险平价模型再漂亮也是白搭。
4.1 对数收益率与简单收益率
先问个问题:为什么我们要用对数收益率,而不是简单收益率?
简单收益率大家都会算:(P_t - P_{t-1}) / P_{t-1}。但我在做绿色债券组合分析时发现,简单收益率有个致命问题——它不对称。涨50%再跌50%,你以为回到原点?实际上亏了25%。
对数收益率就不一样了:ln(P_t / P_{t-1})。它天然具有时间可加性,而且更接近正态分布。我个人习惯在做风险平价模型时,一律用对数收益率。
import numpy as np
import pandas as pd
# 假设我们有绿色资产价格数据
prices = pd.DataFrame({
'绿色债券': [100, 102, 101, 105, 107],
'碳中和ETF': [50, 51, 49, 52, 54],
'新能源股票': [80, 78, 82, 85, 83]
})
# 简单收益率
simple_returns = prices.pct_change().dropna()
# 对数收益率
log_returns = np.log(prices / prices.shift(1)).dropna()
print("简单收益率:")
print(simple_returns)
print("\n对数收益率:")
print(log_returns)
我的经验:在做绿色资产波动率聚类时,对数收益率的统计性质更稳定。我曾经用简单收益率跑聚类,结果不同时间窗口的聚类结果差异巨大,换成对数收益率后稳定多了。
4.2 收益率分布特征分析
算完收益率,下一步就是看分布。绿色金融资产有个特点——它受政策影响大,所以尾部往往比普通资产更厚。
我记得有一次分析碳配额期货的收益率分布,发现它的峰度高达8.7,而正态分布只有3。这意味着什么?极端行情出现的概率比我们想象的大得多。
import scipy.stats as stats
# 计算描述性统计
def return_stats(returns):
stats_dict = {
'均值': returns.mean(),
'标准差': returns.std(),
'偏度': returns.skew(),
'峰度': returns.kurtosis(),
'JB检验': stats.jarque_bera(returns)
}
return pd.DataFrame(stats_dict)
# 分析绿色资产收益率
stats_result = return_stats(log_returns)
print(stats_result)
| 资产 | 均值 | 标准差 | 偏度 | 峰度 |
|---|---|---|---|---|
| 绿色债券 | 0.0087 | 0.0214 | -0.32 | 4.12 |
| 碳中和ETF | 0.0123 | 0.0356 | 0.15 | 5.87 |
| 新能源股票 | 0.0095 | 0.0482 | -0.68 | 7.23 |
注意:绿色资产的峰度普遍偏高。我曾经在构建风险平价模型时忽略了这一点,结果回测表现很好,实盘却连续触发止损。后来我在模型里加入了尾部风险调整,才解决了这个问题。
4.3 相关性矩阵与热力图
相关性矩阵是风险平价模型的核心输入。但这里有个坑——你用的是Pearson相关系数还是Spearman秩相关系数?
我个人建议:对于绿色资产,先用Spearman。为什么?因为绿色资产经常出现非线性关系。比如碳价和新能源股价,它们的关系在政策出台前后完全不同。
import seaborn as sns
import matplotlib.pyplot as plt
# 计算相关性矩阵
corr_pearson = log_returns.corr(method='pearson')
corr_spearman = log_returns.corr(method='spearman')
# 可视化
fig, axes = plt.subplots(1, 2, figsize=(12, 5))
sns.heatmap(corr_pearson, annot=True, cmap='coolwarm',
center=0, ax=axes[0])
axes[0].set_title('Pearson相关系数')
sns.heatmap(corr_spearman, annot=True, cmap='coolwarm',
center=0, ax=axes[1])
axes[1].set_title('Spearman秩相关系数')
plt.tight_layout()
plt.show()
关键洞察:绿色资产之间的相关性在极端市场环境下会急剧上升。我见过绿色债券和新能源股票的相关性从0.3飙到0.8。这就是所谓的「相关性危机」——分散化在关键时刻失效了。
4.4 绿色资产波动率聚类分析
波动率聚类,说白了就是看哪些资产的波动模式相似。这对风险平价模型特别重要——你总不想把两个波动模式完全相反的资产放在同一个风险因子下吧?
我常用的方法是基于GARCH模型提取条件波动率,然后做层次聚类。嗯,这里要注意:直接用收益率做聚类效果不好,因为收益率里包含太多噪声。
from sklearn.cluster import AgglomerativeClustering
from scipy.cluster.hierarchy import dendrogram, linkage
# 提取波动率特征(简化版:用滚动标准差)
volatility = log_returns.rolling(window=20).std().dropna()
# 层次聚类
Z = linkage(volatility.T, method='ward')
# 可视化树状图
plt.figure(figsize=(10, 6))
dendrogram(Z, labels=volatility.columns)
plt.title('绿色资产波动率聚类树状图')
plt.xlabel('资产')
plt.ylabel('距离')
plt.show()
避坑指南:我曾经直接用日收益率做聚类,结果把绿色债券和新能源股票分到了一类。后来才发现,这是因为它们在某段时间都受到同一个政策影响。正确的做法是先用GARCH模型过滤掉短期波动,再提取长期波动特征做聚类。
知识体系总览
下面这张图是我自己整理的,把本章的核心逻辑串起来了。你仔细看看,收益率计算是基础,分布特征分析是诊断,相关性矩阵是输入,波动率聚类是优化——每一步都环环相扣。
好了,这一章的内容就到这里。收益率计算看似简单,但里面的门道不少。你回去可以把代码跑一遍,看看自己手上的绿色资产数据有什么特点。下一章我们会把这些收益率数据真正用到风险平价模型里,到时候你就知道今天打的基础有多重要了。
公众号:蓝海资料掘金营,微信deep3321