如何计算时间序列中多股票间的滚动相关系数矩阵?
计算多只股票滚动相关系数矩阵的解决方案
问题背景
我正在进行股票组合分析,需要计算多只股票间的滚动相关系数矩阵,动态监控它们的相关性变化。
具体需求
针对每个交易日,使用当日及前59天(共60个交易日)的收益数据,计算所有股票对的相关系数。
样本数据
// Generate simulated return data for 4 stocks over 90 days n_days = 90 n_stocks = 4 stock_list = `stock_A`stock_B`stock_C`stock_D // Generate dates and stock symbols (90 days for each stock) trade_date = (2023.10.01 + 0..(n_days-1)) join (2023.10.01 + 0..(n_days-1)) join (2023.10.01 + 0..(n_days-1)) join (2023.10.01 + 0..(n_days-1)) symbol = take(`stock_A, n_days) join take(`stock_B, n_days) join take(`stock_C, n_days) join take(`stock_D, n_days) // Generate return data return_A = norm(0.001, 0.02, n_days) return_B = return_A * 0.7 + norm(0, 0.015, n_days) // Correlated with A return_C = norm(0.0012, 0.018, n_days) return_D = norm(0.0005, 0.015, n_days) daily_return = return_A join return_B join return_C join return_D returns = table(trade_date, symbol, daily_return) // View data structure select top 20 * from returns order by trade_date, symbol
已尝试方案
直接使用corr()函数
// Attempting to calculate correlation in a 60-day rolling window result = select corr(daily_return) as correlation from returns context by symbol // Error: corr requires two parameters, cannot pass only one column // Syntax Error: [line #24] The function [corr] expects 2 argument(s), but the actual number of arguments is: 1
corr()函数需要两个变量作为参数,但数据中不同股票的收益都在daily_return列中,不知道如何配对不同股票来计算相关系数。
核心问题
如何针对这种格式的时间序列数据,计算所有股票对的滚动相关系数?
解决方案
要解决这个问题,需要先将长格式的数据转换为宽格式(每只股票的收益作为单独列),再通过滚动窗口计算相关系数矩阵。以下是完整的Q语言实现步骤:
步骤1:转换数据格式为宽表
首先把长表转换为宽表,每一列对应一只股票的日收益:
// 转换为宽格式:trade_date 作为行索引,每只股票对应一列 wide_returns = pivot(returns, `trade_date, `symbol, `daily_return)
步骤2:定义滚动窗口相关系数计算函数
编写一个函数,输入指定窗口内的收益数据,输出所有股票对的相关系数表:
// 计算相关系数矩阵并转换为长表格式 corrPairs:{[df] // 计算相关系数矩阵 corr_mat = corr each flip df; // 获取股票列表 syms = cols df; // 生成所有股票对(排除自身配对) pairs = syms cross syms where not syms cross syms like each syms; // 提取对应相关系数值 corr_vals = raze corr_mat where not iota[count syms] cross iota[count syms] like each iota[count syms]; // 返回结果表 table(symbol1: first each pairs, symbol2: last each pairs, correlation: corr_vals) }
步骤3:滚动窗口计算
使用rolling函数对宽表应用滚动窗口,结合上述函数计算每个窗口的相关系数:
// 设置滚动窗口大小为60 window_size = 60 // 对每一行,取当前行及前59行的数据计算相关系数 rolling_corr = select trade_date, ungroup corrPairs(wide_returns[window_start::window_end;]) from wide_returns where window_end = iota[count wide_returns], window_start = max(0; window_end - window_size + 1) // 过滤掉窗口数据不足60天的行 where window_end >= window_size - 1
步骤4:结果说明
最终结果表rolling_corr包含以下字段:
trade_date:当前交易日(窗口结束日)symbol1:股票对中的第一只股票symbol2:股票对中的第二只股票correlation:两只股票在过去60个交易日的相关系数
这样就能得到每个交易日对应的所有股票对滚动相关系数,满足动态监控的需求。
内容的提问来源于stack exchange,提问作者xinyu zhang




