Чего бы с биржи стянуть? Изучаем API и способы работы с ним.

Биржам выгодно, что бы вы писали роботов.

И для этого они облегчают работу по их созданию

Для того, что бы автоматизировать и ускорить свою работу на бирже, надо как то научиться с биржей взаимодействовать. Специально для этого, биржи предоставляют специальный интерфейс для программистов. Более того – бирже ВЫГОДНО, что бы вы делали ставки чаще и прокручивали бОльшие суммы – это приносит бирже деньги за счет комиссии, и увеличивает объем торгов, что привлекает новых игроков.

Этот программный интерфейс называется API – аббревиатура от «application programming interface».На русский язык можно перевести как «интерфейс программирования приложений», «интерфейс прикладного программирования» и так далее. Не пугайтесь, все просто – вам достаточно зайти на нужную страницу на сайте биржи, и дело будет сделано.

Например, если вы зайдете на страницу https://api.exmo.com/v1/currency/, вы увидите список валют, по которым торгует биржа.

Данные предоставлены в специальном формате, удобном для программ, но и человеку не очень сложно понять их – например, в данном  случае вы видите список – USD, EUR, RUB и так далее, остальные символы разделяют и упорядочивают данные. Этот формат представления данных называется JSON, и он весьма популярен в Интернете.

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

Например, первым делом программа должна узнать свой баланс на бирже, узнать есть ли у вас открытые неисполненные ордера, потом узнать какие предложения сейчас существуют, создать новый ордер или отменить текущий и так далее. В общем, должна делать все то, что вы обычно делаете руками, и все данные для этого у неё есть.

Некоторые разделы API (страницы) общедоступны – например, последние совершенные сделки и текущие чужие открытые ордера. Такие разделы обычно именуются Public API, и для получения этой информации не требуется авторизация, получить данные может любой желающий.

Другие разделы, влияющие на личные данные пользователя или операции, связанные с деньгами – например, покупка валюты или запрос баланса, требуют определенных прав доступа, и их нужно настраивать отдельно. Такие методы доступа называются Private API. Работа с ними идет точно так же к с Public API, но требуются дополнительные действия при подключении. К таким операциям мы подойдем в следующих статьях, когда будем автоматизировать покупку/продажу.

В этой статье будет рассмотрена работа с Public API – тем более, что вам все равно нужны будут эти данные для полноценной работы робота. Все методы, доступные без авторизации, описаны на этой странице https://exmo.me/ru/api_doc#/public_api



Ладно, в общем, понятно, но как написать программу для работы с биржей?

В принципе, на картинке указан код, который получает те же данные, что и мы в начале статьи. Обратите внимание – всего три строчки кода.

о том, что надо установить на компьютер для написания такого кода, я писал в статье Автоматизируй это! Как перестать тратить время на рутину и заставить компьютер работать, почитайте, там тоже ничего сложного.

Вот сам код:

import requests

r = requests.get('https://api.exmo.com/v1/currency/')
print(r.text)

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

А вот результат вывода программы:

То же самое, что мы и видели на странице, не так ли? Давайте упорядочим полученные данные. Для этого надо немного изменить код. Пусть теперь он выглядит вот так:

import requests
import json

r = requests.get('https://api.exmo.com/v1/currency/')

obj = json.loads(r.text)
print(json.dumps(obj, sort_keys=True, indent=4, separators=(',',': ')))

Сохраним, запустим, что получилось?

Ура, оно вертится! Значит, программа получает и обрабатывает данные с биржи. Теперь надо научиться использовать это в практических целях – данный учебный пример, по большому счету, бесполезен.



Пишем что-то полезное

Что может быть полезным? Ну, например получение списка текущих сделок – мы сможем узнавать, кто что продает и покупает, выводить средний курс и вообще ориентироваться в происходящем.

За эти данные отвечает, как обычно, отдельный метод API, он доступен по этому адресу: https://api.exmo.com/v1/order_book/?pair=BTC_USD. Откроем его в браузере:

