Transcription
Всем привет!
В прошлом уроке было показано, как обрабатываются и анализируются данные с помощью пакета pandas. Следующий шаг в разработке торгового терминала заключается в том, чтобы научиться взаимодействовать с биржами.
Поэтому в данном уроке речь пойдёт о пакетах Python для взаимодействия с биржами BitMEX и Binance. Начнём с биржи BitMEX. Для взаимодействия с этой биржей первым делом следует установить соответствующие файлы. Для этого выполните команду: pip install bitmex. В результате будет установлено два пакета и два модуля. Из этих файлов в скрипте достаточно подключить один модуль под названием bitmex.
Следующий шаг заключается в аутентификации или, проще говоря, в подключении к бирже. Для подключения необходимо иметь API ключ и секрет, которые создаются в аккаунте на бирже. Всё это передаётся функции bitmex из одноимённого модуля. Кроме того, параметру test можно передать логическое значение. По умолчанию параметр имеет значение True, что означает подключение к тестовой бирже BitMEX. Для подключения к реальной бирже параметру необходимо передать значение False.
Функция bitmex возвращает экземпляр класса SwaggerClient, с помощью которого реализуется дальнейшее взаимодействие с биржей. Разберём следующий пример. В этом скрипте реализована покупка контрактов XBTUSD со вторым кредитным плечом на 50 процентов от капитала. После подключения к бирже BitMEX взаимодействие с ней происходит по одному шаблону.
Возьмём, к примеру, выражение для установки кредитного плеча. Это выражение можно разделить на три части. Первая часть — это обращение к атрибуту Position из экземпляра класса SwaggerClient. Обратившись к атрибуту, получим экземпляр класса ResourceDecorator. Из этого объекта можно вызвать метод Position_updateLeverage. Это вторая часть выражения.
Методу следует передать название контракта и размер кредитного плеча. Возвращает метод экземпляр класса HttpFuture, из которого можно вызвать ещё один метод result. Причём этому методу не нужно передавать аргументы. Вызов метода result — это третья и заключительная часть выражения. В данном случае благодаря вызову метода result в аккаунте на бирже для указанного контракта обновилось кредитное плечо.
Таким образом, взаимодействие с BitMEX (без учёта аутентификации) можно свести к шаблону из трёх этапов: обращение к некоторому атрибуту из экземпляра класса SwaggerClient, затем вызов некоторого метода из экземпляра класса ResourceDecorator, и в конце вызов метода result из экземпляра класса HttpFuture.
По такому шаблону в этом скрипте, помимо установки плеча, происходит получение информации о депозите, получение цен «бид» и «аск» контракта, а также открытие длинной позиции. Все эти запросы предполагают соответствующий ответ от биржи. Метод result возвращает кортеж из двух элементов. Ответом биржи является первый элемент кортежа. Это всегда словарь или список из словарей.
Возвращаемые в ответ от биржи словари содержат полезную информацию. В этом примере из таких словарей извлекается размер свободной маржи, цена «аск» контракта и средняя цена сделки. Практически вся необходимая информация о взаимодействии с биржей BitMEX находится в BitMEX API Explorer.
Данный ресурс описывает частные случаи рассмотренного шаблона взаимодействия с биржей. Первая часть шаблона — это обращение к некоторому атрибуту. Список всех атрибутов расположен внизу этой веб-страницы. К примеру, мы хотим узнать, как запросить у BitMEX исторические котировки. В таком случае нам нужен атрибут Trade.
Вторая часть шаблона — это вызов некоторого метода. Кликнув по названию атрибута Trade, откроется список из двух конечных точек. В смысл термина «конечная точка» вдаваться не будем. Для упрощения, отождествим термины «конечная точка» и «Python метод». Единственное, следует уточнить, что название искомого метода добавляется в конец URL адреса при открытии описания конечной точки.
В данном случае метод называется Trade_getBucketed. Посмотрим описание конечной точки. В первую очередь следует обратить внимание на шаблон ответа BitMEX в случае удачного запроса. Ответом является список из словарей со следующими парами ключ-значение. Ниже располагается таблица параметров метода Trade_getBucketed.
Наиболее важными здесь являются три столбца: первый столбец, содержащий имена параметров, третий столбец, содержащий описания параметров и пятый столбец, содержащий типы данных, которые параметры принимают. Посмотрим, как метод Trade_getBucketed используется на практике. Запросим данные последних ста торговых периодов часового графика контракта XBTUSD.
Для получения последних данных параметру reverse необходимо передать значение True. В этом же выражении можно извлечь список из кортежа (который вернёт метод result) с помощью оператора индексации. Так переменной data присвоится список из словарей, каждый из которых содержит данные о закрытом торговом периоде контракта XBTUSD.
Преобразуем полученный список в датафрейм pandas, поскольку эта структура является более функциональной. Для этого передадим классу DataFrame переменную data и список из имён столбцов будущего датафрейма. Здесь следует обратить внимание на пару моментов. Во-первых, классу передаётся перевёрнутый список, чтобы данные в датафрейме расположились в порядке возрастания времени.
Во-вторых, когда классу DataFrame передаются словари, ключи словарей по умолчанию становятся именами столбцов. Следовательно, в этом примере параметру columns передаётся список из имён столбцов, которые следует оставить в датафрейме. Теперь если внимательно посмотреть на индекс датафрейма, можно обнаружить, что каждая временная метка отражает время закрытия торгового периода.
Однако более привычным форматом является время открытия. Чтобы сделать такой формат, строки датафрейма необходимо сдвинуть вверх относительно меток методом shift, а затем извлечь срез до последней строки. В результате получим датафрейм с индексом, отражающим время открытия торговых периодов часового графика.
Перейдём к бирже Binance. Для взаимодействия с Binance следует установить одноимённый пакет. Это делается командой pip install python-binance. После установки пакета подключаем его в скрипте и выполняем аутентификацию. Для аутентификации из пакета binance необходимо вызвать класс Client.
Данный класс возвращает объект, с помощью которого реализуется дальнейшее взаимодействие с биржей. Классу передаются API ключ и секрет, а также логическое значение. По умолчанию параметр testnet имеет значение False, что означает подключение к реальной бирже. При необходимости подключиться к тестовой бирже, передайте параметру True.
Дальнейшее взаимодействие с Binance реализуется путём вызова из экземпляра класса Client соответствующих методов. Например, цены «бид» и «аск» торговых пар получаются путём вызова метода get_orderbook_ticker. Для получения информации о конкретной торговой паре методу следует передать её название. В таком случае метод вернёт словарь с ценами «бид» и «аск» указанной пары.
По такому же принципу в этом скрипте реализованы и другие запросы: получение количества актива на торговом счёте, получение общей информации о торговой паре и покупка актива на спотовом рынке. Хотя взаимодействие с Binance проще, чем с BitMEX, оно всё же не лишено недостатков. Например, Binance вместо чисел возвращает строки.
Из-за этого приходится дополнительно преобразовывать строки в числа. Ещё одним примером служит отсутствие средней цены сделки в словарях, которые возвращают методы, направленные на совершение сделки. Вместо этого возвращаемый такими методами словарь содержит ключ fills. Значением этого ключа является список из словарей, каждый из которых содержит цену и количество купленного или проданного актива в рамках выполнения одного ордера.
В связи с этим среднюю цену приходится вычислять с помощью цикла. Вся необходимая информация о пакете binance находится на следующем сайте. Здесь вы легко найдете описание интересующего вас метода. Например, в разделе «Market Data Endpoints» лежит заголовок метода get_klines.
Данный метод позволяет получить исторические котировки. Если кликнуть по заголовку, откроется его описание. Здесь можно узнать параметры метода и шаблон ответа Binance в случае удачного запроса. В качестве ответа Binance отправляет двумерный список с данными.
Конечно, список не так удобен, как словарь: названия всех элементов списка придётся переписать. Однако такой ответ имеет и свой плюс. Обратите внимание, что среди элементов вложенного списка присутствует как время закрытия торгового периода, так и время открытия. В сравнении с биржей BitMEX, это более удобно.
В качестве самостоятельной работы предлагаю вам изучить данный сайт, а также BitMEX API Explorer. Ссылки на эти ресурсы найдёте в описании данного урока. В заключение урока посмотрим, как метод get_klines используется на практике. В этом примере запрашиваются данные последних ста торговых периодов часового графика пары BTCUSDT.
Результат запроса присваивается переменной data. Далее список переменной data передаётся первым аргументом классу DataFrame. Причём без последнего вложенного списка. Это связано с тем, что последний вложенный список содержит информацию о ещё не завершённом торговом периоде. Поскольку нас интересуют только завершенные периоды, последний вложенный список следует исключить.
Вторым аргументом классу передаётся список с названиями элементов вложенных списков переменной data. Назвать столбцы будущего датафрейма можно как угодно. Однако количество имён должно совпадать с длиной вложенных списков. В результате получим датафрейм со всей информацией о последних девяноста девяти часовых периодах пары BTCUSDT.
После этого можно сформировать ещё один датафрейм, отобрав из первого датафрейма столбец с временными метками и четыре столбца с ценами. Здесь хочу обратить ваше внимание на метод astype. Поскольку Binance вместо чисел возвращает строки, элементы датафрейма следует преобразовать в числа.
Это позволяет сделать метод astype при передаче ему класса float. Кроме того, в этом примере преобразуется индекс датафрейма. Напомню, что функция to_datetime заменяет UNIX-время датой и временем. Так как Binance отправляет UNIX-время в миллисекундах, параметру unit передаётся строка 'ms'.
Таким образом, получим датафрейм с историческими котировками пары BTCUSDT и метками, представленными датой и временем. На этом закончим урок. Свои вопросы оставляйте в комментариях. Всем пока!