Type/to search
3
Follow
1505
Followers
Шаблон политики позволяет вам беспрепятственно использовать рынок WebSocket
Discussions
Created 2024-10-30 09:49:20  Updated 2024-11-05 17:45:31
 0
 2163

img

Это шаблон рынка WebSocket, официально разработанный FMZ. Скопируйте и сохраните его как шаблон, затем выберите этот шаблон в новой стратегии, чтобы использовать его: https://www.fmz.com/strategy/470349

Зачем нам нужен WebSocket?

В настоящее время стратегия FMZ в основном основана на традиционной инкапсуляции REST API. Каждый доступ к API требует установления сетевого соединения и получения рыночных данных посредством опроса. Этот метод прост и удобен в использовании и достаточен для большинства нужд.

Однако протокол REST имеет присущие ему проблемы с задержкой, которые будут усугубляться, когда требуется несколько торговых пар и несколько стратегий обмена. Хотя функции Go платформы могут выполняться одновременно, проблема задержки все еще существует, что затрудняет удовлетворение потребностей относительно высокочастотной стратегии торговли. Кроме того, если торговых пар слишком много, а частота опроса слишком быстро, он столкнется с ограничением частоты доступа торговой платформы.

В настоящее время серверы бирж также испытывают большую нагрузку. Все они предоставляют полноценный протокол WebSocket и рекомендуют его пользователям API. По сравнению с протоколом REST, WebSocket обеспечивает постоянный двусторонний метод соединения, который позволяет бирже передавать данные клиенту в режиме реального времени, избегая частых запросов и ответов и значительно сокращая задержку. В общем случае, если задержка доступа к REST API составляет около 20 мс, задержка передачи данных через WebSocket составляет около 2 мс. Кроме того, протокол WebSocket не ограничен частотой доступа к платформе, и в принципе можно подписаться на десятки торговых пар одновременно.

Введение в шаблон цитаты WebSocket

Количественная торговая платформа FMZ уже давно поддерживает протокол WebSocket, и он относительно удобен в использовании, но для начинающих пользователей все еще слишком сложно обрабатывать несколько подписок, подписываться на несколько биржевых котировок и эффективно и удобно встраивать их в весь процесс стратегии.
Этот публичный шаблон ускорения рыночных данных в реальном времени WebSocket решает эту проблему. Он очень прост в использовании и полностью совместим с текущими инкапсулированными вызовами API. Для большинства исходных стратегий REST вы можете просто изменить их и использовать их напрямую для ускорения ваша стратегия.

Основные характеристики:

  • Поддержка нескольких бирж:Эта стратегия поддерживает соединения WebSocket с несколькими биржами, такими как Binance, OKX, Bybit, Bitget и т. д. Пользователи могут имитировать метод упаковки этого шаблона, чтобы поддерживать больше бирж самостоятельно.
  • Настраиваемая подписка: Позволяет подписаться на определенные рыночные каналы (такие как глубина, торговля и т. д.) и эффективно обрабатывать полученные данные для немедленного использования в торговых стратегиях.
  • Расширенная обработка ошибок: Встроенный механизм отслеживания ошибок и повторного подключения WebSocket для обеспечения надежности и непрерывности потока данных.

Краткое введение в принцип реализации

Обратите внимание, что эта стратегия использует TypeScript, что может показаться немного незнакомым, если вы знакомы только с JavaScript. TypeScript представляет систему типов и более богатые языковые возможности на основе JavaScript. Для таких приложений, как количественная торговля, которым необходимо обрабатывать сложную логику, использование TypeScript может уменьшить потенциальные ошибки и улучшить читаемость и удобство обслуживания кода. Поэтому рекомендуется выучить его просто.

Кроме того, стратегия использует асинхронный механизм платформы FMZ, а механизм sub-thread может быть__Функция threadPostMessage отправляет сообщение в основной поток. Этот метод является асинхронным и подходит для уведомления основного потока об обновлениях данных, сгенерированных в дочернем потоке. Основной поток и дочерний поток могут быть соединены через__threadGetData и__Функция threadSetData обменивается данными. Такой подход позволяет потокам получать доступ к общему состоянию и изменять его. Если вы хотите узнать больше о многопоточности, эта стратегия также является хорошим примером обучения в сочетании с документацией платформы.

Основной принцип этой стратегии заключается в подключении к основным биржам цифровых валют через WebSocket и получении рыночных данных (таких как глубинная информация и информация о транзакциях) в режиме реального времени для предоставления информационной поддержки для принятия количественных торговых решений. Конкретный процесс внедрения выглядит следующим образом:

1. Настройки соединения WebSocket

setupWebsocket Эта функция используется для инициализации соединения WebSocket и получения рыночных данных. Он получает один параметрmain_exchanges, указывающий на биржу, которую необходимо подключить.

  • MyDial функция: Создайте соединение WebSocket, запишите время соединения и выведите время закрытия при закрытии соединения.
  • updateSymbols функция: Регулярно проверяйте наличие новых запросов на подписку и обновляйте текущий список торговых пар по мере необходимости.

2. Обработка данных

supports Объект определяет поддерживаемые обмены и их функции обработки (например,Binance). Функция обработки каждой биржи отвечает за анализ полученных сообщений и извлечение соответствующих данных.

  • processMsg функция: Обработка сообщений от бирж, идентификация различных типов данных (таких как обновления глубины, транзакции и т. д.) и форматирование их в унифицированные объекты событий.

