Hầu hết các sàn giao dịch tiền điện tử hỗ trợ gửi dữ liệu thị trường qua WebSocket, và một số sàn giao dịch cũng hỗ trợ cập nhật thông tin tài khoản qua WebSocket. So với REST API, WebSocket thường có độ trễ thấp hơn, tần số cao hơn và không phải chịu giới hạn tốc độ API nghỉ của nền tảng. Tuy nhiên, nó có nhược điểm của sự gián đoạn tiềm ẩn và xử lý ít trực quan hơn.
Bài viết này chủ yếu giới thiệu việc sử dụng chức năng Dial, được đóng gói trong nền tảng FMZ Quant sử dụng ngôn ngữ JavaScript. Các hướng dẫn và tham số cụ thể có thể được tìm thấy trong tài liệu bằng cách tìm kiếm
Một kết nối trực tiếp thường là đủ, chẳng hạn như nhận được một xu bảo mật ticker push:
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
Khi dữ liệu được trả về ở định dạng nén, nó cần phải được chỉ định trong quá trình kết nối.
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 xử lý bởi ngôn ngữ Go cơ bản. Nó tự động kết nối lại khi kết nối được phát hiện bị ngắt kết nối. Đối với trường hợp dữ liệu yêu cầu đã được bao gồm trong URL, chẳng hạn như ví dụ trước đây với Binance, nó rất thuận tiện và được khuyến cáo sử dụng. Tuy nhiên, đối với trường hợp cần gửi tin nhắn đăng ký, nên duy trì cơ chế kết nối lại bằng tay.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
Đăng ký cho các tin nhắn wss, một số sàn giao dịch có yêu cầu trong url, và cũng có các kênh mà bạn cần phải gửi đăng ký của riêng bạn, chẳng hạn như coinbase:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
Nói chung, nó có thể được đọc liên tục trong một vòng lặp vô hạn.
function main() {
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr");
while (true) {
var msg = client.read()
var data = JSON.parse(msg) // Parse json strings into quotable objects
// Process data
}
}
Tốc độ đẩy dữ liệu wss rất nhanh. Lớp dưới của Golang sẽ lưu trữ tất cả dữ liệu trong hàng đợi, và khi các cuộc gọi của chương trình được đọc, dữ liệu sẽ được trả về. Tuy nhiên, các hoạt động như đặt lệnh trên bot sẽ gây chậm trễ, có thể dẫn đến sự tích lũy dữ liệu. Đối với thông tin như đẩy thực thi giao dịch, đẩy tài khoản và đẩy can thiệp chiều sâu, chúng tôi cần dữ liệu lịch sử. Đối với dữ liệu thị trường báo giá, trong hầu hết các trường hợp, chúng tôi chỉ quan tâm đến dữ liệu mới nhất, không phải dữ liệu lịch sử.
Nếu read() không thêm các tham số, nó sẽ trả về dữ liệu cũ nhất, và chặn cho đến khi trả về khi không có dữ liệu. Nếu bạn 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, nó sẽ trả về null, cần phải được đánh giá trước khi tham chiếu.
Tùy thuộc vào cách xử lý dữ liệu lưu trữ tạm thời cũ và liệu nó có bị chặn khi không có dữ liệu,
Trong trường hợp này, rõ ràng rằng chỉ cần sử dụng
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) // Parameter -1 represents no data and return null immediately; it will not occur that being blocked before there is data to be returned
var msgCoinbase = coinbase.read(-1)
if(msgBinance){
// at this time, Binance has data to return
}
if(msgCoinbase){
// at this time, coinbase has data to return
}
Sleep(1) // Sleep for 1 millisecond
}
}
Phần này của quá trình xử lý khó khăn hơn, bởi vì dữ liệu đẩy có thể bị gián đoạn, hoặc thời gian trì hoãn đẩy cực kỳ dài. Ngay cả khi nhịp tim có thể được nhận, điều đó không có nghĩa là dữ liệu vẫn đang được đẩy. Bạn có thể đặt khoảng thời gian sự kiện; nếu không nhận được cập nhật sau khoảng thời gian, kết nối lại; tốt nhất là so sánh kết quả được trả về bởi
Đối với dữ liệu đẩy đã được sử dụng, chương trình sẽ tự nhiên được viết như sự kiện kích hoạt; chú ý đến tần suất đẩy dữ liệu, bởi vì các yêu cầu tần số cao sẽ dẫn đến việc bị chặn; nói chung bạn có thể viết:
var tradeTime = Date.now()
var accountTime = Date.now()
function trade(data){
if(Date.now() - tradeTime > 2000){//Here it limits only one trade in 2 seconds
tradeTime = Date.now()
// Trading logic
}
}
function GetAccount(){
if(Date.now() - accountTime > 5000){//Here it limits GetAccount only once in 5 seconds
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)
}
}
Phương pháp kết nối, phương pháp truyền dữ liệu, nội dung đăng ký và định dạng dữ liệu của websocket trên mỗi nền tảng thường khác nhau, vì vậy nền tảng không đóng gói nó và cần sử dụng chức năng Dial để kết nối một mình.
PS: Mặc dù một số nền tảng không cung cấp trích dẫn websocket, trên thực tế, khi bạn đăng nhập vào trang web để sử dụng chức năng gỡ lỗi, bạn sẽ thấy rằng tất cả chúng đều sử dụng websocket push. Sau khi nghiên cứu, bạn sẽ thấy rằng một số định dạng đăng ký và định dạng trả về dường như được mã hóa, có thể được nhìn thấy bằng cách giải mã và giải nén với base64.