作者:丁博
公司簡介
深圳市弘源泰平資產管理有限公司組建于2016年,團隊核心成員來自于知名高校,有豐富的資產配置與策略構建的實踐經驗。弘源泰平以套戥交易絕對收益型配置工具為起點,致力于為用戶提供流動性好、費率公允的資產配置工具。產品線全面、豐富,涵蓋股、債、商品等各大類資產,通脹、趨勢等各類因子。
場景簡介+核心訴求
我們的量化交易系統(tǒng)每天要接收大量的行情數(shù)據(jù),也要基于行情產生大量的決策信號。這些數(shù)據(jù)都需要及時存下來,供盤中和盤后使用。
傳統(tǒng)存放行情數(shù)據(jù)的方式有文件系統(tǒng)、關系型數(shù)據(jù)庫或者文檔數(shù)據(jù)庫。我們嘗試了MySQL和知名的時序數(shù)據(jù)庫InfluxDB,但是性能都沒有達到預期。分別遇到了如下問題:
- MySQL:在寫入大量實時的時序數(shù)據(jù)時,性能不理想;即便是優(yōu)化之后,對于資源的浪費仍然十分驚人。而且隨著數(shù)據(jù)量的增加,對設備數(shù)據(jù)的實時查詢、時間范圍分析的需求增加,基于MySQL的查詢分析操作,響應時間會越來越長,甚至會無響應。缺乏自動建表功能,使用很不方便。
- InfluxDB:雖然是時序數(shù)據(jù)庫,但是經過測試后性能不能滿足預期,在完成同樣數(shù)據(jù)量的寫入時對于資源的使用程度也并不能令人滿意。
最后,我們改用TDengine Database徹底解決了實時寫入大量數(shù)據(jù)點和快速查詢的問題。
TDengine Database具體落地
對于策略研究員而言,歷史行情和信號是交易策略研究的重要素材。下面以行情數(shù)據(jù)和策略信號數(shù)據(jù)為案例予以介紹。
數(shù)據(jù)建模
首先,將行情數(shù)據(jù)和信號數(shù)據(jù)分別存儲。在TDengine Database中分別創(chuàng)建了一個行情數(shù)據(jù)庫和信號數(shù)據(jù)庫。
雖然是時序數(shù)據(jù)庫,但是TDengine使用了關系型數(shù)據(jù)庫的模型,建庫,建表,使用SQL,十分便于傳統(tǒng)關系型數(shù)據(jù)庫的用戶入手。并且,他們還很有創(chuàng)意地設計了超級表的概念,與我們的場景十分契合。
因為所有行情數(shù)據(jù)結構相同,行情庫中只需要一個超級表,下面每個工具(衍生品基金等)對應一個子表。比如CU2101表示2021年1月份到期的銅期貨交易合約。在合約到期之前,都會有行情數(shù)據(jù)寫入。下面重點介紹策略信號數(shù)據(jù)庫。
信號庫有兩張超級表,分別對應合約級別信號和策略級別信號,每個交易信號對應一張子表,當前共有 40,000多張表,表結構分別如下所示:

下面是信號庫執(zhí)行show tables的截圖:


數(shù)據(jù)庫配置以及寫入
我們選用的TDengine版本是2.2.0.0,由于單機版尚無壓力,目前還不需要集群。此外,機器有40核,而TDengine的每一個vnode又是擁有獨立運行線程的工作單元。所以,根據(jù)文章《這幾個神秘參數(shù),教你TDengine集群的正確使用方式》,我調整了minTablesPerVnode、tableIncStepPerVnode和maxVgroupsPerDb參數(shù),讓vnode的數(shù)量恰好等于CPU核數(shù),讓每個核獨立運行一個線程,實現(xiàn)了數(shù)據(jù)的合理化分布,以爭取達到最佳性能。

寫入性能
當前,我們大概每秒寫入3萬行數(shù)據(jù)。單節(jié)點TDengine可以十分輕松地實現(xiàn)這個級別數(shù)據(jù)量的寫入。同時,消耗服務器資源又比InfluxDB與MySQL小的多。因此,即便未來業(yè)務擴大,我們也不需要擔心額外的硬件成本。
資源消耗
我們當前的服務器配置如下:64G內存+40核 1.8GHz CPU+機械硬盤。
在業(yè)務運行期間,taosd的%CPU只有4%上下浮動,進程使用的物理內存百分比為11.2%。雖然內存占用稍多,但這是由于我們的vnode配置的比較多,每個vnode都有自己固定的內存緩沖區(qū)。因此,后續(xù)即便是繼續(xù)大量增加新表或者加大寫入量,內存占用也不會有明顯的浮動了。

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



查詢性能
除了寫入與存儲,使用TDengine做日常查詢的速度也十分優(yōu)秀,即便是對于幾十億級別的大表,也是毫秒級響應。我們來看兩個場景。
場景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查詢出的數(shù)據(jù)進行可視化分析的示例。

場景2:查詢滿足模糊查詢條件的信號的最新值。
select name,last(v) from stgbox.global_signal where name like '%keyword%' group by name。


在修改cachelast緩存之前,查詢效率如上。 后面在濤思數(shù)據(jù)的技術支持之下,我們將cachelast參數(shù)設置成了3。

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

這兩個都是我們比較典型的查詢場景,TDengine完美地匹配了我們對功能以及性能上的需求。
寫在最后
我們目前對TDengine的使用還處于初級階段,TDengine不僅僅是時序數(shù)據(jù)庫,還可以作為消息隊列,支持數(shù)據(jù)訂閱。以后我們會探索將TDengine用于更多的業(yè)務場景,以更好地服務于我們的各類分析與交易執(zhí)行。
關于作者:
丁博,弘源泰平量化工程師。目前負責公司交易執(zhí)行系統(tǒng)、交易策略信號系統(tǒng)和交易組合管理系統(tǒng)的研發(fā)。



互聯(lián)網.png)



-1.png)












伙伴.png)



