多因子模型之因子(信号)测试平台----因子值的处理(二)

来源:互联网 发布:demo设计软件 编辑:程序博客网 时间:2024/05/22 15:09

        我们知道,一个因子值的处理大致分为三个步骤,去极值、标准化、中性化,上次我们对因子值进行了去极值和标准化,这一次,我们主要讲一讲中性化,也就是neut。

        neut分为行业中性和风格中性两种。行业中性很好理解,我们知道,一个因子在不同的行业间不一定有可比性。譬如资产权益比,也就是杠杆率。显然,有的行业杠杆率很高,比如房地产行业,而有的行业则杠杆率不高,比如传统机械制造行业。再比如PB,有的轻资产行业PB很高,比如软件,而有的行业PB很低,比如煤炭。所以,很多因子数值在一个行业内比较才是有效的。同样的思路,有些因子虽然看起来不是一些基本的风格因子,比如PE,但是,其实我们知道,PE和市值有很大的关系,大市值的公司,一般是成熟的公司,PE往往不高。所以,我们需要把PE中的市值部分去掉。

1.两种中性的方法

        所谓中性,最本质的意义就是“无关”,我们说市场中性,就是说我们这个组合与市场无关;我们说因子做了行业中性,说明我们的因子和行业没有关系,风格中性也是如此。这里的风格一般包括barra中的十个风格因子。

        中性有两种方法,第一种仅仅可以做行业中性。也就是我们对股票进行行业的分类,然后在每个行业内在进行一次标准化。这种中性法可以用于行业中性,而不能用于风格中性。

        第二种方法既可以用于行业中性,也可以用于风格中性,叫做残差法。也就是做一个回归,其中,因子值是y,需要中性的风格因子的暴露为x,然后我们进行回归。回归之后的残差就是因子值对行业中性化后的值。这里的风格因子可以是一个也可以多个,也就是一元回归和多元回归的区别。

2.行业中性化

        由于分风格因子通常会购买barra的数据服务,所以,这里我们只进行行业中性。

        首先,我们需要获得行业数据,也就是每个股票行业的类别。如果读者有wind的python的api,那么可以使用下面的函数获得我们需要的股票代码和行业代码转换的字典。这里,我们有一个假设,就是股票的行业在整个因子回测区间没有改变。

def ind_dict_get():    from WindPy import w    w.start()    univers = ['000156.SZ.csv', '000157.SZ.csv', '000166.SZ.csv', '000333.SZ.csv',               '000338.SZ.csv', '000402.SZ.csv', '000413.SZ.csv', '000415.SZ.csv',               '000423.SZ.csv', '000425.SZ.csv', '000503.SZ.csv', '000538.SZ.csv',               '000540.SZ.csv', '000555.SZ.csv', '000559.SZ.csv', '000568.SZ.csv',               '000623.SZ.csv', '000625.SZ.csv', '000627.SZ.csv', '000630.SZ.csv',               '000651.SZ.csv', '000671.SZ.csv', '000686.SZ.csv', '000709.SZ.csv',               '000712.SZ.csv', '000718.SZ.csv', '000725.SZ.csv', '000728.SZ.csv',               '000738.SZ.csv', '000750.SZ.csv', '000768.SZ.csv', '000776.SZ.csv',               '000778.SZ.csv', '000783.SZ.csv', '000792.SZ.csv', '000793.SZ.csv',               '000800.SZ.csv', '000826.SZ.csv', '000839.SZ.csv', '000858.SZ.csv',               '000876.SZ.csv', '000895.SZ.csv', '000917.SZ.csv', '000938.SZ.csv',               '000963.SZ.csv', '000977.SZ.csv', '000983.SZ.csv', '001979.SZ.csv',               '002007.SZ.csv', '002008.SZ.csv']    ticker_list = [ticker[:-4] for ticker in univers]    ind_category = w.wsd(','.join(ticker_list), "industry_swcode", "2017-07-27", "2017-07-27", "industryType=1")    return {k: v for (k, v) in zip(ind_category.Codes, ind_category.Data[0])}
        如果没有wind的python的api接口,那么可以从下面的代码中复制,然后读者可以自己运行。

import pandas as pdind_dict = { u'000156.SZ': u'6122010000000000',             u'000157.SZ': u'6107000000000000',             u'000166.SZ': u'1000012613000000',             u'000333.SZ': u'6111000000000000',             u'000338.SZ': u'1000012588000000',             u'000402.SZ': u'6118000000000000',             u'000413.SZ': u'6108000000000000',             u'000415.SZ': u'1000012613000000',             u'000423.SZ': u'6115000000000000',             u'000425.SZ': u'6107000000000000',             u'000503.SZ': u'6115000000000000',             u'000538.SZ': u'6115000000000000',             u'000540.SZ': u'6118000000000000',             u'000555.SZ': u'1000012601000000',             u'000559.SZ': u'1000012588000000',             u'000568.SZ': u'6112000000000000',             u'000623.SZ': u'6115000000000000',             u'000625.SZ': u'1000012588000000',             u'000627.SZ': u'1000012613000000',             u'000630.SZ': u'6105000000000000',             u'000651.SZ': u'6111000000000000',             u'000671.SZ': u'6118000000000000',             u'000686.SZ': u'1000012613000000',             u'000709.SZ': u'6104000000000000',             u'000712.SZ': u'1000012613000000',             u'000718.SZ': u'6118000000000000',             u'000725.SZ': u'6108000000000000',             u'000728.SZ': u'1000012613000000',             u'000738.SZ': u'1000012579000000',             u'000750.SZ': u'1000012613000000',             u'000768.SZ': u'1000012579000000',             u'000776.SZ': u'1000012613000000',             u'000778.SZ': u'6104000000000000',             u'000783.SZ': u'1000012613000000',             u'000792.SZ': u'6103000000000000',             u'000793.SZ': u'6122010000000000',             u'000800.SZ': u'1000012588000000',             u'000826.SZ': u'6116000000000000',             u'000839.SZ': u'6123000000000000',             u'000858.SZ': u'6112000000000000',             u'000876.SZ': u'6101000000000000',             u'000895.SZ': u'6112000000000000',             u'000917.SZ': u'6122010000000000',             u'000938.SZ': u'1000012601000000',             u'000963.SZ': u'6115000000000000',             u'000977.SZ': u'1000012601000000',             u'000983.SZ': u'6102000000000000',             u'001979.SZ': u'6118000000000000',             u'002007.SZ': u'6115000000000000',             u'002008.SZ': u'6108000000000000'}def standardize_series(se):    se_std = se.std()    se_mean = se.mean()    return (se - se_mean)/se_stdtotal_data = pd.read_csv('total_data.csv', index_col=0)total_data['group'] = total_data['sec_id'].apply(lambda x: ind_dict[x])total_data['neuted_score'] = total_data.groupby(['date', 'group'])['z-score'].apply(standardize_series)total_data.to_csv('total_data.csv')
        这个时候,我们再打开total_data.csv中,就可以看到又多了一列neuted_score,如此,我们的行业中性也就结束了。

       目前,我们暂时只进行行业中性,然后进行因子的回测。







阅读全文
0 0
原创粉丝点击