Примечание: Статья посвящена формату XBRL-CSV2 (тэг "@context":"www.cbr.ru/xbrl_csv2").

Авторство формата принадлежит Банку России.
Автор статьи — архитектор, принимавший участие в разработке формата в качестве технического специалиста.

Введение

Банк России использует стандарт XBRL для сбора отчетности от некредитных финансовых организаций. Несмотря на всю продуманность XBRL, при формировании и обработке отчетности возникает проблема, связанная с реестровыми формами.

Эти формы содержат гиперкубы с открытыми осями. При большой вариативности значений таких осей реестровые отчеты становятся чрезвычайно объемными.

Решение этой проблемы — создание производного от XBRL-XML формата: XBRL-CSV.

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

Остальные колонки — это данные, которые определяют три аспекта показателя:

  • имя концепта;

  • аналитический разрез закрытых осей;

  • аспект отчетного периода или даты.

Что не так с классическим XBRL?

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

В результате реестровые формы в классическом XBRL сложно формировать, сложно проверять и сложно обрабатывать.

А как насчет многопоточной обработки?

В классическом XBRL-XML это практически невозможно. Когда данных становится действительно много, хочется обрабатывать их с помощью алгоритмов массово-параллельной обработки — например, в кластере Hadoop, загружая CSV в таблицы Parquet и обрабатывая их с помощью SparkSQL.

Кроме того, ходят слухи о внедрении регулятором дата-центричных таксономий, то есть об отказе от разбиения собираемых показателей по формам и точкам входа на основе ОКУД. Речь идет о переходе к более прагматичной модели — Единой модели собираемых данных (ЕМСД).

В такой модели данные из разных разделов часто связываются между собой, что является прямой аналогией связи таблиц в реляционной системе и очень удобно для реализации в формате XBRL-CSV.

Поэтому в качестве формата для реализации был выбран XBRL-CSV2.

Представляем XBRL-CSV2

Четкое определение: XBRL-CSV2 — это спецификация представления данных XBRL в табличном формате CSV, которая сохраняет всю семантическую строгость стандарта, но при этом делает данные простыми для обработки и понимания.

Мы взяли мощь XBRL и упаковали ее в простоту Excel-таблицы.

Все файловые артефакты формата XBRL-CSV получаются путем автоматической конвертации файловых артефактов таксономии классического XBRL. Это значит, что авторы информационной модели (таксономии) продолжают создавать метаданные на языке XBRL, используя всю его мощь и гибкость, а затем полученная таксономия автоматически конвертируется в набор файловых артефактов XBRL-CSV.

Как это работает? Технический взгляд под капот

Как выглядит отчетность в формате XBRL-CSV?

Это архив, в составе которого есть один JSON-документ (файл маппинга) и группа (минимум один) CSV-файлов с данными.

JSON-документ маппинга содержит общую информацию о пакете данных (заголовочную информацию), а также массив описаний всех приложенных CSV-файлов с описанием состава колонок каждого файла.

Другими словами, JSON-документ маппинга определяет, где и какие данные располагаются в CSV-файлах.

На данный момент состав файловых артефактов XBRL-CSV включает:

  • Набор схем Draft — связанные JSON-документы, необходимые для проверки файла маппинга JSON (прямая аналогия с XSD-схемами в XML).

  • Примеры избыточного заполнения — пакет, у которого заполнены все CSV-файлы и все колонки для определенной точки входа.

  • Набор файлов с SQL-выражениями для обработки данных по контрольным соотношениям формульного слоя таксономии.

Как располагаются данные в CSV-файлах?

Чтобы ответить на этот вопрос, посмотрим на классический XBRL и рассмотрим, как показатель и, что важнее, аспекты показателя трансформируются при конвертации слоев таксономии классического XBRL в структуры схемы Draft, которая, в свою очередь, формирует вид файла маппинга JSON.

В XBRL-отчете показатель определяется контекстом и определением непосредственно показателя: имени концепта, ссылки на контекст, значения показателя, а также возможного определения единицы измерения и указания точности.

Пример контекстов:

