36.黄金与中国国债收益率相关分析(美债作对照)

本章概要

  • 学习材料:本地黄金基金净值与中国国债收益率曲线。
  • 本章任务:对齐完整周五日历,计算黄金收益、收益率变化、52周滚动与滞后相关。
  • 完成后你将得到:两类HDF 字段、覆盖率、全样本/滚动/滞后/压力期结果。
  • 自我检查:用 Series.corr 再算一次同一时间段的相关系数,并检查观测期是否完整、是否进行了不恰当的填充,以及两类数据来源是否标注清楚。
  • 拓展练习:把黄金替换为另一项本地资产且保持利率变换。

待检验假设:黄金与利率是否反向?

  • 黄金:不生息资产,实际利率上升时吸引力下降
  • 国债:无风险资产,收益率上升时吸引力上升
  • 核心公式:实际利率 = 名义利率 − 通胀率
  • 待检验机制:实际利率上升可能提高持有黄金的机会成本,但相关方向会随通胀、避险需求、币种和样本窗口变化。

中国主案例:黄金资产与中国利率

要素 课堂口径
本地资产 fund/ 中黄金 ETF 行情与 yield_curve/ 中中国国债收益率曲线
期间与频率 2019–2025 年,按交易周对齐;10 年期收益率取周变化

中国主案例:验证与决策

要素 课堂口径
验证 全样本、52 周滚动、滞后相关与危机期子样本
决策 仅在相关性稳定且风险预算允许时调整对冲比例

平台美债任务只作国际对照;中国主案例的关联规则、缺周判断条件和分类边界在下页独立核对。

课堂分类只用于辅助判断

  • 切点:−0.5、−0.3、0.3 分隔较强负相关、中度负相关、弱/方向不明与正相关背离。
  • 用途:练习 if/elif 和统一语言口径;不是显著性检验或投资信号。
  • 课堂判断:只有滚动相关系数低于 −0.3 且持续 12 周,才把它列入进一步观察清单;不能据此直接调整投资组合。
  • 数据要求:周频数据不进行前向填充;如果观测期不足、缺口过长或出现无穷值,应先检查数据再计算。

先预测,再区分中国与美国渠道

  • 共同机制:名义收益率上升不等于实际利率上升;必须结合通胀预期判断黄金的机会成本。
  • 中国主案例:黄金 ETF 的人民币收益与中国 10 年国债收益率变化同频对齐,检验的是中国利率渠道。
  • 美国对照:美债—美元—美元计价黄金属于另一传导链,不能直接解释中国利率结果。
  • 预测题:写出通胀上行、避险冲击和汇率变化三种情景下可能的方向,再用全样本、滚动与压力期结果证伪。

运行前预测|平台任务代码

  • 输入预测:运行前先写出 df1df2result 的业务含义、数据类型或取值范围,并判断哪一个输入最可能改变结果。
  • 结果预测:不展开答案,先预测将得到result 的结果;同时写出方向、数量级或表格/图形结构。
  • 完成要求:能独立说明本任务从输入到“平台任务代码”结果的关键步骤,原样录入平台代码并得到可核对的运行结果。

⭐ 平台任务代码

展开完整代码(投影默认折叠)
# 注:该代码块读取远程平台数据文件,且变量名与下方代码不匹配,渲染时无法正确执行
# ⚠️ 平台原始代码 - 请原样输入至教学平台(注释除外),平台才会判定答案正确
import pandas as pd  # 导入Pandas数据分析库
#读取黄金期货历史数据.csv和美国十年期国债收益率历史数据.csv
df1 = pd.read_csv('https://huoran.oss-cn-shenzhen.aliyuncs.com/20230411/csv/1645737586192834560.csv', thousands=',')

# 从CSV文件读取数据存入df2
df2 = pd.read_csv('https://huoran.oss-cn-shenzhen.aliyuncs.com/20230411/csv/1645737641935134720.csv', thousands=',')

