Изучите основы ипотечного кредита и автоматизируйте анализ недвижимости

Я считаю, что этот проект полезен для всех, так как людям нужно так или иначе узнавать об ипотеке по мере взросления. Если вы не принадлежите к меньшинству, у которого достаточно денег, чтобы сделать разовый платеж для покупки недвижимости, вам, скорее всего, понадобится ипотечный кредит. Это, в частности, верно для Гонконга, где я вырос. Гонконг уже несколько лет подряд считается самым дорогим рынком жилья в мире из-за его густонаселенности и нехватки земли (забавный факт — Гонконг в 0,70 раза больше Лондона).

Итак, что такое ипотека?

Ипотека — это ссуда, которую берут физические лица для сбора средств на покупку недвижимости при наложении залогового права на заложенное имущество. То есть имущество выступает в качестве залога, и кредитор имеет право забрать ваше имущество, если вы не вносите платежи по ипотеке. Кредитор кредита, как правило, банк, кредитный союз или строительное общество. Например, вы, возможно, слышали о Nationwide, крупнейшем строительном обществе в Великобритании. При покупке дома вам потребуется первоначальный взнос, а оставшуюся сумму займите. Средний первоначальный взнос для первого покупателя в Великобритании составляет 15% от стоимости недвижимости, поэтому сумма ипотечного кредита составит оставшиеся 85%.

Ипотечные кредиты имеют процентную ставку и подлежат амортизации в течение установленного периода времени. Амортизация относится к процессу погашения кредита путем периодических платежей по основному долгу и процентам. При каждом платеже часть платежа используется в качестве процентов по кредиту, а оставшаяся часть используется для уменьшения основной суммы долга.

Математический вывод

Предположим, вы берете ипотечный кредит с основной суммой P, фиксированной процентной ставкой за период r, и вам нужно сделать N платежей, пока кредит не будет погашен. . Мы можем рассматривать это как график платежей или временную шкалу, охватывающую N периодов. Пустьt — произвольная переменная, представляющая каждый период, так что при погашении t=N;c — платеж за каждый период.

При t = 0: сумма долга равна основному долгу P.

При t = 1: проценты применяются к основной сумме, и вы делаете регулярный платеж c, таким образом, причитающаяся сумма (основная сумма/остаток) составляет (1 +r)P-c.

В t = 2: проценты снова применяются к основной сумме, и вы производите платеж c. Сумма задолженности сейчас

Эта рекурсивная формула повторяется для каждого периода до t=N, где сумма задолженности равна

Теперь, поскольку ипотечный кредит амортизируется, сумма задолженности в конце кредита должна равняться нулю. Чтобы получить окончательную формулу для платежа за период, обратите внимание, что член перед c в приведенном выше уравнении представляет собой просто геометрический ряд с постоянным соотношением (1+r). То есть,

Используя это наблюдение и переформулировав окончательное уравнение, мы получаем

Регулярные платежи, которые необходимо производить, зависят от процентной ставки r, суммы кредитаP и срока кредитаN. Обычно кредитор сообщает вам заявленную годовую процентную ставку R. Если вы будете вносить ежемесячные платежи, ваша процентная ставка за период составит r=R/12.

Что здесь не так очевидно, так это то, что в первые годы ипотеки невыплаченная основная сумма долга все еще велика, и, следовательно, процентные платежи велики. Это означает, что платежи за период, идущие на уменьшение основной суммы долга, очень малы, а капитал в собственности накапливается очень медленно.

Реализация ипотечного калькулятора на питоне

Как всегда, первым делом импортируем необходимые библиотеки

# import packages
import pandas as pd
import datetime 

Следующая функция реализует ипотечный калькулятор:

