第四节:价格衍生特征——收益率与价格关系的实战构建

各位同学,今天我们聊一个非常基础但又极其重要的内容——价格衍生特征。说白了,就是从原始的价格数据里,挖出那些能反映市场本质的指标。

我个人习惯把这类特征叫做“第一层衍生特征”。为什么?因为它们直接从价格计算而来,不需要其他数据源。你想想看,很多量化策略的成败,往往就取决于这些基础特征处理得干不干净。

4.1 收益率计算:简单收益率 vs 对数收益率

收益率,是量化交易里最常用的特征之一。但很多新手容易忽略一个问题:到底用简单收益率,还是对数收益率?

我先说结论:做短线、日内交易,简单收益率够用;做中长线、多资产组合,对数收益率更靠谱。

4.1.1 简单收益率

公式很简单:

简单收益率 = (当前价格 - 前一期价格) / 前一期价格

用Python实现也就一行:

import pandas as pd
import numpy as np

# 假设df是包含收盘价的数据框
df['simple_return'] = df['close'].pct_change()

我在项目中遇到过一个问题:当价格出现极端波动时,简单收益率的分布会严重偏态。比如某只股票一天涨了100%,第二天跌了50%,简单收益率算出来是0,但你的实际资金变化呢?其实是亏了25%。

避坑指南:我曾经在回测一个期货策略时,用了简单收益率计算夏普比率,结果回测曲线漂亮得不行。实盘一跑,直接崩了。后来发现,简单收益率在计算多期累计收益时,存在“路径依赖”问题——不同顺序的涨跌,算出来的累计收益不一样。

4.1.2 对数收益率

对数收益率解决了这个问题:

对数收益率 = ln(当前价格 / 前一期价格)

代码实现:

df['log_return'] = np.log(df['close'] / df['close'].shift(1))

为什么对数收益率更好?三个原因:

  • 可加性:多期对数收益率可以直接相加,得到总收益率。简单收益率不行。
  • 正态性更好:对数收益率更接近正态分布,这对很多统计模型(比如GARCH)很重要。
  • 对称性:涨10%和跌10%,在对数收益率下是对称的。简单收益率不是。

我的建议:如果你做的是统计套利、风险模型、组合优化,请务必使用对数收益率。如果是做简单的趋势跟踪、日内策略,简单收益率也够用,但要注意累计收益的计算方式。

4.2 最高最低价比例

这个特征,说白了就是看一根K线里,价格波动的幅度有多大。我经常用它来识别“异常波动”或者“突破信号”。

常用的计算方式有两种:

# 方式一:最高最低价比例
df['high_low_ratio'] = df['high'] / df['low']

# 方式二:最高最低价差率(更常用)
df['high_low_range'] = (df['high'] - df['low']) / df['close']

我个人更推荐第二种。为什么?因为第一种在低价股上会失真。比如一只1块钱的股票,最高1.5,最低0.5,比例是3,看起来很夸张。但用收盘价归一化后,波动率是100%,更符合实际感受。

特征名称 计算公式 适用场景
最高最低价比例 high / low 识别极端波动
最高最低价差率 (high - low) / close 日内波动率估计
最高最低价对数差 ln(high / low) 统计模型输入

实战经验:我在做商品期货的波动率策略时,发现一个规律:当最高最低价差率连续3天低于历史20%分位数时,往往预示着即将出现大行情。这个特征比单纯的ATR(平均真实波幅)更敏感。

4.3 开盘收盘价关系

开盘价和收盘价的关系,能告诉我们很多信息。比如:

  • 收盘价 > 开盘价:阳线,买方强势
  • 收盘价 < 开盘价:阴线,卖方强势
  • 收盘价 ≈ 开盘价:十字星,多空平衡

但光看涨跌还不够,我们需要量化这个关系:

# 开盘收盘价比例
df['open_close_ratio'] = df['close'] / df['open']

# 开盘收盘价差率
df['open_close_range'] = (df['close'] - df['open']) / df['open']

# 开盘收盘价对数差
df['open_close_log'] = np.log(df['close'] / df['open'])

嗯,这里要注意:开盘收盘价关系,不能单独使用。我见过有人只用这个特征做策略,结果在震荡市里被反复打脸。为什么?因为单根K线的开盘收盘价关系,随机性太强了。

更好的做法是:结合前几根K线的开盘收盘价关系,构建“持续性指标”。比如:

# 连续阳线强度
df['bull_strength'] = (df['close'] > df['open']).rolling(5).sum()

# 开盘收盘价差率的移动平均
df['oc_ma'] = df['open_close_range'].rolling(10).mean()

我曾经踩过的坑:在做股指期货的日内策略时,我直接用开盘收盘价差率作为信号。结果发现,在跳空开盘的情况下,这个指标完全失效。比如今天开盘直接高开2%,收盘只涨了0.5%,差率是负的,但实际价格是上涨的。后来我改用“相对开盘价”的概念,用开盘价减去前一日收盘价做归一化,才解决了这个问题。

4.4 知识体系总览

下面这张图,是我自己整理的价格衍生特征的知识结构。你可以把它当作一个检查清单,看看自己有没有遗漏:

价格衍生特征 收益率计算 简单收益率 对数收益率 最高最低价比例 比例法 差率法 开盘收盘价关系 比例法 差率法 应用场景:波动率估计 · 趋势识别 · 异常检测 · 风险模型 ⚠️ 注意事项 1. 对数收益率更适合统计模型和组合优化 2. 最高最低价差率比单纯比例更稳定 3. 开盘收盘价关系需结合前序K线使用

4.5 实战中的组合用法

单独使用某个特征,效果往往有限。我习惯把这三个特征组合起来,构建一个“价格行为评分”:

def price_behavior_score(df, window=20):
    """
    价格行为评分:综合收益率、波动率、开盘收盘关系
    返回0-100的评分,越高表示越强势
    """
    # 1. 收益率因子
    ret = df['close'].pct_change(window)
    ret_score = (ret - ret.rolling(100).min()) / (ret.rolling(100).max() - ret.rolling(100).min())
    
    # 2. 波动率因子(最高最低价差率)
    vol = (df['high'] - df['low']) / df['close']
    vol_score = 1 - (vol - vol.rolling(100).min()) / (vol.rolling(100).max() - vol.rolling(100).min())
    
    # 3. 开盘收盘强度
    oc = (df['close'] - df['open']) / df['open']
    oc_score = (oc - oc.rolling(100).min()) / (oc.rolling(100).max() - oc.rolling(100).min())
    
    # 综合评分
    score = (ret_score * 0.4 + vol_score * 0.3 + oc_score * 0.3) * 100
    return score.clip(0, 100)

这个评分我在多个期货品种上测试过,效果还不错。当然,参数需要根据品种特性调整。比如股指期货的波动率权重可以调低一些,商品期货可以调高一些。

一个小技巧:当你构建完这些特征后,记得做一下相关性分析。我经常发现,简单收益率和对数收益率的相关性高达0.99以上,但最高最低价比例和开盘收盘价关系之间,相关性往往很低。这说明它们捕捉的是不同的市场信息。

好了,这一节的内容就到这里。价格衍生特征虽然基础,但用好了,能给你的策略带来很大的提升。下一节我们会聊更高级的“时间序列特征”,比如移动平均、布林带这些。但在此之前,我建议你把今天讲的这几个特征,在自己的数据上跑一遍,看看效果。


专注资料整理