Эти данные посложнее для человеческого восприятия, и сходу выглядят как набор непонятных данных. Давайте пойдем по тому же пути, и для начала научимся получать их и выводить в окне программы. Поменяем адрес API (помните, я выделял желтым выше? Код возьмем оттуда же). И вот результат:

Все равно тарабарщина. А ведь это только 100 последних записей, что бы получить тысячу нужно в конец адреса добавить &limit=1000, итоговый адрес будет выглядеть вот так: https://api.exmo.com/v1/order_book/?pair=BTC_USD&limit=1000

Давайте выведем данные покрасивее и поймем, что там за структура – все данные в формате JSON имеют структуру, одни элементы вкладываются в другие и так далее.

ХИНТ: вы можете отформатировать JSON для комфортного просмотра online – перейдите на сайт http://jsoneditoronline.org/, вставьте код в левую колонку и нажмите на кнопку сверху слева. Получится примерно так:

Напишем код, что бы выводить в таком же виде в окне программы

import requests
import json

r = requests.get('https://api.exmo.com/v1/order_book/?pair=BTC_USD')

obj = json.loads(r.text)
print(json.dumps(obj, sort_keys=True, indent=4, separators=(',',': ')))

И выполняем его:

Стало читабельнее, не так ли? Давайте разберем структуру данных – я удалил ненужные пока записи, что бы умещалось на один экран. Вот так выглядит документ по сути:

В корневой узел BTC_USD вложены дочерние узлы:

ask_quantity - объем всех ордеров на продажу
ask_amount - сумма всех ордеров на продажу
ask_top - минимальная цена продажи
bid_quantity - объем всех ордеров на покупку
bid_amount - сумма всех ордеров на покупку
bid_top - максимальная цена покупки
bid - список ордеров на покупку, где каждая строка это цена, количество и сумма
ask - список ордеров на продажу, где каждая строка это цена, количество и сумма

Некоторые параметры представлены готовым значением. Некоторые содержат в себе дополнительные списки. Например “ask” по сути является контейнером, в котором лежат другие записи. Если бы мы могли свернуть “ask”, он выглядел бы примерно вот так:

Эти квадратные скобки – открывающие и закрывающие, являются как бы началом и концом контейнера. Внутри него есть другие элементы, которые так же являются контейнерами и обозначены квадратными скобками.

Каждый такой контейнер внутри “ask” как раз определяет чье-то предложение на покупку. Первая цифра обозначает цену (в данном случае, в долларах) по которой этот человек хочет продать, вторая – сколько валюты он готов отдать(в данном случае, в BTC), а третья – итоговая сумма сделки. В этом примере человек хочет продать 0.001 BTC по цене 1068 долларов. Итоговая цена составит 1068*0.001 = 1.068. долларов. Человек хочет продать биткоинов на доллар, грубо говоря.

Что это вообще дает?

Давайте напишем программу, которая выводит максимальные цены покупки и продажи на текущий момент времени.

Код меняется не сильно, но теперь мы будем обращаться к конкретным полям документа – сейчас нас интересуют поля bid_top и ask_top. Давайте их выведем.

 Немного изменим код:

import requests
import json

r = requests.get('https://api.exmo.com/v1/order_book/?pair=BTC_USD')

obj = json.loads(r.text)
print(
        "минимальная цена продажи",
        obj['BTC_USD']['ask_top'],
        "максимальная цена покупки",
        obj['BTC_USD']['bid_top']
)


Запустим программу – получим текущие данные. Если будем запускать время от времени – они будут меняться, так как меняется максимальная сумма покупки и продажи.

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

import requests
import json
import time

while True:
    r = requests.get('https://api.exmo.com/v1/order_book/?pair=BTC_USD')

    obj = json.loads(r.text)
    print(
            "минимальная цена продажи",
            obj['BTC_USD']['ask_top'],
            "максимальная цена покупки",
            obj['BTC_USD']['bid_top']
    )
    time.sleep(30)

