風險提示:防範以"虛擬貨幣""區塊鏈"名義進行非法集資的風險。——銀保監會等五部門
資訊
發現
搜索
登錄
简中
繁中
English
日本語
한국어
ภาษาไทย
Tiếng Việt
BTC
ETH
HTX
SOL
BNB
查看行情
LUCIDA:如何利用多因子策略建立強大的加密資產投資組合(資料預處理篇)
LUCIDA
特邀专栏作者
2023-11-28 07:51
本文約1774字,閱讀全文需要約3分鐘
具體的資料預處理涉及重複值、異常值/缺失值/極端值、標準化和資料頻率的處理。

前言

書接上回,我們發布了《用多因子策略建立強大的加密資產投資組合》系列文章的第一篇- 理論基礎篇,本篇是第二篇- 資料預處理篇。

在計算因子資料前/後,以及測試單因子的有效性之前,都需要對相關資料進行處理。具體的資料預處理涉及重複值、異常值/缺失值/極端值、標準化和資料頻率的處理。

一、重複值

數據相關定義:

  • 鍵(Key):表示獨一無二的索引。 eg. 對於一份有全部token 所有日期的數據,鍵是“token_id/contract_address - 日期”

  • 值(Value):被鍵索引的物件就稱之為「值」。

診斷重複值的首先需要理解資料「應當」是什麼樣子。通常數據的形式有:

  1. 時間序列資料(Time Series)。鍵是“時間”。 eg.單一token 5 年的價格數據

  2. 橫斷面資料(Cross Section)。鍵是“個體”。 eg.2023.11.01 當日crypto 市場所有token 的價格數據

  3. 面板資料(Panel)。鍵是“個體-時間”的組合。 eg.從2019.01.01-2023.11.01 四年所有token 的價格數據。

原則:確定了資料的索引(鍵),就能知道資料應該在什麼層面沒有重複值。

檢查方式:

pd.DataFrame.duplicated(subset=[key 1, key 2, ...])

  • 檢查重複值的數量:pd.DataFrame.duplicated(subset=[key 1, key 2, ...]).sum()

  • 抽樣看重複的樣本:df[df.duplicated(subset=[...])].sample()找到樣本後,再用df.loc 選出此索引對應的全部重複樣本

pd.merge(df 1, df 2, on=[key 1, key 2, ...], indicator=True, validate='1: 1')

  • 在橫向合併的函數中,加入indicator 參數,會產生_merge 字段,對其使用dfm[_merge].value_counts()可以檢查合併後不同來源的樣本數量

  • 加入validate 參數,可以檢驗合併的資料集中索引是否如預期般一般(1 to 1、 1 to many 或many to many,其中最後一種情況其實等於不需要驗證)。如果與預期不符,合併過程會報錯併中止執行。

二、異常值/缺失值/極端值

產生異常值的常見原因:

  1. 極端情況。例如token 價格0.000001 $或市值僅50 萬美元的token,隨便變動一點,就會有數十倍的回報率。

  2. 數據特性。例如token 價格數據從2020 年1 月1 日開始下載,那麼自然就無法計算出2020 年1 月1 日的回報率數據,因為沒有前一日的收盤價。

  3. 數據錯誤。資料提供者難免會犯錯,例如每token 將12 元記錄成1.2 元。

針對異常值和缺失值處理原則:

  • 刪除。對於無法合理更正或修正的異常值,可以考慮刪除。

  • 替換。通常用於極端值的處理,例如縮尾(Winsorizing)或取對數(不常用)。

  • 填充。對於缺失值也可以考慮以合理的方式填充,常見的方式包括平均值(或移動平均)、插值(Interpolation)、填 0df.fillna( 0)、向前df.fillna(ffill)/向後填充df.fillna(bfill)等,要考慮填充所依賴的假設是否合。

    機器學習慎用向後填充,有Look-ahead bias 的風險

針對極端值的處理方法:

1.百分位法。

通過將順序從小到大排列,將超過最小和最大比例的數據替換為臨界的數據。對於歷史數據較豐富的數據,此方法相對粗略,較不適用,強行刪除固定比例的數據可能造成一定比例的損失。

2.3σ / 三倍標準差法

對資料範圍內的所有因子做出以下調整:

此方法不足在於,量化領域常用的數據如股票價格、token 價格常呈現尖峰厚尾分佈,並不符合正態分佈的假設,在該情況下採用3 σ方法將有大量數據錯誤地被識別為異常值。

3.絕對值差中位數法(Median Absolute Deviation, MAD)

此方法基於中位數和絕對偏差,使處理後的資料對極端值或異常值不那麼敏感。比基於平均值和標準差的方法更穩健。

# 處理因子資料極端值情況

class Extreme(object):
   def __init__(s, ini_data):
       s.ini_data = ini_data    

   def three_sigma(s, n= 3):
       mean = s.ini_data.mean()
       std = s.ini_data.std()
       low = mean - n*std
       high = mean + n*std        

       return np.clip(s.ini_data, low, high) 

  def mad(s, n= 3):
       median = s.ini_data.median()
       mad_median = abs(s.ini_data - median).median()
       high = median + n * mad_median
       low = median - n * mad_median                                          

       return np.clip(s.ini_data, low, high)

   def quantile(s, l = 0.025, h = 0.975):
       low = s.ini_data.quantile(l)
       high = s.ini_data.quantile(h)
       return np.clip(s.ini_data, low, high)

三、標準化

1.Z-score 標準化

2.最大最小值差標準化(Min-Max Scaling)

將每個因子數據轉換為在( 0, 1) 區間的數據,以便比較不同規模或範圍的數據,但它不會改變數據內部的分佈,也不會使總和變為1 。

  • 由於考慮極大極小值,對異常值敏感

  • 統一量綱,利於比較不同維度的資料。

3.排序百分位(Rank Scaling)

將資料特徵轉換為它們的排名,並將這些排名轉換為介於0 和1 之間的分數,通常是它們在資料集中的百分位數。 *

  • 由於排名不受異常值影響,此方法對異常值不敏感。

  • 不保持數據中各點之間的絕對距離,而是轉換為相對排名。

# 標準化因子資料class Scale(object):
   def __init__(s, ini_data, date):
       s.ini_data = ini_data
       s.date = date    
   def zscore(s):
       mean = s.ini_data.mean()
       std = s.ini_data.std()
       return s.ini_data.sub(mean).div(std)
   def maxmin(s):
       min = s.ini_data.min()
       max = s.ini_data.max()
       return s.ini_data.sub(min).div(max - min)
   def normRank(s):
# 對指定欄位進行排名,method=min表示相同值會有相同的排名,而不是平均排名
       ranks = s.ini_data.rank(method='min')
       return ranks.div(ranks.max())

四、數據頻率

有時獲得的數據並非我們分析所需的頻率。例如分析的層次為月度,原始資料的頻率為日度,此時就需要用到“下採樣”,即聚合資料為月度。

下採樣

指的是將一個集合裡的資料聚合為一行數據,例如日度資料聚合為月度。此時需要考慮每個被聚合的指標的特性,通常的操作有:

  • 第一個值/最後一個值

  • 平均數/中位數

  • 標準差

上採樣

指的是將一行數據的數據拆分為多行數據,例如年度數據用在月度分析上。這種情況一般就是簡單重複即可,有時需要將年度資料按比例歸集於各月份。

原文連結


DA
投資
AI總結
返回頂部
具體的資料預處理涉及重複值、異常值/缺失值/極端值、標準化和資料頻率的處理。
作者文庫
LUCIDA
下載Odaily星球日報app
讓一部分人先讀懂 Web3.0
IOS
Android