【數量技術宅|金融資料系列分享】套利策略的價差序列計算,恐怕沒有你想的那麼簡單

數量技術宅發表於2020-11-04

更多精彩內容,歡迎關注公眾號:數量技術宅。想要獲取本期分享的完整策略程式碼,請加技術宅微信:sljsz01

價差計算的“誤區”

我們在測試兩個或多個金融資產相互運算產生的策略訊號時,免不了需要涉及將不同的價格時間序列,按照時間軸進行對齊,套利策略就是其中之一。然而,大部分介紹套利策略、統計套利類的文章,對於價差序列的生成計算,處理的十分簡單,基本就是兩個時間序列相減。對於較為低頻的訊號,這樣處理問題不大,但在中高頻的訊號領域,直接相減,會存在著一定的問題。

這是因為,對於不同資產的價格序列,存在著交易所推送時間、以及到達時間的差異。即使我們回測時看到的兩個Tick的時間戳是完全相同的,在實盤伺服器接收推送行情的時候,也是按照先、後順序達到的。我們在實際交易中發現,比如上海期貨交易所某個品種的不同到期交割月的合約,交易所在切片資料的推送不是同時進行的,而是按照交割月的順序推送的,例如按照RB2010、RB2101、RB2015,類似這樣的先後順序來進行推送的,其他品種也是如此,而對於同一個500ms的切片時間內,收到RB2010、RB2101、RB2015的Tick資料的時間戳,卻是相同的。

再比如數字貨幣的跨交易所套利,兩個交易所即使在相同時間傳送的Tick資料,由於交易所伺服器物理位置不同造成的傳輸時間不同,到達我們策略訊號計算伺服器的時間大概率也會不同。

一個典型的價格到達頻率不同的例子

如果說行情資料到達時間有先後,直接相減計算價差會有一定的“滯後”或“未來函式”問題的話,價格到達頻率不同,則根本就無法直接相減計算價差了。總之,我們需要一套更貼近實際交易的價差計算方式。

我們來看一個價格到達頻率不同的例子,即兩個品種資料的推送頻率是不一樣的。如果我們需要對股指期貨、股票ETF進行期現套利策略的設計,以IC與中證500ETF的資料為例,計算期現套利的價差。

IC股指期貨的Tick資料,我們的資料來源是Wind,IC對應的中金所,它的行情推送頻率是每1秒2筆資料,Level1免費行情推送的是1檔盤口,即只有買1、賣1的資料,資料時間是股指期貨的交易時間:9:29-15:00。我們來看一下IC的Tick資料樣例。

再來看中證500ETF的資料,同樣來源於Wind,500ETF行情資料的推送頻率相比較IC要低很多,每3秒會有1筆資料,Level1免費行情有5檔的盤口,即買1到買5、賣1到賣5,資料推送時間:9:15-15:00,包含股票的集合競價時間段。我們來看一下500ETF的Tick資料樣例。

巧用Pandas的Merge函式

對於這樣推送頻率有差異、時間軸也有差異的資料,計算價差,我們就需要根據時間軸來進行合成。Python Pandas庫的Merge函式,正好符合我們所需要的功能。我們簡要介紹一下Merge函式。

pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None,left_index=False, right_index=False, sort=True,suffixes=('x', 'y'), copy=True, indicator=False,validate=None)

我們在做資料合成的時候,最常用到的是前4組引數:

left: 拼接的左側DataFrame物件

right: 拼接的右側DataFrame物件

on: 要加入的列或索引級別名稱。 必須在左側和右側DataFrame物件中找到,對於金融時間序列,一般來說是時間軸

