多因子数据的处理:主要包括三种方式-----------去极值;标准化;中性化
1.去极值
去极值不是删除而是拉回正常值
(1)分位数去极值
(2)3倍中位数去极值(3mad)
(3)正太分布去极值(3sigma)
首先安装以下需要的工具包
from scipy.stats.mstats import winsorize
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
import numpy as np
import pandas as pd
(1)分位数去极值
获取数据,选择revenue和cost_of_goods_sold两个特征
q = query(fundamentals.income_statement.revenue,
fundamentals.income_statement.cost_of_goods_sold
)
fund = get_fundamentals(q, entry_date="2017-01-03")
#换成截面数据
fund[:,"2017-01-03",:]
#对pe_ratio去极值
#分位数去极值
fund = pe_ratio = get_fundamentals(query(fundamentals.eod_derivative_indicator.pe_ratio), entry_date="2018-01-03")[:,"2018-01-03",:]
fund['pe_ratio_winsorize'] = winsorize(fund['pe_ratio'], limits=0.025)
选取500个数据查看情况
fund['pe_ratio'][:500].plot()
fund['pe_ratio_winsorize'][:500].plot()
还可以自定义一个函数来进行分位数去极值
def quantile(factor, up, down):
#===自实现分位数去极值===
up_scale = np.percentile(factor, up)
down_scale = np.percentile(factor, down)
factor = np.where(factor > up_scale, up_scale , factor)
factor = np.where(factor < down_scale, down_scale , factor)
return factor
quantile(fund['pe_ratio'], 97.5, 2.5)
(2)3倍中位数绝对偏差去极值
#1.找出中位数
#2.得到每个因子值与中位数的绝对偏差 / x - median/
#3.得到绝对偏差值的中位数 MAD, median(/ x - median/)
#4.计算MAD_e = 1.4826*MAD,然后确定参数n,做出调整
#===实现3倍中位数绝对偏差去极值==
def mad(factor):
#1.找出中位数
me = np.median(factor)
#2.得到每个因子值与中位数的绝对偏差 / x - median/
#3.得到绝对偏差值的中位数 MAD, median(/ x - median/)
mad = np.median(abs(factor - me))
#4.计算MAD_e = 1.4826*MAD,然后确定参数n,做出调整
#求出3倍中位数上下限
up = me + (3*1.4826*mad)
down = me - (3*1.4826*mad)
#利用3倍中位数去极值
factor = np.where(factor > up, up, factor)
factor = np.where(factor < down, down, factor)
return factor
#对pe_ratio去极值
fund['pe_ratio_3mad'] = mad(fund['pe_ratio'])
选取500数据查看
fund['pe_ratio'][:500].plot()
fund['pe_ratio_3mad'][:500].plot()
效果明显比之前好很多
(3)正态分布去极值 (3sigma方法去极值)
自定义一个函数
def threesigma(factor):
#计算平均值和标准差
mean = factor.mean()
std = factor.std()
#计算上下限的数据
up = mean + 3*std
down = mean - 3*std
#替换极值
factor = np.where(factor > up, up, factor)
factor = np.where(factor < down, down, factor)
return factor
fund['pe_ratio_3sigma'] = threesigma(fund['pe_ratio'])
选取500查看情况
fund['pe_ratio'][:500].plot()
fund['pe_ratio_3sigma'][:500].plot()
这个效果就不太好了,所以日常主要用第二种方法。
2.标准化
std = StandardScaler()
std.fit_transform(fund['pe_ratio_3mad'].dropna())
或者自实现一个标准化函数
def stand(factor):
mean = factor.mean()
std = factor.std()
return (factor - mean)/ std
stand(fund["pe_ratio_3mad"])
3.中性化
将市值进行中性化处理
#获取两个因子数据
#对目标值因子-市净率进行去极值和标准化处理
#建立市值与市净率回归方程
#通过回归系数,预测新的因子结果y_predict
#求出市净率与y_predict的偏差即为新的因子值
#1.获取数据
q = query(
fundamentals.eod_derivative_indicator.pb_ratio,
fundamentals.eod_derivative_indicator.market_cap
)
fund = get_fundamentals(q, "2018-01-03")[:,"2018-01-03",:]
fund
#2.对因子数据进行处理,3倍中位数,stand
fund['pb_ratio']= mad(fund['pb_ratio'])
fund['pb_ratio']= stand(fund['pb_ratio'])
#3.确定建立回归方程特征值和目标值
#感谢大神,这里传入训练的特征值是二维的形状
x = fund['market_cap'].values.reshape(-1, 1)
y = fund['pb_ratio']
#4.利用线性回归进行预测
lr = LinearRegression()
lr.fit(x,y)
#5.得出每个预测值,让因子的真实值-预测值得出的误差,就是我们中性化处理后的结果
y_predict = lr.predict(x)
res = y - y_predict
fund['pb_ratio'] =res
fund
这便是经过中性化处理的市值数据。