LUCIDA & FALCON:用多因子策略構建強大的加密資產投資組合

Lucida & Falcon
2023-11-28 17:25:55
收藏
數據預處理篇。

作者:LUCIDA \& FALCON


前言

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

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

一、重複值

數據相關定義:

  • 鍵( Key ):表示一個獨一無二的索引。 eg . 對於一份有全部 token 所有日期的數據,鍵是" token _ id / contract _ address - 日期"
  • 值( Value ):被鍵索引的對象就稱之為"值"。

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

  1. 時間序列數據( Time Series )。鍵是"時間"。 eg .單個 token5 年的價格數據
  2. 橫截面數據( Cross Section )。鍵是"個體"。 eg .2023.11.01當日 crypto 市場所有 token 的價格數據
  3. 面板數據( Panel )。鍵是"個體-時間"的組合。 eg .從2019.01.01-2023.11.01 四年所有 token 的價格數據。

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

檢查方式:

  1. pd . DataFrame . duplicated ( subset =[ key1 , key2 , …])

    檢查重複值的數量: pd . DataFrame . duplicated ( subset =[ key1 , key2 , …]). sum ()

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

  2. pd . merge ( df1 , df2 , on =[ key1 , key2 , …], indica to r = True , validate ='1:1')

    在橫向合併的函數中,加入 indica to r 參數,會生成_ 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. 數據錯誤。數據提供商難免會犯錯,比如將12元每token記錄成1.2元每token。

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

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

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

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

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

針對極端值的處理方法:

1.百分位法。

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

2.3σ / 三倍標準差法

標準差 σfactor 體現因子數據分佈的離散程度,即波動性。利用 μ±3×σ 範圍識別並替換數據集中的異常值,約有99.73% 的數據落入該範圍。該方法適用前提:因子數據必須服從正態分佈 ,即 X∼N(μ,σ2)。

其中,μ=∑ⁿᵢ₌₁⋅ Xi / N , σ²=∑ⁿᵢ₌₁=( xi -μ)²/ n ,因子值的合理範圍是[μ−3×σ,μ+3×σ]。

對數據範圍內的所有因子做出如下調整:

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

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

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

絕對偏差值的中位數 MAD = median ( ∑ⁿᵢ₌₁( Xi - X median ) )

因子值的合理範圍是[ Xmedia n - n × MAD , Xmedia n + n × 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 標準化
  • 前提: X N (μ,σ)
  • 由於使用了標準差,該方法對數據中的異常值較為敏感

x'ᵢ=(x−μ)/σ=(X−mean(X))/std(X)

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

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

  • 由於考慮極大極小值,對異常值敏感
  • 統一量綱,利於比較不同維度的數據。

x'ᵢ=(xᵢ−min(x))/max(x)−min(x)

3.排序百分位( Rank Scaling )

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

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

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

NormRankᵢ=(Rankₓᵢ−min(Rankₓᵢ))/max(Rankₓ)−min(Rankₓ)=Rankₓᵢ/N

其中, min ( Rank ₓ)=0, N 為區間內數據點的總個數。

# 標準化因子數據
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())

四、數據頻率

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

下採樣

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

  • 第一個值/最後一個值
  • 均值/中位數
  • 標準差

上採樣

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

關於 LUCIDA \& FALCON

Lucida (https://www.lucida.fund/ )是行業領先的量化對沖基金,在2018年4月進入Crypto市場,主要交易CTA / 統計套利 / 期權波動率套利等策略,現管理規模3000萬美元。

Falcon (https://falcon.lucida.fund /)是新一代的Web3投資基礎設施,它基於多因子模型,幫助用戶"選"、"買"、"管"、"賣"加密資產。Falcon在2022年6月由Lucida所孵化。

更多內容可訪問 https://linktr.ee/lucida_and_falcon

鏈捕手ChainCatcher提醒,請廣大讀者理性看待區塊鏈,切實提高風險意識,警惕各類虛擬代幣發行與炒作,站內所有內容僅係市場信息或相關方觀點,不構成任何形式投資建議。如發現站內內容含敏感信息,可點擊“舉報”,我們會及時處理。
ChainCatcher 與創新者共建Web3世界