PLUS会员

WorldQuant Alpha101因子复现及因子分析

由qxiao创建,最终由qxiao 被浏览 917 用户

1.引言

在学术研究中,Alpha是数学表达式、计算机源代码和配置参数的组合,可以与历史数据一起用于预测各种金融工具的未来走势。而在实践中,Alpha通常意味着进行交易的合理“预期回报”。两者并不一定相同。许多情况下,能够带来合理“预期回报”的Alpha并不容易构建,因此,对于Alpha的挖掘和公式化的研究始终是业界的一个重要课题。在这样的背景下,世坤(WorldQuant)于2015年发布了报告101 Formulaic Alphas。在这篇报告中,世坤提供了101个真实生活中的量化交易Alpha的明确公式(这些也可以看作是计算机代码)。虽然其中的一些模型较为复杂,但世坤设计这些公式化的Alpha模型的初衷是让读者对一些较简单的真实生活中的Alpha有所了解,进一步地,使读者能够在历史数据上复制和测试这些Alpha,进行新的研究和其他实证分析,激励读者提出新的想法,并创造他们自己的Alpha模型。

现在,我们BigQaunt平台上使用相关数据和DAI成功复现了这101个公式化的Alpha,也就是因子,并提供了每个因子在我们平台上调用的方法,以辅助大家更方便地进行使用和做策略。同时,对于101个因子我们还设置了每日的因子分析,大家可以在因子看板上一目了然地看到各因子的表现和趋势。

在接下来的第二部分中,我们将首先分析这101个因子的构建逻辑,讨论它们的一般特性和实证性质,给出一些典型案例以供大家更好理解。在第三部分,我们将简要介绍因子分析的流程。在第四部分,我们将进行简要总结。而在第五部分,我们将给出在BigQuant平台上具体如何调用因子的教程。在最后的附录中,我们将给出世坤Alpha101所有因子的构建公式,其中使用的函数、运算符和输入数据的定义,所有因子的SQL实现和对Alpha101因子的因子分析示例。其中附录一(对因子的原始定义)和附录二(原始定义中使用的函数、运算符等定义)在此页面;附录三,即所有101因子的SQL实现,链接如下:https://bigquant.com/wiki/doc/alpha101-sql-Ixjd3MmB30;附录四,对Alpha101因子的因子分析示例,链接如下:https://bigquant.com/wiki/doc/alpha101-alpha101alpha100-w0D05jdy3i


2.Alpha101因子的构建-短周期量价

2.1构建思路

传统的因子构建主要依赖于对财务数据和分析师一致性预期数据的深入研究,而价量特征数据只占一小部分,因此这样的因子也被称为价值型Alpha。然而,A股市场的交易行为具有明显的随机性,机构投资者的交易效率与成熟市场相比并不高效,再加上缺乏T+0和卖空等交易机制,短期内由交易行为产生的价格失效现象非常常见。任何由投资者交易产生的价格序列都不会是完全随机的。因此,这个领域的超额收益有很大的提升空间,量化模型在这里应发挥其优势。国泰君安证券曾于2017年研究交易型Alpha策略并得到了类似的结论。他们发现在A股市场,与传统的股票价值Alpha收益相比,交易型Alpha收益的空间更大、收益稳定性更强。这与A股市场的投资者结构、交易制度、投资者交易特征有着密切关系。"在A股市场中,即使是最纯粹的价值投资者也必须承认,交易行为在短期内对股票价格产生了决定性的影响。而这种交易型套利空间的挖掘正是量化投资的优势所在,因此量化模型在这个领域应该有广泛的应用空间"。而世坤的Alpha101正是对交易行为进行了刻画,覆盖了按照传统方式构建的因子无法覆盖的地方,起到了很好的补充作用。

2.2显著的量价特征(构建因子的模块)列举

粗略地说,我们可以将世坤的101个Alpha因子视为基于均值回归和动量构建的。在此我们列举几个世坤想要刻画的量价特征:

一般来说,一个均值回归的Alpha信号与其基础的回报有相反的符号,例如,一个简单的均值回归Alpha可以用公式如下公式表示:

$$  -ln( 今日开盘价 / 昨日收盘价 ) $$

这里的昨日收盘价已经考虑了今日的任何拆股和红利。这种Alpha的出发点(或希望)是,如果今日开盘价高于昨日收盘价,股票将回归均值并回撤部分收益;如果今日开盘价低于昨日收盘价,股票将回归均值并收复部分损失。这种Alpha被称为“0延迟”Alpha。这意味着Alpha中使用的某些数据(例如“今日开盘价”)的时间与打算进行交易的Alpha的时间相吻合。理想情况下,这个Alpha应该在今日开盘时或尽可能接近今日开盘时进行交易,当然这也可以是其他时间,例如收盘时。

动量Alpha的一个简单例子如下:

$$ ln ( 昨日收盘价 / 昨日开盘价 ) $$

这里,无论价格是否进行了调整都没有关系。这种Alpha的出发点(或希望)是,如果股票在昨日上涨(或下跌),那么趋势将在今日继续,收益(或损失)将进一步增加。如果打算今日交易,这被称为“1延迟”Alpha。一般来说,”1延迟“意味着Alpha在用于计算它的最近数据的日期的次日进行交易。”2延迟“Alpha的定义类似,其中的2表示交易发生在用于计算Alpha的数据最新日期的后两天。

在复杂的Alpha中,均值回归和动量的元素可以混合,使它们在这方面变得不那么明显。然而,我们可以将这样的Alpha的较小构建块视为基于均值回归或动量。例如,附录中的Alpha#101是一个“1延迟”动量Alpha:如果股票在日内上涨(即,收盘价 > 开盘价并且最高价 > 最低价),那么第二天就会在该股票中建立多头头寸。另一方面,附录A中的Alpha#42基本上是一个“0延迟”均值回归Alpha:如果股票在当日下半场上涨(收盘价 > VWAP)(这里的”vwap“表示”日成交量加权平均价格“),则rank(vwap - close)(这里的rank是按照日期分组,对所有股票按照vwap-close的值大小进行的升序排序,计算所得值越大,排名越靠后,因子值越大)将低于股票下滑(收盘价 < VWAP)的情况。分母对较为昂贵的股票进行了调整。在接近收盘时,会采取“逆向”操作。

那么先找到一些显著的量价特征,作为小的构建块,再随机组合这些构建块,便生成了世坤101的因子。

(注:在101个Alpha中,有四个,即编号为42、48、53和54的Alpha,是“0延迟”Alpha。它们假设在计算它们的交易日收盘时或尽可能接近收盘时进行交易。)

2.3Alpha101因子的一般特性和实证性质

