Este é um modelo de mercado WebSocket oficialmente desenvolvido pela FMZ.https://www.fmz.com/strategy/470349
Atualmente, a estratégia FMZ baseia-se principalmente no encapsulamento tradicional da API REST. Cada etapa do acesso à API requer que uma conexão de rede seja estabelecida e os dados do mercado são obtidos por meio de pesquisa.
No entanto, o protocolo REST tem um problema de atraso inerente. Quando vários pares de negociação e estratégias de troca múltiplos são necessários, o problema de atraso será ampliado. Embora a função Go da plataforma possa ser executada simultaneamente, o problema de atraso ainda existe, o que torna difícil atender às necessidades de negociação de estratégia de frequência relativamente alta. Além disso, se houver muitos pares de negociação e a frequência de votação for muito rápida, ele encontrará o limite de frequência de acesso da plataforma de negociação.
Atualmente, os servidores das exchanges também estão sob grande carga. Todos eles fornecem um protocolo WebSocket completo e o recomendam aos usuários da API. Em comparação com o protocolo REST, o WebSocket fornece um método de conexão bidirecional persistente, que permite que as exchanges empurrem dados para o cliente em tempo real, evitando solicitações e respostas frequentes, reduzindo assim muito a latência. Geralmente, se o atraso no acesso à API REST for de cerca de 20ms, o atraso no envio de dados através do WebSocket é de cerca de 2ms. Além disso, o link para o protocolo WebSocket não é limitado pela frequência de acesso à plataforma e é possível se inscrever em dezenas de pares de negociação ao mesmo tempo.
A plataforma FMZ Quant Trading suporta o protocolo WebSocket há muito tempo, e é relativamente conveniente para chamar, mas para usuários novatos, ainda é muito complicado lidar com múltiplas assinaturas, assinar vários tickers de troca e incorporá-los de forma eficiente e conveniente em todo o processo de estratégia. Este modelo público de aceleração de dados de ticker em tempo real do WebSocket resolve este problema. É muito fácil de usar e é totalmente compatível com a chamada de API encapsulada atual. Para a maioria das estratégias REST originais, você pode simplesmente modificá-las e usá-las diretamente para acelerar sua estratégia.
Características principais:
Observe que esta estratégia usa TypeScript. Se você está apenas familiarizado com JavaScript, pode parecer um pouco estranho. O TypeScript introduz um sistema de tipos e recursos de linguagem mais ricos baseados no JavaScript. Para aplicações como negociação quantitativa que precisam lidar com lógica complexa, o uso do TypeScript pode reduzir possíveis erros e melhorar a legibilidade e a manutenção do código. Portanto, recomenda-se aprendê-lo brevemente.
Além disso, a estratégia usa o mecanismo assíncrono da plataforma FMZ. O thread filho pode enviar mensagens para o thread principal através da função __threadPostMessage. Este método é assíncrono e é adequado para notificar o thread principal de atualizações de dados geradas no thread filho. O thread principal e o thread filho podem compartilhar dados através das funções __threadGetData e __threadSetData. Este método permite que os threads acessem e modifiquem estados compartilhados.
O principal princípio desta estratégia é conectar-se às principais bolsas de moeda digital através do WebSocket e receber dados de mercado (como informações de profundidade e informações de transação) em tempo real para fornecer suporte de dados para decisões quantitativas de negociação.
1. Configurações de conexão WebSocketA funçãosetupWebsocket
é usado para inicializar uma conexão WebSocket e receber dados de mercado.main_exchanges
, indicando a central para se conectar.
MyDial
função: Criar uma conexão WebSocket, gravar o tempo de conexão e a saída do tempo de fechamento ao fechar a conexão.updateSymbols
função: Verifique regularmente se existem novos pedidos de subscrição e atualize a lista de pares de negociação atual conforme necessário.2. Processamento de dadosO objetosupports
Define as trocas suportadas e a sua função de processamento (comoBinance
A função de processamento de cada intercâmbio é responsável pela análise da mensagem recebida e pela extracção dos dados relevantes.
processMsg
função: Processar mensagens de trocas, identificar diferentes tipos de dados (como atualizações de profundidade, transações, etc.) e formatá-los em um objeto de evento unificado.3. Dados de subscriçãoEm cada ligação, o sistema subscreverá os canais de dados de mercado relevantes com base no par de negociação actual.
getFunction
funçãoObtenha a função de processamento correspondente de acordo com o nome da troca.this.wssPublic
função: Iniciar a conexão WebSocket e começar a receber dados.4. Gestão de fiosIniciar um tópico para cada troca, receber dados em tempo real e processar os dados através de funções de callback.
threadMarket
funçãoRecepção de dados em um tópico filho, análise e armazenamento das últimas informações de profundidade e transação.5. Reescrever o método de aquisição de dadosReescrever os métodos para obter informações de profundidade e de negociação para cada bolsa, dando prioridade ao retorno de dados atualizados em tempo real.
$.setupWebsocket()
para inicializar a conexão WebSocket do exchange de destino.GetDepth()
eGetTrades()
funções, a profundidade do mercado e registos de transações são devolvidos automaticamente usando dados WebSocket em tempo real.Se a função EventLoop() for adicionada à estratégia, ela será alterada para um mecanismo de gatilho. Quando houver uma atualização de dados wss, ela será obtida automaticamente imediatamente, e espera se não houver dados mais recentes. É equivalente a uma função de sono inteligente. Claro, você também pode usar o sono diretamente.
function main() {
$.setupWebsocket()
while (true) {
exchanges.map(e=>{
Log(e.GetName(), e.GetDepth())
Log(e.GetName(), e.GetTrades())
})
EventLoop(100) // trigger by websocket
}
}
Consulte o meu guia anterior de estratégia de negociação de várias moedas:https://www.fmz.com/bbs-topic/10508, que pode ser modificado facilmente para suportar WebSocket:
function MakeOrder() {
for (let i in Info.trade_symbols) {
let symbol = Info.trade_symbols[i];
let buy_price = exchange.GetDepth(symbol + '_USDT').Asks[0].Price;
let buy_amount = 50 / buy_price;
if (Info.position[symbol].value < 2000){
Trade(symbol, "buy", buy_price, buy_amount, symbol);
}
}
}
function OnTick() {
try {
UpdatePosition();
MakeOrder();
UpdateStatus();
} catch (error) {
Log("loop error: " + error);
}
}
function main() {
$.setupWebsocket()
InitInfo();
while (true) {
let loop_start_time = Date.now();
if (Date.now() - Info.time.last_loop_time > Info.interval * 1000) {
OnTick();
Info.time.last_loop_time = Date.now();
Info.time.loop_delay = Date.now() - loop_start_time;
}
Sleep(5);
}
}