1. 程式人生 > >多因子模型之因子(訊號)測試平臺----因子值的處理(一)

多因子模型之因子(訊號)測試平臺----因子值的處理(一)

在前面一節,我們成功計算出來了因子值。

在開始今天的內容前,我們要先了解幾個概念。許多書本上,可能不會這樣講,這個僅僅是筆者的一些感悟。

0.幾種factor

        先來弄清楚筆者自己總結的factor的生命週期

1)raw facto

        raw factor就是上一次我們計算出來的factor,沒有什麼可以更多的解釋的。

2)Winsorized-raw factor

        我們知道,金融資料充滿了噪音,也就是意味著,有很多異常值,所以我們要對這些股票的存貨週轉率值做一個處理。比如說,對於異常值,我們可以用Winsorized或者直接剔除的方法。Winsorized方法比較常用,但是也不一定有效。Winsorized方法說白了,就是讓所有的raw factor有一個上下限,大於這個上限的,就等於上限的值,小於下限的,就等於下限值。通常,上下限可以用分位數或者標準差來體現。


3)raw z-score

        這一步其實就是factor的標準化,也就是,減去均值,然後除以標準差。相對而言好理解。把因子值都做標準化後,是為了以後很多因子可以相互combine。如果不做標準化,量綱就不一樣,組合在一起就不會有什麼意義。

4)neut-score

        我們做完標準化後,需要對因子值做中性化處理。包括行業中性和風格中性。

        行業中性比較簡單,只要滿足行業內因子值均值為0,標準差為1,也就是,行業內部再做一次標準化就可以了。而風格中性則需要和風格因子的secore,或者說,exposure做迴歸,然後取殘差作為最後的neut-score。

這裡,前面三步還是比較容易實現的,但是第四部我們需要一個風格因子的score,這就很尷尬了,因為我們並不知道有哪些風格因子。有一個神一般的存在,叫做barra,讀者可以自己去百度一下。總而言之,這個資料供應商給了我們十個風格因子以及每一個因子的score(exposure)。當然,我們也可以自己去建立這個。

        這一小節,我們先嚐試前面三步,後續,我們自己建立一兩個風格因子來neut。

1.資料整合

        為了能夠實現上面這些功能,我們首先要有一個把所有資料放在一起的資料集。
def data_df_get(stock_file_name):
    df = pd.read_csv('./price_data/%s' % stock_file_name, index_col=0, parse_dates=True)
    df['sec_id'] = stock_file_name[:-4]
    return df

pd.concat([data_df_get(stock_file_name) for stock_file_name in univers]).to_csv('total_data.csv')
        然後,我們可以獲得我們universe中所有股票的集合,同時加了一個sec_id欄位。

2.去極值與標準化

import datetime
def winsorize_series(se):
    q = se.quantile([0.025, 0.975])
    if isinstance(q, pd.Series) and len(q) == 2:
        se[se < q.iloc[0]] = q.iloc[0]
        se[se > q.iloc[1]] = q.iloc[1]
    return se

def standardize_series(se):
    se_std = se.std()
    se_mean = se.mean()
    return (se - se_mean)/se_std

paser = lambda x: datetime.datetime.strptime(x, "%Y-%m-%d %H:%M:%S.%f").strftime('%Y-%m-%d')
all_data = pd.read_csv('total_data.csv')
all_data.rename(columns={all_data.columns[0]: 'date'}, inplace=True)
all_data['date'] = all_data['date'].apply(paser)
all_data.sort_values(['date', 'sec_id'], inplace=True)
all_data['win_secore'] = all_data.groupby('date')['raw_factor'].apply(winsorize_series)
all_data['z-score'] = all_data.groupby('date')['win_secore'].apply(standardize_series)
all_data.to_csv('total_data.csv')
         上面這段程式碼,讓我們讀入了剛才的total_data,然後計算出去極值後的score和標準化後的score。讀者執行後,大概csv檔案是下面這樣的。         當然,上面的程式碼中,由於要對date分組,所以,需要一些時間的操作,但都是很基礎的。