worldquant 101alpha是怎么得到的

2024-05-03 16:39

1. worldquant 101alpha是怎么得到的

可分为横截面函数和时间序列函数两大类,其中时间序列函数名多为以ts_开头
大部分函数命名方式较为直观
abs(x) log(x)分别表示x的绝对值和x的自然对数
rank(x)表示某股票x值在横截面上的升序排名序号,并将排名归一到[0,1]的闭区间
delay(x,d)表示x值在d天前的值
delta(x,d)表示x值的最新值减去x值在d天前的值
correlation(x,y,d) covariance(x,y,d)分别表示x和y在长度为d的时间窗口上的Pearson相关系数和协方差
ts_min(x,d) ts_max(x,d) ts_argmax(x,d) ts_argmin(x,d) ts_rank(x) sum(x,d) stddev(x,d)等均可以通过函数名称了!

worldquant 101alpha是怎么得到的

2. worldquant 101alpha是怎么得到的

world quant 101alpha 
世界101alpha quant
重点词汇释义
quant篙; 用篙撑

3. worldquant 101alpha是怎么得到的

nior executives championing the effo

worldquant 101alpha是怎么得到的

4. worldquant 101alpha是怎么得到的

一般会有world quant challenge比赛,找一堆学生等在上面做数据挖掘找alpha,然后模拟比赛阶段会有排名。
在这个平台上就会有来自全世界的人来做alpha,结果比较好的就会被留下存在alpha库里供pm用。一些不那么好的就被公开成了101 alpha

5. worldquant 101alpha是怎么得到的

worldquant101alpha世界上数量101

worldquant 101alpha是怎么得到的

6. 如何用Quartz Signal快速实现Worldquant 101 Alpha

优矿的500万实盘在如火如荼地进行中,我们已经看到有矿友利用经典的机器学习算法和新的Quartz Signal模块对于优矿上现有因子的利用进行探索,但是对于大多数信号/因子研究者来说,寻找新的Alpha依然是其孜孜以求的目标。
如何去寻找新的Alpha因子的灵感成为摆在量化研究者面前无法回避的问题。
我们注意到,Zura Kakushadze 等人最新发表的论文101 Formulaic Alpha(…) 里提到了很多基于价量数据构建的"Alpha"因子,为我们提供了很多新的灵感。
本文将先简单介绍论文中提到的Alpha因子表达式语法以及含义,之后会介绍如何用Quartz Signal便捷地实现这些Alpha,最后会提供2个在论文中出现并且效果不错的Alpha因子供大家参考。

Formulaic Alpha简介
研读过上文提到的论文,我们发现,论文中提到的Formulaic Alpha就是用一个表达式来表示一个Alpha因子:
· 写出的表达式是在每一个调仓日对每一支按照该表达式进行计算
· 例如:1/close; 对universe中每一支,计算1/closePrice,然后此向量被标准化,即除以其数值的总和(所有数值相加的结果为 1)。这将为所有创建了一个基于“权重”的向量,每个权重代表投资组合中投资于该的资金比例
· 其支持的数据有:open(开盘价)/close(收盘价)/high(最高价)/low(最低价)/vwap(日内交易量加权价格)/returns(单日收益率)等等
我们认为这种Formulaic Alpha的表达形式有以下特点:
· 表达简洁,但隐藏了太多细节,用户无法看到具体的调仓信息
· 受限于表达式表达能力的不足,提供了丰富的内置函数,帮助用户完成了cross-sectional信息的处理
内置函数
· 可分为横截面函数和时间序列函数两大类,其中时间序列函数名多为以ts_开头
· 大部分函数命名方式较为直观
· abs(x) log(x)分别表示x的绝对值和x的自然对数
· rank(x)表示某x值在横截面上的升序排名序号,并将排名归一到[0,1]的闭区间
· delay(x,d)表示x值在d天前的值
· delta(x,d)表示x值的最新值减去x值在d天前的值
· correlation(x,y,d) covariance(x,y,d)分别表示x和y在长度为d的时间窗口上的Pearson相关系数和协方差
· ts_min(x,d) ts_max(x,d) ts_argmax(x,d) ts_argmin(x,d) ts_rank(x) sum(x,d) stddev(x,d)等均可以通过函数名称了解其作用
· 更多地函数解释可以参考论文的附录

