前一篇硬核乾貨 - 量化交易系統的自動化實盤細節與思考(一 問題與難點)講了一點幣圈實盤的基本難題。這一篇說說實盤的主要宗旨。
我認爲主要有四個:
一. 貫徹策略的既定邏輯
這一點毋庸置疑。在有信號的時候必須做出相應的操作,開倉,平倉。這一點就要求儘量不要用限價單,不然成交不了還得追單,可能價格都已經飛遠了,最後到底要不要追也是個問題。
長期來看,採用市價單產生的滑點和偶爾錯過限價單,但又追單產生的滑點總量大致類似,所以還不如直接市價進出場,除非你的策略很特殊。
另外,使用限價單的話,你的代碼更復雜,因爲要管理沒有成交的限價單,再去追單。還有如果限價單隻成交了一部分又怎麼辦?是餘下的限價單一直掛着呢?還是錯過部分再另外發市價單?這種一步操作卻又產生多筆成交訂單,後期覆盤也麻煩,容易搞混。所以,不如直接用市價單算了,只要提交成功,基本上就會保證成交。如果確實是滑點敏感的策略,那麼只做流動性好的標的吧。
還有,合約的話,槓桿也不要隨意變動,最好是回測的理想槓桿再打八折。不要人爲主觀去預測行情,手動調整槓桿。倉位變來變去也是自動化交易的大忌。
倉位最好是自動贏衝輸縮,回撤到一定程度就要降低槓桿,而不要反其道而行之,以爲馬上風就要來了,加大槓桿(不過可以加本金、降槓桿)。賬戶活命最重要,先求不敗。可以等資金曲線度過回撤期,再加回槓桿。不過如果是採用複利模式,就已經是簡單的自動贏衝輸縮了。
二. 儘量減少滑點
這點前一篇已經說了。滑點是消除不了的,只能緩解。這需要你能在第一時間獲取市場價格信息,交易所賬號裏的各種資金、倉位信息,才能做到快速反應。
實盤總體架構上,子策略多,又要求獲取各類信息及時,就要有一個專門的 websocket 行情中心來分擔任務。再配一個 Restful 的 Plan B 行情中心做備份。這樣萬一 websocket 掉線連接不上的時候,還有一個比較新的價格來判斷是否需要離場。跑路的時候要快,寧願跑錯,也比被堵在裏面,不知未來如何要強。
三. 長久運行
這一點前一篇也已經說過。幣圈是 7*24 運行,你的代碼是不能停機的。這就要求代碼不會被拋出的各種異常中斷,得有處理各種意外情況的代碼。還有不能帶有內存泄露這種 bug,不然時間長了,程序會崩潰,甚至整個服務器都被拖垮。好在 Python 不容易導致這類問題,它有內存自動回收機制。實在不行,每天或者幾天手動重啓一下交易程序也可以,反正都是中低頻交易。這些都是基本的後端代碼開發要求,容易達成。
一般量化交易都是採用 Python。Python 這種腳本語言一大特點就是動態編譯,運行效率稍低,因爲一邊編譯一邊執行(不過完全不會影響到中低頻交易)不容易調試。如果代碼邏輯上暗含問題,可能不太容易被發現。 譬如有 100 行代碼,第99 行有問題,但是每次都只運行到 95 行,那這個問題就不會被發現,因爲必須運行到第 99 行,觸發了相關代碼,才能發現錯誤,但是這時候可能爲時已晚,程序會直接崩潰,如果你沒有 try catch exception 的話。
另外一個特點,其實已經包含在上面提到的問題裏了。因爲 Python 算是強類型,很少隱式轉換類型。如果你太信任服務器傳來的數據類型,特別是那些數字,那麼很可能會喫虧,因爲有的時候數字會變成字符串。交易所不同的幣種,不同 API 版本,websocket 和 rest 傳來的同一種返回數據,都有可能是不同類型。所以原則上,每次都必須強制轉型一下,或者先判斷需不需要轉。
還有就是,各個策略之間開關倉不要搞混了,特別是一個幣種的,做好隔離。不然在一些極端行情下,a 策略把 b 策略的倉位平了,最後導致對不上,可能得停掉實盤再重新開局,這樣就不連貫了,也可能錯過關鍵行情。
一句話,一切爲了實盤的長期全自動化無干預運行。
然而,如果策略太過複雜,要做到完全無需干預,也不是那麼容易的。簡化策略也是一個入手點,別搞太複雜了。例如少用 OBV 這類信號,因爲 OBV 需要追溯很久遠的價量信息,實盤需要維護太多數據了,每次中斷,重啓都是一個麻煩事。不得已,避免這樣的因子。
四. 風控
這點是實盤要求的重中之重。
其中最危險的,莫過於不能平倉。行情反向了,而且還在繼續暴走,結果你的出場代碼失控,不管什麼原因,不止損平倉了。在幣圈,山寨幣短時間內是可能漲幾倍的。所以,在做空的情況下,就算你沒有使用槓桿,還半倉,自以爲高枕無憂,結果早上起來倉位可能已經爆乾淨了。
所以,要保證退出機制一定生效。開倉機會如果錯過至少不會致命,踏空了頂多惋惜,但是錯過平倉是要出大問題的。
這裏簡單說兩個解決方案,後面有空再詳細講講。
第一點,就是最好要有一個硬止損,就是類似固定虧損比例的止損。例如,大幣虧損超過 10%,小幣 15%,發生了立馬平倉跑路。
硬止損這種方法在開倉時刻就應該定下止損價位了。所以開倉後應儘快提交算法止損單(有的也叫條件單),中途無須更改價格。這樣交易所幫你負責監控實時價格,觸發之後再幫你提交市價單退場。這樣處理可能會有不少滑點,但是大概率比你自己搞的止損穩定可靠,而且就算出問題了,沒有觸發,你還可能找交易所維權索賠(所以得去頭部大交易所)。
當然,這種止損就是用來兜底的,應該極少觸發纔對,最好還是由自己的策略來控制出場時機,這樣回撤大概更小。
第二點,程序不會亂開倉。不要已經開了倉,但是卻以爲沒有,連續開倉,結果開出一個很大敞口。短時間內價格沒有波動還好,還有可能手動介入糾正,要是突然反向,就可能爆倉的,這取決於你到底開出了多少倉位。當然這種是低級錯誤,但是確實可能發生。特別是中途迭代升級了代碼之後,有可能考慮不周。
這種就需要先放慢一點開倉的節奏,必須等待開倉結果的返回。還有開倉前一定要查詢確認當時的賬戶信息,不要連續開倉,當然也可以在本地記錄所有操作,那麼就省卻一點查詢交易所自己賬號情況的 API 請求次數和時間。
還有,更有效的是,可以事先限制交易所的最大槓桿。這個是可以自己調整的。幣安默認 20 倍,你改爲 3 倍,甚至 2 倍(當然,這要求你策略本身就不使用高槓槓,不然你該開高點的時候還開不出來)。那麼代碼再怎麼發神經,也不可能在你睡覺的時候搞出來一個大敞口。這樣就比較穩妥。
總之,實盤有時候不光是交易代碼,還需要佈局一道道其他防線,防止被黑天鵝事件一下擊穿。任何時候都不能掉以輕心,儘量封住死角。