def mortgage_payments(loan_amt, maturity, payments_per_year, interest, option=1, start_date=None):
    '''
    Function that implements a mortgage calculator
    :param loan_amt: Size of mortgage loan
    :param maturity: Number of years until the final mortgage payment date, typically 30
    :param payments_per_year: Number of payments per year
    :param interest: Stated annual interest rate
    :param option: 1 to get payment per period, 2 to get whole payment schedule
    :param start_date: the day you got the mortgage (first payment occurs next month)
    :return: payment per period or whole payment schedule depending on 'option'
    '''
    interest_per_period = interest / payments_per_year
    number_of_payments = payments_per_year * maturity

    # Formula for Payment per Period (e.g. monthly payments)
    payments_per_period = (interest_per_period*loan_amt) / (1-(1+interest_per_period)**(-1*number_of_payments))

    if option == 1:
        return payments_per_period

    else:
        # start date is a string, convert to datetime
        start_date = datetime.datetime.strptime(start_date, '%Y/%m/%d').date()

        if payments_per_year == 12: # monthly payments
            date_range = pd.date_range(start=start_date, periods=maturity * payments_per_year, freq='MS')

        elif payments_per_year == 24: # semi-monthly payments
            date_range = pd.date_range(start=start_date, periods=maturity*payments_per_year, freq='SMS')

        else:
            raise ValueError('Valid payments per year are 12 (monthly) or 24 (semi-monthly/bi-weekly)')

        date_range.name = 'Payment Date'
        df = pd.DataFrame(index=date_range, columns = ['Payment', 'Principal Paid', 'Interest Paid', 'Ending Balance'],
                          dtype = 'float')
        df.reset_index(inplace=True)
        df.index += 1
        df.index.name = 'Period'

        df['Payment'] = round(payments_per_period, 2)
        df.loc[1, 'Interest Paid'] = round(interest_per_period * loan_amt, 2)
        df.loc[1, 'Principal Paid'] = round(payments_per_period - df.loc[1, 'Interest Paid'], 2)
        df.loc[1, 'Ending Balance'] = round(loan_amt - df.loc[1, 'Principal Paid'], 2)

        for k in range(2, len(df) + 1):
            df.loc[k, 'Interest Paid'] = round(interest_per_period * df.loc[k-1, 'Ending Balance'], 2)
            df.loc[k, 'Principal Paid'] = round(df.loc[k, 'Payment'] - df.loc[k, 'Interest Paid'], 2)
            df.loc[k, 'Ending Balance'] = round(df.loc[k-1, 'Ending Balance'] - df.loc[k, 'Principal Paid'], 2)

        return df

Наконец, я включил главную функцию, которая взаимодействуетс пользователем через встроенную функцию Python input() .

def main():
    print('-----Mortgage Calculator-----')
    ### User inputs
    # loan size
    LoanAmount = float(input('Enter the mortgage/loan amount: '))
    # maturity of loan
    Maturity = float(input('Enter the maturity of the loan (years): '))
    # payment frequency, most commonly 12 or 24 (monthly or semi-monthly)
    PaymentsPerYear = float(input('Enter the number of payments per year: '))
    # interest rate
    InterestRate = float(input('Enter the annual interest rate on your loan (decimals): '))
    print('-----------------------------')
    Options = int(input('''Please input the operation you wish to perform.
(1) Calculate your payment per period
(2) Get a detailed summary of your payment schedule
Enter (1/2): '''))

    if Options == 1:
        PaymentPerPeriod = mortgage_payments(LoanAmount, Maturity, PaymentsPerYear, InterestRate, Options)
        print(f"${round(PaymentPerPeriod, 2)}")
    elif Options == 2:
        start_date = input('Enter the start date of mortgage (YYYY/MM/DD): ')
        print('NB: The payment schedule assumes that the payment takes place on the 1st of each month for monthly payments, and on the 1st and 15th for semi-monthly payments.')
        PaymentSchedule = mortgage_payments(LoanAmount, Maturity, PaymentsPerYear, InterestRate, Options, start_date)
        print(PaymentSchedule)
        SaveAsCSV = input('Would you like to save the payment schedule as an Excel file? (Y/N)')
        if SaveAsCSV.upper() == 'Y':
            PaymentSchedule.to_csv('mortgage_payments.csv')
        elif SaveAsCSV.upper() == 'N':
            return None
        else:
            raise ValueError('Please enter a valid option (Y/N).')

    else:
        raise ValueError('Please enter a valid number (1/2/3).')

Основная функция просит пользователя указать основные переменные в ипотеке: сумму кредита, срок кредита (срок погашения), частоту платежей и годовую процентную ставку. Затем он предоставляет возможность просто вернуть сумму платежа или вернуть весь график платежей со дня, когда пользователь взял кредит, до даты, когда пользователь завершает выплату своей ипотеки. Если был выбран последний вариант, программа также спрашивает пользователя, хотят ли они сохранить его в виде файла Excel.

Вот пример использования программы на терминале:

На этом мы подошли к концу этой статьи, и теперь вы сможете заранее планировать свои инвестиции в недвижимость. Полный код Python для этого проекта можно увидеть в моем профиле GitHub.

Этот проект создания ипотечного калькулятора включает в себя наиболее распространенные частоты платежей, а именно ежемесячные и полумесячные платежи. Дальнейшая работа расширит этот инструмент, чтобы включить дополнительные функции, такие как оценка суммы ипотечного кредита на основе вашего годового дохода, а также учет затрат на налоги и страхование. Также было бы интересно посмотреть, как переплата по ипотеке в определенную дату платежа повлияет на полученные будущие платежи. Другой подход заключается в создании визуально приятного веб-приложения с текущим кодом в качестве основной функциональности.