提示词

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
import pandas as pd
import numpy as np

# 读取历史行情数据
df = pd.read_excel('2-1.xlsx')

# 保留要用的字段
df = df[['日期', '收盘']]

# 转换日期格式并设为index
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)

# 用对数收益来描述价格变动
df['对数收益'] = np.log(df['收盘']/df['收盘'].shift(1))

# 定义一个计算实现波动率的函数
def realized_volatility(x):
return np.sqrt(np.sum(x**2))

# 将数据按照月度重组,并计算实现波动率
df_rv = (
df.groupby(pd.Grouper(freq="M"))
.apply(lambda x: realized_volatility(x['对数收益'])) # 确保只处理对数收益列
.to_frame(name="月实现波动率") # 转换为DataFrame并命名列
)

# 计算年化实现波动率 = 月波动率 × √12 (年化转换因子)[2,3](@ref)
df_rv['年化实现波动率'] = df_rv['月实现波动率'] * np.sqrt(12)

# 格式化为百分比字符串便于阅读
df_rv['年化实现波动率_pct'] = df_rv['年化实现波动率'].apply(lambda x: f"{x:.2%}")

# 检查最后12个月的结果
print(df_rv.tail(12))

现在我要把上面代码中计算的年化实现波动率与股价的对数收益进行可视化对比,年化实现波动率在df_rv['年化实现波动率']中,对数收益率在df['对数收益']中,我需要一个包含2行1列子图的图形。请给出示例代码。

答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick

# 创建2行1列的子图布局
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), sharex=False)

# ===== 上方子图:每日对数收益率 =====
ax1.plot(df.index, df['对数收益'], color='blue', alpha=0.7, linewidth=1.2)
ax1.set_title('每日对数收益率', fontsize=14, fontweight='bold')
ax1.set_ylabel('对数收益率', fontsize=12)
ax1.grid(True, linestyle='--', alpha=0.6)

# 添加零线参考
ax1.axhline(y=0, color='red', linestyle='--', alpha=0.5)

# ===== 下方子图:月度年化实现波动率 =====
# 计算柱状图的x位置(每月最后一天)
x_pos = df_rv.index

# 绘制柱状图
bars = ax2.bar(x_pos, df_rv['年化实现波动率'],
width=20, # 柱宽(根据日期调整)
color='green',
alpha=0.7)

# 设置波动率标签
ax2.set_title('月度年化实现波动率', fontsize=14, fontweight='bold')
ax2.set_ylabel('波动率', fontsize=12)
ax2.grid(True, linestyle='--', alpha=0.6)

# 将波动率格式化为百分比
ax2.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))

# ===== 整体布局优化 =====
plt.xticks(rotation=45) # 旋转x轴标签防止重叠
plt.tight_layout() # 自动调整子图间距

# 添加整体标题
fig.suptitle('股价对数收益率与年化波动率对比分析',
fontsize=16,
fontweight='bold',
y=0.98)

# 显示图表
plt.show()

只给了画图代码 前面数据处理要拼接上

另外输出图形,windows中文显示乱码。需要加上

1
2
3
4
5
6
#指定图像样式
plt.style.use('seaborn-v0_8')
#指定字体,防止中文出现乱码,windows系统指定为‘SimHei’
plt.rcParams['font.sans-serif'] = ['SimHei']
#这行代码让中文的负号“-”可以正常显示
plt.rcParams["axes.unicode_minus"]=False

最后结果:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
import matplotlib.pyplot as plt
import matplotlib.ticker as mtick
import pandas as pd
import numpy as np

# 读取历史行情数据
df = pd.read_excel('2-1.xlsx')

# 保留要用的字段
df = df[['日期', '收盘']]

# 转换日期格式并设为index
df['日期'] = pd.to_datetime(df['日期'])
df.set_index('日期', inplace=True)

# 用对数收益来描述价格变动
df['对数收益'] = np.log(df['收盘']/df['收盘'].shift(1))