Работает, показывает данные (для выключения закройте окно программы)

Но.. как то скучно. Цена редко меняется, да и по одной валюте всего. Давайте используем другой метод - https://api.exmo.com/v1/ticker/.

Вот что он нам вернет (по всем валютам):

high - максимальная цена сделки за 24 часа
low - минимальная цена сделки за 24 часа
avg - средняя цена сделки за 24 часа
vol - объем всех сделок за 24 часа
vol_curr - сумма всех сделок за 24 часа
last_trade - цена последней сделки
buy_price - текущая максимальная цена покупки
sell_price - текущая минимальная цена продажи
updated - дата и время обновления данных

Немного поменяем код – как всегда, и выведем поля «текущая максимальная цена покупки» и «текущая минимальная цена продажи» для каждой валюты.

import requests
import json
import time

# программа будет работать бесконечно
while True:
    # получить данные с биржи
    r = requests.get('https://api.exmo.com/v1/ticker/')
    # переводим данные во понятный программе формат
    obj = json.loads(r.text)
    # находим все валюты, перечисленные в файле
    for pair in obj:

        print(
            "Валюта",
            pair,
            "текущая максимальная цена покупки",
            obj[pair]['buy_price'],
            "текущая минимальная цена продажи",
            obj[pair]['sell_price']
        )
   
    # подождать три секунды и начать заново
    time.sleep(3)

Вы можете спросить – зачем мне все это делать, если курсы я и так могу глазами посмотреть? Логично, но это нужно для того, что бы потом отрабатывать условия и давать роботу указания – например, если текущая цена такой-то валютной пары ниже такой-то суммы, то продавай.  Если программирование вас увлечет, вы можете эти данные не просто выводить на экран, а сохранять, анализировать, строить графики и т.п. Как вы уже видели, много кода писать не надо – все делается в несколько строк.

Для домашних экспериментов и практики могу посоветовать вам научиться получать и выводить информацию по всем методам, описанным на этой странице https://exmo.me/ru/api_doc#/public_api (от раздела  PUBLIC API до раздела AUTHENTICATED API – всего 5 методов).

Так же я особо не налегаю на разъяснение языка программирования, который использую здесь, так как это отдельная большая тема для изучения, но может быть стоит какие-то моменты прояснять подробнее? Для человека, пока далекого от программирования, биржевой торговли и прочего этот материал может показаться сложным.

В любом случае, жду ваших вопросов и замечаний в комментариях, а вам желаю хороших заработков и удачи!



Последнее изменение:


Крипто-кошельки для помощи и благодарности проекту:

Bitcoin адрес проекта: [[address]]

Перевод на сумму [[value]] BTC получен. Спасибо!.
[[error]]

Ethereum адрес проекта: [[address]]



Комментарии
14.05.2017 11:47:34
Примечание для тех, у кого exmo.com заблокирован Ростелекомом. Вы можете продолжать пользоваться API, но все вхождения api.exmo.com вам нужно будет заменить на api.exmo.me.
Пример: 
строку
r = requests.get('https://api.exmo.com/v1/order_book/?pair=BTC_USD')
нужно заменить на
r = requests.get('https://api.exmo.me/v1/order_book/?pair=BTC_USD')

Если ваш скрипт будет после этого ругаться (вот так: requests.exceptions.SSLError: hostname 'api.exmo.me' doesn't match 'api.exmo.com')  и не работать, то нужно еще дописать verify=False в параметры, вот так:
r = requests.get('https://api.exmo.me/v1/order_book/?pair=BTC_USD', verify=False)

При этом ваш трафик пойдет по протоколу http, что, по идее, небезопасно, но так как на данном этапе вы не указываете никаких секретных данных, а только пользуетесь общедоступными методами, то вы ничем и не рискуете.
ПроголосоватьПроголосовать
1 0
19.06.2017 20:50:35
спасибо.все понятно и доступно. а дальше что?. хотелось бы получить разницу между максимальным и минимальным значением цены и найти самое максимальное из них.
ПроголосоватьПроголосовать
1 0
23.06.2017 19:42:27
А дальше в других статьях цикла )