3. Данные о подписке

При каждом подключении система будет подписываться на соответствующие каналы рыночных данных на основе текущей торговой пары.

  • getFunction функция: Получить соответствующую функцию обработки в соответствии с названием биржи.
  • this.wssPublic функция: Инициализируйте соединение WebSocket и начните получать данные.

4. Управление потоками

Запускайте поток для каждого обмена, получайте данные в режиме реального времени и обрабатывайте их с помощью функций обратного вызова.

  • threadMarket функция: Получение данных в дочернем потоке, анализ и сохранение последней информации о глубине и транзакциях.

5. Перепишите метод сбора данных.

Переписать методы получения глубины рынка и торговой информации для каждой биржи, отдавая приоритет возвращению данных, обновляемых в режиме реального времени.

Как использовать шаблон

  1. инициализация:использовать $.setupWebsocket() Инициализируйте соединение WebSocket с целевым обменом.
  2. подписка: Система автоматически подпишется на соответствующие каналы (такие как глубина, торговля и т. д.) для продуктов, которыми вы торгуете.
  3. Сбор данных: ПозвонивGetDepth() и GetTrades() Функция автоматически использует данные WebSocket в режиме реального времени для возврата глубины рынка и записей о транзакциях.
  4. Обработка ошибок: Политика включает механизм отслеживания, который регистрирует ошибки подключения и данных и автоматически пытается восстановить подключение в случае потери соединения.

Если функция EventLoop() будет добавлена ​​в стратегию, она будет изменена на триггерный механизм. Когда данные wss будут обновлены, они будут автоматически получены немедленно, а если последних данных нет, то будут ждать. Это эквивалентно интеллектуальной функции Sleep. Конечно, вы также можете использовать Sleep напрямую.

function main() { $.setupWebsocket() while (true) { exchanges.map(e=>{ Log(e.GetName(), e.GetDepth()) Log(e.GetName(), e.GetTrades()) }) EventLoop(100) // trigger by websocket } }

Ознакомьтесь с моим предыдущим руководством по стратегиям мультивалютной торговли https://www.fmz.com/digest-topic/10506, которое можно легко модифицировать для поддержки 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("循环出错: " + 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); } }

Как добавить новую биржу самостоятельно

Просто следуйте шаблону стратегии, имитируйте следующий формат и обратитесь к документации API биржи:

supports["Binance"] = function (ctx:ICtx) { let processMsg = function (obj) { let event = { ts: obj.E, instId: obj.s, depth: null, trades: [], } if (obj.e == "depthUpdate") { let depth = { asks: [], bids: [] } obj.b.forEach(function (item) { depth.bids.push({ price: Number(item[0]), qty: Number(item[1]) }) }) obj.a.forEach(function (item) { depth.asks.push({ price: Number(item[0]), qty: Number(item[1]) }) }) event.depth = depth } else if (obj.e == 'bookTicker') { event.depth = { asks: [{ price: Number(obj.a), qty: Number(obj.A) }], bids: [{ price: Number(obj.b), qty: Number(obj.B) }] } } else if (obj.e == 'aggTrade') { event.ts = obj.E event.trades = [{ price: Number(obj.p), qty: Number(obj.q), ts: obj.T, side: obj.m ? "sell" : "buy" }] } else if (typeof (obj.asks) !== 'undefined') { event.ts = obj.E || new Date().getTime() let depth = { asks: [], bids: [] } obj.bids.forEach(function (item) { depth.bids.push({ price: Number(item[0]), qty: Number(item[1]) }) }) obj.asks.forEach(function (item) { depth.asks.push({ price: Number(item[0]), qty: Number(item[1]) }) }) event.depth = depth } else { return } return event } let channels = ["depth20@100ms", /*"bookTicker", */"aggTrade"] let ws = null let endPoint = "wss://stream.binance.com/stream" if (ctx.name == "Futures_Binance") { endPoint = "wss://fstream.binance.com/stream" } while (true) { if (!ws) { let subscribes = [] ctx.symbols.forEach(function (symbol) { channels.forEach(function (channel) { subscribes.push(symbol.toLowerCase() + "@" + channel) }) }) ws = MyDial(endPoint + (subscribes.length > 0 ? ("?streams=" + subscribes.join("/")) : "")) } if (!ws) { Sleep(1000) continue } updateSymbols(ctx, function(symbol:string, method:string) { ws.write(JSON.stringify({ "method": method.toUpperCase(), "params": channels.map(c=>symbol.toLowerCase()+'@'+c), "id": 2 })) }) let msg = ws.read(1000) if (!msg) { if (msg == "") { trace("websocket is closed") ws.close() ws = null } continue } if (msg == 'ping') { ws.write('pong') } else if (msg == 'pong') { } else { let obj = JSON.parse(msg) if (obj.error) { trace(obj.error.msg, "#ff0000") continue } if (!obj.stream) { continue } if (obj.stream.indexOf("depth") != -1) { if (typeof(obj.data.s) !== 'string') { // patch obj.data.s = obj.stream.split('@')[0].toUpperCase() } } let event = processMsg(obj.data) if (event) { ctx.callback(event) } } } }
Comment
All comments (0)
No data
No data
  • 1
iPhone Download
Forums
PINE Language
© 2015 - ∞ INVENTOR PTE LTD (SG)