基本的にはすべての仮想通貨取引所がwebsocketの送付行情をサポートしており,一部の取引所ではwebsocketの更新アカウント情報をサポートしている.rest APIと比較して,websocketは一般的に遅延が低く,頻度が高く,プラットフォームrest APIの頻度制限などから解放されている.欠点は,中断の問題があり,処理は直感的ではない.websocketの概要については,以前この記事を参照してください: https://zhuanlan.zhihu.com/p/22693475
この記事では,主にFMZの発明者による量化プラットフォーム,JavaScript言語,プラットフォームの封装されたDial関数を使用して接続する,詳細とパラメータをドキュメントで,検索Dial,様々な機能を実現するために,Dial関数は何度か更新されました.この記事は,この点をカバーし,wssベースのイベント駆動の戦略,および複数の取引所の接続の問題について説明します.
コインのセキュリティティッカーの推送など,一般的には直接接続できます.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
返されるデータが圧縮形式である場合,接続時に指定する必要があります.compressは圧縮形式を指定し,modeは返されるデータを送信するときに圧縮される必要があります.例えば,接続OKEX:
var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
Dial関数は再接続をサポートし,底層のGo言語で完了し,検出された接続断絶会再接続,リクエストデータコンテンツが既にurlにある場合,例えば今度のBinanceの例のように,便利で,使用が推奨されます. メッセージを送信する必要がある場合,再接続メカニズムを自分で維持できます.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
コインベース (coinbase) のようなチャンネルは,自己登録の必要性がある:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
このコードは,通常,デッドループで読み取れます.
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
while (true) {
var msg = client.read()
var data = JSON.parse(msg) //把json字符串解析为可引用的object
// 处理data数据
}
}
wssのデータプッシュは高速で,Goの底層はすべてのデータをキューブに保存し,等プログラムがreadを呼び出すとき,次々に返します。そして,ロボットの下位命令のような操作は,遅延をもたらし,データの蓄積を引き起こす可能性があります。交付プッシュ,アカウントプッシュ,深度挿入値プッシュなどの情報には,歴史データが必要で,実態データについては,ほとんどの場合,最新のデータだけを気にせず,歴史データに関心を持たない。
read() が参数加えなければ,最も古いデータが返され,データがない場合は返されるまでブロックされます。最新データが必要な場合は,client.read(-2) ですぐに最新のデータが返され,データがない場合はnullが返され,判断して再引用する必要があります。
read は,キャッシュされた古いデータをどのように扱うか,また,データがないときにブロックされるかどうかによって,異なるパラメータを持つ.具体的には,以下の図のように,複雑に見えますが,プログラムをより柔軟にします.

このような場合,単純にread () を使うことは明らかにできない,なぜなら,ある取引所が待機しているメッセージをブロックし,その間,他の取引所が新しいメッセージがあったとしても受信できないからです.一般的処理方法は:
function main() {
var binance = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
var coinbase = Dial("wss://ws-feed.pro.coinbase.com", 60)
coinbase.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
while (true) {
var msgBinance = binance.read(-1) // 参数-1代表无数据立即返回null,不会阻塞到有数据返回
var msgCoinbase = coinbase.read(-1)
if(msgBinance){
// 此时币安有数据返回
}
if(msgCoinbase){
// 此时coinbase有数据返回
}
Sleep(1) // 可以休眠1ms
}
}
この部分では処理が面倒であるため,推送データは中断したり,推送遅延が非常に高く,ハートビットを受信してもデータが推送されているわけではない.イベント間隔を設定し,更新が受信されていない間隔を超えた場合は再接続し,しばらくの間,restと返された結果と比較してデータの正確さを確認する.この特殊なケースでは,直接自動再接続を設定できます.
推送データを使用しているため,プログラムも自然にイベントドライブに書き込む必要があります. 推送データの頻度に注意し,過度の要求によって封鎖されないように注意してください. 一般的に次のように書き込むことができます.
var tradeTime = Date.now()
var accountTime = Date.now()
function trade(data){
if(Date.now() - tradeTime > 2000){//这里即限制了2s内只交易一次
tradeTime = Date.now()
//交易逻辑
}
}
function GetAccount(){
if(Date.now() - accountTime > 5000){//这里即限制了5s内只获取账户一次
accountTime = Date.now()
return exchange.GetAccount()
}
}
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true");
while (true) {
var msg = client.read()
var data = JSON.parse(msg)
var account = GetAccount()
trade(data)
}
}
各取引所のwebsocketの接続方法,データ送信方法,購読可能なコンテンツ,データフォーマットは,しばしば異なっています.したがって,プラットフォームはパッケージ化されず,ダイアル関数を使用して自主接続する必要があります.この文章は,基本的にはいくつかの基本的な注意事項をカバーしています.もし疑問があれば,質問をお願いします.
PS.一部の取引所はWebSocketの行方を提供していないが,実際にWebSocketの設定機能を利用したサイトにアクセスすると,WebSocketの推送が使用されていることがわかります.調べてみると,サブスクリプションフォーマットと返却フォーマットが見られます.