4. 探索性数据分析

在量化研究与系统化交易中,拿到一份行情或因子数据后,最危险的做法是立刻写策略、跑回测。真正专业的流程是先做探索性数据分析(EDA):用统计量、分布形态、相关结构和图形化手段,快速建立对数据的“体感”,发现异常、缺失、偏态、非线性与时间依赖。EDA 不直接产生交易信号,但它决定了后续建模是否建立在可靠假设之上。

一、核心原理:EDA 在量化流程中的位置

EDA 的本质是“用最小的假设成本,换取对数据生成过程的最大理解”。它通常围绕五个问题展开:数据是否干净?单变量的中心与离散程度如何?分布是否对称、是否有厚尾?变量之间是否存在线性或非线性关联?时间维度上是否存在趋势、周期、波动聚集或结构突变?

在系统化交易中,EDA 的结论会直接影响后续选择:若收益率厚尾,就不能默认正态分布去估计 VaR;若因子间高度共线,就要做正交化或降维;若价差序列非平稳,就不能直接做均值回归回归检验。因此,EDA 是策略假设的“过滤器”,而不是可跳过的装饰步骤。

关键认知:EDA 的目标不是证明某个策略有效,而是尽早证伪错误假设。发现“数据不支持”与发现“数据支持”同样有价值。

二、统计描述与分布分析

统计描述是 EDA 的第一层。对价格序列,通常关注均值、标准差、最小值、最大值、分位数;对收益率序列,则更关注偏度、峰度、极值占比。常用做法是先用一行代码输出描述性统计,再针对关键变量画直方图与核密度估计。

import pandas as pd
import numpy as np

# 假设 df 包含 close 与 ret
desc = df[['close', 'ret']].describe(
    percentiles=[0.01, 0.05, 0.25, 0.5, 0.75, 0.95, 0.99]
)
print(desc)
print("偏度:", df['ret'].skew())
print("峰度:", df['ret'].kurt())
print("缺失值:", df.isna().sum())

分布分析要重点观察三件事:偏度反映尾部方向,峰度反映极端值频率,分位数间距反映主体波动范围。金融收益率常呈现“尖峰厚尾+轻微负偏”,这意味着极端亏损出现的概率高于正态假设。若直接使用正态分布计算风险,会系统性低估尾部风险。

统计量 含义 量化中的典型用途
均值 / 中位数 中心位置,中位数更抗极端值 判断收益中枢是否稳定
标准差 / IQR 离散程度,IQR 更稳健 波动率估计与异常值筛查
偏度 分布左右不对称程度 判断极端收益方向
峰度 尾部厚度与尖峰程度 风险模型是否需厚尾修正
分位数 特定概率下的取值边界 VaR、止损阈值设定

三、相关性分析与可视化方法

相关性分析用于判断变量之间是否携带重复信息。最常用的是 Pearson 相关系数,但它只捕捉线性关系,且对异常值敏感。更稳健的做法是同时计算 Spearman 秩相关,并配合散点图观察非线性结构。

corr_p = df[['ret_a', 'ret_b', 'factor1']].corr(method='pearson')
corr_s = df[['ret_a', 'ret_b', 'factor1']].corr(method='spearman')
print(corr_p)
print(corr_s)

可视化是 EDA 中信息密度最高的环节。建议按目的选择图形:直方图与箱线图看分布,散点图看关系,热力图看相关矩阵,折线图看时间演变。不要为了“好看”堆砌图形,每张图都应回答一个明确问题。

实践建议:相关矩阵热力图应同时标注数值,并采用发散色阶,使正负相关方向一目了然。若两个因子相关系数超过 0.8,应优先考虑剔除、合成或正交化,而不是直接放入同一模型。

四、时间序列初步观察与常见误区

时间序列的 EDA 与横截面数据不同,必须检查平稳性、自相关、波动聚集与结构突变。最直接的起点是画出价格与收益率的时间序列图,再绘制 ACF/PACF 观察记忆性。若收益率平方的 ACF 显著,说明存在波动聚集,后续可考虑 GARCH 类模型。

from statsmodels.graphics.tsaplots import plot_acf, plot_pacf
from statsmodels.tsa.stattools import adfuller

adf_stat, pval, _, _, crit, _ = adfuller(df['ret'].dropna())
print("ADF 统计量:", adf_stat, "p值:", pval)
print("临界值:", crit)

# 绘图:价格走势、收益率、ACF
df['close'].plot(title='Price')
df['ret'].plot(title='Return')
plot_acf(df['ret'].dropna(), lags=40)
plot_pacf(df['ret'].dropna(), lags=40)

常见误区包括:第一,用价格而非收益率做相关分析,导致伪相关;第二,忽略缺失值处理,直接 dropna 造成样本选择偏差;第三,只看全样本相关,忽略滚动窗口下相关结构的变化;第四,把统计显著直接等同于交易可盈利,忽略交易成本与滑点。

复盘提醒:EDA 阶段发现的任何异常——极端值、缺失、分布突变、相关性反转——都应在研究日志中记录。后续回测若出现异常收益,优先回到 EDA 结论中寻找解释,而不是急于调参。

综上,探索性数据分析是量化研究的地基。统计描述给出数据轮廓,分布分析揭示尾部风险,相关性分析识别信息冗余,可视化提升洞察效率,时间序列观察则确保模型尊重数据的动态结构。把这五步做扎实,后续的策略构建与回测才具备可信的起点。