Что бы получить максимальное значение из нескольких, есть соответствующая функция max, только значения надо привести к числовому типу float (числу с плавающей точкой).
Получится вот так (замените это в коде): 
        print(
            "Валюта",
            pair,
            "текущая максимальная цена покупки",
            obj[pair]['buy_price'],
            "текущая минимальная цена продажи",
            obj[pair]['sell_price'],
            "Максимальная вообще",
            max(float(obj[pair]['buy_price']), float(obj[pair]['sell_price']))
        )
ПроголосоватьПроголосовать
0 0
17.07.2017 14:36:41
import requests
import json
import time

# программа будет работать бесконечно
while True:
    # получить данные с биржи
    r = requests.get('https://api.exmo.com/v1/ticker/')

До сюда доходит и ничего не происходить, если убрать цикл с таймером то все работает. В чем может быть причина?
ПроголосоватьПроголосовать
0 0
19.07.2017 17:09:23
А как вы узнали, что дошло до туда, если ничего не происходит? )
Пальцем в небо - попробуйте таймаут добавить к коннекту

r = requests.get('https://api.exmo.com/v1/ticker/', timeout=10)
ПроголосоватьПроголосовать
0 0
24.07.2017 13:56:53
Спс, за доходчивый урок(все круто). Ради этого не поленился даже зарегистрироваться))))
ПроголосоватьПроголосовать
0 0
24.07.2017 15:30:46
Спасибо вам )
ПроголосоватьПроголосовать
0 0
25.07.2017 01:43:46
Если можно нужна помощь!
1. В конце списка нужно еще выводить один параметр которого нет, ((high-low)*100)/avg (подставлял само собой не так). Никак не получается это сделать, хоть и пытался менять тип данных.
2. Полученные данные мне снова нужно конвертировать в json. С этим у меня тоже проблемы, я так понимаю сначала нужно конвертануть в словарь, а потом в json?
import requests
import json

while True:
    r = requests.get('https://api.exmo.com/v1/ticker/')
    obj = json.loads(r.text)

    total = []
    for pair in obj:
        all_pair = (
            'pair:', pair.lower(),
            'updated:', obj[pair]['updated'],
            'last_trade:', obj[pair]['last_trade'],
            'high:', obj[pair]['high'],
            'low:', obj[pair]['low'],
            'avg:', obj[pair]['avg'],
            'buy:', obj[pair]['buy_price'],
            'sell:', obj[pair]['sell_price'],
            'vol_curr:', obj[pair]['vol_curr'],
            'vol:', obj[pair]['vol']
            float(obj[pair]['high']) - float(obj[pair]['low'])
        )
        total.append(all_pair)
    print(total)

P.S. Не судите строго еще нуб, только разбираюсь!
ПроголосоватьПроголосовать
0 0
25.07.2017 02:06:54
С первым вроде как разобрался. Так что быду благодарен если с json поможешь.
И плохо что свои комменты не можна редактировать!
ПроголосоватьПроголосовать
0 0
25.07.2017 02:12:37
import requests
import json
import  time

while True:
    r = requests.get('https://api.exmo.com/v1/ticker/')
    obj = json.loads(r.text)
    total = []
    
    for pair in obj:
        all_pair = (
            'pair:', pair.lower(),
            'updated:', obj[pair]['updated'],
            'last_trade:', obj[pair]['last_trade'],
            'high:', obj[pair]['high'],
            'low:', obj[pair]['low'],
            'avg:', obj[pair]['avg'],
            'buy:', obj[pair]['buy_price'],
            'sell:', obj[pair]['sell_price'],
            'vol_curr:', obj[pair]['vol_curr'],
            'vol:', obj[pair]['vol'],
            'volatilyty', ((float(obj[pair]['high']) - float(obj[pair]['low'])) * 100) / float(obj[pair]['avg'])
        )
        total.append(all_pair)
    print(total)
    time.sleep(300)
