Блог им. AndreyFilippovich
Сильно улучшил таблицу и добавил большое количество новых полей. Некоторые из них у меня просили уже очень давно.
В таблице реализовано:
— Краткое название бумаги
— Доходность купона в %
— Доходность купона в рублях
— НКД
— Цена бумаги в процентах
— Номинал бумаги
— Цена бумаги в рублях (смог решить вопрос с амортизируемыми бумагами)
— Дата погашения
— Дата оферты
— Доходность к оферте
— YTM
— Эффективная доходность
— G-spread
— Дней до погашения
— Дюрация
Всё это будет вам доступно лишь при введении ISIN бумаги. Реализовано много решений, которые сильно упрощают работу.
+ ко всему этому в таблице есть простенькие формулы, помогающие в подсчёте не для одной бумаги, а если их у вас множество
Сама таблица находится тут
В этой статье я разберу каждый из пунктов по отдельности, чтобы сразу ответить на все вопросы
Для большего понимания можете также заглянуть в мою предыдущую статью. В ней я подробно рассказываю как работают формулы
Это два самых главных элемента, которые нужны для расчёта всех остальных формул.
ISIN подставляется руками, а режим торгов высчитывается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/securities/»&A2&"/securities.xml?iss.meta=off&iss.only=marketdata&marketdata.columns=BOARDID");"//document//data//rows//row/@BOARDID")
Название бумаги выдаётся краткое, чтобы можно было проще читать. Оно отдаётся посредством формулы:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=SHORTNAME");"//document//data//rows//row/@SHORTNAME")
Количество бумаг указывается вами в зависимости от размера вашего портфеля. Снизу автоматически подсчитывается суммарное количество по всем бумагам в портфеле.
Купон в процентах - это годовая процентная доходность облигации, считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=SECID,COUPONPERCENT");"//document//data//rows//row/@COUPONPERCENT")
Купон в рублях- это размер 1 купона в рублях, считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=COUPONVALUE");"//document//data//rows//row/@COUPONVALUE")
НКД указывается актуальный, также считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=ACCRUEDINT");"//document//data//rows//row/@ACCRUEDINT")
Это моя личная гордость, долго мучался с тем как же считать цену бумаги. Сначала проценты умножал на 10, но это не помогало, если у компании была хоть одна амортизация или же нестандартный номинал.
Цена бумаги в % показывает процентную стоимость бумаги относительно номинала. Номинал берётся за 100%. Это считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=marketdata&marketdata.columns=LAST");"//document//data//rows//row/@LAST")
Номинал бумаги особенно актуален для расчёта бумаг с амортизацией и считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=FACEVALUE");"//document//data//rows//row/@FACEVALUE")
И наконец цена бумаги. Умножается номинал на процентную цену и показывает текущую цену в рублях.
Стоимость бумаг в портфеле- это обычное перемножение количество бумаг в портфеле на цену 1 облигации
В дате погашения ничего удивительного, она считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=MATDATE");"//document//data//rows//row/@MATDATE")
В формуле по дате оферты я добавил условие, чтобы если оферты нет, то писалось «нет оферты» вместо выпадающей ошибки. Считается по формуле:
=ЕСЛИОШИБКА(ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=OFFERDATE");"//document//data//rows//row/@OFFERDATE");«нет оферты»)
Доходность к оферте показывает доходность к ближайшей оферте. Если оферты нет, то и доходность такая не считается. Находим значение по формуле:
=ЕСЛИОШИБКА(ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=marketdata&marketdata.columns=YIELDTOOFFER");"//document//data//rows//row/@YIELDTOOFFER");«нет оферты»)
YTM показывает % годовых, которые даёт бумага. Рассчитывается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=orderbook&orderbook.columns=YIELD");"//document//data//rows//row/@YIELD")
Тут могут немного некорректно отображаться доходности флоатеров или бумаг с близкими офертами.
Эффективная доходность показывает значение в годовых, но до ближайшего события (погашение/оферта)
Например, в примере на скриншоте последняя строка- это облигации М.Видео. Их YTM составляет 21,64% годовых, но оферта уже менее, чем через год, поэтому Эффективная доходность чуть меньше и составляет 21,3267
Эффективная доходность считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=marketdata_yields&marketdata_yields.columns=EFFECTIVEYIELD");"//document//data//rows//row/@EFFECTIVEYIELD")
G-spread подтягивается с Мосбиржи и показывает разницу в доходности относительно ОФЗ. Считается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=marketdata_yields&marketdata_yields.columns=GSPREADBP");"//document//data//rows//row/@GSPREADBP")
Дни до погашения не смог по формуле из API подтянуть, не ожидал такого))))
В итоге отнимаю от даты погашения сегодняшнюю дату и получаю нужное значение)
Дюрация уже считается нормально по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=marketdata_yields&marketdata_yields.columns=DURATION");"//document//data//rows//row/@DURATION")
Дата следующего купона подтягивается по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=SECID,NEXTCOUPON,COUPONVALUE");"//document//data//rows//row/@NEXTCOUPON")
Если среди вас есть человек, который знает как можно подтягивать сразу все будущие выплаты, то буду вам безмерно благодарен, если подскажите
Частота купонных выплат указывается в количестве раз в год и считаются по формуле:
= 365/ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/boards/»&B2&"/securities/"&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=COUPONPERIOD");"//document//data//rows//row/@COUPONPERIOD")
Из-за того, что в формуле присутствует обычное деление, то иногда могут быть такие числа как 3,4 или 7,1. Исправлю этот недочёт в будущем.
Тут вопросов, думаю, возникнуть не должно. В заголовках уже всё расписано, чтобы понять что к чему относится. Никаких сложных формул нет.
Индесксы
iss.moex.com/iss/engines/stock/markets/index/securities/
Валюта
iss.moex.com/iss/engines/currency/markets/selt/securities/
Акции
iss.moex.com/iss/engines/stock/markets/shares/securities
Фючерсы
iss.moex.com/iss/engines/futures/markets/forts/securities
Просто это добавляет юзабельности таблице, когда возникает необходимость отфильтровать массив именно по ТКД.
Все никак руки не доходили, хоть и мысль была:)
iss.moex.com/iss/engines/futures/markets/forts/securities/cnyrubf.xml?iss.dp=comma&iss.meta=off&iss.only=marketdata&marketdata.columns=SWAPRATE
=ПОДСТАВИТЬ(@ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/futures/markets/forts/securities/»&I14&".xml?iss.meta=off&iss.only=marketdata&marketdata.columns=SWAPRATE");"//document//data//rows//row/@SWAPRATE");".";",")
в гугл доке — было очень удобно через указание биржи и тикета.
в яндекс документах — вообще ничего подобного не нашёл ((
В гугле будет работать, но надо формулы менять. Там синтаксис немного отличается. Но то что работает, это точно.
На я-таблицаз тоже скорее всего. Если синтаксис языка таблицы позволяет работать с api.
Единственное что проблематично в гугл таблицах — при больших обьемах данных требовательны к интернету. А в этих таблицах обьем данных большой.
Спасибо, полезно. Только что-то ОФЗ не достаёт. ПО ISIN RU000A106E90
Они в другом месте хранятся?
Офз 26238
Isin RU000A1038V6
Торговый код/тикер(SecID в формулах) SU26238RMFS4
Смотреть можно на сайте мосбиржи.
Еще как вариант во второй ячейке, где выводится режим торгов, замени marketdata на securities
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/securities/»&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=BOARDID");"//document//data//rows//row/@BOARDID")
Не могу проверить — нет екселя под рукой, но должно получиться.
Глубоко не разбирался, как правильно выбрать правильный режим, вижу, что в SPOB вообще нет котировки, поэтому вот так помогло:
Исправить XPath так:
"//document//data//rows//row[@LAST>0]/@BOARDID"
Суть изменения — брать не первую попавшуюся marketdata, а ту, где LAST цена отлична от 0.
Возможно правильнее вообще брать не из marketdata, а из marketdata_yields (из неё сейчас достаётся Эффективная доходность). Там вообще только одна борда.
А если
Попробывать так
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/engines/stock/markets/bonds/securities/»&A2&"/securities.xml?iss.meta=off&iss.only=securities&securities.columns=BOARDID");"//document//data//rows//row[@MARKETCODE=FNDT & @FACEUNIT=SUR]/@BOARDID"
Убьешь сразу 2х зайцев
-вводишь только isin (в маркетдате использует тикер, и у корпоратов тикер=isin, но у офз он отличается)
— оставляешь один тип торгов не только у офз (MARKETCODE=FNDT, но и что бы все торговалось в рублях FACEUNIT=SUR, ведь могут быть корпораты с 1 isin/ тикиром, но в разных валютах. Например RU000A107RH8.
П.с. Не уверен что правильно xPath написал, когда & два условия.
А все выплаты можно, например, так:
iss.moex.com/iss/statistics/engines/stock/markets/bonds/bondization/RU000A0JVN64.xml?iss.meta=off&iss.only=coupons&coupons.columns=name,coupondate,value&start=0&limit=100
подскажите для чайника что нужно исправить?
Кирилл Крамаров,
=IMPORTxml(СЦЕПИТЬ("iss.moex.com/iss/engines/stock/markets/bonds/securities/",B8,"? iss.only=securities&securities.columns=SECID,BOARDID,MARKETCODE,CURRENCYID"), СЦЕПИТЬ("//row[@CURRENCYID='SUR'and @MARKETCODE='FNDT']/@BOARDID"))
только для офз вводить не ISIN (например, офз 26238 RU000A1038V6), а тикер или код ценной бумаги по другому (для офз26238 это SU26238RMFS4).
для остальных облиг можно вводить ISIN
п.с. В8 — номер ячейки где у вас указана облигация. нужно заминить на соответствующую вашей ситуации
1. Облигации с переменным доходом RUONIA +% — как что указываете вы? может как идея для каждой акции писать формулу (тянуть с официальной ставкой на текущий день + % который эмитент дает сверху)
2. Криво тянется купон. Проверял на сайте вся информация есть, а формула затягиевает дичь какуюто
3. НКД тоже некоректные данные подгружает
4. и цена бумаги в % некоторые бумаги не хочет видеть цену.
в чем может быть причина, как вылечить?
Я бы предложил режим торгов всё же получать по формуле:
=ФИЛЬТР.XML(ВЕБСЛУЖБА(«iss.moex.com/iss/securities/»&A2&".xml?iss.meta=off&iss.only=boards&boards.columns=secid,boardid,is_primary");"//document//data//rows//row[@is_primary=1]/@boardid")
Параметр is_primary=1: выбирает именно основной режим торгов для инструмента.
Только сейчас дошли руки посмотреть на файл, плюс проверил на ОФЗ.
Your bunny wrote, мысль понятна. но не реашет вопрос с одним режимом торгов но разными валютами (RU000A107RH8 например)
я использовал сочетание MARKETCODE («FNDT») и CURRENCYID («SUR»)
один отвечает за тип валюты, второй за тип рынка.
П.с. у вас часом не екселевские операторы используются?
п.п.с чисто для облиг использую вот такой url адрес
iss.moex.com/iss/engines/stock/markets/bonds/securities/",B8,"
B8 — ячейка в таблице с Isin или тикером (для офз)