1. 程式人生 > 其它 >設計模式 -> 行為型 - 策略(Strategy)

設計模式 -> 行為型 - 策略(Strategy)

公司簡介

深圳市弘源泰平資產管理有限公司組建於2016年,團隊核心成員來自於知名高校,有豐富的資產配置與策略構建的實踐經驗。弘源泰平以套戥交易絕對收益型配置工具為起點,致力於為使用者提供流動性好、費率公允的資產配置工具。產品線全面、豐富,涵蓋股、債、商品等各大類資產,通脹、趨勢等各類因子。

場景簡介+核心訴求

我們的量化交易系統每天要接收大量的行情資料,也要基於行情產生大量的決策訊號。這些資料都需要及時存下來,供盤中和盤後使用。

傳統存放行情資料的方式有檔案系統、關係型資料庫或者文件資料庫。我們嘗試了MySQL和知名的時序資料庫InfluxDB,但是效能都沒有達到預期。分別遇到了如下問題:

  • MySQL:在寫入大量實時的時序資料時,效能不理想;即便是優化之後,對於資源的浪費仍然十分驚人。而且隨著資料量的增加,對裝置資料的實時查詢、時間範圍分析的需求增加,基於MySQL的查詢分析操作,響應時間會越來越長,甚至會無響應。缺乏自動建表功能,使用很不方便。
  • InfluxDB:雖然是時序資料庫,但是經過測試後效能不能滿足預期,在完成同樣資料量的寫入時對於資源的使用程度也並不能令人滿意。

最後,我們改用TDengine徹底解決了實時寫入大量資料點和快速查詢的問題。

TDengine具體落地

對於策略研究員而言,歷史行情和訊號是交易策略研究的重要素材。下面以行情資料和策略訊號資料為案例予以介紹。

資料建模

首先,將行情資料和訊號資料分別儲存。在TDengine中分別建立了一個行情資料庫和訊號資料庫。

雖然是時序資料庫,但是TDengine使用了關係型資料庫的模型,建庫,建表,使用SQL,十分便於傳統關係型資料庫的使用者入手。並且,他們還很有創意地設計了超級表的概念,與我們的場景十分契合。

因為所有行情資料結構相同,行情庫中只需要一個超級表,下面每個工具(衍生品基金等)對應一個子表。比如CU2101表示2021年1月份到期的銅期貨交易合約。在合約到期之前,都會有行情資料寫入。下面重點介紹策略訊號資料庫。

訊號庫有兩張超級表,分別對應合約級別訊號和策略級別訊號,每個交易訊號對應一張子表,當前共有 40,000多張表,表結構分別如下所示:

下面是訊號庫執行show tables的截圖:

資料庫配置以及寫入

我們選用的TDengine版本是2.2.0.0,由於單機版尚無壓力,目前還不需要叢集。此外,機器有40核,而TDengine的每一個vnode又是擁有獨立執行執行緒的工作單元。所以,根據文章《

這幾個神祕引數,教你TDengine叢集的正確使用方式》,我調整了minTablesPerVnode、tableIncStepPerVnode和maxVgroupsPerDb引數,讓vnode的數量恰好等於CPU核數,讓每個核獨立執行一個執行緒,實現了資料的合理化分佈,以爭取達到最佳效能。

寫入效能

當前,我們大概每秒寫入3萬行資料。單節點TDengine可以十分輕鬆地實現這個級別資料量的寫入。同時,消耗伺服器資源又比InfluxDB與MySQL小的多。因此,即便未來業務擴大,我們也不需要擔心額外的硬體成本。

資源消耗

我們當前的伺服器配置如下:64G記憶體+40核 1.8GHz CPU+機械硬碟。

在業務執行期間,taosd的%CPU只有4%上下浮動,程序使用的實體記憶體百分比為11.2%。雖然記憶體佔用稍多,但這是由於我們的vnode配置的比較多,每個vnode都有自己固定的記憶體緩衝區。因此,後續即便是繼續大量增加新表或者加大寫入量,記憶體佔用也不會有明顯的浮動了。

截至目前,通過TDengine錄入的兩個訊號表已經寫入了82億條資料,原資料大概為92GB,實際佔用儲存空間為20G左右,壓縮率高達23%,如果是整型資料應該還會更高。

查詢效能

除了寫入與儲存,使用TDengine做日常查詢的速度也十分優秀,即便是對於幾十億級別的大表,也是毫秒級響應。我們來看兩個場景。

場景1:查詢特定策略訊號下一段時間的均值。

select avg(v) from stgbox.strategy_signal where stg_name = '{stg_id}' and signal_name ='{signal_name}' and ts >= '{from_date} 00:00:00' and ts <= '{to_date} 23:59:59.999' interval({interval})

   

以下是我們用場景1查詢出的資料進行視覺化分析的示例。

場景2:查詢滿足模糊查詢條件的訊號的最新值。

select name,last(v) from stgbox.global_signal where name like '%keyword%' group by name。

 

 

在修改cachelast快取之前,查詢效率如上。

後面在濤思資料的技術支援之下,我們將cachelast引數設定成了3。

 

再執行了同樣的查詢,查詢效率得到了很大提升:

 

這兩個都是我們比較典型的查詢場景,TDengine完美地匹配了我們對功能以及效能上的需求。

寫在最後

我們目前對TDengine的使用還處於初級階段,TDengine不僅僅是時序資料庫,還可以作為訊息佇列,支援資料訂閱。以後我們會探索將TDengine用於更多的業務場景,以更好地服務於我們的各類分析與交易執行。

關於作者:

丁博,弘源泰平量化工程師。目前負責公司交易執行系統、交易策略訊號系統和交易組合管理系統的研發。


想了解更多 TDengine Database的具體細節,歡迎大家在GitHub上檢視相關原始碼。