世坤的Alpha101因子主要基于“价格-成交量”(日收盘价至收盘价的收益、开盘价、收盘价、最高价、最低价、成交量和成交均价)构建,在部分Alpha中使用了“基本面”数据,包括一个利用市值(total market value)的因子,以及一些使用某种二元行业分类(如GICS、BICS、NAICS、SIC等)的因子,这些分类用于对各种计算所得量进行行业中性化。(注:在我们的构建中,基于投资标的为中国股市股票,故采取的分类标准为申万2021年版本的一级行业分类。)

世坤根据个别因子的夏普比率、换手率、每股分钱和样本协方差矩阵,讨论了这些Alpha因子的实证性质,结果显示:1. 因子平均持有期大约在0.6到6.4天之间;2. 因子的对间相关性较低,平均数为15.9%;3. 因子收益(return)与波动性(volatility,日收益标准差,σ)有强烈的相关性;4. 此外,因子收益对换手率(turnover)没有显著的依赖性。

2.4部分因子构建公式及构建方法展示

在这里我们将列举部分因子的构建方式(所有Alpha101因子的SQL实现详见附录三https://bigquant.com/wiki/doc/alpha101-sql-Ixjd3MmB30):


***Alpha#4: (-1 * Ts_Rank(rank(low), 9)) ***

计算Alpha#4首先需要获取每个交易日所有股票的最低价数据,并以日期作为横截面,在每个交易日对所有股票的最低价进行升序排序,得到每个交易日每支股票的当日最低价排名值(这里对排名进行缩放处理,排名值域为 [0, 1] ,股票日最低价越高,则股票在当日的排名值越大)。

在Bigquant平台上我们对部分SQL窗口函数和聚合函数进行了封装,这样可以在SQL体系下快速完成我们想要的计算。例如上一步的排名可以用**pct_rank_by(date, low)**在平台上快速计算。

接下来对每支股票得到的排名值再进行滚动9日的时序排序(升序),对于每支股票在每个交易日将所得横截面排名值与前8个交易日的横截面排名值进行比较,得到该股票在该交易日的九日时序排名值。这一步用**m_rolling(排名值, 9)**指令即可快速完成。最后再将所得值乘以-1,得到Alpha#4。最终代码展示如下:

SELECT date, instrument, 
    -1 * m_rolling_rank(pct_rank_by(date, low),9) as alpha_6004
FROM cn_stock_bar1d 
WHERE date >= '2015-01-05' 
ORDER BY date , instrument; 

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

计算Alpha#6首先需要获取每个交易日所有股票的开盘价和成交量数据,以十期为窗口计算每支股票两列数据的相关系数(当期往前推十期计算相关系数,作为当期的因子值),并乘以-1得到Alpha#6。最终代码展示如下:

SELECT instrument, date,
    -1 * m_corr(open, volume, 10) AS alpha_6006
FROM cn_stock_bar1d
WHERE date >= '2015-01-01'
ORDER BY date, instrument;

***Alpha#10: rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0) ? delta(close, 1) : (-1 * delta(close, 1))))) ***

计算Alpha#10首先需要获取股票的日收盘价(后复权)数据,对于每支股票,计算当期往前推一期(上一个交易日)的收盘价的连续四期最小值作为第一个当期的计算所得量,记为factor1,将factor1与0作比较,如果大于0,则当期因子值(Alpha#10)为上一个交易日的收盘价。如果factor1小于0,则在当期计算上一个交易日收盘价的连续四期最大值作为第二个计算所得量,记为factor2,并将factor2再与0作比较,如果factor2小于0,则因子值(Alpha#10)取上一期收盘价,否则取-1乘以上一期收盘价。最终代码展示如下:

SELECT
    instrument,
    date,
    pct_rank_by(date, if(m_min((close-m_lag(close, 1)), 4) IS NULL, NULL, 
                            if(0 < m_min((close-m_lag(close, 1)), 4), (close-m_lag(close, 1)), 
                                  if(m_max((close-m_lag(close, 1)), 4) < 0, (close-m_lag(close, 1)), -1 * (close-m_lag(close, 1)))))) AS alpha_6010
FROM cn_stock_bar1d
WHERE date >= '2015-01-01'
ORDER BY instrument, date;

***Alpha#15: (-1 * sum(rank(correlation(rank(high), rank(volume), 3)), 3)) ***

计算Alpha#15首先需要获取股票的日最高价和成交量数据并计算每支股票每个交易日的最高价和成交量的横截面升序排名,再计算每支股票两列排名值的相关系数,窗口期取三期,得到factor1。此时再对每支股票的factor1值进行按照日期分组的横截面升序排名,再取三期窗口期,对该排名值进行三期求和运算,得到factor2。即 factor2 = 当期排名值 + 上一期排名值 + 上上期排名值 。最后将factor2乘以-1得到Alpha#15因子。最终代码展示如下:

SELECT instrument, date, 
    -1 * m_sum(pct_rank_by(date, m_corr(pct_rank_by(date, high), pct_rank_by(date, volume), 3)), 3) AS alpha_6015 
FROM cn_stock_bar1d 
WHERE date >= '2015-01-01' 
ORDER BY instrument, date; 

***Alpha#25: rank(((((-1 * returns) * adv20) * vwap) * (high - close))) ***

计算Alpha#25首先需要计算个股的日收益率returns。在构建的过程中,我们这样计算returns。当期returns = 当期后复权close / 上一期后复权close - 1,这里的“期”指交易日,在BigQuant平台上,该计算可以用SQL代码 returns = close / m_lag(close, 1) - 1 实现。同时构建该Alpha因子还需要计算个股的adv20数据,adv20代表个股连续20期的dollar volume均值,我们这里用成交额(amount)来代表dollar volume。在平台上,该计算可以用 adv20 = m_avg(amount, 20) 来实现。最后,构建该Alpha还需计算个股的vwap,即“成交量加权平均价格”。这里我们用成交额(amount)除以成交量(volume)来表示vwap,即 vwap = amount / volume 。在得到三个计算量后,我们还需获取个股日最高价和后复权收盘价。最后用-1乘以returns,adv20,vwap及个股最高价和后复权收盘价的差值,最后得到Alpha#25。最终代码展示如下:

SELECT instrument, date, 
    pct_rank_by(date, (-1 * (close/m_lag(close, 1)-1) * m_avg(amount, 20) * (amount/volume) * (high-close))) AS alpha_6025 
FROM cn_stock_bar1d 
WHERE date >= '2015-01-01' 
ORDER BY date, instrument; 

***Alpha#29: (min(product(rank(rank(scale(log(sum(ts_min(rank(rank((-1 * rank(delta((close - 1), 5))))), 2), 1))))), 1), 5) + ts_rank(delay((-1 * returns), 6), 5)) ***

计算Alpha#29首先需要获取个股的每日后复权收盘价,计算每支股票当期收盘价减一与五期前收盘价减一的差值,及 (当期close - 1) - (往前推五期的close - 1) ,在平台上我们可以这样计算 (close -1) - m_lag((close - 1), 5) 。在得到该差值后我们对每个股票每日的该值进行横截面升序排序,将所得值乘以-1后再进行两次同样的操作。然后再对每支股票的所得值进行连续两期的最小值计算,即股票当期的value值为当期所得值与上一期所得值中的最小值。得到该value后再对每支股票的value进行连续一期的求和,显然这里连续一期即取当期的value。接下来再对所得的value进行对数计算,这里用SQL内置函数即可,LOG(value) 。接下来再对所得值进行缩放计算,这里的scale函数定义如下:scale(x, a) = rescaled x such that sum(abs(x)) = a (the default is a = 1) 。在这里,缩放是对横截面的数据进行缩放,即使得每日每支股票的所得值绝对值加总为1。我们使用指令 ABS(所得值) / SUM(ABS(所得值)) OVER (PARTITION BY date) 来完成缩放操作。获得缩放后数据后,我们再对每只股票的缩放值进行连续一期的求积,这里连续一期同样是只取当期即可。最后再将所得值与数值5进行比较,取小作为Alpha#29的一部分,我们记为factor1。Alpha#29的另一个部分需要我们首先计算个股的日收益率。获得个股每期收益率后乘以-1并取每期往前推6期的收益率作为当期计算量,在平台上我们用 m_lag(-1 * returns, 6) 获得该计算量,最后再对每支股票的该计算量进行连续5日的时序排名,得到factor2。将factor1加上factor2最终得到Alpha#29。最终代码展示如下:

WITH scale_computation AS (
SELECT instrument, date, close, 
    m_min(pct_rank_by(date, pct_rank_by(date, -1 * pct_rank_by(date, close - m_lag(close, 5)))), 2) AS sum_min, 
    LOG(sum_min) AS pre_scale, 
    ABS(pre_scale)/SUM(ABS(pre_scale)) OVER (PARTITION BY date) AS after_scale, 
    pct_rank_by(date, pct_rank_by(date, after_scale)) AS factor 
FROM cn_stock_bar1d 
WHERE date >= '2015-01-01')

SELECT instrument, date, 
    if(after_scale IS NULL, NULL, if(factor < 5, factor, 5)) + 
    m_rolling_rank(m_lag(-1 * (close/m_lag(close, 1) - 1), 6), 5)/5 AS alpha_6029 
FROM scale_computation 
ORDER BY instrument, date;

***Alpha#31: ((rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10)))) + rank((-1 * delta(close, 3)))) + sign(scale(correlation(adv20, low, 12)))) ***

计算Alpha#31首先需要获取个股的每日后复权收盘价,计算每支股票当期收盘价与十期前收盘价的差值,及 当期close - 往前推十期的close ,在平台上我们可以这样计算: close - m_lag(close, 10) 。再对每支股票的上述差值进行两次日期横截面升序排序,对所得值乘以-1后再计算其窗口期为十日的线性衰减加权均值,即decay_linear(x, a) ,该处理的定义如下:decay_linear(x, d) = weighted moving average over the past d days with linearly decaying weights d, d – 1, …, 1 (rescaled to sum up to 1) 。decay_linear均值与普通的时序均值的区别在于普通的时序均值对窗口期的数据进行的是等权处理,而在decay_linear中,离当期越近的数据拥有更高的权重。在我们的平台上可直接使用 m_decay_linear(-1 * 所得值, 10) 完成上述操作。获得线性衰减加权均值后,我们对该值再进行三轮日期横截面升序排序,获得Alpha#31的一部分,记为factor1。再计算每支股票当期收盘价与三期前收盘价的差值乘以-1的值的横截面升序排名,记为factor2。最后计算个股的滚动20期平均dollar volume,并计算该值与个股日最低值的滚动12日相关系数,并对求得的相关系数进行缩放处理。最后再取所得值的符号,记为factor3。这里SQL有内置的符号函数, SIGN(x) ,直接使用即可。最后对factor1,factor2和factor3进行求和,得到Alpha#31。最终代码展示如下:

SELECT instrument, date, 
    pct_rank_by(date, pct_rank_by(date, pct_rank_by(date, m_decay_linear(-1 * pct_rank_by(date, pct_rank_by(date, close-m_lag(close, 10))), 10)))) + 
    pct_rank_by(date, -1 * (close - m_lag(close, 3))) + 
    SIGN(ABS(m_corr(m_avg(amount, 20), low, 12))/(SUM(ABS(m_corr(m_avg(amount, 20), low, 12))) OVER (PARTITION BY date))) AS alpha_6031
FROM cn_stock_bar1d 
WHERE date >= '2015-01-01' 
ORDER BY date, instrument;

***Alpha#40: ((-1 * rank(stddev(high, 10))) * correlation(high, volume, 10)) ***

计算Alpha#40首先需要获取个股的日最高价和日成交量数据,计算每支股票日最高价的滚动十日标准差,即取当期往前十期的最高价序列计算标准差。在BigQuant平台上使用 m_stddev(high, 10) 即可完成上述指令。获得标准差后对每支股票的该值进行横截面升序排序,对所得排名乘以-1,再乘以该支股票最高价与成交量的滚动十日相关系数,获得Alpha#40。最终代码展示如下:

SELECT instrument, date, 
    -1 * pct_rank_by(date, m_stddev(high, 10)) * m_corr(high, volume, 10) AS alpha_6040 
FROM cn_stock_bar1d 
WHERE date >= '2015-01-01' 
ORDER BY instrument, date;

***Alpha#58: (-1 * Ts_Rank(decay_linear(correlation(IndNeutralize(vwap, IndClass.sector), volume, 3.92795), 7.89291), 5.50322)) ***

计算Alpha#58首先需要计算个股的vwap,即“成交量加权均价”数据,再对vwap进行行业中性化操作。此处行业中性化的定义如下 indneutralize(x, g) = x cross-sectionally neutralized against groups g (subindustries, industries, sectors, etc.), i.e., x is cross-sectionally demeaned within each group g 。我们将行业中性化理解为 indneutralize_value = value - avg(value.industry) ,即某支股票的某值减去该股票所处行业的该值的均值得到该股票行业中性化后的该值。同时,我们采取申万2021年发布的一级行业分类标准来确定每支股票所处的行业。在确定了定义后,在具体计算中我们采取如下SQL代码 value - AVG(value) OVER (PARTITION BY industry_code) 来获得每支股票行业中性化后的value,这里的industry_code即对应每支股票所处行业的行业编码。回到计算,获得各支股票行业中性化后的vwap后,计算各股票该值与成交量的滚动3.92795日相关系数。这里的3.92795日按照小数点后一位的值进行四舍五入,得到4日,也就是实际上是作滚动4日的相关系数计算。在表达式中碰到日期小数均按照上述规则进行处理。得到相关系数后计算每支股票的该值的滚动7.89291日线性衰减加权均值(实际上就是滚动8日)。获得该均值后再计算每支股票该值的滚动5.50322日时序排名(实际上就是滚动6日)。最后将所得排名乘以-1得到Alpha#58。最终代码展示如下:

WITH industry_data AS (
SELECT instrument, date, industry_level1_code 
FROM cn_stock_industry_component
WHERE date >= '2015-01-01' AND industry = 'sw2021'
), 
factor_data AS(
SELECT instrument, date, amount/volume AS vwap, volume
FROM cn_stock_bar1d 
WHERE date >= '2015-01-01'
), 
merged_data AS (
SELECT b.instrument, b.date, b.volume, b.vwap - AVG(b.vwap) OVER (PARTITION BY a.industry_level1_code, a.date) AS industry_vwap
FROM industry_data a 
JOIN factor_data b ON a.instrument = b.instrument AND a.date = b.date)

SELECT instrument, date, 
    -1 * m_rolling_rank(m_decay_linear(m_corr(industry_vwap, volume, 3.92795), 7.89291), 5.50322) AS alpha_6058
FROM merged_data
ORDER BY instrument, date; 

***Alpha#100: (0 - (1 * (((1.5 * scale(indneutralize(indneutralize(rank(((((close - low) - (high - close)) / (high - low)) * volume)), IndClass.subindustry), IndClass.subindustry))) - scale(indneutralize((correlation(close, rank(adv20), 5) - rank(ts_argmin(close, 30))), IndClass.subindustry))) * (volume / adv20)))) ***

计算Alpha#100首先需要获得个股的后复权收盘价,最低价,最高价和成交量。计算每支股票每日的 (close - low) - (high - low) 值,再乘以成交量,并对所得值进行按照日期分组的横截面升序排序,所得排序记为factor1。再对factor1进行两轮行业中性化处理,并缩放所得值,得到Alpha#100的一部分,记为factor2。我们另取个股每日后复权收盘价,计算每支股票该值与滚动20日平均dollar volume横截面排名的滚动五日相关系数,另计算每支股票当期往前推30期出现的离当期最近的后复权收盘价最小值所在的期距离当期的期数,并对该期数数据进行横截面升序排名。这里计算期数需要首先对所有数据按照股票代码(instrument)分组后另附索引,索引值按照日期值呈现降序。再根据每支股票当期索引与前30期内出现最小后复权收盘价的日期的索引的最小值求差值,得到需要求得的距离期数。取前述相关系数减去该距离期数的横截面排名,并对所得值进行行业中性化处理和缩放处理,得到factor3。最后取0减去factor2,factor3和成交量与滚动20日平均dollar volume之商的乘积,得到Alpha#100。最终代码展示如下:

WITH industry_data AS (
SELECT instrument, date, industry_level1_code 
FROM cn_stock_industry_component 
WHERE date >= '2015-01-01' AND industry = 'sw2021'
), 
windows AS (
SELECT instrument, date, ((close - low)-(high - close))/(high - low)*volume AS pre_1, close, m_avg(amount, 20) AS adv20, volume, 
    ROW_NUMBER() OVER (PARTITION BY instrument ORDER BY date DESC) AS rn, m_min(close, 30) AS min_close 
FROM cn_stock_bar1d WHERE date >= '2015-01-01'
), 
windows2 AS (
SELECT w1.instrument, w1.date, w1.pre_1, w1.close, w1.adv20, w1.volume, MIN(w2.rn) AS rn2, rn2 - w1.rn AS ts_argmin 
FROM windows w1 LEFT JOIN windows w2 ON w1.instrument = w2.instrument AND w1.min_close = w2.close WHERE w1.rn <= w2.rn AND w2.rn < w1.rn + 30 
GROUP BY w1.instrument, w1.date, w1.pre_1, w1.rn, w1.close, w1.adv20, w1.volume
), 
merged_data AS (
SELECT b.instrument, b.date, b.pre_1 - AVG(b.pre_1) OVER (PARTITION BY a.industry_level1_code, a.date) AS indus_pre_1, 
    indus_pre_1 - AVG(indus_pre_1) OVER (PARTITION BY a.industry_level1_code, a.date) AS indus_pre, 
    1.5 * ABS(indus_pre)/SUM(ABS(indus_pre)) OVER (PARTITION BY b.date) AS factor_1, b.close, b.adv20, b.volume, b.ts_argmin 
FROM industry_data a JOIN windows2 b ON a.instrument = b.instrument AND a.date = b.date 
), 
merged_data2 AS (
SELECT instrument, date, factor_1, m_corr(close, pct_rank_by(date, adv20), 5) - pct_rank_by(date, ts_argmin) AS indus_pre_2, volume, adv20 
FROM merged_data
)

SELECT b.instrument, b.date, b.indus_pre_2 - AVG(b.indus_pre_2) OVER (PARTITION BY a.industry_level1_code, a.date) AS indus_pre2, 
    ABS(indus_pre2)/SUM(ABS(indus_pre2)) OVER (PARTITION BY b.date) AS factor_2, 
    0 - ((b.factor_1 - factor_2) * (b.volume/b.adv20)) AS alpha_6100 
FROM industry_data a JOIN merged_data2 b ON a.instrument = b.instrument AND a.date = b.date 
ORDER BY b.date, b.instrument;

3.Alpha101因子分析介绍

在这一部分,我们将展示我们是如何在BigQaunt平台上对Alpha101进行因子分析的。

3.1因子分析流程介绍

首先我们需要读取因子数据,在我们的平台上可直接使用DAI和相关的SQL代码完成此操作。

第二步,我们需要设置因子分析的参数。因为我们需要将股票在每日按照因子值大小分组,这里就需要设置分组的数量,是分三组、五组还是十组。在对Alpha101的分析中,我们默认将股票分成十组,不过有极个别因子由于其因子值是时序排名形式的,无法分成十组,故分成五组或者三组。参数中的投资标的可以理解为选股的范围,在Alpha101分析中,我们默认设置的范围是A股全市场。大家在做因子分析的时候,可以按照自己的需求对选股范围进行调整。参数中的因子方向是指因子值大小与股票收益率是否正相关,如果填“1”则代表所测试的因子与收益率是正相关的,如果填“-1”则代表所测试的因子与收益率是负相关的。此参数的设置与后续因子分析的结果的方向有关。参数中的比较基准就是我们因子分析过程中,计算得到各种收益率的参照物。在此次分析中,我们设置的基准是中证500指数。此外,大家还可以根据自身的需求对因子数据再作进一步的预处理,比如去除st,新股,北交所股票,去除股票停牌期间数据等。

第三步就是因子分析。具体而言,首先我们需要将每日选定范围内的股票按照因子值大小分组,然后分别计算持有各组股票的累计收益率。对于一个好的因子,各组股票的收益率走势应有一个明显的分层现象。此外,我们在测试因子时的逻辑是:如果是一个正相关因子,那么做多因子值最大的组的股票,做空因子值最小的股票;反之,如果是负相关因子,就做多因子值最小的组,做空因子值最大的组。此时第二步中设置的因子方向参数就发挥作用了。除了计算分组收益率,我们还需要计算IC值。在具体计算IC值时,除了每日IC,还要计算近22日IC均值和累计IC并作图。IC值的绝对值越高反映因子值与股票收益率的相关性越高。最后我们按照做多因子值大的股票,做空因子值小的股票的逻辑构建策略,并分别测试多头、空头、多空组合的策略效果,计算上述策略的整体绩效指标和年度绩效指标,进一步观察因子的有效性和趋势,完成因子分析流程。

最后我们将分析结果上传至因子库,在“因子研究”中各因子的'因子看板"页面,供大家参阅。下列即为一个较为完整的因子分析流程的示意图:

\

3.2因子分析示例

在这一部分,我们将以在2.4章节介绍过的Alpha#100为例,给大家展示一个常规的因子分析流程。关于Alpha#100因子的定义,计算方式,SQL语言构建方式,请大家参考正文2.4章节。

对于Alpha#100因子,因子分析参数的设置如下:

params = {'group_num':10, 'factor_field':'alpha_6100', 'instruments':'全市场', 'factor_direction':1, 'benchmark':'中证500', 'data_process':True}

由上述代码可见,在对Alpha#100作因子分析的时候:1. 我们选取的股票范围为全市场;2. 我们将这些股票按照因子值大小分成十组;3. 我们假定该因子与股票收益率正相关;4. 我们选取的比较基准是中证500指数。

该因子的因子分析结果如下所示:


首先从Alpha#100因子的分组累计收益率图可以看出,该因子具有一定的分层能力,因子值极端的股票组收益率与其他组别有明显的区分,但我们也可以看出因子值趋于中间平稳时,其区分性就下降了。(注:ls线=9组-1组;bm为benchmark标的的收益率线)。


其次从IC分析结果来看,Alpha#100与股票收益率相关性较高,蕴含股票收益率信息量较多。最后对该因子的整体绩效指标检测和年度绩效指标检测结果如下:


上述流程详见附录四,链接:https://bigquant.com/wiki/doc/alpha101-alpha101alpha100-w0D05jdy3i


4.总结

在这份报告中,我们再次回归世坤Alpha101因子,分析其背后的逻辑并展示其构建的方法。世坤Alpha101因子是关注刻画交易行为的量价因子,主要关注的是通过交易行为产生的超额收益机会,并希望从中找到与传统价值型因子不同的Alpha来源。显然,由于A股市场的交易行为具有显著的随机性,加上机构投资者的交易效率并不高,以及T+0交易和融资融券卖空交易模型的稀缺,使得短期内交易行为导致的定价无效情况相对常见。国泰君安证券的研究发现,与传统的价值型因子构建的策略相比,交易型Alpha因子的收益潜力更大,稳定性也更优。实证研究结果也表明,世坤的Alpha101的因子体系具有高显著性和低相关性的特点,并对超额收益具有强大的预测能力,这为后续策略构建提供了坚实的基础。

显然,由于量化交易的高度专有性和保密性,世坤Alpha101因子的展示只触及了交易型Alpha空间的冰山一角。不过此次我们再次回到世坤Alpha101因子,构建并为大家提供快速调用方法的目的是想给大家提供一个窥探现代不断发展的量化交易复杂世界的机会,并尽可能地向大家揭示其神秘面纱。量化交易的Alpha是目前可用的交易信号中数量最多的,在股市中,个股持有情况的无数种排列方式都可能在不同频率的时间范围内产生正回报。同时,数据源扩展也存在较大提升空间。世坤Alpha101因子的构建体系主要依赖日频率的价格和交易量信息,但日内的高频数据含有更多重要的预测信息,值得进一步地深入研究。同时,非交易数据信息也包含大量的预测信息,通过整体的进一步构建策略的设计,构建因子的来源和方式有无限种可能,量化交易仍是一片尚待开发的蓝海。


5.如何在BigQuant上调用

在进入BigQaunt主页后,点击因子研究,再点击股票因子库,就可以进入这个页面,最后点选Alpha101因子就可以查看这一系列因子的相关信息了~在这个页面也可以访问其他你感兴趣的因子:

进入Alpha101因子专栏后我们就可以随机点开自己感兴趣的因子了。这里以Alpha#4(编号为Alpha_6004)为例,在因子详情页面我们可以看到该因子近期的表现,而想要在自己的策略中调用该因子我们需要点击因子访问页面,在因子访问页面复制SQL代码:

复制之后,我们编写如下代码访问因子。在访问之前记得先import dai,然后把复制的sql代码粘贴至图中勾选位置即可直接运行,最终得到以date和instrument为索引的股票Alpha#4因子的DataFrame表格。其他的因子也都可以按照此方式进行访问哦。

import dai

sql = """
SELECT date, instrument, 
    -1 * m_rolling_rank(pct_rank_by(date, low),9) as alpha_6004
FROM cn_stock_bar1d 
WHERE date >= '2015-01-05' 
ORDER BY date , instrument; 
"""

df = dai.query(sql).df()
df

附录

附录一:世坤Alpha101因子表达式

Alpha#1: (rank(Ts_ArgMax(SignedPower(((returns < 0) ? stddev(returns, 20) : close), 2.), 5)) - 0.5) 
Alpha#2: (-1 * correlation(rank(delta(log(volume), 2)), rank(((close - open) / open)), 6)) 
Alpha#3: (-1 * correlation(rank(open), rank(volume), 10)) 
Alpha#4: (-1 * Ts_Rank(rank(low), 9)) 
Alpha#5: (rank((open - (sum(vwap, 10) / 10))) * (-1 * abs(rank((close - vwap))))) 
Alpha#6: (-1 * correlation(open, volume, 10)) 
Alpha#7: ((adv20 < volume) ? ((-1 * ts_rank(abs(delta(close, 7)), 60)) * sign(delta(close, 7))) : (-1 * 1)) 
Alpha#8: (-1 * rank(((sum(open, 5) * sum(returns, 5)) - delay((sum(open, 5) * sum(returns, 5)), 10)))) 
Alpha#9: ((0 < ts_min(delta(close, 1), 5)) ? delta(close, 1) : ((ts_max(delta(close, 1), 5) < 0) ? delta(close, 1) : (-1 * delta(close, 1)))) 
Alpha#10: rank(((0 < ts_min(delta(close, 1), 4)) ? delta(close, 1) : ((ts_max(delta(close, 1), 4) < 0) ? delta(close, 1) : (-1 * delta(close, 1))))) 
Alpha#11: ((rank(ts_max((vwap - close), 3)) + rank(ts_min((vwap - close), 3))) * rank(delta(volume, 3))) 
Alpha#12: (sign(delta(volume, 1)) * (-1 * delta(close, 1))) 
Alpha#13: (-1 * rank(covariance(rank(close), rank(volume), 5))) 
Alpha#14: ((-1 * rank(delta(returns, 3))) * correlation(open, volume, 10)) 
Alpha#15: (-1 * sum(rank(correlation(rank(high), rank(volume), 3)), 3)) 
Alpha#16: (-1 * rank(covariance(rank(high), rank(volume), 5))) 
Alpha#17: (((-1 * rank(ts_rank(close, 10))) * rank(delta(delta(close, 1), 1))) * rank(ts_rank((volume / adv20), 5))) 
Alpha#18: (-1 * rank(((stddev(abs((close - open)), 5) + (close - open)) + correlation(close, open, 10)))) 
Alpha#19: ((-1 * sign(((close - delay(close, 7)) + delta(close, 7)))) * (1 + rank((1 + sum(returns, 250))))) 
Alpha#20: (((-1 * rank((open - delay(high, 1)))) * rank((open - delay(close, 1)))) * rank((open - delay(low, 1)))) 
Alpha#21: ((((sum(close, 8) / 8) + stddev(close, 8)) < (sum(close, 2) / 2)) ? (-1 * 1) : (((sum(close, 2) / 2) < ((sum(close, 8) / 8) - stddev(close, 8))) ? 1 : (((1 < (volume / adv20)) || ((volume / adv20) == 1)) ? 1 : (-1 * 1)))) 
Alpha#22: (-1 * (delta(correlation(high, volume, 5), 5) * rank(stddev(close, 20)))) 
Alpha#23: (((sum(high, 20) / 20) < high) ? (-1 * delta(high, 2)) : 0) 
Alpha#24: ((((delta((sum(close, 100) / 100), 100) / delay(close, 100)) < 0.05) || ((delta((sum(close, 100) / 100), 100) / delay(close, 100)) == 0.05)) ? (-1 * (close - ts_min(close, 100))) : (-1 * delta(close, 3))) 
Alpha#25: rank(((((-1 * returns) * adv20) * vwap) * (high - close))) 
Alpha#26: (-1 * ts_max(correlation(ts_rank(volume, 5), ts_rank(high, 5), 5), 3)) 
Alpha#27: ((0.5 < rank((sum(correlation(rank(volume), rank(vwap), 6), 2) / 2.0))) ? (-1 * 1) : 1) 
Alpha#28: scale(((correlation(adv20, low, 5) + ((high + low) / 2)) - close)) 
Alpha#29: (min(product(rank(rank(scale(log(sum(ts_min(rank(rank((-1 * rank(delta((close - 1), 5))))), 2), 1))))), 1), 5) + ts_rank(delay((-1 * returns), 6), 5)) 
Alpha#30: (((1.0 - rank(((sign((close - delay(close, 1))) + sign((delay(close, 1) - delay(close, 2)))) + sign((delay(close, 2) - delay(close, 3)))))) * sum(volume, 5)) / sum(volume, 20)) 
Alpha#31: ((rank(rank(rank(decay_linear((-1 * rank(rank(delta(close, 10)))), 10)))) + rank((-1 * delta(close, 3)))) + sign(scale(correlation(adv20, low, 12)))) 
Alpha#32: (scale(((sum(close, 7) / 7) - close)) + (20 * scale(correlation(vwap, delay(close, 5), 230)))) 
Alpha#33: rank((-1 * ((1 - (open / close))^1))) 
Alpha#34: rank(((1 - rank((stddev(returns, 2) / stddev(returns, 5)))) + (1 - rank(delta(close, 1)))))
Alpha#35: ((Ts_Rank(volume, 32) * (1 - Ts_Rank(((close + high) - low), 16))) * (1 - Ts_Rank(returns, 32))) 
Alpha#36: (((((2.21 * rank(correlation((close - open), delay(volume, 1), 15))) + (0.7 * rank((open - close)))) + (0.73 * rank(Ts_Rank(delay((-1 * returns), 6), 5)))) + rank(abs(correlation(vwap, adv20, 6)))) + (0.6 * rank((((sum(close, 200) / 200) - open) * (close - open))))) 
Alpha#37: (rank(correlation(delay((open - close), 1), close, 200)) + rank((open - close))) 
Alpha#38: ((-1 * rank(Ts_Rank(close, 10))) * rank((close / open))) 
Alpha#39: ((-1 * rank((delta(close, 7) * (1 - rank(decay_linear((volume / adv20), 9)))))) * (1 + rank(sum(returns, 250)))) 
Alpha#40: ((-1 * rank(stddev(high, 10))) * correlation(high, volume, 10)) 
Alpha#41: (((high * low)^0.5) - vwap) 
Alpha#42: (rank((vwap - close)) / rank((vwap + close))) 
Alpha#43: (ts_rank((volume / adv20), 20) * ts_rank((-1 * delta(close, 7)), 8))
Alpha#44: (-1 * correlation(high, rank(volume), 5)) 
Alpha#45: (-1 * ((rank((sum(delay(close, 5), 20) / 20)) * correlation(close, volume, 2)) * rank(correlation(sum(close, 5), sum(close, 20), 2)))) 
Alpha#46: ((0.25 < (((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10))) ? (-1 * 1) : (((((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)) < 0) ? 1 : ((-1 * 1) * (close - delay(close, 1))))) 
Alpha#47: ((((rank((1 / close)) * volume) / adv20) * ((high * rank((high - close))) / (sum(high, 5) / 5))) - rank((vwap - delay(vwap, 5)))) 
Alpha#48: (indneutralize(((correlation(delta(close, 1), delta(delay(close, 1), 1), 250) * delta(close, 1)) / close), IndClass.subindustry) / sum(((delta(close, 1) / delay(close, 1))^2), 250)) 
Alpha#49: (((((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)) < (-1 * 0.1)) ? 1 : ((-1 * 1) * (close - delay(close, 1)))) 
Alpha#50: (-1 * ts_max(rank(correlation(rank(volume), rank(vwap), 5)), 5)) 
Alpha#51: (((((delay(close, 20) - delay(close, 10)) / 10) - ((delay(close, 10) - close) / 10)) < (-1 * 0.05)) ? 1 : ((-1 * 1) * (close - delay(close, 1)))) 
Alpha#52: ((((-1 * ts_min(low, 5)) + delay(ts_min(low, 5), 5)) * rank(((sum(returns, 240) - sum(returns, 20)) / 220))) * ts_rank(volume, 5)) 
Alpha#53: (-1 * delta((((close - low) - (high - close)) / (close - low)), 9)) 
Alpha#54: ((-1 * ((low - close) * (open^5))) / ((low - high) * (close^5))) 
Alpha#55: (-1 * correlation(rank(((close - ts_min(low, 12)) / (ts_max(high, 12) - ts_min(low, 12)))), rank(volume), 6)) 
Alpha#56: (0 - (1 * (rank((sum(returns, 10) / sum(sum(returns, 2), 3))) * rank((returns * cap))))) 
Alpha#57: (0 - (1 * ((close - vwap) / decay_linear(rank(ts_argmax(close, 30)), 2)))) 
Alpha#58: (-1 * Ts_Rank(decay_linear(correlation(IndNeutralize(vwap, IndClass.sector), volume, 3.92795), 7.89291), 5.50322)) 
Alpha#59: (-1 * Ts_Rank(decay_linear(correlation(IndNeutralize(((vwap * 0.728317) + (vwap * (1 - 0.728317))), IndClass.industry), volume, 4.25197), 16.2289), 8.19648)) 
Alpha#60: (0 - (1 * ((2 * scale(rank(((((close - low) - (high - close)) / (high - low)) * volume)))) - scale(rank(ts_argmax(close, 10))))))
Alpha#61: (rank((vwap - ts_min(vwap, 16.1219))) < rank(correlation(vwap, adv180, 17.9282))) 
Alpha#62: ((rank(correlation(vwap, sum(adv20, 22.4101), 9.91009)) < rank(((rank(open) + rank(open)) < (rank(((high + low) / 2)) + rank(high))))) * -1) 
Alpha#63: ((rank(decay_linear(delta(IndNeutralize(close, IndClass.industry), 2.25164), 8.22237)) - rank(decay_linear(correlation(((vwap * 0.318108) + (open * (1 - 0.318108))), sum(adv180, 37.2467), 13.557), 12.2883))) * -1) 
Alpha#64: ((rank(correlation(sum(((open * 0.178404) + (low * (1 - 0.178404))), 12.7054), sum(adv120, 12.7054), 16.6208)) < rank(delta(((((high + low) / 2) * 0.178404) + (vwap * (1 - 0.178404))), 3.69741))) * -1) 
Alpha#65: ((rank(correlation(((open * 0.00817205) + (vwap * (1 - 0.00817205))), sum(adv60, 8.6911), 6.40374)) < rank((open - ts_min(open, 13.635)))) * -1) 
Alpha#66: ((rank(decay_linear(delta(vwap, 3.51013), 7.23052)) + Ts_Rank(decay_linear(((((low * 0.96633) + (low * (1 - 0.96633))) - vwap) / (open - ((high + low) / 2))), 11.4157), 6.72611)) * -1) 
Alpha#67: ((rank((high - ts_min(high, 2.14593)))^rank(correlation(IndNeutralize(vwap, IndClass.sector), IndNeutralize(adv20, IndClass.subindustry), 6.02936))) * -1) 
Alpha#68: ((Ts_Rank(correlation(rank(high), rank(adv15), 8.91644), 13.9333) < rank(delta(((close * 0.518371) + (low * (1 - 0.518371))), 1.06157))) * -1) 
Alpha#69: ((rank(ts_max(delta(IndNeutralize(vwap, IndClass.industry), 2.72412), 4.79344))^Ts_Rank(correlation(((close * 0.490655) + (vwap * (1 - 0.490655))), adv20, 4.92416), 9.0615)) * -1) 
Alpha#70: ((rank(delta(vwap, 1.29456))^Ts_Rank(correlation(IndNeutralize(close, IndClass.industry), adv50, 17.8256), 17.9171)) * -1) 
Alpha#71: max(Ts_Rank(decay_linear(correlation(Ts_Rank(close, 3.43976), Ts_Rank(adv180, 12.0647), 18.0175), 4.20501), 15.6948), Ts_Rank(decay_linear((rank(((low + open) - (vwap + vwap)))^2), 16.4662), 4.4388)) 
Alpha#72: (rank(decay_linear(correlation(((high + low) / 2), adv40, 8.93345), 10.1519)) / rank(decay_linear(correlation(Ts_Rank(vwap, 3.72469), Ts_Rank(volume, 18.5188), 6.86671), 2.95011))) 
Alpha#73: (max(rank(decay_linear(delta(vwap, 4.72775), 2.91864)), Ts_Rank(decay_linear(((delta(((open * 0.147155) + (low * (1 - 0.147155))), 2.03608) / ((open * 0.147155) + (low * (1 - 0.147155)))) * -1), 3.33829), 16.7411)) * -1) 
Alpha#74: ((rank(correlation(close, sum(adv30, 37.4843), 15.1365)) < rank(correlation(rank(((high * 0.0261661) + (vwap * (1 - 0.0261661)))), rank(volume), 11.4791))) * -1) 
Alpha#75: (rank(correlation(vwap, volume, 4.24304)) < rank(correlation(rank(low), rank(adv50), 12.4413))) 
Alpha#76: (max(rank(decay_linear(delta(vwap, 1.24383), 11.8259)), Ts_Rank(decay_linear(Ts_Rank(correlation(IndNeutralize(low, IndClass.sector), adv81, 8.14941), 19.569), 17.1543), 19.383)) * -1) 
Alpha#77: min(rank(decay_linear(((((high + low) / 2) + high) - (vwap + high)), 20.0451)), rank(decay_linear(correlation(((high + low) / 2), adv40, 3.1614), 5.64125))) 
Alpha#78: (rank(correlation(sum(((low * 0.352233) + (vwap * (1 - 0.352233))), 19.7428), sum(adv40, 19.7428), 6.83313))^rank(correlation(rank(vwap), rank(volume), 5.77492))) 
Alpha#79: (rank(delta(IndNeutralize(((close * 0.60733) + (open * (1 - 0.60733))), IndClass.sector), 1.23438)) < rank(correlation(Ts_Rank(vwap, 3.60973), Ts_Rank(adv150, 9.18637), 14.6644))) 
Alpha#80: ((rank(Sign(delta(IndNeutralize(((open * 0.868128) + (high * (1 - 0.868128))), IndClass.industry), 4.04545)))^Ts_Rank(correlation(high, adv10, 5.11456), 5.53756)) * -1) 
Alpha#81: ((rank(Log(product(rank((rank(correlation(vwap, sum(adv10, 49.6054), 8.47743))^4)), 14.9655))) < rank(correlation(rank(vwap), rank(volume), 5.07914))) * -1) 
Alpha#82: (min(rank(decay_linear(delta(open, 1.46063), 14.8717)), Ts_Rank(decay_linear(correlation(IndNeutralize(volume, IndClass.sector), ((open * 0.634196) + (open * (1 - 0.634196))), 17.4842), 6.92131), 13.4283)) * -1) 
Alpha#83: ((rank(delay(((high - low) / (sum(close, 5) / 5)), 2)) * rank(rank(volume))) / (((high - low) / (sum(close, 5) / 5)) / (vwap - close))) 
Alpha#84: SignedPower(Ts_Rank((vwap - ts_max(vwap, 15.3217)), 20.7127), delta(close, 4.96796)) 
Alpha#85: (rank(correlation(((high * 0.876703) + (close * (1 - 0.876703))), adv30, 9.61331))^rank(correlation(Ts_Rank(((high + low) / 2), 3.70596), Ts_Rank(volume, 10.1595), 7.11408))) 
Alpha#86: ((Ts_Rank(correlation(close, sum(adv20, 14.7444), 6.00049), 20.4195) < rank(((open + close) - (vwap + open)))) * -1) 
Alpha#87: (max(rank(decay_linear(delta(((close * 0.369701) + (vwap * (1 - 0.369701))), 1.91233), 2.65461)), Ts_Rank(decay_linear(abs(correlation(IndNeutralize(adv81, IndClass.industry), close, 13.4132)), 4.89768), 14.4535)) * -1) 
Alpha#88: min(rank(decay_linear(((rank(open) + rank(low)) - (rank(high) + rank(close))), 8.06882)), Ts_Rank(decay_linear(correlation(Ts_Rank(close, 8.44728), Ts_Rank(adv60, 20.6966), 8.01266), 6.65053), 2.61957)) 
Alpha#89: (Ts_Rank(decay_linear(correlation(((low * 0.967285) + (low * (1 - 0.967285))), adv10, 6.94279), 5.51607), 3.79744) - Ts_Rank(decay_linear(delta(IndNeutralize(vwap, IndClass.industry), 3.48158), 10.1466), 15.3012)) 
Alpha#90: ((rank((close - ts_max(close, 4.66719)))^Ts_Rank(correlation(IndNeutralize(adv40, IndClass.subindustry), low, 5.38375), 3.21856)) * -1) 
Alpha#91: ((Ts_Rank(decay_linear(decay_linear(correlation(IndNeutralize(close, IndClass.industry), volume, 9.74928), 16.398), 3.83219), 4.8667) - rank(decay_linear(correlation(vwap, adv30, 4.01303), 2.6809))) * -1) 
Alpha#92: min(Ts_Rank(decay_linear(((((high + low) / 2) + close) < (low + open)), 14.7221), 18.8683), Ts_Rank(decay_linear(correlation(rank(low), rank(adv30), 7.58555), 6.94024), 6.80584)) 
Alpha#93: (Ts_Rank(decay_linear(correlation(IndNeutralize(vwap, IndClass.industry), adv81, 17.4193), 19.848), 7.54455) / rank(decay_linear(delta(((close * 0.524434) + (vwap * (1 - 0.524434))), 2.77377), 16.2664))) 
Alpha#94: ((rank((vwap - ts_min(vwap, 11.5783)))^Ts_Rank(correlation(Ts_Rank(vwap, 19.6462), Ts_Rank(adv60, 4.02992), 18.0926), 2.70756)) * -1) 
Alpha#95: (rank((open - ts_min(open, 12.4105))) < Ts_Rank((rank(correlation(sum(((high + low) / 2), 19.1351), sum(adv40, 19.1351), 12.8742))^5), 11.7584)) 
Alpha#96: (max(Ts_Rank(decay_linear(correlation(rank(vwap), rank(volume), 3.83878), 4.16783), 8.38151), Ts_Rank(decay_linear(Ts_ArgMax(correlation(Ts_Rank(close, 7.45404), Ts_Rank(adv60, 4.13242), 3.65459), 12.6556), 14.0365), 13.4143)) * -1) 
Alpha#97: ((rank(decay_linear(delta(IndNeutralize(((low * 0.721001) + (vwap * (1 - 0.721001))), IndClass.industry), 3.3705), 20.4523)) - Ts_Rank(decay_linear(Ts_Rank(correlation(Ts_Rank(low, 7.87871), Ts_Rank(adv60, 17.255), 4.97547), 18.5925), 15.7152), 6.71659)) * -1) 
Alpha#98: (rank(decay_linear(correlation(vwap, sum(adv5, 26.4719), 4.58418), 7.18088)) - rank(decay_linear(Ts_Rank(Ts_ArgMin(correlation(rank(open), rank(adv15), 20.8187), 8.62571), 6.95668), 8.07206))) 
Alpha#99: ((rank(correlation(sum(((high + low) / 2), 19.8975), sum(adv60, 19.8975), 8.8136)) < rank(correlation(low, volume, 6.28259))) * -1) 
Alpha#100: (0 - (1 * (((1.5 * scale(indneutralize(indneutralize(rank(((((close - low) - (high - close)) / (high - low)) * volume)), IndClass.subindustry), IndClass.subindustry))) - scale(indneutralize((correlation(close, rank(adv20), 5) - rank(ts_argmin(close, 30))), IndClass.subindustry))) * (volume / adv20)))) 
Alpha#101: ((close - open) / ((high - low) + .001)) 

附录二:因子表达式中各符号所代表的意义

函数及运算符定义:
(Below “{ }” stands for a placeholder. All expressions are case insensitive.) 
abs(x), log(x), sign(x) = standard definitions; same for the operators “+”, “-”, “*”, “/”, “>”, “<”, “==”, “||”, “x ? y : z”
rank(x) = cross-sectional rank 
delay(x, d) = value of x d days ago 
correlation(x, y, d) = time-serial correlation of x and y for the past d days 
covariance(x, y, d) = time-serial covariance of x and y for the past d days 
scale(x, a) = rescaled x such that sum(abs(x)) = a (the default is a = 1) 
delta(x, d) = today’s value of x minus the value of x d days ago 
signedpower(x, a) = x^a 
decay_linear(x, d) = weighted moving average over the past d days with linearly decaying weights d, d – 1, …, 1 (rescaled to sum up to 1) 
indneutralize(x, g) = x cross-sectionally neutralized against groups g (subindustries, industries, sectors, etc.), i.e., x is cross-sectionally demeaned within each group g 
ts_{O}(x, d) = operator O applied across the time-series for the past d days; non-integer number of days d is converted to floor(d) 
ts_min(x, d) = time-series min over the past d days 
ts_max(x, d) = time-series max over the past d days 
ts_argmax(x, d) = which day ts_max(x, d) occurred on 
ts_argmin(x, d) = which day ts_min(x, d) occurred on 
ts_rank(x, d) = time-series rank in the past d days 
min(x, d) = ts_min(x, d) 
max(x, d) = ts_max(x, d) 
sum(x, d) = time-series sum over the past d days
product(x, d) = time-series product over the past d days
stddev(x, d) = moving time-series standard deviation over the past d days 

输入数据定义:
returns = daily close-to-close returns 
open, close, high, low, volume = standard definitions for daily price and volume data 
vwap = daily volume-weighted average price 
cap = market cap 
adv{d} = average daily dollar volume for the past d days 
IndClass = a generic placeholder for a binary industry classification such as GICS, BICS, NAICS, SIC, etc., in indneutralize(x, IndClass.level), where level = sector, industry, subindustry, etc. 
Multiple IndClass in the same alpha need not correspond to the same industry classification. 

\

标签

Alpha交易
评论
  • 访问因子的代码在哪里?没有看到啊
  • 抱歉,现在我们放上去了哈
{link}