4、风格因子定义:成长/价值、大盘/小盘、消费/科技等风格分类方法,以及风格因子的标准化处理

聊到北向资金,很多人第一反应就是看净流入流出。但说实话,只看总量,你很难判断资金到底在打什么牌。真正的高手,盯的是风格切换。

什么叫风格?说白了,就是资金在选股时的偏好。是喜欢买贵的成长股,还是捡便宜的价值股?是抱大盘蓝筹,还是炒小盘题材?这些偏好一旦形成趋势,就是风格因子在起作用。

我刚开始做量化那会儿,也踩过坑。以为把几个指标拼在一起就能定义风格,结果回测一跑,信号乱得像心电图。后来才明白——风格因子不是拍脑袋想出来的,得有清晰的分类逻辑和标准化的处理流程。

4.1 风格因子的核心分类

我们先看最常见的三组风格分类。每一组,我都用实际项目中的经验来讲。

4.1.1 成长 vs 价值

这是最经典的一组。成长因子,衡量的是公司未来的扩张潜力;价值因子,看的是当前股价是否被低估。

成长因子的常见代理变量:

  • 营收增长率(过去3年复合)
  • 净利润增长率
  • ROE(净资产收益率)趋势
  • 研发投入占比

价值因子的常见代理变量:

  • 市盈率(PE)倒数——也就是E/P
  • 市净率(PB)倒数
  • 股息率
  • 自由现金流收益率
我的经验: 别只用单一指标。比如只看PE,银行股永远都是价值风格,但有些银行其实在转型成长。我习惯把3-4个指标合成一个复合因子,效果更稳定。

4.1.2 大盘 vs 小盘

这个分类相对简单,但容易犯一个错误——直接用市值排序。你想想看,茅台和工商银行都是大盘,但它们的资金行为完全不同。

我建议这样处理:

  • 按总市值排名,前30%定义为大盘,后30%为小盘,中间40%为中盘
  • 或者用对数市值,减少极端值的影响
  • 记得每月或每季度重新调整一次分类
注意: 北向资金在大盘和小盘上的切换,往往领先于A股整体风格。我曾经在2021年初观察到北向持续加仓中盘股,而当时市场还在疯炒大盘。两个月后,中盘风格果然爆发。

4.1.3 消费 vs 科技

这是行业层面的风格分类。消费和科技,是北向资金最偏爱的两大方向。

消费风格包含:

  • 食品饮料
  • 医药生物
  • 家用电器
  • 农林牧渔

科技风格包含:

  • 电子
  • 计算机
  • 通信
  • 电力设备(新能源)

嗯,这里要注意。有些股票横跨多个行业,比如比亚迪,既是汽车又是新能源。我一般用申万一级行业分类为主,如果遇到跨行业公司,看它的主营业务收入占比,超过50%就算。

4.2 风格因子的标准化处理

定义好分类之后,下一步就是标准化。为什么要标准化?因为不同指标的量纲不一样。营收增长率是百分比,PE是倍数,市值是亿元。不标准化,你没法把它们放在一起比较。

我常用的标准化方法有三种,按使用频率排序:

方法 公式 适用场景
Z-score标准化 (x - μ) / σ 数据近似正态分布时
百分位排名 rank(x) / N 数据有极端值或偏态时
Min-Max缩放 (x - min) / (max - min) 需要将数据映射到[0,1]区间时

我个人最常用的是百分位排名。为什么?因为金融数据经常有极端值,比如某只股票突然暴涨,PE变得特别高。如果用Z-score,这个极端值会严重扭曲结果。百分位排名就不怕,它只看相对位置。

来看一段代码示例,这是我实际项目中用过的处理逻辑:

import pandas as pd
import numpy as np

