AI实现层次风险平价
编辑
0
2025-06-30

提示词
merged_df = pd.read_excel('../数据/HRP实验数据.xlsx',#换成你保存数据的路径
index_col='日期')
# 将index转换为datetime格式
merged_df.index = pd.to_datetime(merged_df.index)
现在我有10只股票的每日收盘价,保存在一个DataFrame中,需要使用这个数据演示如何实现HRP,并要求层次聚类的部分有可视化,请给出示例代码。
答案
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from scipy.cluster.hierarchy import dendrogram, linkage
from scipy.spatial.distance import squareform
# ========== 1. 数据预处理 ==========
def preprocess_data(merged_df):
"""
计算对数收益率和相关性矩阵
"""
# 计算日收益率
returns = merged_df.pct_change().dropna()
# 计算相关性矩阵
corr_matrix = returns.corr()
# 将相关性转换为距离矩阵 (范围[0, 1])
distance_matrix = np.sqrt(0.5 * (1 - corr_matrix))
return returns, corr_matrix, distance_matrix
# ========== 2. 层次聚类与可视化 ==========
def hierarchical_clustering(distance_matrix, asset_names):
"""
执行层次聚类并绘制树状图
"""
# 将距离矩阵转换为压缩形式
condensed_dist = squareform(distance_matrix.values, checks=False)
# 使用平均链接法进行层次聚类
Z = linkage(condensed_dist, method='average')
# 绘制树状图
plt.figure(figsize=(12, 8))
dendrogram(Z, labels=asset_names, orientation='top', leaf_rotation=90)
plt.title('资产层次聚类树状图', fontsize=15)
plt.ylabel('距离', fontsize=12)
plt.tight_layout()
plt.savefig('聚类树状图.png', dpi=300)
plt.show()
return Z
# ========== 3. 准对角化处理 ==========
def quasi_diagonalization(Z, asset_names):
"""
根据聚类结果重新排序资产
"""
# 从树状图中提取排序
order = dendrogram(Z, no_plot=True)['leaves']
# 获取重新排序后的资产名称
ordered_assets = [asset_names[i] for i in order]
return ordered_assets, order
# ========== 4. 递归二分权重分配 ==========
def recursive_bisection(cov, sort_order):
"""
递归分配权重 (HRP核心算法)
"""
# 初始化权重
weights = np.ones(cov.shape[0])
def recursive_step(indices):
n = len(indices)
if n == 1:
return
# 将当前组分为两个子组
mid = n // 2
left = indices[:mid]
right = indices[mid:]
# 计算子组的方差
var_left = _get_cluster_variance(cov, left)
var_right = _get_cluster_variance(cov, right)
# 计算权重调整因子
alpha = 1 - var_left / (var_left + var_right)
# 调整子组权重
weights[left] *= alpha
weights[right] *= (1 - alpha)
# 递归处理子组
recursive_step(left)
recursive_step(right)
# 从根节点开始递归
recursive_step(sort_order)
# 归一化权重
return weights / weights.sum()
def _get_cluster_variance(cov, indices):
"""计算资产簇的方差"""
cov_cluster = cov[np.ix_(indices, indices)]
w = 1 / np.diag(cov_cluster) # 反方差加权
w /= w.sum()
return w.T @ cov_cluster @ w
# ========== 5. 结果分析与可视化 ==========
def plot_asset_weights(weights, asset_names):
"""绘制资产权重分布图"""
plt.figure(figsize=(12, 6))
weights_df = pd.DataFrame({'资产': asset_names, '权重': weights})
weights_df = weights_df.sort_values('权重', ascending=False)
# 绘制柱状图
sns.barplot(x='资产', y='权重', data=weights_df, palette='viridis')
plt.title('HRP资产权重分配', fontsize=15)
plt.xticks(rotation=45)
plt.grid(axis='y', linestyle='--', alpha=0.7)
plt.tight_layout()
plt.savefig('资产权重分布.png', dpi=300)
plt.show()
return weights_df
# ========== 主执行流程 ==========
if __name__ == "__main__":
# 假设merged_df是包含10只股票收盘价的DataFrame
# 列名为股票代码,索引为日期 (已转换为DatetimeIndex)
# 步骤1: 数据预处理
returns, corr_matrix, dist_matrix = preprocess_data(merged_df)
asset_names = returns.columns.tolist()
# 步骤2: 层次聚类与可视化
linkage_matrix = hierarchical_clustering(dist_matrix, asset_names)
# 步骤3: 准对角化
ordered_assets, sort_order = quasi_diagonalization(linkage_matrix, asset_names)
# 可视化重新排序的相关矩阵
plt.figure(figsize=(10, 8))
sns.heatmap(corr_matrix.loc[ordered_assets, ordered_assets],
cmap='coolwarm', center=0, annot=False)
plt.title('准对角化后的资产相关性', fontsize=15)
plt.tight_layout()
plt.savefig('准对角化相关矩阵.png', dpi=300)
plt.show()
# 步骤4: 递归权重分配
cov_matrix = returns.cov() * 252 # 年化协方差矩阵
weights = recursive_bisection(cov_matrix.values, sort_order)
# 步骤5: 结果可视化
weights_df = plot_asset_weights(weights, asset_names)
# 打印权重分配结果
print("HRP权重分配结果:")
print(weights_df.sort_values('权重', ascending=False).reset_index(drop=True))
结果:
- 0
- 0
-
赞助
支付宝
微信
-
分享