在Quantlab里复现WorldQuant101因子表达式引擎(代码+数据)

从专业量化投资的角度,核心第一要务是因子。

因子挖掘,分为手工构造,机器挖掘,以及星球在尝试的GPT挖掘

手工注定是低效的,尽管现在在很小小型私募里仍然有效。

我们重心放在后两者上。

gpt大家可以先看这几篇文章:

Quantlab3.9代码:内置大模型LLM因子挖掘,全A股数据源以及自带GUI界面

AlphaGPT v0.1发布后答疑——基于大模型的智能因子挖掘框架(代码)

机器挖掘当下也有两个方向:gplearn和强化学习。在这DeepAlpha我们都覆盖了:DeepAlpha通用因子挖掘:支持GPlearn遗传算法和深度强化学习挖掘因子(代码+数据下载)

但这个系统有个缺陷,基于qlib,另外它生成的因子还没有办法在Quantlab直接使用、回测。

Qlib的表达式系统有一个天生的缺陷,就是不支持截面因子!——因为它的表达式是基于一个个类,而类是针对单个symbol来计算的。截面计算,需要group by date。

在咱们代码目录AlphaGPT下,我带了WorldQuant101的因子表达式集合,给GPT few-shot学习用的。

大家仔细看下,满眼的rank,这就是典型的“截面函数”。——qlib不支持且无法支持!

图片

Alpha#3: (-1 * correlation(rank(open), rank(volume), 10))

比如这个三号因子,就是10日开盘价与交易量的负相关性,在投资上,我们称之为“价量背离”。——一个很好理解的因子,它不是用价格和成交量的值来算相关系数,因为量纲不一样,取rank后,量纲就一致了。

因此rank是一个很通用的函数。

qlib只能算时序,不能算截面,就限制了它的表达式引擎不可用

我们重定并改进了这个缺点。

咱们同样在dataloader下计算因子:

图片

所有数据加载到一个DataFrame里后,选group_by_date,按日期分组,然后调用相应的函数,比如rank即可。

@calc_by_date
def rank(se: pd.Series):
    ret = se.rank()
    return ret

我们后续会还原WorldQuant101里这100多个因子:

其实就是把常用函数实现就好了,比如 delay, delta, rank

import pandas as pd
from .expr_utils import calc_by_symbol, calc_by_date


@calc_by_symbol
def delay(se: pd.Series, periods=5):
    return se.shift(periods=periods)


@calc_by_date
def delta(se: pd.Series, periods=20):
    se_result = se - se.shift(periods=periods)
    return se_result

测试代码如下:

import numpy as np
import pandas as pd

from config import DATA_DIR
from datafeed.expr import calc_expr

sh300 = pd.read_csv(DATA_DIR.joinpath('quotes').joinpath('000300.SH.csv').resolve())
sh905 = pd.read_csv(DATA_DIR.joinpath('quotes').joinpath('000905.SH.csv').resolve())
sh016 = pd.read_csv(DATA_DIR.joinpath('quotes').joinpath('000016.SH.csv').resolve())
df = pd.concat([sh300, sh905, sh016])

df['date'] = df['date'].apply(lambda x: str(x))
df.dropna(inplace=True)

df.set_index(['date', 'symbol'], inplace=True)
df = df.loc[df.index.get_level_values('date') > '20100101', :]

# Alpha#101: ((close - open) / ((high - low) + .001))
se = calc_expr(df, expr='((close - open) / ((high - low) + .001))')
df['alpha_101'] = se

# Alpha#12: (sign(delta(volume, 1)) * (-1 * delta(close, 1)))
se = calc_expr(df, expr='(sign(delta(volume, 1)) * (-1 * delta(close, 1)))')
df['alpha_12'] = se
print(df)

计算两个alpha,比如简单:

图片

测试代码在如下位置:

图片

公用函数其实就那么一些,我们实现一下就好了(之前是qlib的标准,我会按WorldQuant101的标准重新刷一轮):

abs(x),log(x),sign(x) = standard definitions
分别为:取绝对值、对数值、正负号(正数返回1,负数返回-1)

rank(x) = 截面rank
股票的排名,数值从1-最后,若输入值含nan,则nan不参与排名,输出为股票对应排名的boolean值(排名所占总位数的百分比)

delay(x,d) = value of x d days ago
x变量d天之前的值

correlation(x,y,d) = time-serial correlation of x and y for the past d days
x和y两个变量d天以来的值的相关系数

covariance(x,y,d) = time-serial covariance of x and y for the past d days
x和y两个变量d天以来的值的协方差

scale(x,a) = rescaled x such that sum(abs(x))=a (the default is a=1)
将x中的值标准化,使x的绝对值的和为a,默认a=1

delta(x,d) = today’s value of x minus the value of x d days ago
指定enddate的x值减去d天之前的x值

signedpower(x,a) = x^a
x值的a次方,如果x为一个list或者series,则为x中每一个值的a次方

decay_linear(x,d) = weighted moving average over the past d days with linearly decaying weights d,d-1,…,1 (rescaled up to 1)
x中时间从最远到最近的值,分别乘权重d,d-1,…,1(权重要进行标准化,使和为1)再求和

ts_min(x,d) = time-series min over the past d days
x中d天内最小的值

ts_max(x,d) = time-series max over the past d days
x中d天内最大的值

ts_argmin(x,d) = which day ts_min(x,d) occurred on
ts_min(x,d)发生在d天中的第几天,最远的天为第一天

ts_argmax(x,d) = which day ts_max(x,d) occurred on
ts_max(x,d)发生在d天中的第几天,最远的天为第一天

ts_rank(x,d) = time-series rank in the past d days
x中,最后一天的值,在这d天中,排多少名,最后输出的名次为boolean值(即该名次占总排名数的百分比)

min(x,d) = ts_min(x,d)
当遇到min函数时,当ts_min函数处理——-注意!!实际上遇到min时,当min中的输入不是(x,d)而是(x,y)时,取x、y两个值中的最小值

max(x,d) = ts_max(x,d)
当遇到max函数时,当ts_max函数处理——注意!!实际上遇到max时,当max中的输入不是(x,d)而是(x,y)时,取x、y两个值中的最大值

sum(x,d) = time-series sum over the past d days
d天以来x值的和

product(x,d) = time-series product over the past d days
d天以来x值的乘积

stddev(x,d) = moving time series standard deviation over the past d days
d天以来,x值的标准差

从因子函数库的实现角度分析:

1、单时间序列计算:比如log, sign,abs这种,numpy都有函数,技术分析类的,可以直接调用ta-lib。

2、单时间序列的rolling, 比如shift, delta,使用pd.Series的rolling加apply即可。

3、多序列直接运算,比如加,减,金叉之类的。直接序列运算即可。

4、多序列多为双序列窗口计算,比如correlation等。这种计算有性能问题,我还在想办法,RSRS计算就是一个典型场景,计算high和low两个序列的rolling的beta。

后续这些因子引擎与gplearn和强化学习自动挖掘因子打通,形成一个“自动化的因子工厂”!

代码已经发布至星球:

图片

发布者:股市刺客,转载请注明出处:https://www.95sca.cn/archives/103415
站内所有文章皆来自网络转载或读者投稿,请勿用于商业用途。如有侵权、不妥之处,请联系站长并出示版权证明以便删除。敬请谅解!

(0)
股市刺客的头像股市刺客
上一篇 2024 年 7 月 29 日
下一篇 2024 年 7 月 29 日

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注