def style_factor_standardization(df, factor_cols, method='rank'):
    """
    风格因子标准化处理
    df: 包含因子数据的DataFrame
    factor_cols: 需要标准化的因子列名列表
    method: 'rank' 或 'zscore' 或 'minmax'
    """
    df_std = df.copy()
    
    for col in factor_cols:
        if method == 'rank':
            # 百分位排名,结果在0到1之间
            df_std[col + '_std'] = df_std[col].rank(pct=True)
        elif method == 'zscore':
            # Z-score标准化
            mean = df_std[col].mean()
            std = df_std[col].std()
            df_std[col + '_std'] = (df_std[col] - mean) / std
        elif method == 'minmax':
            # Min-Max缩放
            min_val = df_std[col].min()
            max_val = df_std[col].max()
            df_std[col + '_std'] = (df_std[col] - min_val) / (max_val - min_val)
    
    # 处理缺失值:用中位数填充
    df_std = df_std.fillna(df_std.median())
    
    return df_std

# 使用示例
factors = ['growth_rate', 'pe_ratio', 'market_cap']
df_processed = style_factor_standardization(df_raw, factors, method='rank')
核心要点: 标准化之后,每个因子的取值都在0到1之间(如果用百分位法)。这样我们就可以把成长因子、价值因子、市值因子直接相加或加权,构建一个综合的风格得分。

4.3 风格因子的合成与使用

有了标准化的因子,下一步就是合成。比如我想定义一个“成长价值偏离度”指标:

# 成长因子 = 营收增长率 + 净利润增长率 + ROE趋势
df['growth_score'] = (df['revenue_growth_std'] + 
                      df['profit_growth_std'] + 
                      df['roe_trend_std']) / 3

# 价值因子 = E/P + 股息率 + 自由现金流收益率
df['value_score'] = (df['ep_ratio_std'] + 
                     df['dividend_yield_std'] + 
                     df['fcf_yield_std']) / 3

# 成长价值偏离度:正值偏向成长,负值偏向价值
df['gv_deviation'] = df['growth_score'] - df['value_score']

这个偏离度指标,我经常用来观察北向资金的风格偏好。如果北向资金持续买入成长偏离度高的股票,说明他们在加仓成长风格;反之,就是在转向价值。

我曾经用这个指标在2022年10月捕捉到一次明显的风格切换。当时北向资金连续5天净买入价值偏离度高的股票,而成长偏离度持续走低。我判断资金在避险,于是跟着减仓了科技股。一个月后,市场果然回调,价值风格跑赢了成长风格10个点。

一个小技巧: 不要只看一天的风格偏离度,噪音太大。我习惯看5日移动平均,或者用滚动窗口计算趋势。趋势比绝对值更有参考价值。

4.4 本章知识体系

下面这张图,是我自己整理的一套风格因子处理流程。从原始数据到最终信号,每一步都有讲究。

风格因子处理流程 原始数据 财务指标、行情数据 因子定义 成长/价值/市值/行业 标准化处理 Z-score/百分位/Min-Max 因子合成 加权平均/偏离度计算 风格得分 成长/价值/大盘/小盘 北向资金匹配 净流入 vs 风格得分 风格切换信号 买入/卖出/持仓建议 回测验证 收益/风险/胜率评估 反馈优化 图:风格因子从原始数据到交易信号的完整处理流程 虚线表示回测结果反馈到因子定义的优化循环

你看,从原始数据到最终信号,中间要经过因子定义、标准化、合成、匹配、回测五个关键步骤。每一步都可能出错,但每一步也都有优化空间。

我个人觉得,标准化这一步是最容易被忽视的。很多人拿到数据就直接用,结果因子之间量纲不统一,合成出来的风格得分毫无意义。记住一句话:没有标准化的因子,就像没有校准的仪器——测出来的数据你敢信吗?

好了,这一章的内容就到这里。风格因子的定义和标准化是基本功,但也是后面所有分析的基础。你把这个搞透了,后面看北向资金的风格切换,就会清晰很多。


公众号:蓝海资料掘金营,微信deep3321