# 定义一个计算实现波动率的函数
def realized_volatility(x):
return np.sqrt(np.sum(x**2))

# 将数据按照月度重组,并计算实现波动率
df_rv = (
df.groupby(pd.Grouper(freq="M"))
.apply(lambda x: realized_volatility(x['对数收益'])) # 确保只处理对数收益列
.to_frame(name="月实现波动率") # 转换为DataFrame并命名列
)

# 计算年化实现波动率 = 月波动率 × √12 (年化转换因子)[2,3](@ref)
df_rv['年化实现波动率'] = df_rv['月实现波动率'] * np.sqrt(12)

# 格式化为百分比字符串便于阅读
df_rv['年化实现波动率_pct'] = df_rv['年化实现波动率'].apply(lambda x: f"{x:.2%}")

#指定图像样式
plt.style.use('seaborn-v0_8')
#指定字体,防止中文出现乱码,windows系统指定为‘SimHei’
plt.rcParams['font.sans-serif'] = ['SimHei']
#这行代码让中文的负号“-”可以正常显示
plt.rcParams["axes.unicode_minus"]=False

# 创建2行1列的子图布局
fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10), sharex=False)

# ===== 上方子图:每日对数收益率 =====
ax1.plot(df.index, df['对数收益'], color='blue', alpha=0.7, linewidth=1.2)
ax1.set_title('每日对数收益率', fontsize=14, fontweight='bold')
ax1.set_ylabel('对数收益率', fontsize=12)
ax1.grid(True, linestyle='--', alpha=0.6)

# 添加零线参考
ax1.axhline(y=0, color='red', linestyle='--', alpha=0.5)

# ===== 下方子图:月度年化实现波动率 =====
# 计算柱状图的x位置(每月最后一天)
x_pos = df_rv.index

# 绘制柱状图
bars = ax2.bar(x_pos, df_rv['年化实现波动率'],
width=20, # 柱宽(根据日期调整)
color='green',
alpha=0.7)

# 设置波动率标签
ax2.set_title('月度年化实现波动率', fontsize=14, fontweight='bold')
ax2.set_ylabel('波动率', fontsize=12)
ax2.grid(True, linestyle='--', alpha=0.6)

# 将波动率格式化为百分比
ax2.yaxis.set_major_formatter(mtick.PercentFormatter(1.0))

# ===== 整体布局优化 =====
plt.xticks(rotation=45) # 旋转x轴标签防止重叠
plt.tight_layout() # 自动调整子图间距

# 添加整体标题
fig.suptitle('股价对数收益率与年化波动率对比分析',
fontsize=16,
fontweight='bold',
y=0.98)

# 显示图表
plt.show()

输出结果还可以,需要改进,例如坐标轴y轴的起点,年化实现波动率也可以换成折线图展示

参考代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import matplotlib.pyplot as plt
#指定图像样式
plt.style.use('seaborn-v0_8')
#指定字体,防止中文出现乱码,windows系统指定为‘SimHei’
plt.rcParams['font.sans-serif'] = ['SimHei']
#这行代码让中文的负号“-”可以正常显示
plt.rcParams["axes.unicode_minus"]=False

# 创建一个包含2行1列子图的图形
fig, axes = plt.subplots(nrows=2, ncols=1, sharex=True, dpi=300)

# 子图1:年化实现收益率
axes[0].plot(df_rv['年化实现波动率'], label='年化实现波动率', color='blue')
axes[0].set_title('年化实现波动率')
axes[0].set_ylabel('波动率')
axes[0].legend()

# 子图2:对数收益率
axes[1].plot(df['对数收益'], label='对数收益', color='green')
axes[1].set_title('对数收益率')
axes[1].set_xlabel('日期')
axes[1].set_ylabel('对数收益')
axes[1].legend()

# 调整子图之间的间距
plt.tight_layout()

#保存图像文件
plt.savefig('2-1.jpg', dpi=300)
# 显示图形
plt.show()

savefig还可以将图片直接保存出来。