Về cơ bản, tất cả các sàn giao dịch tiền kỹ thuật số đều hỗ trợ websocket gửi đi, một số sàn giao dịch hỗ trợ thông tin cập nhật tài khoản websocket. So với Rest API, websocket thường có độ trễ thấp, tần số cao, không bị giới hạn tần số Rest API của nền tảng, nhược điểm là có vấn đề gián đoạn, xử lý không trực quan. https://zhuanlan.zhihu.com/p/22693475
Bài viết này sẽ chủ yếu giới thiệu về nền tảng định lượng của nhà phát minh FMZ, sử dụng ngôn ngữ JavaScript, sử dụng hàm Dial được đóng gói trong nền tảng để kết nối, chi tiết và tham số trong tài liệu, tìm kiếm Dial, hàm Dial đã được cập nhật một vài lần để thực hiện các chức năng khác nhau, bài viết này sẽ bao gồm điều này và giới thiệu về chiến lược điều khiển sự kiện dựa trên wss, và các vấn đề liên kết nhiều sàn giao dịch.
Thông thường, bạn có thể kết nối trực tiếp, chẳng hạn như nhận được ticker bảo mật tiền tệ:
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
Đối với dữ liệu được trả về là định dạng nén, cần phải được chỉ định trong kết nối, compress chỉ định định dạng nén, mode đại diện cho gửi dữ liệu trở lại cần được nén, như kết nối OKEx:
var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
Chức năng Dial hỗ trợ kết nối lại, được thực hiện bởi ngôn ngữ Go cấp dưới, kết nối bị ngắt kết nối sẽ được kết nối lại, rất tiện lợi và được đề nghị sử dụng cho nội dung dữ liệu yêu cầu đã có trong url, như ví dụ của Binance vừa qua. Đối với những người cần gửi tin nhắn đặt hàng, bạn có thể tự duy trì cơ chế kết nối lại.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
Đăng ký tin tức wss, một số sàn giao dịch yêu cầu trong url, và một số kênh cũng yêu cầu gửi đăng ký riêng, như coinbase:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
Có thể đọc liên tục trong vòng lặp chết, mã như sau:
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 đẩy dữ liệu rất nhanh, tầng dưới của Go sẽ lưu tất cả dữ liệu trong hàng đợi, các chương trình gọi read, và sau đó quay trở lại. Các hoạt động như đặt hàng của robot sẽ dẫn đến sự chậm trễ, có thể gây ra sự tích lũy dữ liệu. Đối với chuyển giao đẩy, đẩy tài khoản, đẩy giá trị sâu, chúng tôi cần dữ liệu lịch sử, đối với dữ liệu thực tế, chúng tôi chỉ quan tâm đến dữ liệu mới nhất, không quan tâm đến dữ liệu lịch sử.
read() nếu không thêm tham số, sẽ trả về dữ liệu cũ nhất, nếu không có dữ liệu, sẽ bị chặn để trả về. Nếu muốn dữ liệu mới nhất, bạn có thể sử dụng client.read(-2) để trả về dữ liệu mới nhất ngay lập tức, nhưng khi không có dữ liệu, trả về null, cần phải đánh giá và tham khảo.
Read có các tham số khác nhau, tùy thuộc vào cách xử lý dữ liệu cũ trong bộ nhớ cache và có bị tắc khi không có dữ liệu hay không, cụ thể như hình dưới đây, có vẻ phức tạp, nhưng cho phép chương trình linh hoạt hơn.

Đối với trường hợp này, rõ ràng là không thể sử dụng read () đơn giản trong quy trình, vì một sàn giao dịch sẽ chặn tin nhắn chờ đợi, trong khi sàn giao dịch khác sẽ không nhận được tin nhắn ngay cả khi có tin tức mới.
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
}
}
Phần xử lý này khá rắc rối, vì dữ liệu đẩy có thể bị gián đoạn hoặc chậm trễ rất cao, ngay cả khi nhận được heartbeat không có nghĩa là dữ liệu vẫn đang được đẩy, bạn có thể thiết lập một khoảng thời gian sự kiện, nếu vượt quá khoảng thời gian không nhận được cập nhật, hãy kết nối lại, và tốt nhất là so sánh kết quả với rest trở lại sau một thời gian để xem dữ liệu có chính xác không. Đối với trường hợp đặc biệt này, bạn có thể thiết lập tự động kết nối lại trực tiếp.
Vì đã sử dụng dữ liệu đẩy, chương trình tự nhiên phải được viết thành ổ đĩa sự kiện, lưu ý rằng dữ liệu đẩy thường xuyên, không cần quá nhiều yêu cầu dẫn đến bị chặn, thường có thể được viết như sau:
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)
}
}
Cách kết nối websocket của các sàn giao dịch, cách gửi dữ liệu, nội dung có thể đăng ký và định dạng dữ liệu thường khác nhau, vì vậy nền tảng không được đóng gói và cần kết nối tự động bằng hàm Dial. Bài viết này về cơ bản bao gồm một số lưu ý cơ bản.
PS. Một số sàn giao dịch mặc dù không cung cấp websocket, nhưng thực sự truy cập trang web sử dụng chức năng định dạng, bạn sẽ thấy rằng tất cả đều sử dụng websocket push, nghiên cứu sẽ tìm thấy định dạng đăng ký và định dạng trả về.