apimoex icon indicating copy to clipboard operation
apimoex copied to clipboard

Состав индекса мосбиржи

Open NickelTG opened this issue 3 years ago • 8 comments

Есть ли возможность вытаскивать состав индекса и доли бумаг в нем? Например imoex?

NickelTG avatar Apr 19 '22 11:04 NickelTG

В принципе можно с помощью этого запроса к API https://iss.moex.com/iss/reference/147, но специально такая функция не реализована. При желании можно с помощью клиента получить данные:

import requests

import apimoex
import pandas as pd


api_url = 'https://iss.moex.com/iss/statistics/engines/stock/markets/index/analytics/IMOEX.json'

with requests.Session() as session:
    iss = apimoex.ISSClient(session, api_url)
    data = iss.get_all()
    df = pd.DataFrame(data['analytics'])
    print(df)

WLM1ke avatar Apr 19 '22 11:04 WLM1ke

К сожалению это недостоверная информация, возможно тестовые данные.

В индексе сейчас 43 бумаги:

https://www.moex.com/ru/index/IMOEX/constituents/

NickelTG avatar Apr 19 '22 11:04 NickelTG

Так и тут 43 - нумерация с нуля идет

   indexid   tradedate ticker  shortnames secids  weight  tradingsession
0    IMOEX  2022-04-18   AFKS  Система ао   AFKS    0.33               3
1    IMOEX  2022-04-18   AFLT    Аэрофлот   AFLT    0.27               3
2    IMOEX  2022-04-18   ALRS   АЛРОСА ао   ALRS    1.64               3
3    IMOEX  2022-04-18   CBOM      МКБ ао   CBOM    0.31               3
4    IMOEX  2022-04-18   CHMF    СевСт-ао   CHMF    1.55               3
5    IMOEX  2022-04-18   DSKY  ДетскийМир   DSKY    0.33               3
6    IMOEX  2022-04-18   ENPG  ЭН+ГРУП ао   ENPG    0.55               3
7    IMOEX  2022-04-18   FEES  ФСК ЕЭС ао   FEES    0.19               3
8    IMOEX  2022-04-18   FIVE    FIVE-гдр   FIVE    1.09               3
9    IMOEX  2022-04-18   FIXP    FIXP-гдр   FIXP    0.72               3
10   IMOEX  2022-04-18   GAZP  ГАЗПРОМ ао   GAZP   15.98               3
11   IMOEX  2022-04-18   GLTR    GLTR-гдр   GLTR    0.31               3
12   IMOEX  2022-04-18   GMKN   ГМКНорНик   GMKN    9.01               3
13   IMOEX  2022-04-18   HHRU   iHHRU-адр   HHRU    0.46               3
14   IMOEX  2022-04-18   HYDR    РусГидро   HYDR    0.74               3
15   IMOEX  2022-04-18   IRAO  ИнтерРАОао   IRAO    0.73               3
16   IMOEX  2022-04-18   LKOH      ЛУКОЙЛ   LKOH   13.06               3
17   IMOEX  2022-04-18   MAGN         ММК   MAGN    0.76               3
18   IMOEX  2022-04-18   MGNT   Магнит ао   MGNT    2.36               3
19   IMOEX  2022-04-18   MOEX    МосБиржа   MOEX    1.12               3
20   IMOEX  2022-04-18   MTSS      МТС-ао   MTSS    1.48               3
21   IMOEX  2022-04-18   NLMK     НЛМК ао   NLMK    1.61               3
22   IMOEX  2022-04-18   NVTK  Новатэк ао   NVTK    5.77               3
23   IMOEX  2022-04-18   OZON    OZON-адр   OZON    0.46               3
24   IMOEX  2022-04-18   PHOR  ФосАгро ао   PHOR    1.95               3
25   IMOEX  2022-04-18   PIKK      ПИК ао   PIKK    0.69               3
26   IMOEX  2022-04-18   PLZL       Полюс   PLZL    3.38               3
27   IMOEX  2022-04-18   POGR   Petropavl   POGR    0.19               3
28   IMOEX  2022-04-18   POLY   Polymetal   POLY    2.48               3
29   IMOEX  2022-04-18   ROSN    Роснефть   ROSN    3.87               3
30   IMOEX  2022-04-18   RTKM  Ростел -ао   RTKM    0.49               3
31   IMOEX  2022-04-18   RUAL    РУСАЛ ао   RUAL    1.44               3
32   IMOEX  2022-04-18   SBER    Сбербанк   SBER    8.89               3
33   IMOEX  2022-04-18  SBERP  Сбербанк-п  SBERP    0.89               3
34   IMOEX  2022-04-18   SNGS    Сургнфгз   SNGS    1.84               3
35   IMOEX  2022-04-18  SNGSP  Сургнфгз-п  SNGSP    1.60               3
36   IMOEX  2022-04-18   TATN  Татнфт 3ао   TATN    2.12               3
37   IMOEX  2022-04-18  TATNP  Татнфт 3ап  TATNP    0.41               3
38   IMOEX  2022-04-18   TCSG     TCS-гдр   TCSG    2.72               3
39   IMOEX  2022-04-18  TRNFP  Транснф ап  TRNFP    0.54               3
40   IMOEX  2022-04-18   VKCO      VK-гдр   VKCO    0.44               3
41   IMOEX  2022-04-18   VTBR      ВТБ ао   VTBR    0.77               3
42   IMOEX  2022-04-18   YNDX  Yandex clA   YNDX    4.45               3

