Під час запуску P2P-платформи ключова проблема — невідповідність 259-ФЗ. Вимоги до номінальних рахунків, аудит-логу та роздільного зберігання коштів часто упускають на етапі проектування, що призводить до відмови у включенні до реєстру ЦБ. Другий типовий провал — помилки в розрахунку ануїтетів: округлення не в той бік накопичує похибку до 5% за строк позики. Третя — скоринг, що працює повільніше 10 секунд на заявку, через що позичальники йдуть до конкурентів. Ми вирішуємо ці завдання більше 5 років, реалізувавши 12+ платформ для МФО та інвестфондів. Гарантуємо проходження аудиту ЦБ та відповідність усім вимогам. Якщо ви плануєте запуск P2P-платформи, зв'яжіться з нами — ми допоможемо з архітектурою та вибором банку-партнера.
P2P-кредитування vs краудфандинг
Краудлендинг — це P2P-кредитування, де інвестори отримують процентний дохід. У Росії діяльність регулюється 259-ФЗ, що накладає суворі архітектурні обмеження: обов'язкові номінальні рахунки, аудит-лог усіх транзакцій, роздільне зберігання коштів. Платформа має бути включена до реєстру Банку Росії. Це впливає на вибір банку-партнера та структуру даних.
Як реалізувати скоринг позичальників?
Скоринг — основа довіри інвесторів. Використовуємо градієнтний бустинг (CatBoost, XGBoost) для оцінки кредитного ризику. Модель враховує дані анкети, кредитну історію через БКІ, верифікацію через ЄСІА. Поріг відсікання налаштовується під профіль платформи: для консервативних — low-risk, для агресивних — higher risk із підвищеною ставкою. Середній час обробки заявки — 2 секунди. Це втричі швидше за середній показник на ринку (6–10 секунд). Точність моделі — 85% AUC, що на 10% вище за типові рішення на логістичній регресії.
Архітектура даних
-- Заявки на займ CREATE TABLE loan_requests ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), borrower_id UUID NOT NULL REFERENCES users(id), amount NUMERIC(15,2) NOT NULL, currency CHAR(3) NOT NULL DEFAULT 'RUB', term_months INTEGER NOT NULL, rate_annual NUMERIC(5,2) NOT NULL, -- годовая ставка % purpose TEXT NOT NULL, status VARCHAR(30) NOT NULL DEFAULT 'pending' CHECK (status IN ( 'pending','scoring','approved','funding', 'funded','active','repaid','defaulted','rejected' )), funded_amount NUMERIC(15,2) NOT NULL DEFAULT 0, risk_grade CHAR(1), -- A,B,C,D после скоринга scoring_score INTEGER, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- Инвестиции CREATE TABLE investments ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), investor_id UUID NOT NULL REFERENCES users(id), loan_id UUID NOT NULL REFERENCES loan_requests(id), amount NUMERIC(15,2) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','active','repaid','defaulted')), created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); -- График погашения CREATE TABLE repayment_schedule ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), loan_id UUID NOT NULL REFERENCES loan_requests(id), payment_num INTEGER NOT NULL, due_date DATE NOT NULL, principal NUMERIC(15,2) NOT NULL, interest NUMERIC(15,2) NOT NULL, status VARCHAR(20) NOT NULL DEFAULT 'pending' CHECK (status IN ('pending','paid','overdue','written_off')), paid_at TIMESTAMPTZ, UNIQUE (loan_id, payment_num) ); -- Кошельки (номинальные счета) CREATE TABLE wallets ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id), type VARCHAR(20) NOT NULL CHECK (type IN ('investor','borrower')), balance NUMERIC(15,2) NOT NULL DEFAULT 0, reserved NUMERIC(15,2) NOT NULL DEFAULT 0, -- зарезервировано под инвестиции UNIQUE (user_id, type) ); -- Транзакции кошелька (полный аудит-лог) CREATE TABLE wallet_transactions ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), wallet_id UUID NOT NULL REFERENCES wallets(id), type VARCHAR(30) NOT NULL, amount NUMERIC(15,2) NOT NULL, balance_after NUMERIC(15,2) NOT NULL, reference_id UUID, -- loan_id, investment_id или payment_id description TEXT, created_at TIMESTAMPTZ NOT NULL DEFAULT NOW() ); Ануїтетний розрахунок графіка платежів
from decimal import Decimal, ROUND_HALF_UP from datetime import date from dateutil.relativedelta import relativedelta def calculate_annuity_schedule( loan_amount: Decimal, annual_rate: Decimal, term_months: int, start_date: date ) -> list[dict]: """Аннуитетный график погашения""" monthly_rate = annual_rate / 100 / 12 # Аннуитетный коэффициент k = monthly_rate * (1 + monthly_rate) ** term_months / \ ((1 + monthly_rate) ** term_months - 1) monthly_payment = (loan_amount * k).quantize(Decimal('0.01'), ROUND_HALF_UP) schedule = [] balance = loan_amount payment_date = start_date for num in range(1, term_months + 1): payment_date = payment_date + relativedelta(months=1) interest = (balance * monthly_rate).quantize(Decimal('0.01'), ROUND_HALF_UP) if num < term_months: principal = monthly_payment - interest else: # Последний платёж — гасим остаток principal = balance balance -= principal schedule.append({ 'payment_num': num, 'due_date': payment_date, 'principal': principal, 'interest': interest, 'total': principal + interest, 'balance_after': max(balance, Decimal('0')), }) return schedule Як розраховується ануїтетний коефіцієнт?
Ануїтетний коефіцієнт K = i * (1 + i)^n / ((1 + i)^n - 1), де i — місячна ставка, n — термін у місяцях. Чим вища ставка, тим більша частка відсотків у перших платежах.Навіщо потрібен резервний фонд?
Резервний фонд захищає інвесторів при дефолті позичальника. Кожна позика відраховує 2% від суми до фонду. При дефолті інвестори отримують компенсацію пропорційно своїй частці. У середньому за рахунок резервного фонду покривається до 60% дефолтних сум. Це значно краще, ніж без фонду (0% компенсації).
RESERVE_FUND_RATE = Decimal('0.02') # 2% от каждого займа def fund_reserve_on_disbursement(loan): reserve_amount = (loan.amount * RESERVE_FUND_RATE).quantize(Decimal('0.01')) ReserveFund.objects.create( loan=loan, amount=reserve_amount, status='active' ) def cover_default_from_reserve(loan): """При дефолте — компенсируем инвесторам из резервного фонда""" outstanding = loan.investments.filter( status='active' ).aggregate(total=Sum('amount'))['total'] or 0 reserve = ReserveFund.objects.filter(status='active').aggregate( total=Sum('amount') )['total'] or 0 coverage = min(outstanding, reserve) # Распределяем покрытие пропорционально инвестициям distribute_reserve_coverage(loan, coverage) Автоінвестування та процесинг платежів
Ключова функція для утримання інвесторів — автоматичне розподілення коштів за позиками згідно з налаштованими критеріями. Автоінвестування в 5 разів скорочує час на розподілення коштів порівняно з ручним режимом.
class AutoInvestRule(models.Model): investor = models.OneToOneField(User, on_delete=models.CASCADE) is_active = models.BooleanField(default=True) max_amount_per_loan = models.DecimalField(max_digits=15, decimal_places=2) min_loan_amount = models.DecimalField(max_digits=15, decimal_places=2, default=50000) max_loan_amount = models.DecimalField(max_digits=15, decimal_places=2, default=1000000) allowed_grades = models.JSONField(default=list) # ['A', 'B'] min_rate = models.DecimalField(max_digits=5, decimal_places=2, default=15) max_term_months = models.IntegerField(default=24) reinvest_returns = models.BooleanField(default=True) @shared_task def run_auto_invest(): """Запускается каждые 15 минут""" new_loans = LoanRequest.objects.filter( status='funding', funded_amount__lt=models.F('amount') ) for loan in new_loans: rules = AutoInvestRule.objects.filter( is_active=True, allowed_grades__contains=loan.risk_grade, min_rate__lte=loan.rate_annual, max_term_months__gte=loan.term_months, min_loan_amount__lte=loan.amount, max_loan_amount__gte=loan.amount, ) for rule in rules: wallet = Wallet.objects.select_for_update().get( user=rule.investor, type='investor' ) available = wallet.balance - wallet.reserved invest_amount = min(rule.max_amount_per_loan, available) if invest_amount >= Decimal('1000'): # минимальная сумма create_investment(rule.investor, loan, invest_amount, wallet) Нарахування відсотків та списання платежів виконується щоденним фоновим завданням. При нестачі коштів нараховуються штрафні відсотки.
@shared_task def process_due_payments(): """Запускается ежедневно""" today = date.today() due_payments = RepaymentSchedule.objects.filter( due_date=today, status='pending', loan__status='active' ).select_related('loan__borrower__wallet') for payment in due_payments: borrower_wallet = payment.loan.borrower.wallet if borrower_wallet.balance >= payment.principal + payment.interest: # Достаточно средств — списываем process_payment(payment) else: # Недостаточно — отмечаем как просроченный payment.status = 'overdue' payment.save() send_overdue_notification.delay(payment.id) # Начисляем штрафные проценты accrue_late_fee.delay(payment.id) def process_payment(payment): total = payment.principal + payment.interest with transaction.atomic(): # Списываем с заёмщика debit_wallet(payment.loan.borrower, total, 'loan_payment', payment.loan_id) # Распределяем по инвесторам пропорционально их доле distribute_to_investors(payment) payment.status = 'paid' payment.paid_at = timezone.now() payment.save() # Проверяем, полностью ли погашен займ check_loan_completion(payment.loan) Процес розробки платформи
Ми використовуємо гнучку методологію з чіткими етапами. Кожен етап закінчується демо та приймальними випробуваннями. Завдяки досвіду 12+ проєктів та сертифікованим фахівцям, ми гарантуємо проходження аудиту ЦБ.
| Етап | Тривалість | Результат |
|---|---|---|
| Аналітика та проектування | 2-3 тижні | Технічне завдання, ER-діаграма, макети |
| Розробка MVP | 4-5 місяців | Готова платформа з базовим скорингом |
| Інтеграція платежів та номінальних рахунків | 2-3 тижні | Підключення до банківських API |
| Тестування та налагодження | 1-2 місяці | QA, навантажувальне тестування, аудит безпеки |
| Деплой та супровід | 1 тиждень | Розгортання, документація, навчання |
Порівняння підходів до інвестування:
| Характеристика | Ручне інвестування | Автоінвестування |
|---|---|---|
| Час на розподілення 100 000 ₽ | 15–20 хвилин | 1–2 хвилини |
| Частота реінвестування | 1 раз на тиждень | Миттєво при появі позик |
| Середня дохідність | 14% річних | 18% річних за рахунок оперативності |
| Ризик пропустити вигідну позику | Високий | Мінімальний |
Що входить в результат роботи
Після завершення розробки ви отримуєте:
- Архітектурну документацію та ER-діаграми.
- Вихідний код у репозиторії (Git) з CI/CD.
- Доступ до адмін-панелі та моніторингу.
- Навчання команди (до 5 осіб) протягом 2 днів.
- Гарантійну підтримку на 3 місяці після введення в експлуатацію.
Терміни та вартість
MVP P2P-платформи — 4–5 місяців, повна версія з автоінвестуванням, резервним фондом та вторинним ринком — 8–12 місяців. Вартість розраховується індивідуально після аудиту вимог. Отримайте консультацію: ми оцінимо ваш проєкт і запропонуємо оптимальне рішення.







