閒扯比特幣套利交易系統的設計
關於比特幣套利交易的文章,坊間一搜一大堆,尤以2014,2015 為甚。那時交易所間價差相當可觀,套利的機會很多,躺著賺錢並非難事。如今,套利區間收窄,留在沙場上的估計只剩下大玩家,想要不費力氣躺贏機會渺茫。最近幫朋友牽線尋找幣圈量化交易的機會,本欲做個打醬油的中間人,事了拂衣去,安安靜靜做個三河市微胖界扛把子,誰料還是一時技癢,不小心昨夜搭進去六七個小時。
關於如何做套利交易,我就不贅述,大家可以看這篇文章,有內容有故事:https://daily.zhihu.com/story/4831821。
本文沒有故事,只有技術和產品上的分析。
既然要做可行性分析,那麼第一步就是觀察交易數據。國內的交易市場雖然在政策要求下清場出局,國外的交易市場還算紅火。從bitfinex,kraken 一路到bithumb,korbit 等,都提供rest API,少量提供websocket 接口。雖然文檔欠缺,但這些接口都很簡單,上手並不困難。
用nodejs 小試牛刀後,我決定全面使用elixir 重寫。
這麼做有幾個原因:
單就數據抓取來說,需要一些內部的micro service。比如bithumb / korbit 的報價是韓元,而其他都是美元。如果用美元統一,那勢必要有一個穩定的內部service 提供這種轉換。erlang / OTP 的結構,天然呆萌,阿不,天然鬆散,各個GenServer 自成一體,很適合這樣的需求。
數據的抓取和數據的處理我想分開來做。在定期從各個交易市場拿到數據後,我們可以使用pubsub 結構把數據publish 出去,然後讓各個子系統去subscribe —— 找交易機會的去算交易機會,做持久化的去寫數據庫,以後想到什麼新的消費數據的姿勢,隨時可加入新的subscriber。如果用別的語言,少不了再引入ZeroMQ 這樣的依賴(引入複雜性和其他問題)。erlang / OTP 有process group,適合pubsub,而phoenix_pubsub 對此已精巧封裝,開箱即用。
erlang / OTP 的容錯和並發/並行能力能讓效率大大提高。
because I can - Insider Man (2006)。
數據抓取出來後,可算出一些隨著時間變化的,理論上的套利空間(真正做是另一回事),但數據本身太抽象,不足以打動自己,打動別人。比如說,過去1 小時有10 個大於0.5% 的套利機會(扣除雙邊的手續費也就剩不到0.1%),這樣的機會究竟可行性如何,長得什麼樣,無從得知。
廣東十大傑出青年方世玉他媽苗翠花說:行走江湖,最重要的就是一個「顏」字。乾癟的數字,枯燥的理論如同一具具骷髏,即便切中要害,也很難在產品汪和商務喵身上找到共鳴。所謂無圖不丈夫,不搞點UI,整些可視化,金礦也會被掩埋在黃土之下。《奮鬥》裡陸濤他爹怕他對三十萬元這樣一個數字沒有概念,叫人取出現銀,裝一大紙袋裡給他,這就是可視化。
但構建一套擴展性好的可視化UI 豈非一日之功?你好不容易整個chart 支持line / bar / area 和multiple series,做著做著可能又要在兩個series 之間做四則運算,之後可能需要更加複雜的操作。本來塗脂抹粉裝個大家閨秀就是個權宜之計,結果一入前端深似海,從此變更永纏身。所以,不到萬不得已,別自己做可視化。我試過幾個比特幣套利交易的開源代碼,UI 相當一般,擴展性很差,吃力不討好。
不自己做,那誰來做?
平日里我工作,接觸多的是datadog。datadog 是做性能監控的,我們只管打點,存儲和可視化交給datadog。雖然它和量化交易八竿子打不著,但如果我們卻可以把這顏值擔當交給datadog 來試試看。
打點很簡單,寫個subscriber,監聽爬下來的數據,然後這麼寫入datadog:
abt.xchg.btc.bid:4182|h|#bitfinex
abt.xchg.dsh.bid:344.38|h|#bitfinex
abt.xchg.eth.bid:301.93|h|#bitfinex
abt.xchg.xmr.bid:97.762|h|#bitfinex
abt.xchg.xrp.bid:0.2023|h|#bitfinex
abt.xchg.zec.bid:299.22|h|#bitfinex
abt.xchg.btc.bid:4009.071877180739|h|#bithumb
abt.xchg.dsh.bid:330.42568039078856|h|#bithumb
abt.xchg.eth.bid:288.8171667829728|h|#bithumb
abt.xchg.xmr.bid:93.35310537334263|h|#bithumb
abt.xchg.xrp.bid:0.1936496859734822|h|#bithumb
...
我們為每個幣種提供一個metrics,以交易所的名字做tag,一個batch 把同一時間獲取的數據push 到datadog。這樣,我們就可以可視化出這樣的結果:
很明顯,就比特幣來說,bitfinex 和bithumb 間有足夠的套利機會:
這個圖是將兩個series 相減,其差異換算成百分比得到的,所以縱軸是百分之幾。datadog 深耕於APM 市場多年,對此在UI 上已有支持,我們直接可以編輯操作,暖不暖心?
《讓子彈飛》裡張麻子問:什麼TMD 是以圖服人?方世玉他媽的親家公答:我這就是以圖服人。現在套利的區間一路了然。我們看所有幣種的機會:
機會有,但有沒有可能兌現,是另一回事,不在本文討論之列。而且目前只有少量的數據,還不充分。
看到這裡我們再梳理一下這個系統的架構:
系統有四個Application,Exchanges負責抓取數據並publish,Catcher負責持久化數據(寫入datadog或influxdb),Simulator負責模擬交易(目前僅考慮實時數據的模擬交易,以後應該考慮對歷史數據模擬交易) ,Trader則真正把一個個合適的機會轉化為交易Exchanges和Catcher已經基本實現,Simulator考慮實現,Trader再說Simulator可以根據一些配置的條件動態生成交易員(有點像遊戲中的NPC),接受實時數據並尋找各自的交易機會(使用真實的交易手續費,以及模擬各種延遲),每當產生交易,交易的數據和交易後的總市值會push到datadog,最後可以在datadog裡生成一個實時群芳譜,看看Ada,Bella,Clare,Daisy一干人等究竟誰牛系統的容錯性不錯,理論上任何部分crash都會自我修復,不會有致命影響(比如publisher掛掉,當前時刻沒法出去的數據會丟,可能丟失一些交易機會 )
下圖是exchanges_app 的skeleton:
在Catcher 裡,我們除了把數據寫入datadog,還打算寫入influxdb,這是為何?我雖然很喜歡datadog,但它的專長是APM,數據的發送有很長的延時(默認20s),也就是說你一個batch 寫進去的數據,先本地UDP 給到了datadog agent,agent 悠哉悠哉晾你一下,覺著差不多了,再發送給datadoghq。這個延時對事後分析來說無傷大雅,但如果盯盤,就不那麼舒服了。而influxdb 完全由我們自己控制,不存在這個問題。這是其一。
我上次使用influxdb / grafana 已是一年前,最近聽人說起grafana 也引入alarm 的功能,正好這個項目可以把它們拾起來好好研究。influxdb / grafana 實時性比較好,可以讓一些操作直接在grafana 裡完成,比如用查詢語句尋找交易機會,然後trigger 一個alarm,alarm 的endpoint 是一個webhook,在webhook 裡進行交易。這樣的話,發現交易機會的公式只要可以用query 寫出來,就不必寫代碼,大大增強系統的靈活性和可擴展性。這是其二。
目前總共撰寫近700 行代碼,大約花費五六個小時。一些感悟:
善用工具。有些工具,就像本文中的datadog,從另一個角度去使用它,會有意想不到的收穫。
我們的時間真的彈性很大,與其說「沒有時間」,不如說「我沒興趣」,或者說「它不重要」。昨晚從7:30 算起,到凌晨1點多我睡,中間我有半個小時1:1,以及一個多小時的new hire training。平日里我如果花上兩個小時和同事開會或者探討問題,那麼那晚我就會累得什麼都不想做,早早上床休息。然而昨夜我硬是擠出時間精神高度集中地寫代碼。
合適的挑戰可以勾起一個人的興趣,然後一切就可以自然流動。
轉貼自: 煉數成金
留下你的回應
以訪客張貼回應