#将index设置为日期,并转换为datetime类型
df1.set_index('日期', inplace=True)
df1.index = pd.to_datetime(df1.index)  # 转换为日期时间格式
df2.set_index('日期', inplace=True)  # 将日期列设为df2数据框的索引
df2.index = pd.to_datetime(df2.index)  # 转换为日期时间格式
#数据倒转
df1 = df1.iloc[::-1]
df2 = df2.iloc[::-1]  # 将数据按逆序排列
#提取黄金期货历史数据.csv中的收盘价,并转换为float类型
df1 = df1['收盘']
df1 = df1.astype(float)  # 转换数据类型
#提取美国十年期国债收益率历史数据.csv中的收盘价,并转换为float类型
df2 = df2['收盘']
df2 = df2.astype(float)  # 转换数据类型
 
#计算相关系数
result = df1.corr(df2)
print(result)  # 输出分析结果数据

任务复盘|平台任务代码

运行后核对:核对 df1df2result 是否按预测参与运算,实际输出是否与预测一致;若不一致,先检查类型、单位、索引/字段和运算顺序。

拓展练习:把对象或期间改为一家长三角上市公司或一组 A 股资产;先预测指标方向,再说明结果能支持和不能支持的决策。

数据准备关键步骤解析

  • 读取CSVpd.read_csv() 从URL加载远程数据
  • 设置索引set_index('日期') 将日期列设为行索引
  • 类型转换pd.to_datetime() 将字符串转为日期格式
  • 数据倒序iloc[::-1] 将时间序列按正序排列
  • 提取列:从DataFrame中取出”收盘”列为Series
  • 计算相关系数df1.corr(df2) 计算Pearson相关系数

Pearson相关系数原理

\[ \large \rho = \frac{\text{Cov}(X, Y)}{\sigma_X \times \sigma_Y} \]

  • \(\rho = 1\):完全正相关
  • \(\rho = -1\):完全负相关
  • \(\rho = 0\):无线性相关

课堂区间与边界归属

  • \(\rho < -0.5\):较强负相关,与课堂理论方向一致
  • \(-0.5 \le \rho < -0.3\):中度负相关
  • \(-0.3 \le \rho < 0.3\):弱相关或方向不明
  • \(\rho \ge 0.3\):正相关背离,需要核对窗口与机制

边界值归入右侧区间;三个切点用于教学分类和边界测试,不代替样本量、置信区间或稳健性检验。

相关性计算与解读

# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

# 计算Pearson相关系数
correlation = gold_price.corr(treasury_yield)

# 格式化输出相关系数
print(f'黄金价格与国债收益率相关系数: {correlation:.4f}')

相关系数结果的条件判断

展开完整代码(投影默认折叠)
# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

print('\n相关性解读:')

if correlation < -0.5:
    # 较强负相关:与权威分类器同名
    print('  较强负相关')
elif correlation < -0.3:
    # 中度负相关:与权威分类器同名
    print('  中度负相关')
elif correlation < 0.3:
    # 弱相关或方向不明:与权威分类器同名
    print('  弱相关或方向不明')
else:
    # 正相关背离:与权威分类器同名
    print('  正相关背离')

if-elif-else 判断逻辑解析

  • if correlation < -0.5:较强负相关
  • elif correlation < -0.3:中度负相关
  • elif correlation < 0.3:弱相关或方向不明
  • else(≥ 0.3):正相关背离

核心思路:根据相关系数的阈值区间,给出不同的经济学解释

可视化:双Y轴趋势图

# 注:该代码块依赖的数据来自上方平台任务代码块,因其未执行,本块也无法执行

fig, ax1 = plt.subplots(figsize=(14, 6))

# 左轴:黄金价格(蓝色)
ax1.plot(gold_price.index, gold_price.values,
         'b-', label='黄金价格', linewidth=2)
