Новый алгоритм
выплат transit

Презентация для понимания: что и зачем меняем
12ч → 1ч
время закрытия
−97%
для важных мерчантов
0.44%
потери (было 2.5%)
15 слайдов · 5 минут чтения · стрелки ← →
1. Контекст

Что такое transit-выплаты

Простыми словами:

Игрок А хочет вывести деньги — мерчант должен ему заплатить.

Игрок Б в это же время вносит депозит — мерчант должен от него получить.

Наш алгоритм сводит их напрямую: Б платит А по реквизитам, мерчант просто фиксирует что обе операции прошли.

Это альтернатива «трейдерам». Дешевле и быстрее — если получается свести.

Сейчас работает только для виджет-мерчантов (Orbit, MoXB, MRGB) → метод UPI в Индии.

2. Проблема

Сейчас выплата может ждать 12 часов

В большинстве случаев (90% выплат) — закрываются в течение этого времени.

Это недопустимо: мерчанты жалуются, теряем трафик, особенно крупный.

Что страдает

  • Половина выплат закрывается быстро (за час)
  • Но 40% — застревают на часы
  • Хуже всего вечером (с 18 до 23)
  • Самый страдающий мерчант — KPMI (55% объёма)

Почему так

  • Алгоритм матчинга — это «7 правил подряд», накопленных за годы
  • Эти правила противоречат друг другу
  • Старые выплаты получают приоритет — но они старые ровно потому что их не получается закрыть
  • Зависшие выплаты блокируются и ждут разблокировки 3+ минут
3. Цель

Куда хотим прийти

Важные мерчанты (KPMI)
≤ 60 мин
9 из 10 выплат за час
Остальные мерчанты
≤ 180 мин
9 из 10 выплат за 3 часа
Потери от ошибок
≤ 2%
было 2.5%, хотим 1.5–2%

Если этого добиться — мерчанты дают больше трафика, мы зарабатываем больше.

4. Как работает сейчас

Старый алгоритм: 7 правил подряд

Когда приходит платёж от игрока, программа выбирает кому из ожидающих выплат его отдать. Выбор делается по цепочке 7 правил:

  1. Старые выплаты вперёд — самая старая получает первой
  2. Точное совпадение сумм
  3. Минимальный «ущерб круглости» остатка
  4. Максимально круглый остаток
  5. Минимальный остаток
  6. Минимальная переплата
  7. Случайный выбор если всё равно
Это не «формула выбора», это история фиксов — каждое правило добавляли когда что-то ломалось.

Правила конфликтуют между собой. Старая выплата с большим остатком всегда побеждает свежую с идеальным размером — и зависает дальше.

5. Новая архитектура

Решение: 5 независимых улучшений

Каждое улучшение — отдельный «слой» с своей задачей. Вместе они дают целевые показатели.

1
Кого матчить
Правильно сузить кандидатов, асимметричный допуск, кратность сумм
2
Скоринг игроков
4 группы по истории: TRUSTED / STANDARD / COLD / RISKY
3
Кому отдавать
Одна формула «оценки» вместо 7 правил подряд
4
Зависшие
Мгновенная разблокировка, умные таймауты
5
Переплаты
Книга переплат вместо тихих потерь

Дальше — слайды с каждым слоем подробно.

Слой 1 из 5

Кого вообще можно матчить

Правильно настроенный фильтр кандидатов

Три ключевых изменения:

🎯 Асимметричный допуск

Бизнес-правило: игрок может прислать чуть больше чем надо (мы съедим переплату), но никогда меньше — мерчант должен получить полную сумму.

Сейчас в коде разрешено в обе стороны → это бизнесово неправильно и расширяет окно вдвое.

⚙️ Отдельные настройки для каждого мерчанта

Сейчас один общий выключатель «можно ли частично закрывать» для всех. Делаем отдельно:

🔢 Round-500: попросить KPMI выдавать суммы кратные 500

Сейчас KPMI выдаёт выплаты типа 1013, 1009 рупий — таких сумм почти не бывает у плательщиков. Если попросить мерчанта выдавать 1000, 1500, 2000… — точное совпадение взлетит с 84% до 100%.

Требует переговоров с мерчантом — это самое большое улучшение для KPMI.

Слой 2 из 5

Скоринг отправителей

Делим всех игроков на 4 группы по их прошлой истории — и обрабатываем каждую группу по-своему.

🟢
TRUSTED
86%
≥5 прошлых платежей, ≥90% успешных, без жалоб
Держим дольше — почти всегда платит
🔵
STANDARD
59%
средняя история
Стандартная обработка
COLD
47%
новый, <5 платежей
Стандартная обработка
🔴
RISKY
6%
≥5 платежей, ≤10% успешных
Сразу к трейдерам — не блокируем

Большое число — это сколько процентов их платежей реально завершаются успехом.

RISKY чаще «играют» — копируют реквизиты, ничего не платят, потом пишут апелляцию. Их выгоднее сразу отдавать трейдерам, чем занимать ими выплаты.

TRUSTED — наоборот, на них можно положиться: блокировать выплату для них дольше — окупится.

Слой 3 из 5

Кому отдать платёж — одна формула вместо 7 правил

Каждый кандидат-выплата получает «оценку» (score). Выбираем того, у кого оценка выше.

оценка =
+ 1.2 × бонус важности мерчанта
− 0.5 × возраст выплаты # старые НЕ в приоритете
− 0.5 × переплата
− 1.0 × остаток после матча
− 1.2 × штраф за «узкое окно»
+ 1.3 × бонус хорошего игрока
− 100 × если выплата «проблемная»

Числа перед каждым слагаемым (1.2, 0.5, и т.д.) — «веса», их можно крутить и подбирать оптимально.