xml

  <context id="context_0">
    <entity>
      <identifier>111111111111111</identifier>
    </entity>
    <period>
      <instant>2025-07-04</instant>
    </period>
    <scenario>
      <xbrldi:typedMember dimension="dim-int:openAxis1_Taxis">
        <dim-int:typedMember1>123</dim-int:typedMember1>
      </xbrldi:typedMember>
      <xbrldi:typedMember dimension="dim-int:openAxis2_Taxis">
        <dim-int:typedMember1>ABCD</dim-int:typedMember1>
      </xbrldi:typedMember>
     <xbrldi:explicitMember dimension="dim-int:explicitAxis1">mem-int:explicitMember1</xbrldi:explicitMember>
    </scenario>
  </context>

<context id="context_1">
    <entity>
      <identifier>111111111111111</identifier>
    </entity>
    <period>
      <instant>2025-07-04</instant>
    </period>
    <scenario>
      <xbrldi:typedMember dimension="dim-int:openAxis1_Taxis">
        <dim-int:typedMember1>123</dim-int:typedMember1>
      </xbrldi:typedMember>
      <xbrldi:typedMember dimension="dim-int:openAxis2_Taxis">
        <dim-int:typedMember2>ABCD</dim-int:typedMember2>
      </xbrldi:typedMember>
     <xbrldi:explicitMember dimension="dim-int:explicitAxis1">mem-int:explicitMember2</xbrldi:explicitMember>
    </scenario>
  </context>

И примеры показателей, связанные с этими контекстами:

xml

  <purcb-dic:reportingConcept1 contextRef="context_01">X</purcb-dic:reportingConcept1>
  <purcb-dic:reportingConcept1 contextRef="context_02">Z</purcb-dic:reportingConcept1>

Представленные примеры концептов описывают гиперкуб, в аналитическом разрезе которого участвуют:

  • Открытая ось (typed dimension) — dim-int:openAxis1_Taxis

  • Открытая ось (typed dimension) — dim-int:openAxis2_Taxis

  • Закрытая ось (explicit dimension) — dim-int:explicitAxis1

    • Член закрытой оси (explicit member) — mem-int:explicitMember1

    • Член закрытой оси (explicit member) — mem-int:explicitMember2

К этому гиперкубу привязан концепт reportingConcept1, и такая связь образует раздел с именем R1.

Вот как это будет выглядеть в CSV-файле:

.dimint_openAxis1_Taxis

.dimint_openAxis2_Taxis

.purcbdic_reportingConcept1_dimGrp_1_periodGrp_1

.purcbdic_reportingConcept1_dimGrp_2_periodGrp_1

123

ABCD

X

Z

Почему здесь одна строка, если контекста два? Одна строка — потому что аналитический разрез открытых осей у этих контекстов одинаков. Состав открытых осей и их значения совпадают.

Структура колонок:

  • Первые две колонки — открытые оси.

  • Третья и четвертая колонки — данные, имена которых различаются суффиксами dimGrp_1 и dimGrp_2.

Это различие обусловлено тем, что оба значения концепта reportingConcept1 принадлежат одному аналитическому разрезу открытых осей (поэтому оба значения показателя лежат на одной строке), но разному аналитическому разрезу закрытых осей (поэтому есть две колонки данных с частично одинаковыми именами, различающимися суффиксом аналитического разреза закрытых осей гиперкуба).

Теперь посмотрим на описание такого файла данных в файле маппинга JSON (фрагмент):

json

