Это скорее статья не о том, как лучше всего написать кредитный калькулятор, а о том, как это проще всего реализовать на Python.
Теория
Для начала определимся с терминами.
Существует две схемы начисления процентов по кредитам (будем рассматривать долгосрочные кредиты, сроком от одного года):
-
дифференцированная;
аннуитетная.
При дифференцированных платежах вся сумма основного долга (сумма кредита) делится на равные части (по количеству периодов начисления процентов) и ежемесячно выплачивается эта часть плюс проценты, начисленные на остаток основного долга.
*рис.1 Формула рассчета месячного дифференцированного платежа
debt reaminder — остаток долга по кредиту.
total months count — количество периодов оплаты (обычно кол-во месяцев).
interests — процентная ставка.
12*100 — деление производится для перевода ставки в проценты и вычисления процентов за один расчетный период (месяц).
При аннуитетных платежах сохраняется одинаковый ежемесячный платеж по кредиту за счет перераспределения сумм основного долга и процентов таким образом, что они варьируются от периода к периоду, но формируют единый неизменный аннуитетный платеж.
*рис.2 Формула рассчета аннуитетного коэффициента
— процентная ставка за один период (всего периодов n)
— количество периодов на протяжении всего действия аннуитета.
(следует учитывать, что данная формула является чисто математической, то есть на практике возможны некоторые девиации, вызванные округлением, а также неодинаковой продолжительностью месяца и года; особенно это касается последнего по сроку платежа).
Предполагается, что выплаты производятся постнумерандо, то есть в конце каждого периода. И тогда величина периодической выплаты A = K·S, где S — величина кредита.
Практика
Реализация будет самая что ни на есть простая: двумя функциями, заключенными в класс.
Приступим. Определяем класс и инициализируем исходные данные.
class BankInterest(object):
def __init__(self, summ, period, perc):
self.summ = summ
self.period = period
self.perc = perc
Исходными данными, которые будет задавать пользователь в таком порядке: сумма кредита, период (в годах), процентная ставка.
Функция рассчета дифференцированных платежей.
def diff_int(self):
arr = []
mp_cnt = self.period * 12
rest = self.summ
mp_real = self.summ / (self.period * 12.0)
while mp_cnt != 0:
mp = mp_real + (rest * self.perc / 1200)
arr.append(round(mp, 2))
rest = rest - mp_real
mp_cnt = mp_cnt - 1
return arr, round(sum(arr), 2)
arr[] — это мы задаем пустой массив для наполнения его месячными платежами в будущем.
** mp_cnt**— это total months count.
rest — это debt remainder.
mp_real — первая часть формулы до знака + (см. рис.1)
Далее идет простой цикл, в котором мы рассчитываем ежемесячный платеж и заносим его в массив, до тех пор, пока не закрнчится срок кредита.
round(x, 2) округляет значение до двух знаков после запятой.
Функция возвращает кортеж из массива с месячными платежами и общей суммой, которую должник заплатит банку.
Пример.
Вася Пупкин берет в кредит миллион рублей под 15% на 10 лет.
>>> ipoteka.BankInterest(1000000, 10, 15).diff_int()
([20833.33, 20729.17, 20625.0, 20520.83, 20416.67, 20312.5, 20208 .33, 20104.17, 20000.0, 19895.83, 19791.67, 19687.5, 19583.33, 19479.17, 19375.0, 19270.83, 19166.67, 19062.5, 18958.33, 18854.17, 18750.0, 18645.83, 18541.67, 18437.5, 18333.33, 18229.17, 18125.0, 18020.83, 17916.67, 17812.5, 17708.33, 17604.17, 17500.0, 17395.83, 17291.67, 17187.5, 17083.33, 16979.17, 16875.0, 16770.83, 16666.67, 16562.5, 16458.33, 16354.17, 16250.0, 16145.83, 16041.67, 15937.5, 15833.33, 15729.17, 15625.0, 15520.83, 15416.67, 15312.5, 15208.33, 15104.17, 15000.0, 14895.83, 14791.67, 14687.5, 14583.33, 14479.17, 14375.0, 14270.83, 14166.67, 14062.5, 13958.33, 13854.17, 13750.0, 13645.83, 13541.67, 13437.5, 13333.33, 13229.17, 13125.0, 13020.83, 12916.67, 12812.5, 12708.33, 12604.17, 12500.0, 12395.83, 12291.67, 12187.5, 12083.33, 11979.17, 11875.0, 11770.83, 11666.67, 11562.5, 11458.33, 11354.17, 11250.0, 11145.83, 11041.67, 10937.5, 10833.33, 10729.17, 10625.0, 10520.83, 10416.67, 10312.5, 10208.33, 10104.17, 10000.0, 9895.83, 9791.67, 9687.5, 9583.33, 9479.17, 9375.0, 9270.83, 9166.67, 9062.5, 8958.33, 8854.17, 8750.0, 8645.83, 8541.67, 8437.5], 1756250.0)
В первый месяц Вася заплатит самую большую сумму — 20,833.33 рубля, а потом по убывающей. Последний месяц ему нужно будет заплатить всего лишь каких-то 8,437.5 рубля.
Итого он принесет в банк 1,756,250 рублей.
Рассчет аннуитетных платежей выглядит вот так.
def ann_int(self):
mp_cnt = self.period * 12
r = self.perc / 1200.0
ak = (r * (1 + r) ** mp_cnt) / (((1 + r) ** mp_cnt) - 1)
mp = self.summ * ak
total = mp * mp_cnt
return round(mp, 2), round(total, 2)
mp_cnt — это total months count.
r — это i (см. рис.2).
** ak** — это K (см. рис.2).
mp — размер месячного платежа (он неизменен).
total — общая сумма выплаты.
Функция возвращает кортеж из значения месячного платежа и общей суммы выплаты.
Пример.
Вася Пупкин берет в кредит миллион рублей под 15% на 10 лет.
>>> ipoteka.BankInterest(1000000, 10, 15).ann_int()
(16133.5, 1936019.48)
Он будет платить 16,133.5 рубля в месяц и в итоге заплатит банку 1,936,019.48 рублей, вместо миллиона одолженных.
Вот как это выглядит целиком.
class BankInterest(object):
'''Class contains two functions to calculate different interests for loans.
Input parameters are loan amount, loan period in years, and interests on the loan.
Example: 1000000, 10, 15'''
def __init__(self, summ, period, perc):
self.summ = summ
self.period = period
self.perc = perc
# Differentiated formula
def diff_int(self):
arr = []
mp_cnt = self.period * 12
rest = self.summ
mp_real = self.summ / (self.period * 12.0)
while mp_cnt != 0:
mp = mp_real + (rest * self.perc / 1200)
arr.append(round(mp, 2))
rest = rest - mp_real
mp_cnt = mp_cnt - 1
return arr, round(sum(arr), 2)
# Annuity formula
def ann_int(self):
mp_cnt = self.period * 12
r = self.perc / 1200.0
ak = (r * (1 + r) ** mp_cnt) / (((1 + r) ** mp_cnt) - 1)
mp = self.summ * ak
total = mp * mp_cnt
return round(mp, 2), round(total, 2)