WLM1ke avatar Apr 19 '22 11:04 WLM1ke

Странно, я дёрнул https://iss.moex.com/iss/statistics/engines/stock/markets/index/analytics/IMOEX.json

Там гораздо меньше строк:

{ "analytics": { "metadata": { "indexid": {"type": "string", "bytes": 36, "max_size": 0}, "tradedate": {"type": "date", "bytes": 10, "max_size": 0}, "ticker": {"type": "string", "bytes": 36, "max_size": 0}, "shortnames": {"type": "string", "bytes": 189, "max_size": 0}, "secids": {"type": "string", "bytes": 36, "max_size": 0}, "weight": {"type": "double"}, "tradingsession": {"type": "int32"} }, "columns": ["indexid", "tradedate", "ticker", "shortnames", "secids", "weight", "tradingsession"], "data": [ ["IMOEX", "2022-04-18", "AFKS", "Система ао", "AFKS", 0.33, 3], ["IMOEX", "2022-04-18", "AFLT", "Аэрофлот", "AFLT", 0.27, 3], ["IMOEX", "2022-04-18", "ALRS", "АЛРОСА ао", "ALRS", 1.64, 3], ["IMOEX", "2022-04-18", "CBOM", "МКБ ао", "CBOM", 0.31, 3], ["IMOEX", "2022-04-18", "CHMF", "СевСт-ао", "CHMF", 1.55, 3], ["IMOEX", "2022-04-18", "DSKY", "ДетскийМир", "DSKY", 0.33, 3], ["IMOEX", "2022-04-18", "ENPG", "ЭН+ГРУП ао", "ENPG", 0.55, 3], ["IMOEX", "2022-04-18", "FEES", "ФСК ЕЭС ао", "FEES", 0.19, 3], ["IMOEX", "2022-04-18", "FIVE", "FIVE-гдр", "FIVE", 1.09, 3], ["IMOEX", "2022-04-18", "FIXP", "FIXP-гдр", "FIXP", 0.72, 3], ["IMOEX", "2022-04-18", "GAZP", "ГАЗПРОМ ао", "GAZP", 15.98, 3], ["IMOEX", "2022-04-18", "GLTR", "GLTR-гдр", "GLTR", 0.31, 3], ["IMOEX", "2022-04-18", "GMKN", "ГМКНорНик", "GMKN", 9.01, 3], ["IMOEX", "2022-04-18", "HHRU", "iHHRU-адр", "HHRU", 0.46, 3], ["IMOEX", "2022-04-18", "HYDR", "РусГидро", "HYDR", 0.74, 3], ["IMOEX", "2022-04-18", "IRAO", "ИнтерРАОао", "IRAO", 0.73, 3], ["IMOEX", "2022-04-18", "LKOH", "ЛУКОЙЛ", "LKOH", 13.06, 3], ["IMOEX", "2022-04-18", "MAGN", "ММК", "MAGN", 0.76, 3], ["IMOEX", "2022-04-18", "MGNT", "Магнит ао", "MGNT", 2.36, 3], ["IMOEX", "2022-04-18", "MOEX", "МосБиржа", "MOEX", 1.12, 3] ] }, "analytics.cursor": { "metadata": { "INDEX": {"type": "int64"}, "TOTAL": {"type": "int64"}, "PAGESIZE": {"type": "int64"},

NickelTG avatar Apr 19 '22 11:04 NickelTG

Данный запрос имеет страничную выдачу - размер страницы 20. Нужно дополнительно запрашивать следующие страницы. Вызов

iss = apimoex.ISSClient(session, api_url)
data = iss.get_all()

автоматически определяет наличие и выкачивает все страницы. Если сделать вызов

iss = apimoex.ISSClient(session, api_url)
data = iss.get()

То будет получена только первая страница, как у вас.

WLM1ke avatar Apr 19 '22 12:04 WLM1ke

Спасибо, вы очень помогли

NickelTG avatar Apr 19 '22 18:04 NickelTG

Предлагаю упаковать в функцию, в файл requests.py. Вариант:

def get_index_tickers(
    session: requests.Session,
    index: str,
    date: Optional[str] = None,
    columns: Optional[Tuple[str, ...]] = (
        "ticker",
        "from",
        "till",
        "tradingsession",
    ),
    market: str = "index",
    engine: str = "stock",
):
    """Получить информацию по составу указанного индекса за указанную дату.

    Описание запроса - https://iss.moex.com/iss/reference/148

    :param session:
        Сессия интернет соединения.
    :param index:
        Название индекса. Например, IMOEX. Список: https://iss.moex.com/iss/statistics/engines/stock/markets/index/analytics
    :param date:
        Дата вида ГГГГ-ММ-ДД. Если указано, то будут показаны только активные инструменты, по которым тогда рассчитывалось значение индекса. Если в указанный день не было торгов, то вернёт пустой список! При отсутствии данные будут загружены с начала истории. 
    :param columns:
        Кортеж столбцов, которые нужно загрузить - по умолчанию режим торгов, дата торгов, цена закрытия и объем в
        штуках и стоимости. Если пустой или None, то загружаются все столбцы.
    :param market:
        Рынок - по умолчанию индексы.
    :param engine:
        Движок - по умолчанию акции.

    :return:
        Список словарей, которые напрямую конвертируется в pandas.DataFrame.
    """
    url = (
        f"https://iss.moex.com/iss/statistics/engines/{engine}/markets/{market}/"
        f"analytics/{index}/tickers.json"
    )
    table = "tickers"
    query = _make_query(date=date, table=table, columns=columns)
    return _get_short_data(session, url, table, query)

Ещё добавить в тот же файл:

__all__ = [
   ...
    "get_index_tickers",
]
def _make_query(
    ...
    date: Optional[str] = None,
    ...
) :
    ...
    :param date:
        Точная дата (используется при получении тикеров в индексе).
    ...
    if date:
        query["date"] = date

А это в автотесты:

def test_get_index_tickers(session):
    data = requests.get_market_history(session, index='IMOEX', date='2023-03-03')
    assert len(data) == 40
    assert data[15]['ticker'] == 'MAGN'
    assert data[25]['till'] == '2023-03-03'
    assert data[35]['tradingsession'] == 3

AlekseyGur avatar Mar 12 '23 17:03 AlekseyGur

Без проблем - делайте PR

WLM1ke avatar Mar 12 '23 17:03 WLM1ke