how: One of ‘left’, ‘right’, ‘outer’, ‘inner’,預設inner。inner是取交集,outer取並集。比如left:[‘A’,‘B’,‘C’];right[’'A,‘C’,‘D’];inner取交集的話,left中出現的A會和right中出現的買一個A進行匹配拼接,如果沒有是B,在right中沒有匹配到,則會丟失。'outer’取並集,出現的A會進行一一匹配,沒有同時出現的會將缺失的部分新增缺失值。

而這4組引數,對於套利價差計算的預處理,how欄位最重要。我們用實際的資料,來看不同how欄位的取值,會對最終價差的計算,帶來怎樣的影響。

首先,how = “inner”,取時間軸的交集,只有兩個表DATETIME列都有的時間,才會出現在最終的總表。我們展示計算得到的總表,並計算價差序列後繪圖。

 

其次,how = “outer”,取時間軸的並集,只要兩個表DATETIME列任意一表有的時間,都會出現在最終的總表,若另一個表沒有資料,則按nan值填充。

由於outer的資料處理方式,存在著大量的nana值,我們無法直接計算價差,通常的處理方式是前向填充空值資料,即將nan值用離得最近的非空值進行填充替代,再計算期現(中間價)價差,並繪圖。

再次,how = 'left',按左表時間軸合併。按左表(IC)的時間軸與右表逐一匹配,左表的時間軸全部保留,右表有該時間的,則併入總表,右表沒有該時間的,以nan代替。

同樣需要前向填充空值資料,然後才能計算期現(中間價)價差。

最後,how = 'right',按右表時間軸合併。按右表(500ETF)的時間軸與左表逐一匹配,右表的時間軸全部保留,左表有該時間的,則併入總表,左表沒有改時間的,以nan代替。

由於期貨資料頻率相比股票ETF更高,nan主要出現在股票比期貨集合競價更早的階段,這部分nan資料可酌情刪除。

我們將不同價差計算方式所繪製的圖合併到一起,可以看到,左上how="inner"的圖,點最為稀疏,因為需要同時兩個價格在該時刻都有資料,才會計算價差;而右上how="outer"的圖,價差點最為密集,只需其中一組價格變動,就會計算1次價差,而下方的兩張圖how="left"、how="right",密集程度位於兩者之間。

價差計算方式不同,帶來策略驅動方式的差異

價差不同的計算方式,表面來看是Merge函式所選擇how的引數不同,造成的價差序列計算結果不同。然而不同how引數的選擇,背後實則對應著不同的策略原理、策略邏輯。

我們無論在策略的回測中,對待行情資料,都需要採用一種“事件驅動”的方式來進行測試,這是最貼近實盤交易的回測方式。我們假設歷史資料也是像實盤那樣,每生成一個新的資料,推送給我們一次,而我們每收到一個新的資料,相當於是一個新的事件,這個事件驅動了後續的策略訊號計算,以及訊號對應的開平倉條件的判斷。

我們再回到價差不同的計算方式,其對應的,實則是策略不同的驅動方式。

how=‘outer’:對應的是期貨、股票雙路行情的併發驅動,即只要有股票、期貨任意資料的更新,我們的程式就更新價差,判斷是否觸發交易訊號,此時的訊號計算和觸發,最為頻繁。

how = 'left':對應的是期貨行情的單路驅動,即我們不管股票行情是否到達,只要期貨資料更新,股票採用最新儲存的資料合併計算價差,並判斷是否觸發交易訊號。

how = 'right':對應股票行情的單路驅動,即我們不管期貨行情達到與否,只要股票資料更新,期貨用最新儲存的資料合併計算價差,並判斷是否觸發交易訊號,left和right的觸發方式,訊號不如outer頻繁。

how=‘inner’:對應的是期貨、股票雙路行情同時驅動,我們一般在回測、實盤中均不採用這種方式,在本文第一小節,為大家介紹過,行情基本上不可能同時到達,這種驅動方式太過理想化,也會在無形中減少很多交易機會。

實盤應該選用的驅動方式

綜上,我們在回測、交易中可選的交易方式,可以分為兩大類:雙路行情的併發驅動、單路行情的驅動。那麼,這兩大類不同的驅動方式,究竟又該如何選擇?

筆者根據統計套利策略的實盤交易經驗,提出如下幾點建議:

  1. 計算價差的兩類資產,有明確的活躍度區分、從屬關係:例如期貨的遠近月(近月合約的交易活躍度通常大於遠月)、股票與股指期貨的期現套利(股指期貨對於股票現貨有價格發現的作用)等,此時應該以交易活躍、具有領先作用的品種,作為主驅動品種,採用單路行情的驅動

  2. 計算價差的兩類資產,無明確區分、從屬關係:例如數字貨幣的跨交易所套利(OKEX、火幣交易所之間的套利,活躍程度相當,關係對等),可以採用雙路行情的併發驅動,以此來捕捉更多的交易機會

  3. 一旦確定了驅動方式,在資料合併、回測、以及實盤交易系統的開發中,都需要採用同一種驅動方式,以最大程度確保回測結果與實盤交易的一致性。

如果你對本次分享的Python程式碼感興趣,歡迎新增技術宅微信:sljsz01,與我交流

 

 

 


往期乾貨分享推薦閱讀

【數量技術宅|量化投資策略系列分享】成熟交易者期貨持倉跟隨策略

如何獲取免費的數字貨幣歷史資料

【數量技術宅|量化投資策略系列分享】多週期共振交易策略

【數量技術宅|金融資料分析系列分享】為什麼中證500(IC)是最適合長期做多的指數

商品現貨資料不好拿?商品季節性難跟蹤?一鍵解決沒煩惱的Python爬蟲分享

【數量技術宅|金融資料分析系列分享】如何正確抄底商品期貨、大宗商品

【數量技術宅|量化投資策略系列分享】股指期貨IF分鐘波動率統計策略

【數量技術宅 | Python爬蟲系列分享】實時監控股市重大公告的Python爬蟲

相關文章