ax1.set_xlabel('日期', fontsize=12)
ax1.set_ylabel('黄金价格', fontsize=12, color='b')
ax1.tick_params(axis='y', labelcolor='b')
ax1.legend(loc='upper left')

可视化:完成右轴与版式

展开完整代码(投影默认折叠)
# 注:承接上页的fig与ax1对象,补齐右轴、标题和输出

# 右轴:国债收益率(红色)
ax2 = ax1.twinx()
ax2.plot(treasury_yield.index, treasury_yield.values,
         'r-', label='国债收益率', linewidth=2)
ax2.set_ylabel('国债收益率(%)', fontsize=12, color='r')
ax2.tick_params(axis='y', labelcolor='r')
ax2.legend(loc='upper right')

plt.title('黄金价格与国债收益率趋势', fontsize=14)
fig.tight_layout()
plt.show()

双Y轴图表的关键技术

  • plt.subplots():创建画布和主坐标轴
  • ax1.twinx():创建共享X轴的次Y轴
  • 为什么需要双轴?
    • 黄金价格范围:约1500–2000美元/盎司
    • 国债收益率范围:约1%–5%
    • 数值量纲差异巨大,单轴无法同时展示

负相关的三大传导机制

机制 传导路径 效果
替代效应 国债收益率↑ → 国债吸引力↑ 黄金需求↓
机会成本 国债收益率↑ → 持有黄金成本↑ 金价承压
美元汇率 国债收益率↑ → 美元升值 金价下跌

负相关关系的”背离”情况

  • 通胀预期高企:通胀上升 → 黄金保值需求增加 → 金价上涨
  • 避险需求激增:地缘政治风险 → 资金同时流入黄金和国债
  • 实际利率为负:通胀 > 名义利率 → 实际利率下降 → 黄金吸引力上升

这些特殊情况可能导致黄金与国债收益率同向变动

本章小结

  • 黄金收益与利率变化的方向是待检验、会时变的样本关系
  • Series.corr() 方法可快速计算Pearson相关系数
  • if-elif-else 结构用于对相关系数进行区间判断
  • twinx() 双Y轴技术解决量纲差异可视化问题
  • 负相关关系在特定宏观环境下可能出现背离

随堂练习

  • 问题 1|怎样完成本章分析?:独立重新计算教师参考解答中的 full_correlationrolling_correlationlagged_correlation:写出两类 HDF 数据的字段、共同周频样本量、全样本系数和滚动尾值,并用 Series.corr() 核对同一时间段的结果。
  • 问题 2|结果说明什么?:用 2—3 句话区分名义利率、实际利率、中国利率渠道与美债—美元渠道,并指出一个会导致相关背离的条件。
  • 问题 3|换一个情境,怎样继续应用?:把黄金收益替换为另一项本地可访问资产收益,保持完整周五日历、无填充变换和52周滚动窗口不变;写出资产字段、覆盖率判断条件检查,并比较全样本、滚动、滞后与压力期四类输出结构。
  • 作答提示:请完成三道题,并在回答中引用实际运行结果;拓展练习中不要把课堂示例写成普遍规律或因果结论。

教师参考解答

教师参考解答|答案与说明 1

  • 所用数据与字段fund/funds.h5:/funds 为 Pandas HDF,字段 symbol, datetime, closeyield_curve/yield_curve.h5:/data 为原生 HDF5 复合宽表,字段 date, 10Y。黄金代码统一 518880.XSHG → 518880.SH
  • 完整答案|按真实字段 读取基金并检查(平台保护块之外):

教师参考解答|代码 1