"tables": [
  {
    "uri": "R1.csv",
    "roleUri": "http://www.cbr.ru/xbrl/aaa/bbb/rep/YYYY-MM-DD/tab/R1",
    "csvRowsCount": 1,
    "typedFiltering": true,
    "columns": [
      {
        "columnId": "dim_int_openAxis1_Taxis",
        "xbrldi:typedMember": {
          "dimension": "dim-int_openAxis1_Taxis",
          "typedDomain": "dim-int_typedMember1"
        }
      },
      {
        "columnId": "dim_int_openAxis2_Taxis",
        "xbrldi:typedMember": {
          "dimension": "dim-int_openAxis2_Taxis",
          "typedDomain": "dim-int_typedMember2"
        }
      },
      {
        "columnId": "purcb_dic_reportingConcept1_dimGrp_1_periodGrp_1",
        "aspect": {
          "type": {
            "datatype": "string",
            "http://www.cbr.ru/xbrl-csv/model#columnType": "xbrli:stringItemType"
          },
          "xbrl:concept": "purcb-dic_reportingConcept1"
        },
        "xbrli:period": {
          "periodType": "instant",
          "xbrli:instant": "$par:refPeriodEnd"
        },
        "flatDimension": false,
        "xbrldi:explicitMemberArray": [
          {
            "dimension": "dim-int_explicitAxis1",
            "member": "mem-int_explicitMember1"
          }
        ]
      },
      {
        "columnId": "purcb_dic_reportingConcept1_dimGrp_2_periodGrp_1",
        "aspect": {
          "type": {
            "datatype": "string",
            "http://www.cbr.ru/xbrl-csv/model#columnType": "xbrli:stringItemType"
          },
          "xbrl:concept": "purcb-dic_reportingConcept1"
        },
        "xbrli:period": {
          "periodType": "instant",
          "xbrli:instant": "$par:refPeriodEnd"
        },
        "flatDimension": false,
        "xbrldi:explicitMemberArray": [
          {
            "dimension": "dim-int_explicitAxis1",
            "member": "mem-int_explicitMember2"
          }
        ]
      }
    ]
  }
]

А вот сокращенный вариант:

json

"tables": [
  {
    "uri": "R1.csv",
    "roleUri": "http://www.cbr.ru/xbrl/aaa/bbb/rep/YYYY-MM-DD/tab/R1",
    "csvRowsCount": 1,
    "typedFiltering": true,
    "columns": [
      { "columnId": "dim_int_openAxis1_Taxis" },
      { "columnId": "dim_int_openAxis2_Taxis" },
      { "columnId": "purcb_dic_reportingConcept1_dimGrp_1_periodGrp_1" },
      { "columnId": "purcb_dic_reportingConcept1_dimGrp_2_periodGrp_1" }
    ]
  }
]

Согласитесь, сокращенный вариант маппинга выглядит достаточно компактным, особенно если сравнить с оформлением в классическом XBRL.

h3. Как появилась возможность использовать сокращенный вариант маппинга?

Если передать такой маппинг в пакете надзорному органу, сможет ли он расшифровать, какой показатель, с какими аналитическими разрезами и за какой отчетный период подразумевается в колонке? Да, сможет.

Все дело в константных именах файлов данных, колонок осей и колонок данных.

  • Имена файлов данных совпадают с именем раздела в точке входа (R1) — это однозначно определяет гиперкуб.

  • Имена колонок открытых осей состоят из нормализованных имен этих осей и однозначно определяют их в гиперкубе.

С колонками данных немного сложнее. Их имена не только идентифицируют данные в таблицах, но и кодируют аспекты показателя.

Например, возьмем две колонки данных:

  • purcb_dic_reportingConcept1_dimGrp_1_periodGrp_1

  • purcb_dic_reportingConcept1_dimGrp_2_periodGrp_1

Имя колонки состоит из трех частей:

  1. Нормализованное имя концепта — purcb_dic_reportingConcept1

  2. Суффикс группы аналитического разреза закрытых осей — dimGrp_1 и dimGrp_2

  3. Суффикс группы параметра аспекта даты-периода показателя — periodGrp_1 и periodGrp_2

С концептом все понятно.

Что такое суффикс группы аналитического разреза?

Вернемся к нашему учебному гиперкубу. В нем одна закрытая ось dim-int:explicitAxis1 и два связанных с ней члена: mem-int:explicitMember1 и mem-int:explicitMember2.

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

  • mem-int:explicitMember1 → dimGrp_1

  • mem-int:explicitMember2 → dimGrp_2

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

Рассмотрим более сложный случай гиперкуба

  • Закрытая ось (explicit dimension) — dim-int:explicitAxis1

    • Член — mem-int:explicitMember11

    • Член — mem-int:explicitMember12

  • Закрытая ось (explicit dimension) — dim-int:explicitAxis2

    • Член — mem-int:explicitMember21

    • Член — mem-int:explicitMember22

