最近羣裏的小夥伴們都在討論simnow
停用的事情,從3月31日開始,要持續一個半月,不出意外的話也要5月中旬才能恢復。因而不少搞CTA
的研發人員可能最近都面臨着到哪裏去找仿真環境的問題。
筆者不禁得想起來,若干年前市面上尚未simnow
的時候,要找一個期貨仿真環境真的是很麻煩。一方面要看期貨公司是否是部署了仿真環境,只有期貨公司有仿真環境纔好測試;另外一方面,可以交易的交易所和合約也是很是有限的;並且,全部的訂單都須要對手盤,否則根本不會撮合,因此在測試的過程當中還須要請期貨公司的人幫忙下對手單,要否則就只有本身搞自成交了。
本文主要內容就是介紹如何利用WonderTrader搭建本地仿真環境。python
WonderTrader在v0.3.6
發佈的時候,發佈過一個TraderMocker
模塊,基於該模塊用戶能夠很是容易地搭建一個純本地的仿真環境,而不用依賴任何第三方環境。
筆者最初在設計TraderMocker
的時候,正在給WonderTrader適配股票交易。當時接入的是中泰XTP
接口,XTP
比較流行也比較容易接入,有互聯網的測試環境,API
也很是友好。
不過市面上不少股票測試環境多少都有一些問題,總結下來大概以下:git
顯然在這樣的仿真環境下測試,策略仿真的結果實際上是有很大的迷惑性的。在這樣的狀況下,筆者便決定本身開發一個仿真環境。可是WonderTrader做爲一個量化交易框架,自己都是各用戶獨立部署的,也沒有中心化的服務,開發一套C/S
的仿真環境,還須要硬件投入。對於WonderTrader這樣的開源平臺來講,成本過高的話是不現實的。另外仿真環境的部署通常要根據市場、品種分別部署,對於WonderTrader這樣面向全市場全品種的平臺來講,成本就更是翻了好幾倍了。筆者縱然願意分享源碼,可是也沒有辦法持續性的投入資金去維護這樣的仿真服務。基於這些基本考量,TraderMocker
這種全本地化的、去中心的仿真模塊就應運而生了。github
爲了儘可能的模擬真實的接口調用,TraderMocker
在設計上也有一些特色:json
異步執行segmentfault
異步執行的主要目的是爲了還原真實交易的事件發生順序。如下單爲例,生產環境下,調用下單接口遵循如下數據: 下單接口調用-> 下單結果返回-> 訂單回報-> 成交回報。若是不採用異步執行的機制,那麼就會出現下單接口尚未返回的時候,已經收到訂單回報和成交回報了,這樣就不符合生產環境的真實場景了。
根據價格撮合session
TraderMocker
天然不多是一個徹底的仿真環境,因此撮合的機制也相對簡單。可是爲了儘可能模擬實盤環境,TraderMocker
會嚴格按照價格優先的機制進行撮合。這裏的撮合,指的是不須要對手盤的撮合,即只要價格條件知足,即直接撮合成交,推送訂單回報和成交回報。
支持不一樣的品種架構
TraderMocker
做爲一個輔助的簡化的本地仿真模塊,要充分考慮對不一樣的品種的支持。這樣才能增長TraderMocker
的應用場景。
基於以上的設計原則,TraderMocker
也表現出一些特色:框架
仿真的程度有限異步
TraderMocker
畢竟不是真正的撮合系統,只是利用行情對訂單作一個仿真處理。並且接入的行情,就算是期貨,也是500ms
一筆的快照。另外,考慮到不一樣行情源檔位不一樣,因此撮合處理的時候只利用了買一賣一的數據。TraderMocker
對訂單之間的競爭也不考慮進去,統一按照最新的tick
的委託量進行處理。
不適合大單測試async
TraderMocker
並無處理訂單對限價訂單簿的衝擊。主要考慮到期貨行情只有一檔,沒法進行衝擊的處測算,因此就簡化了。因此當一個訂單的委託價格高於對手價的時候,一次撮合不完會等到下一筆tick
進來再利用對手價進行撮合,這顯然不大符合真實場景。所以大單仿真的還原程度會更低,參考性也更低了。
不作驗資操做
TraderMocker
由於其特殊性,不會進行資金檢查,只要合法的訂單都能下單成功。一方面是由於TraderMocker
是爲通用性設計的,因此沒法兼顧全部的幣種,若是增長驗資的機制會增長複雜性。另一方面, WonderTrader的 1+N執行架構,其實是隔絕了策略對資金的關注,即便作驗資,也沒法將問題傳遞給策略。
不作結算處理
TraderMocker
爲了簡化處理,不會進行結算處理。若是引入結算機制,會增長複雜性,並且還會要求仿真器一直在線直到接收到結算價爲止。可是在策略的實操中,其實都主要關心的仍是進場價和出廠價,結算的意義對於策略來講並不大。不過若是不結算,全部的持倉都是今倉,所以對於有些品種來講,仿真環境中的手續費的設置就須要把平今設置爲跟平昨一致。
訂單都在內存中
對於TraderMocker
這樣的簡易仿真模塊, 只會把必要的數據落地。目前TraderMocker
只會保存持倉數據,而 訂單數據和成交數據都只在內存中。一單平臺重啓,訂單和成交就都都沒有了。
交易指令簡化
TraderMocker
爲了兼容不一樣的品種,因此 只能實現通用的指令,即 買賣和撤單的指令。其餘的特殊指令就不支持了,好比ETF
申贖、期權的報價和執行等指令。
固然TraderMocker
只是筆者倉促寫出來的一個簡易的仿真模塊,有不少仿真功能由於使用場景有限,並無徹底實現。若是各位讀者有興趣的話,能夠自行根據本身的需求進行完善。到時候若是願意分享給你們的話,也能夠提交一個PR
。
前文介紹了一下TraderMocker
模塊,下面本文就將介紹如何在利用WonderTrader搭建這樣的本地仿真環境。搭建本地仿真環境,須要用到datakit_fut
和hft_fut_mocker
兩個demo
。這兩個demo
筆者已經提交到wtpy/demos
下,有須要的讀者能夠自行獲取,若是master
分支沒有的話,請到dev
分支下載便可。
行情配置datakit_fut
是經過CTP
接口落地行情數據的數據組件demo
,基本配置以下:
{ "basefiles":{ "session":"./common/sessions.json", "commodity":"./common/commodities.json", "contract":"./common/contracts.json", "holiday":"./common/holidays.json" }, "writer":{ "path":"./FUT_Data/", "savelog":false, "async":false, "groupsize":20 }, "parsers":[ { "active":true, "module":"ParserCTP.dll", "front":"tcp://180.168.146.187:10111", "broker":"9999", "user":"你的SIMNOW帳號", "pass":"你的SIMNOW密碼", "code":"CFFEX.IF2005,SHFE.au2012" } ], "broadcaster":{ "active":true, "bport":3997, "broadcast":[ { "host":"255.255.255.255", "port":9001, "type":2 } ] }
在使用的時候,將parsers
小節的CTP
前置和帳號密碼改爲生產環境,並將code
改爲本身須要的合約代碼進行訂閱,而後啓動runDT.py
就能夠正常運行了。
仿真配置hft_fut_mocker
則是從UDP
廣播通道接入行情,並調用TraderMocker
進行仿真,配置以下:
{ "basefiles":{ "session":"./common/sessions.json", "commodity":"./common/commodities.json", "contract":"./common/contracts.json", "holiday":"./common/holidays.json", "hot":"./common/hots.json" }, "env":{ "name":"hft", "mode": "product", "product":{ "session":"TRADING" }, "filters":"filters.json", "fees":"fees.json", }, "data":{ "store":{ "path":"./FUT_Data/" } }, "traders":[ { "active":true, "id":"mocker", "module":"TraderMocker.dll", "front":"mocker://localhost", "mockerid":9999, "span":100, "newpx":true, "maxqty":100, "minqty":1, "user":"mocker9999", "udp_port":9001, "savedata":true } ], "parsers":[ { "active":true, "id":"parser1", "module":"ParserUDP.dll", "host":"127.0.0.1", "bport":9001, "sport":3997, "filter":"" } ], "bspolicy":"actpolicy.json" }
從上面的配置能夠看出,TraderMocker
仿真器,要從udp
廣播通道接收最新的行情,才能進行撮合。可能有人會有疑問:爲何不從行情通道經過WonderTrader直接向TraderMocker
傳遞行情數據呢?其實也很好解釋,由於Trader
模塊解耦之後,WonderTrader只和Trader
交互交易數據,而行情數據,不在接口支持的數據範圍內,因此TraderMocker
只能本身解決行情接入的問題。所以TraderMocker
天然就會依賴數據伺服組件提供的行情廣播服務了。
配置修改好了之後,再檢查一下策略啓動入口:
from wtpy import WtEngine,EngineType from strategies.HftStraDemo import HftStraDemo if __name__ == "__main__": #建立一個運行環境,並加入策略 engine = WtEngine(EngineType.ET_HFT) engine.init('./common/', "config.json") engine.commitConfig() straInfo = HftStraDemo(name="hft_IF", code="CFFEX.IF.2104", expsecs=5, offset=100, freq=0) engine.add_hft_strategy(straInfo, 'mocker') engine.run() kw = input('press any key to exit\n')
最後,運行run.py
就能夠正常進行仿真測試了,如圖:
若是有須要進行股票仿真的,只須要修改./common
目錄下相應的基礎文件,並修改配置文件中的行情接入模塊的配置文件便可。若有不明白的地方,讀者也能夠私信諮詢筆者。
如何利用WonderTrader的仿真模塊TraderMocker
來搭建本地的仿真環境,總結下來就是兩個步驟:先運行一個數據伺服,再運行仿真環境。簡單的兩個步驟,就能夠搞定一個仿真環境。相信對於有須要的人來講,這是一個很輕鬆的事情。
對於想用simnow
的用戶來講,在simnow
缺位的這段時間,只須要一個CTP
s實盤帳號便可進行仿真測試。對於那些不知足於券商提供的股票仿真環境的人來講,本文介紹的這個攻略也許能夠提高你仿真測試的效率。
固然,筆者水平有限,TraderMocker
的開發也比較倉促,不免有不少錯漏之處,各位讀者在使用的時候還須要自行判斷一下是否知足本身的需求。另外,仿真畢竟不是實盤,策略的表現是否合理還須要各位仔細辨別。
最後再安利一下WonderTrader
WonderTrader旨在給各位量化從業人員提供更好的輪子,將技術相關的東西都封裝在平臺中,力求給策略研發帶來更好的策略開發體驗。
WonderTrader的github
地址:https://github.com/wondertrad...
WonderTrader官網地址:https://wondertrader.github.io
wtpy的github
地址:https://github.com/wondertrad...
市場有風險,投資需謹慎。以上陳述僅做爲對於歷史事件的回顧,不表明對將來的觀點,同時不做爲任何投資建議。