Basicamente, todas as exchanges de moeda digital suportam o envio de websocket, e algumas exchanges suportam a atualização de informações de conta do websocket. Em comparação com a rest API, a websocket geralmente tem um atraso baixo, alta frequência, não é limitada pela frequência da rest API da plataforma, o inconveniente é que há problemas de interrupção e o processamento não é intuitivo. https://zhuanlan.zhihu.com/p/22693475
Este artigo irá abordar principalmente a plataforma de quantificação dos inventores do FMZ, usando o JavaScript, usando a função Dial embutida na plataforma para conectar, com especificações e parâmetros no documento, a busca no Dial, que foi atualizada várias vezes para implementar várias funções. Este artigo irá cobrir isso e abordar a estratégia de direção de eventos baseada no wss, bem como a questão de conectar várias exchanges.
Em geral, a conexão é direta, como o envio de ticker de segurança de moeda:
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr")
Para que os dados retornados sejam em formato de compressão, é necessário especificar o formato de compressão na conexão, comprimir especifica o formato de compressão, o modo representa o envio de dados retornados que precisam ser comprimidos, como a conexão OKEX:
var client = Dial("wss://real.okex.com:10441/websocket?compress=true|compress=gzip_raw&mode=recv")
A função Dial suporta a reconexão, feita pela linguagem Go de nível inferior, a detecção da conexão desligada e a reconexão, é conveniente e recomendada para o conteúdo de dados solicitados já no url, como o exemplo de Binance recentemente. Para aqueles que precisam enviar mensagens por encomenda, o mecanismo de reconexão pode ser mantido por conta própria.
var client = Dial("wss://stream.binance.com:9443/ws/!ticker@arr|reconnect=true")
Para subscrever as mensagens do wss, algumas das exchanges pedem no url, e também há alguns canais que precisam enviar suas próprias assinaturas, como a coinbase:
client = Dial("wss://ws-feed.pro.coinbase.com", 60)
client.write('{"type": "subscribe","product_ids": ["BTC-USD"],"channels": ["ticker","heartbeat"]}')
O código é o seguinte:
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 data push é muito rápido, o nível de base do Go vai guardar todos os dados na fila, quando o programa é chamado de leitura, e depois retornar. E a operação de encomenda do robô vai trazer atrasos, o que pode causar acumulação de dados. Para o envio de transações, o envio de contas, o envio de inserções de profundidade, etc., precisamos de dados históricos, para os dados atuais, a maioria das vezes só nos preocupamos com os mais recentes, não nos preocupamos com os dados históricos.
read() se não adicionar um parâmetro, retornará o dado mais antigo, bloqueado para retornar quando não há dados. Se você quiser dados mais recentes, você pode usar client.read(-2) para retornar os dados mais recentes imediatamente, mas retornará null quando não houver mais dados, precisando de julgamento e referência.
Dependendo de como tratar os dados antigos armazenados no cache, e se eles estão bloqueados quando não há dados, o read possui diferentes parâmetros, como o gráfico abaixo, que parece complicado, mas permite maior flexibilidade no programa.

Para este tipo de situação, o procedimento não pode ser simplesmente usado, pois uma bolsa bloqueia a mensagem em espera, enquanto a outra bolsa não recebe a mensagem, mesmo que haja uma nova. O procedimento geral é:
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
}
}
Esta parte do processamento é um pouco problemático, porque o envio de dados pode ser interrompido, ou o envio de atraso é muito alto, mesmo que possa receber o heartbeat não significa que os dados ainda estão sendo enviados, você pode configurar um intervalo de evento, se exceder o intervalo sem receber atualizações, re-conecte-se, e é melhor comparar o resultado com o rest retornado em um período de tempo para ver se os dados estão corretos. Para este caso especial, o envio de moeda pode ser configurado diretamente.
Uma vez que os dados de push já foram usados, o programa também deve ser escrito como um driver de eventos, observe que os dados de push são frequentes e não são bloqueados com muitas solicitações, geralmente pode ser escrito como:
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)
}
}
O modo de conexão, o modo de envio de dados, o conteúdo de assinatura e o formato de dados de cada plataforma geralmente são diferentes, então a plataforma não é encapsulada e precisa se conectar automaticamente com a função Dial. Este artigo abrange basicamente alguns cuidados básicos.
PS. Algumas casas de câmbio não oferecem websocket, mas quando você acessa o site e usa a função de modelagem, você descobre que eles usam o websocket push. Se você pesquisar, você encontrará o formato de assinatura e o formato de retorno. Algumas parecem criptografadas e podem ser decodificadas com base64.