Упорядоченный список будет выглядеть так:

  1. dim-int:explicitAxis1(mem-int:explicitMember11); dim-int:explicitAxis2(mem-int:explicitMember21);

  2. dim-int:explicitAxis1(mem-int:explicitMember12); dim-int:explicitAxis2(mem-int:explicitMember21);

  3. dim-int:explicitAxis1(mem-int:explicitMember11); dim-int:explicitAxis2(mem-int:explicitMember22);

  4. dim-int:explicitAxis1(mem-int:explicitMember12); dim-int:explicitAxis2(mem-int:explicitMember22);

Гиперкуб с такой конфигурацией закрытых осей даст четыре аналитических разреза, и мы присвоим им четыре группы: dimGrp_1dimGrp_2dimGrp_3dimGrp_4.

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

Суффикс группы параметра аспекта даты-периода показателя

Это похожая история, но группы создаются глобально для всего отчета. Для этого собираются все имена переменных аспектов дат всего отчета, они упорядочиваются по алфавиту, и затем им присваиваются номера.

Как определяется состав переменных аспектов дат и что это такое?

Здесь работает алгоритм "контроля дат", который, кстати, отсутствует в классическом XBRL. В XBRL-XML каждый контекст содержит значение отчетного периода или даты показателя, и отчитывающаяся организация может без контроля указать любую дату или период для любого контекста. Это ухудшает качество данных и создает потенциал для ошибок.

В XBRL-CSV2 отчетные даты и периоды формируются и передаются иначе.

Передается единственная отчетная дата как значение атрибута в заголовке маппинга "header"\@"reportDate", а аспект каждой колонки данных содержит переменную аспекта отчетной даты или периода.

Это выглядит как "xbrli:instant" : "$par:refPeriodEnd", и каждое значение такой переменной рассчитывается по XPATH-выражениям параметров дат из таксономии. Список этих выражений находится в файле .\www.cbr.ru\xbrl\ext\params-rend.xml и содержит набор XPATH-выражений для расчета отчетных дат относительно отчетной даты всего отчета.

Например, у вас "header"\@"reportDate"="2025-10-05", а в аспекте показателя (в описании колонки данных) указан аспект даты: par:RegStartInsQuart. Какая отчетная дата подразумевается для такой колонки? Очевидно, это начало четвертого квартала 2025 года относительно 2025-10-05, то есть 2025-10-01.

Как XBRL-CSV2 "понимает", какие даты требуются для подачи в отчете?

Все дело в табличном слое таксономии.

Если структура гиперкубов — это "слой определений таксономии", то правила, связывающие аспекты показателя с отчетными датами, описаны именно в табличном слое. Поэтому ядро операций XBRL-CSV2 анализирует табличные слои и формирует требования к маппингу с учетом правил: какие показатели, с какими аналитическими разрезами и за какую дату или период должны быть поданы.

Текущий статус формата

На данный момент регулятор реализует первый проект для сбора отчетности в формате XBRL-CSV2 — это нерегулярная отчетность по запросу от департамента ДИФП Банка России. Но у ЦБ есть планы по развитию данного формата и переводу на него других потоков сбора отчетности.

Заключение

Кратко резюмирую: Мы сохранили всю мощь и стандартизацию XBRL, но избавились от его главного недостатка — сложности. Теперь финансовая отчетность может быть по-настоящему открытой и доступной для анализа.

Эта статья не затронула описание "слоя отделяемых формул" — набора файлов, содержащих SQL-выражения для обработки данных по контрольным соотношениям формульного слоя таксономии. Эта тема еще более обширна и заслуживает отдельной статьи.

Полезные ссылки:

https://cbr.ru/projects_xbrl/taxonomy_xbrl/xbrl-csv

Комментарии (2)


  1. itGuevara
    20.10.2025 14:49

    Банк России не планирует какой-либо XBRL-RDF? Или что-то из стека Linked Data применительно к Единой модели собираемых данных (ЕМСД), Качеству данных (управление данными)?


    1. lkill Автор
      20.10.2025 14:49

      Я не являюсь сотрудником ЦБ, поэтому могу поделиться лишь неподтверждённой информацией, которая циркулирует в качестве слухов.
      Вот статья про планы ЦБ о сборе отчетности:
      https://www.profbanking.com/news/188-2025/5279-clever-regulator