ПроголосоватьПроголосовать
0 0
25.07.2017 09:59:09
В JSON можно конвертировать и массивы [], и словари {}, смотря какая структура данных нужна на выходе.
Насчет кода пару замечаний - для создания словаря нужны {}, а не () 
В данном случае создавался кортеж из значений, разделенных запятой, а от двоеточий не было смысла, т.к. внутри кавычек они становятся не разделителями, а частью строки. В общем - словарь должен обрамляться {}, а все значения  в нем должны иметь вид "ключ" : "значение", например  {'pair': pair.lower(), 'updated': obj[pair]['updated']}. Кавычки могут быть, могут не быть, там по ситуации. Поправил код:

import requests
import json
import  time

while True:
    r = requests.get('https://api.exmo.com/v1/ticker/')
    obj = json.loads(r.text)
    total = []
    
    for pair in obj:
        all_pair = {
            'pair': pair.lower(),
            'updated': obj[pair]['updated'],
            'last_trade': obj[pair]['last_trade'],
            'high': obj[pair]['high'],
            'low': obj[pair]['low'],
            'avg': obj[pair]['avg'],
            'buy': obj[pair]['buy_price'],
            'sell': obj[pair]['sell_price'],
            'vol_curr': obj[pair]['vol_curr'],
            'vol': obj[pair]['vol'],
            'volatilyty': ((float(obj[pair]['high']) - float(obj[pair]['low'])) * 100) / float(obj[pair]['avg'])
        }
        total.append(all_pair)

    # Вывести содержимое получившегося массива со словарями
    #print(total)

    # Перевести структуру в объект JSON и вывести содержимое
    # all_pair_json = json.dumps(total)
    # print(all_pair_json)
    
    # Сформировать JSON и вывести в файл, расположенный там, откуда запускается скрипт
    with open('pair.json', 'w') as output:
        print(json.dumps(total), file=output)

    #time.sleep(300)

Насчет комментариев да, увы.. Подумаю, как лучше это сделать
ПроголосоватьПроголосовать
1 0
16.08.2017 14:53:18
Большая просьба написать подобную статью по бирже Poloniex. Если на Exmo в руководстве всё довольно подробно расписано, то на Poloniex мануал по API крайне скудный. Не находил в интернете такой информации, думаю ваша статья была бы популярной.
ПроголосоватьПроголосовать
0 0
12.09.2017 18:56:56
Подскажите нубу, как вывести значение из контейнера?
Вот такие данные получаю при запросе, как вывести например Ask
    "result": [
        {
            "Ask": 4270.0,
            "BaseVolume": 24494449.12946066,
            "Bid": 4269.0,
            "Created": "2015-12-11T06:31:40.633",
            "High": 4377.0,
            "Last": 4270.0,
            "Low": 4161.0,
            "MarketName": "USDT-BTC",
            "OpenBuyOrders": 5256,
            "OpenSellOrders": 2467,
            "PrevDay": 4283.99999982,
            "TimeStamp": "2017-09-12T14:56:06.36",
            "Volume": 5722.23013955
        }
ПроголосоватьПроголосовать
0 0
12.09.2017 19:00:27
] в конце еще забыл
ПроголосоватьПроголосовать
0 0
23.09.2017 17:10:18
Добрый!

result это массив, в массиве словари, первый словарь находится в позиции 0, второй в позиции 1 и т.п.

В данном случае
ask = obj['result'][0]['Ask']
ПроголосоватьПроголосовать
0 0
26.09.2017 16:19:19
добрый день если не сложно то yiobit.net такой же урок
ПроголосоватьПроголосовать
0 0
04.10.2017 23:43:21
Добрый день!
Не вопрос - https://bablofil.ru/yobit-api-python/
ПроголосоватьПроголосовать
0 0
Пожалуйста, авторизуйтесь, что бы оставить свой комментарий