3. 投资组合构建流程:数据获取与清洗、因子选择、权重优化、回测框架搭建

做量化投资这些年,我最大的感触就是:组合构建不是一锤子买卖。它更像是在搭积木——每一块都得严丝合缝,否则整个结构说塌就塌。今天咱们就聊聊这个流程里的四个核心环节。

核心逻辑一句话:数据是原料,因子是配方,权重是火候,回测是试吃。缺一个,这菜就做不地道。

数据获取与清洗 原始数据 → 干净数据 因子选择 有效因子 → 因子组合 权重优化 目标函数 → 最优权重 回测框架搭建 策略验证 → 绩效评估 投资组合构建四步走:每一步都依赖上一步的输出 数据 → 因子 → 权重 → 回测,形成闭环迭代

3.1 数据获取与清洗:地基打不牢,房子会晃

说实话,我见过太多人一上来就搞什么机器学习、深度学习,结果数据源都没搞清楚。你想想看,如果拿到的日频数据里混着停牌日、复权没做对、甚至还有未来数据——那后面的一切都是白搭。

数据获取的常见来源:

  • 行情数据:日线、分钟线、Tick 级数据。我个人习惯用 Wind 或聚宽做主力源,再用 Tushare 做交叉验证。
  • 财务数据:季报、年报、业绩预告。注意财报的发布时间——我踩过坑,直接用财报发布日期当信号,结果发现数据里混入了「未来信息」。
  • 另类数据:舆情、龙虎榜、供应链数据。这些数据噪声大,但有时能挖到超额收益。

我的小习惯:每次拿到新数据,先画个时间轴,看看数据覆盖的起止日期、缺失率、异常值。别急着建模,先「摸一摸」数据长什么样。

清洗环节,我一般做这几步:

  1. 去重:同一个交易日出现两条数据?保留第一条,或者取均值。
  2. 处理缺失值:用前向填充(ffill)还是插值?看情况。如果是停牌日,我倾向于用复牌后的第一笔数据。
  3. 异常值检测:比如某只股票一天涨了 1000%——这大概率是数据错误,不是真的收益。
  4. 复权处理:后复权还是前复权?我建议用后复权做回测,因为能真实反映持有期的收益。
# 一个简单的数据清洗示例(Python 伪代码)
import pandas as pd

def clean_price_data(df):
    # 去重
    df = df.drop_duplicates(subset=['date', 'code'])
    # 前向填充缺失值
    df['close'] = df.groupby('code')['close'].ffill()
    # 剔除异常值(超过 5 个标准差)
    df = df[df['close'].groupby(df['code']).transform(
        lambda x: (x - x.mean()).abs() < 5 * x.std()
    )]
    return df

⚠️ 曾经踩过的坑:有一次我用聚宽的数据做回测,发现策略收益高得离谱。查了半天,原来是数据里混入了「未来复权因子」——回测时用了未来的复权比例,导致历史收益被放大。从那以后,我每次都会手动检查数据的时间戳。

3.2 因子选择:不是越多越好,是越「纯」越好

因子选择这块,说白了就是找那些能解释股票收益的「特征」。但这里有个误区——很多人觉得因子越多越好,恨不得把几百个因子全塞进去。结果呢?过拟合,样本外一塌糊涂。

我常用的因子分类:

因子类型 常见因子 我的经验
动量因子 过去 1 个月、6 个月、12 个月收益 短期动量(1 个月)在 A 股效果不错,但要注意反转效应
价值因子 PE、PB、PS、股息率 低估值策略在熊市里很抗跌,但牛市容易跑输
质量因子 ROE、毛利率、资产负债率 高 ROE 的股票长期持有体验好,但短期可能不涨
情绪因子 换手率、波动率、分析师评级 换手率高的股票,短期波动大,适合做波段

因子筛选的步骤:

  • 单因子测试:算 IC(信息系数)、IR(信息比率)。IC 绝对值大于 0.02 才算有点用。
  • 相关性分析:两个因子相关系数超过 0.7?留一个就行,不然多重共线性会让你头疼。
  • 分组回测:把股票按因子值分成 5 组或 10 组,看看多空组合的收益曲线是否平滑。

一个实用的原则:因子要「逻辑自洽」。你选的因子,得能讲出故事来。比如「低波动率因子」——为什么低波动的股票长期跑赢高波动的?因为投资者过度追捧彩票型股票,导致高波动股被高估。这个逻辑说得通,因子才靠谱。

3.3 权重优化:数学很美,但别太迷信

权重优化,说白了就是决定每只股票买多少。经典的均值-方差模型(Markowitz)大家都学过,但实际用起来,你会发现它特别「敏感」——输入参数稍微变一点,权重就天翻地覆。

常见的优化方法:

  1. 等权重:简单粗暴,但效果不差。我做过回测,等权重组合长期跑赢市值加权组合。
  2. 风险平价:让每个资产对组合的风险贡献相等。适合低波动环境。
  3. 均值-方差优化:追求给定风险下的最大收益。但要注意——预期收益率的估计误差会放大权重偏差。
  4. Black-Litterman 模型:结合先验分布和主观观点,比纯均值-方差更稳健。
# 风险平价权重的简单实现
import numpy as np

def risk_parity_weights(cov_matrix):
    n = cov_matrix.shape[0]
    # 初始化等权重
    w = np.ones(n) / n
    for _ in range(100):
        # 计算边际风险贡献
        mrc = cov_matrix @ w
        # 调整权重使风险贡献相等
        w = w * (1 / mrc)
        w = w / w.sum()
    return w

我的建议:别把优化结果当圣旨。每次跑完优化,我都会手动检查一下权重——有没有某只股票占比超过 10%?有没有行业过度集中?数学上最优的,现实中可能根本执行不了。

3.4 回测框架搭建:别让回测骗了你

回测框架,是检验策略的「试金石」。但说实话,回测本身很容易「作弊」——比如用了未来数据、没考虑交易成本、假设可以无限成交。这些坑,我几乎都踩过一遍。

一个靠谱的回测框架应该包含:

  • 事件驱动 vs 向量化:事件驱动更贴近真实交易,但速度慢;向量化快,但容易忽略细节。我一般先用向量化做快速验证,再用事件驱动做精细回测。
  • 交易成本:佣金、印花税、滑点。滑点我一般按 0.1% 估算,流动性差的股票会更高。
  • 持仓限制:单只股票最大仓位、行业集中度、换手率限制。
  • 绩效指标:年化收益、夏普比率、最大回撤、胜率、盈亏比。

⚠️ 我曾经犯过的错:有一次回测一个高频策略,收益曲线漂亮得不行。结果发现——我忘了加滑点!实际交易中,每次买卖都要付出 0.1% 的成本,高频交易下来,收益全被吃掉了。从那以后,我回测的第一件事就是检查「成本假设」。

回测的「避坑指南」:

  • 前视偏差:确保回测时只用到了「当时」能获取的数据。
  • 生存偏差:别忘了把退市的股票加进来,否则回测结果会偏乐观。
  • 过拟合:参数调得越多,样本外表现越差。我一般限制参数不超过 3 个。

最后说一句:回测通过只是第一步。真正的考验是实盘。我见过太多策略回测年化 30%,实盘一跑就亏钱。原因?回测时没考虑「流动性冲击」和「市场冲击成本」。所以,回测框架里一定要加上「冲击成本模型」——哪怕只是个简单的线性近似。

好了,这一章的内容就到这儿。数据、因子、权重、回测——这四个环节环环相扣,任何一个出问题,整个组合都会受影响。下一章咱们聊聊更具体的因子挖掘方法,到时候再细说。


专注资料整理