多因子數據的處理:主要包括三種方式-----------去極值;標準化;中性化
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
這便是經過中性化處理的市值數據。