Набор предложений и контрфактические подсказки (T17)¶
offers.py собирает вместо одного контрпредложения несколько вариантов (SPEC §10). Каждый вариант — один вызов quote из limits.py (T16), поэтому лимит и ставка в предложении посчитаны так же, как в досье (LIMITS.md).
generate_offers(request, cash_flow, score, route_for, as_of) -> OfferSet
cash_flow— изcash_flow_from_responses(T16),score—ScoreResultосновной модели, никогда не претендента.route_for(amount) -> Route— маршрут для суммы:route_for(grade, flags, data_quality)изrouting.py(T18,ROUTING.md).as_of— день решения: от него считаютсяvalid_untilиreapply_after.
OfferSet содержит всё, что движок (T19) кладёт в Decision: offers, counterfactuals, reasons, matches_request, reapply_after, и ещё routes — маршрут, по которому посчитана цена каждого предложения. Статус решения выбирает T19: есть предложения — offered, нет — declined или in_review по маршруту.
Продукт и обеспечение¶
- Продукт —
preferred_productиз заявки, а если его нет, то продукт по цели (PURPOSE_PRODUCT): оборудование → инвестиционный кредит, кассовый разрыв → овердрафт, сезонный разрыв или контракт → кредитная линия, остальное → оборотный кредит. - Срок вне диапазона продукта приводится к ближайшей границе: у овердрафта и кредитной линии лимит всегда на 12 месяцев. Тогда предложение не совпадает с запросом.
- Стандартное обеспечение (SPEC §3–4):
| Продукт | ООО | ИП |
|---|---|---|
| Оборотный кредит | поручительство собственника | нет |
| Инвестиционный кредит | залог оборудования + поручительство | залог оборудования |
| Овердрафт, кредитная линия | нет | нет |
ИП отвечает по долгу всем личным имуществом, поэтому поручительство ему не нужно. LGD берётся по лучшему обеспечению (pricing.lgd), так что у инвестиционного кредита ООО LGD = 0,35.
Варианты¶
Варианты перебираются в порядке SPEC §10. После удаления одинаковых остаются первые MAX_OFFERS = 3.
kind |
Что это | Когда появляется |
|---|---|---|
as_requested |
Запрошенные продукт, сумма и срок | Лимит покрывает запрос |
longer_term |
Запрошенная сумма на минимальном сроке больше запрошенного, при котором quote.amount == amount |
Запрос не проходит; не для овердрафта и кредитной линии |
max_amount |
Запрошенный срок, максимальная сумма | Запрос не проходит, но лимит больше 0 |
with_collateral |
Плюс гарантия Корпорации МСП | Только если она даёт то, чего не даёт стандартное обеспечение: запрошенную сумму или ставку под потолком |
other_product |
Продукт по цели заявки | Клиент выбрал другой продукт, например оборотный кредит для кассового разрыва |
Вариант можно предложить, если сумма больше 0, не ниже минимума продукта, а ставка вместе с комиссией гарантии не выше 30% (within_cap). Выше потолка риск не укладывается в цену: система пробует гарантию МСП, а если не помогает — вариантов нет (SPEC §9.2).
Гарантия МСП вдвое снижает LGD, но стоит 1% годовых сверх ставки. Если клиент и без неё получает то же самое, гарантия обходится ему дороже, поэтому без пользы её не предлагаем. Поручительство и залог уже входят в стандартное обеспечение.
matches_request = true только у as_requested со сроком из заявки.
Маршрут каждого предложения¶
Стоимость обработки зависит от маршрута, а маршрут — от суммы (матрица полномочий, ROUTING.md). Поэтому вариант считается по маршруту запрошенной суммы, а если итоговая сумма попала на другой маршрут — пересчитывается по нему. Если маршруты не сходятся за MAX_ROUTE_ITERATIONS, берётся более дорогой. Предложения одной заявки могут оказаться на разных маршрутах (OfferSet.routes). Как из них получить один Decision.route, решает T19.
Тексты для клиента¶
tradeoff— компромисс варианта: «Запрошенная сумма, но срок 17 мес. вместо 12», «Запрошенный срок 12 мес., сумма до 730 000 ₽». У гарантии МСП там же её комиссия, у другого продукта — его условия (транши овердрафта на 60 дней). У кредитной линии указана комиссия 1% годовых за неиспользованный лимит: её нет ни в ставке, ни вOffer.reasons— почему сумма такая: определяющее ограничение лимита на запрошенном сроке (limit_cash_flow,limit_leverage,limit_collateral,limit_turnover,limit_product_max) с числами для сотрудника и простой фразой для клиента. Плюсrate_above_cap, если ставка выше потолка, иlimit_below_product_minimum, если предложений нет из-за маленького лимита.- Без предложений
reapply_after = as_of + 90 дней: за квартал по счёту накопится новая история.
Контрфактические подсказки¶
Подсказки считаются повторным запуском quote с изменённым CashFlow или заявкой, только для ограничения, которое определяет лимит на запрошенном сроке, и только если запрос не проходит.
| Ограничение | lever |
Подсказка |
|---|---|---|
cash_flow |
monthly_debt_payments |
Платёжная нагрузка по текущим кредитам, при которой проходит запрошенная сумма («при платёжной нагрузке по текущим кредитам до 13 817 ₽/мес. на 12 месяцев будет доступно 600 000 ₽»). Если такой нагрузки нет (нужна отрицательная) — сумма при погашении текущих кредитов |
leverage |
current_debt |
Текущий долг, при котором проходит запрошенная сумма |
collateral |
down_payment |
Собственный взнос 15% цены оборудования, если он меньше |
В примере decision_offered.json подсказка «без текущего кредита» — 890 тыс. ₽. Движок даёт 900 тыс. ₽: он пересчитывает ставку под новую сумму (20,61% вместо 20,75%), и при более низкой ставке лимит выше. Пример — образец формата, а не эталон (CONTRACTS.md).
Для уровня THIN подсказки по потоку нет: лимит по потоку не считается (SPEC §5.1). Подсказка «накопите историю по счёту» — задача экрана предложений (T28) по DataQuality.client_message.
Упрощения¶
# SIMPLIFICATION:политика предложений — константы вoffers.py, а не вconfig/: не больше 3 предложений, срок действия 10 дней, повторное обращение через 90 дней, комиссия 1% за неиспользованный лимит кредитной линии, соответствие цели и продукта. Перенос вconfig/credit_policy.json— отдельный PR в общую папку (docs/v2/NOTES.md).# MOCK:гарантия Корпорации МСП — множитель к LGD и фиксированная комиссия, без заявки в Корпорацию (LIMITS.md).- Срок повторного обращения после экономического отказа одинаковый для всех. В банке он зависел бы от причины: для
THIN— когда наберётся история, для долговой нагрузки — когда закроется кредит.