ПРАКТИКУМ И ДОКАЗАТЕЛЬСТВАP1L3
LAB-TRM: график сделки, календарь и синтетическая оценка
Воспроизводимый синтетический сценарий: купонный график, перенос рабочей даты, новая ревизия сделки, интерполяция кривой и приведённая стоимость с независимым эталоном.
5 мин чтения·Проверенный учебный пример
Ревизия 1
Общие понятия
Частичное покрытие
Контекст: CTX-GENERAL
документальная опора: недостаточно данныхэталонная проверка: прошло
LAB-TRM: график сделки, календарь и синтетическая оценка#
Эта лаборатория расширяет локальный TRM reference model до графика процентных потоков и оценки по заданной zero curve. Все входы придуманы для обучения; это не SAP-проводка, не текущие рыночные данные и не финансовая рекомендация. Проверенный результат относится к Python-модели и независимому golden fixture, а не к SAP Transaction Manager.
Условия примера#
Задана фиксированная синтетическая сделка на 1 000 000 минимальных денежных единиц в RUB с 30 января по 30 июля 2026 года. Годовая ставка равна 6%, платежи каждые два месяца, база начисления 30E/360. Каждая незавершённая сумма купона выплачивается по окончании периода; номинал погашается вместе с последним купоном.
Календарь не считает субботу и воскресенье рабочими днями; 1 июня 2026 года добавлен как учебный праздничный день. Используется перенос following. Границы начисления остаются договорными, а рабочий календарь сдвигает только платежную дату.
Расчёт графика#
Для каждого двухмесячного периода используется формула:
coupon_minor = round_half_up(principal_minor × annual_rate × 30E/360_days / 360)
Каждый период от 30-го числа до 30-го числа даёт 60 дней по 30E/360: 1 000 000 × 0.06 × 60 / 360 = 10 000 минимальных единиц. Это не означает, что фактическое число календарных дней в каждом периоде равно 60.
| Начисление |
Договорная граница |
Платёжная дата |
Купон |
Погашение номинала |
| 1 |
30.01-30.03 |
30.03.2026 |
10 000 |
0 |
| 2 |
30.03-30.05 |
02.06.2026 |
10 000 |
0 |
| 3 |
30.05-30.07 |
30.07.2026 |
10 000 |
1 000 000 |
30 мая приходится на субботу, 31 мая : воскресенье, а понедельник 1 июня явно задан как праздник, поэтому following переносит платёж на 2 июня. Дата конца начисления остаётся 30 мая. При revised trade revision 2 и ставке 7% исходные потоки сохраняются; новый расчёт даёт купон 11 667 в каждом периоде после half-up округления.
Синтетическая zero curve и present value#
На valuation date 30 января заданы узлы кривой: 3.5% на 30 марта и 4.5% на 30 июля. Между zero rates применяется линейная интерполяция по фактическим календарным дням. Дисконтирование задано непрерывной конвенцией DF = exp(-r × days/365). Это явный учебный выбор формулы, а не утверждение о способе оценки в SAP.
| Платёж |
Сумма, минимальные единицы |
Ставка кривой |
Present value, минимальные единицы (округлено для отображения) |
| 30.03.2026 |
10 000 |
3.5000% |
9 943.5844 |
| 02.06.2026 |
10 000 |
4.0246% |
9 865.2924 |
| 30.07.2026 |
1 010 000 |
4.5000% |
987 711.3916 |
Итого до округления: 1 007 520.2684; после half-up до минимальной единицы : 1 007 520. В условном RUB с двумя десятичными знаками это 10 075.20 RUB. Независимый fixture хранит тот же ожидаемый целочисленный итог. Если кривая имеет другую валюту, не покрывает дату потока, отсутствует или её as_of_date не равна дате оценки, модель прекращает расчёт. Экстраполяция и stale curve запрещены.
Что проверяет лаборатория#
- Условия сделки, даты и календарь проходят закрытую валидацию; ставки задаются точным decimal string, не
float.
- Каждый поток несёт trade ID и revision; новая версия добавляется в историю, не заменяя старую.
- ACT/360, 30E/360 и ACT/365F остаются разными конвенциями; платежное смещение не меняет accrual boundary.
- Оценка использует только не оплаченные на valuation date потоки, валюту и zero curve с явным источником/датой/узлами.
- Нет недостающих ставок, молчаливого округления Python
round, смешения валют и экстраполяции за кривую.
- Golden fixture содержит ожидаемые границы, даты и PV независимо от вызываемой модели.
Запуск и доказательства#
Из корня репозитория выполните:
python -m unittest sites/sap-fico/lab/tests/test_trm_lifecycle.py -v
Полный набор лаборатории запускается командой из руководства лаборатории. Доказательство functional_oracle: passed привязано к хешам кода, тестов и fixture из локального manifest. Статус не меняет LAB-TRM SAP runtime: not_run: модель не вызывает SAP, не создаёт реальную сделку и не формирует FI-проводку.
Границы#
Модель фиксированного купона не поддерживает плавающие ставки, кривые нескольких базисов, валютную переоценку, риск-модели, сложные business-day calendars, налоги, продуктовые настройки, posting rules или SAP release behavior. Для нового продукта или рынка нужны отдельные договорные условия, источник рынка, правила кривой и независимый эталон. Материал частично иллюстрирует календарь, изменение сделки, рыночную кривую и дисконтирование из общей тематической карты.
Документация SAP#
Эти страницы описывают области Transaction Manager и передачу потоков в FI. Они не подтверждают совпадение численного результата независимой Python-модели с SAP.
LAB-TRM: trade schedule, calendar, and synthetic valuation#
This lab extends the local TRM reference model to scheduled interest flows and valuation on a specified zero curve. All inputs are invented for learning; this is not an SAP posting, current market data, or financial advice. The verified result applies to the Python model and its independent golden fixture, not SAP Transaction Manager.
Example terms#
A synthetic fixed-rate trade has a principal of 1,000,000 minor units in RUB and runs from January 30 to July 30, 2026. Its annual rate is 6%, payments occur every two months, and accrual uses 30E/360. Each coupon is paid at period end; principal is repaid with the last coupon.
The calendar excludes Saturday and Sunday and lists June 1, 2026 as a synthetic holiday. The following adjustment is applied. Accrual boundaries remain contractual; the business calendar shifts only the payment date.
Schedule calculation#
For each two-month period, the model uses:
coupon_minor = round_half_up(principal_minor × annual_rate × 30E/360_days / 360)
Each period from day 30 to day 30 counts as 60 days under 30E/360: 1,000,000 × 0.06 × 60 / 360 = 10,000 minor units. This does not mean each period has 60 actual calendar days.
| Accrual |
Contractual boundary |
Payment date |
Coupon |
Principal repayment |
| 1 |
Jan 30-Mar 30 |
2026-03-30 |
10,000 |
0 |
| 2 |
Mar 30-May 30 |
2026-06-02 |
10,000 |
0 |
| 3 |
May 30-Jul 30 |
2026-07-30 |
10,000 |
1,000,000 |
May 30 is a Saturday, May 31 is Sunday, and Monday June 1 is an explicit holiday, so following moves payment to June 2. The accrual period still ends on May 30. With revised trade revision 2 and a 7% rate, the original flows remain unchanged; the new calculation gives an 11,667 coupon for each period after half-up rounding.
Synthetic zero curve and present value#
The zero curve is dated January 30 and has nodes of 3.5% for March 30 and 4.5% for July 30. Between nodes, zero rates are interpolated linearly by actual calendar days. Discounting is specified as continuous compounding: DF = exp(-r × days/365). This is an explicit learning choice, not a claim about SAP valuation methods.
| Payment |
Amount, minor units |
Curve rate |
Present value, minor units (rounded for display) |
| 2026-03-30 |
10,000 |
3.5000% |
9,943.5844 |
| 2026-06-02 |
10,000 |
4.0246% |
9,865.2924 |
| 2026-07-30 |
1,010,000 |
4.5000% |
987,711.3916 |
Total before rounding: 1,007,520.2684; after half-up rounding to a minor unit: 1,007,520. In illustrative RUB with two decimal places, that is RUB 10,075.20. The independent fixture stores the same expected integer total. If the curve currency differs, a payment date is outside its nodes, the curve is missing, or its as_of_date is not the valuation date, the model stops. Extrapolation and stale curves are rejected.
What the lab checks#
- Trade terms, dates, and calendar are validated against a closed contract; rates use exact decimal strings, not
float.
- Every flow carries a trade ID and revision; a new version is appended without replacing the old one.
- ACT/360, 30E/360, and ACT/365F remain separate conventions; a payment-date shift does not alter accrual boundaries.
- Valuation includes only flows unpaid on the valuation date and requires a currency and zero curve with explicit source, date, and nodes.
- Missing rates, silent Python
round, currency mixing, and extrapolation beyond the curve are rejected.
- The golden fixture records expected boundaries, dates, and present value independently of the called model.
Run and evidence#
From the repository root, run:
python -m unittest sites/sap-fico/lab/tests/test_trm_lifecycle.py -v
The complete lab suite is described in the lab guide. The functional_oracle: passed evidence is tied to hashes of code, tests, and fixture in a local manifest. It does not change LAB-TRM SAP runtime: not_run: the model does not call SAP, create a real trade, or produce an FI posting.
Limitations#
The fixed-coupon model does not support floating rates, multi-curve valuation, FX revaluation, risk models, complex business calendars, taxes, product configuration, posting rules, or SAP release behavior. A new product or market requires its own contractual terms, market source, curve rules, and independent oracle. This material partially illustrates calendar handling, trade revision, market curve, and discounting from the normative topic map.
SAP documentation#
These pages describe Transaction Manager scope and flow transfer to FI. They do not confirm that the independent Python model's numerical result matches SAP.