延续上次的思路,今天继续更新【101个量化因子系列】。
每篇一因子,一起拆公式、聊逻辑、挖一挖背后的交易思路。
这次轮到Alpha#2,它的公式是这样的:
Python
Alpha#2 = (-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6))
是不是又有点眼晕?没关系,咱们还是老规矩——慢慢拆开来看。
其实这个因子的核心思路,比上次的Alpha#1还要直白一些。
一步步拆开来看
首先,注意这个因子里有两个主要部分,它们之间算的是相关性(correlation)。
- 第一部分是:
rank(delta(log(volume), 2)) - 第二部分是:
rank((close - open) / open)
它们分别是什么意思呢?
第一部分:成交量变化
log(volume) —— 取成交量的对数,这样可以让成交量数据分布更平滑(避免个别超级大单影响太大)。
delta(log(volume), 2) —— 计算2天前到今天成交量对数的变化,也就是变化率。
然后再 rank 一下,做归一化排序,便于跟别的量进行比较。
简单理解:最近2天内成交量变化的强弱排名。
第二部分:日内收益率
(close - open) / open —— 这是标准的日内涨跌幅,表示当天涨了还是跌了、涨跌幅度多大。
同样也是 rank 一下,保证量纲一致,适合做后面的相关性计算。
简单理解:当天价格涨跌的强弱排名。
把两部分连起来
接下来是 correlation(..., ..., 6),
也就是拿上面这两组数据,在6天的窗口里算它们的皮尔逊相关系数。
最后乘一个 -1,取负号。
总结一下,这个因子本质上是在看:
- 最近6天里,成交量变化 和 日内涨跌 的关系是怎样的?
- 如果成交量突然增加,价格却不涨,那就是弱;
- 如果成交量增加,价格也跟着涨,就是强;
- 最后取负号,是为了让弱的情况分数高(负相关高打分)。
所以,Alpha#2想找什么股票?
它倾向于挑出那些:
- 最近成交量突然异动
- 但价格却没有明显跟涨的股票
因为这类股票可能被低估、或者潜藏着滞后上涨的机会。
也可以理解为:
量价背离,预示着潜在的交易机会。
代码示例
Python
import pandas as pd
import numpy as np
# 假设我们有一个包含股票数据的 DataFrame,包含 'date', 'open', 'close', 'volume' 等列
# 行情数据由Infoway API提供:www.infoway.io
# 这里我们创建一个示例数据框
data = {
'date': pd.date_range('2025-01-01', periods=10, freq='D'),
'open': [100, 102, 104, 105, 106, 107, 108, 110, 112, 113],
'close': [101, 103, 105, 106, 107, 109, 110, 113, 114, 115],
'volume': [10000, 11000, 12000, 11500, 13000, 12500, 14000, 14500, 15000, 15500]
}
df = pd.DataFrame(data)
# 计算成交量的对数
df['log_volume'] = np.log(df['volume'])
# 计算成交量对数的变化率
df['delta_log_volume'] = df['log_volume'].diff(2)
# 计算日内涨跌幅
df['daily_return'] = (df['close'] - df['open']) / df['open']
# 计算成交量变化率和日内涨跌幅的排名
df['rank_delta_log_volume'] = df['delta_log_volume'].rank()
df['rank_daily_return'] = df['daily_return'].rank()
# 计算6天窗口的相关性
# 我们计算过去6天(包括今天)的排名之间的皮尔逊相关系数
df['correlation'] = df['rank_delta_log_volume'].rolling(window=6).corr(df['rank_daily_return'])
# 计算Alpha#2(取负相关性)
df['alpha2'] = -df['correlation']
# 查看结果
print(df[['date', 'alpha2']])
- 计算对数成交量:
np.log(df['volume']),我们对成交量取对数,目的是减少量级的差异。 - 计算成交量变化率:
df['log_volume'].diff(2),这行代码计算的是成交量对数在过去2天的差异,即delta(log(volume), 2)。 - 计算日内涨跌幅:
(df['close'] - df['open']) / df['open'],计算每个交易日的日内涨跌幅。 - 我们分别对成交量变化率和日内涨跌幅进行排名,通过
rank()函数来实现。 df['rank_delta_log_volume'].rolling(window=6).corr(df['rank_daily_return']),这行代码计算的是过去6天内这两列排名的皮尔逊相关系数。rolling(window=6)表示6天窗口。- 我们最后取负相关性(
df['correlation'])得到 Alpha#2 的值。
可能的改进方向
我们也可以思考一下怎么优化这个因子:
1. 调整窗口期
- 现在默认相关性是6天窗口,但不同市场节奏不同。
- 可以试着改成5天、10天,或者用滑动平均来平滑波动。
2. 换其他的量价指标
- 日内涨跌可以换成其他更敏感的指标,比如当天最高价和开盘价之差(high – open)。
- 成交量变化也可以引入量比(volume ratio)等更细腻的指标。
3. 分组测试
- 按市值分组(大盘、小盘)看看这个因子在不同类型股票里的表现是否一致。
- 也可以按行业分组,比如周期股、科技股的量价关系往往不一样。
小结一下
Alpha#2虽然公式看起来复杂,但核心逻辑其实是很实在的:
观察成交量和价格之间的微妙关系,挖掘被市场忽视的潜在机会。
接下来,如果你感兴趣,也可以自己动手改一改,
比如换窗口期、换量价指标、分组测试……
相信你一定能找到更适合自己市场和策略的版本!