繁簡切換您正在訪問的是FX168財經網,本網站所提供的內容及信息均遵守中華人民共和國香港特別行政區當地法律法規。

FX168财经网>人物频道>帖子

【笔记】单因子有效性分析(二):行业市值中性化

作者/uudfhshhf 2019-05-10 07:10 0 来源: FX168财经网人物频道

在第一篇中介绍了数据处理的各种方法,接下来到了一个很关键的地方,其实它也属于数据处理的一部分,但是由于我觉得他比较重要,所以单独拎出来说一下。

行业中性化分为以下几个步骤
1、为什么要做行业中性化
2、如何做行业市值中性化

1、为什么要做行业中性化

众所周知,行业和市值是两个十分显著对因子有影响力的因素。在进行截面回归判断每个单因子的收益情况和显著性时,需要特别关注这两个十分显著的因素。
我们做因子分析是为了挑选出有效因子,并对其值进行排序,按顺序或者倒叙来选择股票,但如果不剔除行业或者市值的影响,可能会导致选出的股票集中在某个行业或者是某种市值范围内,从而导致并不能很有效的分散风险,所以我们需要看的是在剔除了这两个因素之外,因子值的有效性。在这里我用聚宽上的因子做一个例子。
选取‘hs300_alpha’因子为例,股票范围选取沪深300指数成分股,行业分类标准选取申万一级行业分类。
echarts.png
从图中我们可以看出“综合”这个行业的因子值显著高于其他行业,这对我们进行因子分析是不利的。加下来就会介绍剔除行业和市值影响的行业市值中性化处理。

2、如何做行业市值中性化

我们通过建立回归方程来剔除行业和市值的影响,我们把想要剔除的因子暴露(如市值)作为X值,而Y值就是因子值本身,通过回归我们想要得到不能被X也就是该因素所解释的部分----残差值。
我们想要得到市值是十分容易的,但是行业要如何剔除呢。我们建立一个矩阵,就是如果股票属于某个行业,则该股票在该行业的因子暴露(因子值)等于1,在其他行业的因子暴露为0.这样就可以得到行业的哑变量矩阵,再通过回归得到残差值,就是我们想要得到的剔除行业中性化的值。
代码:见研究

from jqfactor import Factor, calc_factors
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
import statsmodels.api as sm
stock = get_index_stocks('000300.XSHG')

class Hs300Alpha(Factor):
    # 设置因子名称
    name = 'hs300_alpha'
    # 设置获取数据的时间窗口长度
    max_window = 10
    # 设置依赖的数据
    dependencies = ['close']

    # 计算因子的函数, 需要返回一个 pandas.Series, index 是股票代码,value 是因子值
    def calc(self, data):
        # 获取个股的收盘价数据
        close = data['close']
        # 计算个股近10日收益
        stock_return = close.iloc[-1,:]/close.iloc[0,:] -1
        # 获取指数(沪深300)的收盘价数据
        index_close = self._get_extra_data(securities=['000300.XSHG'], fields=['close'])['close']
        # 计算指数的近10日收益
        index_return = index_close.iat[-1,0]/index_close.iat[0,0] - 1
        # 计算 alpha
        alpha = stock_return - index_return
        return alpha
factors = calc_factors(stock, [Hs300Alpha()], start_date='2017-01-01', end_date='2017-12-31')
/opt/conda/envs/python3new/lib/python3.6/site-packages/statsmodels/compat/pandas.py:56: FutureWarning: The pandas.core.datetools module is deprecated and will be removed in a future version. Please use the pandas.tseries module instead.
  from pandas.core import datetools
data=factors['hs300_alpha']
from jqdata import *
sw=get_industries(name='sw_l1').index
a=[0]*len(sw)
for i in range(len(sw)):
    a[i]=data[list(set(data.columns).intersection(set(get_industry_stocks(sw[i]))))].mean().mean()
from pyecharts import Bar
from pyecharts import online
online()
bar = Bar()
names=["农林牧渔","采掘","化工","钢铁",'有色金属','电子','家用电器','食品饮料','纺织服装','轻工制造',
'医药生物','公用事业','交通运输','房地产','商业贸易','休闲服务','综合','建筑材料','建筑装饰','电气设备',
'国防军工','计算机','传媒I','通信','银行','非银金融','汽车','机械设备']
bar.add("各行业因子值均值", names, a,
        is_more_utils=True)
bar
#获得行业哑变量矩阵
from jqdata import *
sw=get_industries(name='sw_l1').index
industry=pd.DataFrame(0,columns=data.columns,index=range(0,28))
for i in range(len(sw)):
    temp=list(set(data.columns).intersection(set(get_industry_stocks(sw[i]))))
    industry.loc[i,temp]=1

#去除市值、行业因素,得到新的因子值 
newx=pd.DataFrame()
for i in range(len(data.index)):
    m= get_fundamentals(query(valuation.circulating_cap,valuation.code).filter(valuation.code.in_(data.columns)), date=data.index[i])
    m.index=np.array(m['code'])
    m=m.iloc[:,0]
    m=(m-mean(m))/std(m)
    x=data.iloc[i,:]
    conc=pd.concat([x,m,industry.T],axis=1).fillna(mean(m))
    est=sm.OLS(conc.iloc[:,0],conc.iloc[:,1:]).fit()
    y_fitted = est.fittedvalues
    newx[i]=est.resid
newx=newx.T
newx.index=data.index
newx=newx.iloc[1:,:]
分享到:
举报财经168客户端下载

全部回复

0/140

投稿 您想发表你的观点和看法?

更多人气分析师

  • 张亦巧

    人气2144文章4145粉丝45

    暂无个人简介信息

  • 梁孟梵

    人气2152文章3177粉丝39

    qq:2294906466 了解群指导添加微信mfmacd

  • 指导老师

    人气1856文章4423粉丝52

    暂无个人简介信息

  • 李冉晴

    人气2296文章3821粉丝34

    李冉晴,专业现贷实盘分析师。

  • 刘钥钥1

    人气2016文章3119粉丝34

    专业从事现货黄金、现货白银模似实盘操作分析指导

  • 张迎妤

    人气1896文章3305粉丝34

    个人专注于行情技术分析,消息面解读剖析,给予您第一时间方向...

  • 金泰铬J

    人气2320文章3925粉丝51

    投资问答解咨询金泰铬V/信tgtg67即可获取每日的实时资讯、行情...

  • 金算盘

    人气2696文章7761粉丝125

    高级分析师,混过名校,厮杀于股市和期货、证券市场多年,专注...

  • 金帝财神

    人气4728文章8329粉丝118

    本文由资深分析师金帝财神微信:934295330,指导黄金,白银,...