Главное отличие от старого: можно отлаживать. Видно почему алгоритм выбрал именно эту выплату — можно изменить один вес и понять как поведение меняется.

Слой 4 из 5

Зависшие выплаты — арифметика времени

Откуда берётся хвост из «12 часов» и сколько минут срезает каждое изменение.

Что показали данные за неделю

Откуда минуты в хвосте

Источник простояМинут / случайКого затрагивает
3-минутный цикл acqUnlocker3-10 минкаждая выплата с failures >0
1 переназначение менеджера в вечерний пик100-200 мин30% выплат
6+ переназначений (циркуляция)+390 мин (869 vs 477)14% выплат
Forever-блок после 5 ошибокчасы до ручной разблокировки1.2% (239 выплат / нед)

Что меняем и сколько срезает

1. Мгновенная разблокировка

Убирает 3-мин цикл. Если у выплаты 5 циклов блок-разблок за хвостовое время — это 15+ минут простоя удалено.

2. Растущие паузы (1ч / 2ч / 4ч)

Эти 239 «проблемных» выплат перестают циркулировать в pool 5+ раз. Это освобождает менеджеров для обычных выплат.

3. Skip-problematic после 4ч

1.2% «безнадёжных» отправляются трейдерам, а не висят. Их вклад в p99 (самые долгие 1%) — почти весь.

4. Per-merchant capacity awareness

Вместо борьбы за peak hours — алгоритм распределяет выплаты с учётом нагрузки. Эффект на evening p90: 699 → ~150 мин.

Совокупный эффект в sim: от preset C (без recovery) к preset G (полное): p90 хвоста 194 → 98 мин (−50%), p99 1103 → 1121 почти одинаково, но Tier-A p90: 163 → 36 мин (−78%).

Слой 5 из 5

Переплаты — арифметика снижения потерь

Конкретно откуда берётся падение Loss с 2.09% до 0.44%.

Что считается «потерями» в наших цифрах

Откуда переплаты возникают (3 случая)

СценарийСколькоДоля
Игрок округлил вверх (1000 → 1100)100-200 ₹ / случай~70%
Игрок перевёл на старую цену, мерчант изменил сумму500-2000 ₹~20%
Намеренная переплата «для надёжности»50-300 ₹~10%

Старое vs новое поведение

Старое

Шаг 1: игрок перевёл 1100₹, надо 1000₹

Шаг 2: 100₹ записываются в Expense(SYSTEM_ERRORS) как «системная ошибка»

Шаг 3: деньги списаны с баланса, никто не пытается вернуть игроку

Результат: ~2% объёма transit-payment'ов исчезает в потерях

Новое

Шаг 1: игрок перевёл 1100₹, надо 1000₹

Шаг 2: 100₹ записываются в customerOverpayLedger со ссылкой на этот платёж и счёт игрока

Шаг 3: раз в сутки batch-job: возвращаем игрокам всё что в ledger

Результат: переплаты возвращаются → исчезают из «потерь»

Арифметика дельты Loss% 2.09 → 0.44

Это не магия: деньги те же, но теперь они идут не в «потери», а в «пассив с обязательством вернуть». Возвращаем — балансовая запись очищается.

6. Что получаем

Результаты в симуляции

Прогнали ~25 итераций симуляции на реальных данных за неделю. Финал — preset OPTIMAL.

Tier-A (KPMI)
36 мин
было 8.2 часа → −97%
Tier-B (Orbit)
143 мин
было 11.9 часа → −80%
Потери
0.44%
было 2.5% → в 5.7× меньше

Важно: симуляция чуть пессимистичнее реальности (baseline 18 часов в симе vs 12 в проде). Реальные результаты могут быть лучше прогноза.

7. Сравнение

Что выкидываем · что приходит на смену

СтароеНовое
Сортировка по 7 правиламОдна формула оценки
Старые выплаты в приоритетеВозраст — мягкий бонус
Сохранять круглость остаткаШтраф за создание узкого окна
5 ошибок = блок навсегдаРастущие паузы: 1ч / 2ч / 4ч…
Допуск в обе стороныТолько переплата, недоплата запрещена
Разблокировка каждые 3 минутыМгновенная разблокировка
Один общий «можно ли частично»Отдельно для каждого мерчанта
Переплаты в тихие потериКнига переплат + refund
Все игроки обрабатываются одинаково4 группы по истории
8. Реализация

План внедрения — около месяца

Неделя 1
параллельно
Переговоры с KPMI про кратность сумм 500 рупий. Внешний трек — не зависит от кода.
Неделя 1-2
код
Базовые изменения в алгоритме:
• асимметричный допуск
• новая формула оценки вместо ORDER BY
• мгновенная разблокировка
• растущие паузы для ошибок
Неделя 2
новая БД-таблица
customerOverpayLedger + batch refund job (возврат переплат раз в сутки)
Неделя 2-3
скоринг
4-bucket скоринг отправителей на текущих данных (без ML-моделей пока)
Неделя 3
А/Б-тест
Постепенный rollout: 5% → 20% → 50% → 100% трафика, каждый шаг 24-48ч наблюдения
Неделя 4
доводка
Калибровка весов формулы на основе реальных данных. Метрики становятся target'ами.
9. Дальше копать

Куда углубиться

Дальнейшие улучшения

  • Скоринг V2: когда соберём поведенческую телеметрию виджета — можно перейти на ML-модель (LR/GBM) на 30+ фичах
  • Логирование (D): точки причин не-матча, события виджета, false-positive детектор
  • Расширение payin: подключить host-to-host (50% трафика) через скоринг — потенциал удвоить capacity