Привет, Хабр! В этой статье я хочу дать поверхностное представление о том, как работает взаимодействие с MOEX ISS через модуль requests Python. Да, сегодня уже существуют готовые решения для работы с MOEX, например aiomoex. Но как по мне, лучше всегда сначала что‑то захардкодить и понять, как это работает под капотом. Если вы только знакомитесь с MOEX ISS или начинаете заниматься анализом временных рядов, думаю, вам эта статья будет полезна. Если же вы более продвинутый специалист, то вряд ли найдете здесь что‑то новое.
В конечном итоге мы получим утилиту, с помощью которой, зная тикер ценной бумаги, можно получать датасет из сделок по этой бумаге. Такой датасет можно, например, использовать для анализа рынка на тренды. Спойлер: мы займемся этим в следующей статье.
Что такое MOEX ISS?
MOEX ISS, по версии самой MOEX — это информационно‑статистический сервер Московской Биржи, который функционирует в рамках программного комплекса Интернет‑представительства Московской Биржи и служит для предоставления клиентским приложениям данных с рынков Московской Биржи.
Короче, это REST API для получения статистики биржи MOEX. Существует ряд методов, который перечислен тут. Нас интересуют только securities методы, которые позволят получить данные по цене акции в какой‑то день. Начнем.
Если вы не знакомы с REST протоколом, не волнуйтесь. Это очень популярный и простой протокол, который часто реализован на обычном HTTP. Поэтому достаточно просто знать url и передавать правильные параметры. В ответ вы можете получить json, xml, csv, html — любой формат, который поддерживает API. Как правило это json, с ним мы и будем работать дальше. Хотя MOEX поддерживает все вышеперечисленные.
Ползаем
Для начала давайте предположим, что мы не знаем тикер нашей бумаги. Как нам найти его, используя MOEX ISS? Для этого есть вот эта ручка. Давайте дернем:)
import requests
print(requests.get('https://iss.moex.com/iss/securities.json?q=Yandex').json())
{
"securities": {
"metadata": {
"id": {
"type": "int32"
},
"secid": {
"type": "string",
"bytes": 51,
"max_size": 0
},
...
},
"columns": [
"id",
"secid",
"shortname",
...
"marketprice_boardid"
],
"data": [
[
69458,
"YNDX",
"Yandex clA",
null,
"PLLC Yandex N.V. class A shs",
"NL0009805522",
1,
38185,
"Public Limited Liability Company Yandex N.V.",
"0010034514",
null,
null,
"common_share",
"stock_shares",
"TQBR",
"TQBR"
],
...
]
}
}
Выглядит страшно — время разбираться. В формате json всегда будет возвращаться 3 важных блока информации: metadata, columns и data. В некоторых методах их может быть больше, но эти обязательны. Такой формат на самом деле очень удобен для того, чтобы засунуть его в pandas.DataFrame. Сделаем это.
import pandas as pd
import requests
j = requests.get('https://iss.moex.com/iss/securities.json?q=Yandex').json()
data = [{k : r[i] for i, k in enumerate(j['securities']['columns'])} for r in j['securities']['data']]
print(pd.DataFrame(data))
Итак, теперь мы видим более приятную картинку. В столбце secid можно увидеть тикер. А в столбце type — тип бумаги: акция, облигация, фьючерс и т. д. Нас интересует common_share, т. е. обычная (непревилигированная) акция. Есть единственная бумага с таким типом, у которой тикер YNDX. Дальше мы будем работать именно с ней. Подробнее про типы бумаг можно почитать тут в подзаголовке securitytypes.
Учимся ходить
Теперь предлагаю посмотреть агрегированную информацию за определенный день по этим акциям. Для этого мы воспользуемся новой ручкой. Дернем!
import pandas as pd
import requests
j = requests.get('https://iss.moex.com/iss/securities/YNDX/aggregates.json?date=2022-09-21').json()
data = [{k : r[i] for i, k in enumerate(j['aggregates']['columns'])} for r in j['aggregates']['data']]
print(pd.DataFrame(data))
Мы получим данные по торгам за 21 сентября 2022 года. На этом этапе уже можно подсчитать усредненную цену акций, по которой они торговались в этот день. Для этого достаточно value / volume.
Примечание. Параметр date в запросе по умолчанию ставится на сегодня. Если вы хотите получить данные за сегодня, то его необязательно указывать.
Таким образом мы научились искать цену в определенный день. Для того чтобы найти ряд цен в диапазоне дат, нужна уже новая, более мощная ручка.
Начинаем бегать
http://iss.moex.com/iss/engines/[engine]/markets/[market]/securities/[security]/candles.json
В нашем случае engine=stock; market=shares; security=YNDX. Но как узнать эти параметры в остальных случаях? Что ж, для этого есть другие ручки (либо посмотреть тут)! Вообще, исходя из руководства разработчика, философия запросов к MOEX ISS заключается в том, что мы должны сделать не один, а несколько запросов, чтобы получить то, что хотим. Это может показаться сложным, но на самом деле такой подход позволяет предоставить пользователю очень широкие возможности. Обязательно прочитайте руководство, там много примеров) Вернемся к нашей ручке.
import pandas as pd
import requests
from matplotlib import pyplot as plt
j = requests.get('http://iss.moex.com/iss/engines/stock/markets/shares/securities/YNDX/candles.json?from=2023-05-25&till=2023-09-01&interval=24').json()
data = [{k : r[i] for i, k in enumerate(j['candles']['columns'])} for r in j['candles']['data']]
frame = pd.DataFrame(data)
plt.plot(list(frame['close']))
plt.savefig("shares.png")
Таким образом можно построить график акций с определенным интервалом: 1m, 10m, 60m, 1d, 1w, 1m или 1y. Параметр interval в запросе может принимать значения соответственно: 1, 10, 60, 24, 7, 31 или 4.
Сравним его с графиком за этот период на самом MOEX.
Заключение
В этой статье мы поверхностно рассмотрели функционал MOEX ISS. Как видно, даже используя такой ограниченный функционал, можно получить неплохие данные для дальнейшего анализа. Хотите больше — идите глубже. Надеюсь, эта статья вдохновила вас. В следующей статье мы будем рассматривать алгоритм построения трендов на полученных данных.
andrewfromtver
Спасибо за интересный материал! Недавно тоже делал подобную штуку для акций из своего портфеля, только там был телеграм бот - который уведомлял о просадках цены за бумагу больше n пунктов. Плюсую вам и с нетерпеньем жду статью о построении трендов!