Quartz Signal模块简介
正如API帮助文档中提到的,Signal模块是优矿为方便因子/信号研究者提供的工具,将用户从与信号研究无关的数据获取、下单逻辑中抽离出来,用户可以将精力集中于按照自己的思路开发新的信号。
使用Signal自定义信号的通用实现过程如下:
def foo(data, dependencies=['PE&# 39;], max_window=4):
    return data['PE&# 39;].mean()
# in initialize(account)
a = Signal("signal_a", foo)
account.signal_generator = SignalGenerator(a)
#  in handle_data(account)
account.signal_result['signal_a'] 

我们可以将Quartz Signal的使用过程分为四个步骤:
定义实现信号逻辑的函数(在上例中即为foo函数)
在initialize函数中定义Signal,在实例化Signal类时将信号名字和描述函数作为参数传入
在initialize函数中将需要使用的信号注册到account.signal_generator中,可以注册多个信号
在handle_data中通过account.signal_result获取计算好的信号值

我们重点介绍一下用户需要完成的信号描述函数:
信号描述函数实际上是用户在每一个调仓日对于可以获得数据的处理逻辑
信号描述函数名可以按照Python函数的命名规范任意定义,但其参数必须为一个非关键字参数data,两个关键字参数dependencies和max_window
dependencies的参数格式必须为str构成的list,list的元素为该函数中需要使用的因子名称,具体支持因子列表参考帮助文档
max_window的参数格式为int,表示用户希望用到过去max_window天的因子数据
data则是根据dependencies和max_window,Quartz Signal模块帮助用户取到的数据,其格式为一个dict,key为因子名称,value为max_window*universe_length的Pandas DataFrame
信号描述函数的返回值必须为一个长度与data中每一元素列数相同的Pandas Series
如下图所示:

上图描述的就是data的结构,其中data只有一个元素,其key为"PE",value就是上图表格所示的Pandas DataFrame,具体地,其columns为universe的secID,其index为%Y%m%d格式的日期字符串

Quartz Signal v.s. Formulaic Alpha
由上述描述可见,使用Quartz Signal模块可以便捷地实现Formulaic Alpha,同时相比Formulaic Alpha表达式有以下优势:
更加直观:
    o用户在预先定义信号描述函数时,就可以明晰地定义自己需要的因子数据和时间窗口
    o用户可以在Quartz框架中灵活定义自己的调仓频率和下单逻辑,并可以直观地看到每次调仓的列表
更加灵活:
    oFormulaic Alpha限制了表达式的计算结果必须代表相应在投资组合中的权重,而Quartz Signal并没有此限制,用户可以在handle_data中按照自己的想法任意处理信号值
    o信号描述函数的data是以Pandas DataFrame的格式传入的,这样用户就可以在函数中同时看到横截面数据和时间序列数据,为用户提供了更多可能
更加强大:信号描述函数的data是以Pandas DataFrame的格式传入的,Pandas丰富的内置函数可以帮助我们完成较复杂Formulaic Alpha表达式才能完成的任务(见最后一个示例)
更多数据:Quartz Signal不仅支持openPrice/closePrice/highPrice/lowPrice/turnoverVol等价量信息,还支持PE、RSI等更丰富的因子
下面我们就用Quartz Signal模块实现了一个论文中提到的Formulaic Alpha:

用Quartz Signal实现一个Formulaic Alpha
以WebSim论文中alpha 53为例,其原始表达式为:
(−1∗delta((((close−low)−(high−close))/(close−low)),9))
化简可得,((close - low) - (high - close)) / (close - low)的9日之前值-当前值 
继续化简可得:(2∗close−low−high)/(close−low)

我们深入研究该因子可以发现:
(2∗close−low−high)/(close−low)=1−(high−close)/(close−low)
前面的常数1可以通过delta消掉,其实可以简化为(high−close)/(close−low)的现值-9天之前的值
而(high−close)/(close−low)本身则代表了收盘价在日内波动中的位置,可以看做是买入意愿的一种体现

我们强烈建议大家在实现这些Formulaic Alpha因子之前先花一些精力去理解其经济含义,不仅可以加深对其原理的理解,在某些时候还可以简化实现。
我们以论文中的Alpha 26为例,其原始表达式为:
−1∗ts_max(correlation(ts_rank(volume,5),ts_rank(high,5),5),3)
我们当然可以按照其原始表达式一步步地先对过去5天的成交量和最高价进行排名,再取相关系数;但是较熟悉Pandas DataFrame内置函数或者统计知识较丰富的研究者可以发现,correlation(ts_rank(volume,5),ts_rank(high,5),5) 其实就是在计算Spearman Rank Correlation Coefficient,使用DataFrame内置的corr(method="spearman")函数就可以完成计算,可以大大提高开发效率。

在我们的模拟的过程中发现,如果按照原公式进行计算,无论是long还是short的结果都跑不赢大盘,同时对于成交量和最高价相关性较高的将会是市场追逐的热点,应该分配更大的权重。
所以在上述代码中我们将原Formulaic Alpha前面的负号去掉。

当然,对于论文中出现的某些因子可能较难于理解其经济学意义,我们鼓励大家用Quartz Signal将其实现之后发到社区上与大家一起讨论。
对于Quartz Signal模块有哪些不尽如人意的地方也可以反馈给我们,帮助我们持续改进。

7. worldquant 101alpha是怎么得到的

world quant 101 alpha
世界上数量101

worldquant 101alpha是怎么得到的

8. 如何用优矿Quartz Signal快速实现Worldquant 101 Alpha

import numpy as npstart = '2012-01-01'                       # 回测起始时间end = '2016-01-01'                         # 回测结束时间benchmark = 'HS300'                        # 策略参考标准universe = set_universe("HS300", end)  # 证券池,支持股票和基金capital_base = 100000                      # 起始资金freq = 'd'                                 # 策略类型,'d'表示日间策略使用日线回测,'m'表示日内策略使用分钟线回测refresh_rate = 5                           # 调仓频率,表示执行handle_data的时间间隔,若freq = 'd'时间间隔的单位为交易日,若freq = 'm'时间间隔为分钟def foo(data, dependencies=['closePrice', 'highPrice', 'lowPrice'], max_window=9):    today = (2*data['closePrice'].ix[-1]-data['lowPrice'].ix[-1]-data['highPrice'].ix[-1])/(data['closePrice'].ix[-1]-data['lowPrice'].ix[-1])    day_9 = (2*data['closePrice'].ix[-9]-data['lowPrice'].ix[-9]-data['highPrice'].ix[-9])/(data['closePrice'].ix[-9]-data['lowPrice'].ix[-9])    return day_9 - today    def initialize(account):                   # 初始化虚拟账户状态    a = Signal("worldquant_53", foo)    account.signal_generator = SignalGenerator(a)    def handle_data(account):                  # 每个交易日的买入卖出指令    weight = account.signal_result['worldquant_53']    weight = weight[weight>0]    weight = weight.replace([np.inf, -np.inf], np.nan).dropna()    weight = weight/weight.sum()        buy_list = weight.index    sell_list = account.valid_secpos    for stk in sell_list:        if stk not in buy_list:            order_to(stk, 0)            total_money = account.referencePortfolioValue    prices = account.referencePrice     for stk in buy_list:        if stk not in prices:            continue        if np.isnan(prices[stk]) or prices[stk] == 0:  # 停牌或是还没有上市等原因不能交易            continue        order_num = int(total_money * weight[stk] / prices[stk] /100)*100        if order_num < 100:            order_num = 100        order_to(stk, order_num)