展开代码(代码区可独立滚动)
from pathlib import Path  # 导入路径工具
import pandas as pd  # 导入表格库
import numpy as np  # 导入有限值与方差检查工具
import hashlib  # 导入快照指纹工具
import h5py  # 读取原生HDF5复合数据集
GOLD_SECURITY_CODE='518880.SH'  # 配置命名中国黄金ETF稳定代码
GOLD_SECURITY_NAME='华安黄金ETF'  # 配置供人工核对的证券名称
root=Path('/home/ubuntu/r2_data_mount/data')  # 指定可用根目录
gold_path=root/'fund'/'funds.h5'  # 绑定课程规定基金文件
yield_path=root/'yield_curve'/'yield_curve.h5'  # 绑定课程规定收益率文件
if not gold_path.exists() or not yield_path.exists(): raise FileNotFoundError('未找到课程数据文件,请从课程数据下载入口获取并核对文件位置')  # 文件缺失即停止
fund_frame=pd.read_hdf(gold_path,key='/funds')  # 按真实Pandas HDF key读取
required_fund={'symbol','datetime','close'}  # 声明基金字段要求
if not required_fund.issubset(fund_frame.columns): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 字段结构不符即停止
normalized_symbol=fund_frame['symbol'].astype(str).str.replace('.XSHG','.SH',regex=False).str.replace('.XSHE','.SZ',regex=False)  # 统一交易所后缀
gold_frame=fund_frame.loc[normalized_symbol.eq(GOLD_SECURITY_CODE),['symbol','datetime','close']].copy()  # 精确选择华安黄金ETF
gold_frame['datetime']=pd.to_datetime(gold_frame['datetime'].astype(str),format='%Y%m%d%H%M%S',errors='coerce')  # 解析真实时间字段
gold_frame=gold_frame.loc[gold_frame['datetime'].between('2019-01-01','2025-12-31')]  # 固定课堂期间
security_column='symbol'  # 记录真实证券字段
audit_rows=[{'kind':'fund','file':gold_path.name,'key':'/funds','selector':GOLD_SECURITY_CODE,'matches':len(gold_frame),'schema_ok':True}]  # 保存绑定检查
if gold_frame.empty: raise ValueError(f'输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 证券缺失即停止

教师参考解答|答案与说明 2

  • 完整答案|按原生 HDF5 /data 宽表读取 10Y

教师参考解答|代码 2

展开代码(代码区可独立滚动)
with h5py.File(yield_path,mode='r') as handle:  # 以原生HDF5只读打开
    if '/data' not in handle: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 数据集缺失即停止
    raw_curve=handle['/data'][()]  # 读取复合数组快照
    if not {'date','10Y'}.issubset(raw_curve.dtype.names): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 检查宽表字段
curve_frame=pd.DataFrame({'date':pd.to_datetime(raw_curve['date'].astype(str),format='%Y%m%d',errors='coerce'),'yield_10y':raw_curve['10Y']})  # 标准化日期与10Y列
curve_frame=curve_frame.loc[curve_frame['date'].between('2019-01-01','2025-12-31')].assign(tenor='10Y')  # 固定期间并显式保留期限
curve_date,tenor_column,yield_column,tenor_label='date','tenor','yield_10y','10Y'  # 绑定后续统一接口
yield_key='/data'  # 记录真实原生HDF5数据集路径
ten_year_curve=curve_frame.copy()  # 10Y已从宽表精确选择
audit_rows.append({'kind':'yield','file':yield_path.name,'key':yield_key,'selector':'10Y','matches':len(ten_year_curve),'schema_ok':True})  # 保存曲线检查
audit_table=pd.DataFrame(audit_rows)  # 形成文件/key/证券/期限检查表
print(audit_table)  # 挂载存在时发布完整候选检查,不只发布成功项

教师参考解答|答案与说明 3

  • 完整答案|频率对齐、有限值判断条件与四类相关

教师参考解答|代码 3

展开代码(代码区可独立滚动)
gold_date=next((column for column in ['datetime','date','trade_date'] if column in gold_frame.columns),None)  # 识别黄金日期字段
gold_value=next((column for column in ['close','nav','unit_nav'] if column in gold_frame.columns),None)  # 识别黄金价格字段
if None in [gold_date,gold_value,security_column,curve_date,tenor_column,yield_column] or gold_frame.empty or curve_frame.empty: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 字段或数据无法对应时停止
def collapse_observations(frame,date_column,value_column,label,require_positive=False):  # 定义观测键冲突请先检查数据后再继续接口
    work=frame.assign(observation_date=pd.to_datetime(frame[date_column],errors='coerce'),observation_value=pd.to_numeric(frame[value_column],errors='coerce'))[['observation_date','observation_value']].copy()  # 统一日期与数值类型
    invalid=work['observation_date'].isna() | ~np.isfinite(work['observation_value']) | (work['observation_value'].le(0) if require_positive else False)  # 识别无效日期、非有限值或非正价格
    if invalid.any(): raise ValueError(f'输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 观测值不可用时停止
    duplicate_mask=work.duplicated('observation_date',keep=False)  # 识别同日重复观测
    conflicting_dates=int(work.loc[duplicate_mask].groupby('observation_date')['observation_value'].nunique(dropna=False).gt(1).sum()) if duplicate_mask.any() else 0  # 统计同日数值冲突键
    if conflicting_dates: raise ValueError(f'输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 同日数值冲突时停止
    collapsed=work.drop_duplicates(['observation_date','observation_value']).drop_duplicates('observation_date').sort_values('observation_date')  # 仅合并数值完全一致的重复观测
    audit={'label':label,'duplicate_rows':int(duplicate_mask.sum()),'conflicting_dates':conflicting_dates,'unique_dates':len(collapsed)}  # 形成观测键去重检查
    return collapsed.set_index('observation_date')['observation_value'],audit  # 返回唯一日期序列与检查
gold_daily,gold_observation_audit=collapse_observations(gold_frame,gold_date,gold_value,'gold',require_positive=True)  # 检查并合并完全一致的黄金同日观测
yield_daily,yield_observation_audit=collapse_observations(ten_year_curve,curve_date,yield_column,'ten-year yield')  # 检查并合并完全一致的十年期同日观测
gold_weekly_observed=gold_daily.resample('W-FRI').last()  # 将唯一日频黄金价格转为观测周末值
yield_weekly_observed=yield_daily.resample('W-FRI').last()  # 将唯一日频十年收益率转为观测周末值
calendar_start=max(gold_weekly_observed.index.min(),yield_weekly_observed.index.min())  # 固定两资产共同周频起点
calendar_end=min(gold_weekly_observed.index.max(),yield_weekly_observed.index.max())  # 固定两资产共同周频终点
if calendar_end<calendar_start: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 无共同周频窗口时停止

教师参考解答|代码 4

展开代码(代码区可独立滚动)
weekly_calendar=pd.date_range(calendar_start,calendar_end,freq='W-FRI')  # 建立不允许静默缺周的完整周五日历
gold_series=gold_weekly_observed.reindex(weekly_calendar)  # 按完整日历显式保留黄金缺周
ten_year_series=yield_weekly_observed.reindex(weekly_calendar)  # 按完整日历显式保留收益率缺周
def longest_missing_run(series):  # 定义连续缺周检查函数
    missing=series.isna()  # 标记缺失周
    groups=missing.ne(missing.shift()).cumsum()  # 为连续缺失段编号
    return int(missing.groupby(groups).sum().max()) if missing.any() else 0  # 返回最长连续缺周数
weekly_coverage_audit={'policy':'COMPLETE_WEEKLY_CALENDAR_NO_FILL_THEN_COMPLETE_CASE','calendar_weeks':len(weekly_calendar),'gold_observed_weeks':int(gold_series.notna().sum()),'gold_missing_weeks':int(gold_series.isna().sum()),'gold_longest_gap':longest_missing_run(gold_series),'yield_observed_weeks':int(ten_year_series.notna().sum()),'yield_missing_weeks':int(ten_year_series.isna().sum()),'yield_longest_gap':longest_missing_run(ten_year_series)}  # 发布双资产覆盖与缺口检查
minimum_weekly_coverage=0.80  # 事先设定课堂周频水平值覆盖最低要求
if gold_series.notna().mean()<minimum_weekly_coverage or ten_year_series.notna().mean()<minimum_weekly_coverage: raise ValueError(f'输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 任一资产覆盖不足时停止
if weekly_coverage_audit['gold_longest_gap']>4 or weekly_coverage_audit['yield_longest_gap']>4: raise ValueError(f'输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 连续缺口超过四周时停止
weekly_transforms=pd.concat({'gold_return':gold_series.pct_change(fill_method=None),'yield_change':ten_year_series.diff()},axis=1)  # 不填充地计算黄金收益与利率变动
weekly_coverage_audit['joint_transform_weeks']=int(weekly_transforms.notna().all(axis=1).sum())  # 记录同一时间段可用变动周数
aligned_frame=weekly_transforms.dropna()  # 仅在无填充变换后采用同一时间段完整观测
if len(aligned_frame)<52: raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 周频窗口不足时停止
if aligned_frame[['gold_return','yield_change']].std().eq(0).any(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 常数序列禁止相关输出
full_correlation=aligned_frame.corr().loc['gold_return','yield_change']  # 计算全样本相关
rolling_correlation=aligned_frame['gold_return'].rolling(52).corr(aligned_frame['yield_change'])  # 计算52周滚动相关
lagged_correlation=pd.Series({lag:aligned_frame['gold_return'].corr(aligned_frame['yield_change'].shift(lag)) for lag in range(-4,5)},name='correlation')  # 计算正负4周滞后相关
stress_mask=aligned_frame['yield_change'].abs()>=aligned_frame['yield_change'].abs().quantile(0.90)  # 定义利率变动绝对值前10%的压力期

教师参考解答|代码 5

展开代码(代码区可独立滚动)
stress_frame=aligned_frame.loc[stress_mask]  # 固定压力期样本
if len(stress_frame)<5 or stress_frame.std().eq(0).any(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 压力窗检查要求
stress_correlation=stress_frame.corr().loc['gold_return','yield_change']  # 计算压力期相关
reported_rolling=rolling_correlation.dropna(); evidence=np.r_[full_correlation,stress_correlation,reported_rolling.to_numpy(),lagged_correlation.to_numpy()]  # 汇总拟发布依据
if reported_rolling.empty or not np.isfinite(evidence).all(): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # NaN/inf不得发布
fingerprint=hashlib.sha256(pd.util.hash_pandas_object(aligned_frame,index=True).values.tobytes()).hexdigest()[:16]  # 生成同一时间段快照指纹
binding_contract={'fund_file':gold_path.name,'yield_file':yield_path.name,'hdf_key':yield_key,'fund_security':GOLD_SECURITY_CODE,'tenor':str(tenor_label),'schema':{'gold_date':gold_date,'gold_value':gold_value,'curve_date':curve_date,'yield_value':yield_column},'observation_audit':[gold_observation_audit,yield_observation_audit],'weekly_coverage_audit':weekly_coverage_audit,'period':[str(aligned_frame.index.min()),str(aligned_frame.index.max())],'fingerprint':fingerprint}  # 返回完整绑定、观测键与周频缺口检查
print(binding_contract,{'n':len(aligned_frame),'full':full_correlation,'stress':stress_correlation},reported_rolling.tail(),lagged_correlation)  # 输出绑定与四类相关依据

教师参考解答|答案与说明 4

  • 条件判断答案|全样本相关的课堂区间分类

教师参考解答|代码 6

展开代码(代码区可独立滚动)
def classify_correlation(value):  # 定义与课文完全一致的相关区间分类器
    if not np.isfinite(value): raise ValueError('输入文件、字段、样本量或数值不符合当前分析要求,请按本页说明检查')  # 非有限相关值请先检查数据后再继续
    if value < -0.5: return '较强负相关'  # 严格低于−0.5归入较强负相关
    if value < -0.3: return '中度负相关'  # −0.5至−0.3归入中度负相关
    if value < 0.3: return '弱相关或方向不明'  # −0.3至0.3归入弱或方向不明
    return '正相关背离'  # 0.3及以上归入正相关背离
correlation_class=classify_correlation(full_correlation)  # 使用统一函数分类全样本相关
classification={'measure':'full_correlation','value':full_correlation,'class':correlation_class,'cut_points':[-0.5,-0.3,0.3],'threshold_status':'课堂语言规则,非显著性判断或稳定投资信号'}  # 形成含切点与边界的分类依据
expected_classes={-0.5:['较强负相关','中度负相关','中度负相关'],-0.3:['中度负相关','弱相关或方向不明','弱相关或方向不明'],0.3:['弱相关或方向不明','正相关背离','正相关背离']}  # 事先设定三个切点的下/等/上预期类别
boundary_rows=[]  # 初始化可见边界测试行
for cut_point in [-0.5,-0.3,0.3]:  # 逐切点构造三个精确位置
    test_values=[np.nextafter(cut_point,-np.inf),cut_point,np.nextafter(cut_point,np.inf)]  # 构造下方、等于与上方浮点值
    for position,value,expected_class in zip(['below','at','above'],test_values,expected_classes[cut_point]):  # 将位置、精确值与预期类别对齐
        actual_class=classify_correlation(value)  # 调用权威分类器
        boundary_rows.append({'cut_point':cut_point,'position':position,'signed_delta':f'{value-cut_point:+.3e}','exact_value':value.hex(),'expected_class':expected_class,'actual_class':actual_class})  # 保存可见差值、精确表示与类别
boundary_sensitivity=pd.DataFrame(boundary_rows)  # 形成学生可逐行核对的边界表
if not boundary_sensitivity['actual_class'].eq(boundary_sensitivity['expected_class']).all(): raise AssertionError('correlation boundary classification mismatch')  # 权威分类与预期序列不一致时停止
try:  # 显式测试非有限值检查要求
    classify_correlation(np.nan)  # 将NaN送入分类器检查请先检查数据后再继续
    nonfinite_guard='FAILED'  # 若未异常则标记检查要求失败
except ValueError as error:  # 捕获预期的请检查数据
    nonfinite_guard=str(error)  # 保存非有限值检查要求依据
print(classification)  # 输出统一分类依据
print(boundary_sensitivity.to_string(index=False))  # 无省略地输出九行切点位置、精确值、差值与预期/实际类别
print({'nonfinite_guard':nonfinite_guard})  # 输出非有限值检查要求

教师参考解答|答案与说明 5

  • 解释答案:中国黄金基金收益与中国十年国债收益率变动必须同币种、同频率、同一时间段口;负相关是样本条件关系,不等于稳定的避险因果。
  • 拓展应用答案:将观察窗拆为常态与压力期,并比较滞后峰值;预期相关方向和强度可能随窗口改变;用不同周频终点和26/52周滚动窗做敏感性核对。
  • 本章数据结果(截至 2025-12-31):共有 350 个共同观测周(2019-01-11—2025-12-26);全样本相关约为 −0.129,压力期约为 −0.147,52 周滚动相关约在 −0.407 至 0.083 之间,可解释为“弱相关或方向不明”。数据更新后应重新计算。
  • 参考结果:数据文件、证券、期限、字段和时间范围;周五频率下的共同观测周数、缺失周数与最长缺口;全样本相关、52 周滚动相关、前后 4 周错位比较和压力期相关。所需基金与收益率曲线数据可从课程数据下载入口取得。
  • 边界 / 局限:事先设定利率水平或变动口径;相关不等于避险因果
  • 常见错误:黄金美元价与中国利率混用;频率未对齐