def vypocet(self): self.dsti_splatka = ziadatel.dsti() self.dti_vyska_uveru = ziadatel.dti() self.bezna_splatka = (pmt( ((self.urokova_sadzba) / 100) / 12, 12 * self.doba_splatnosti_v_rokoch, self.mozna_vyska_uveru)) * (-1) self.zvysena_splatka = (pmt( ((self.urokova_sadzba + 2) / 100) / 12, 12 * self.doba_splatnosti_v_rokoch, self.mozna_vyska_uveru)) * (-1) rozdiel = self.zvysena_splatka - self.dsti_splatka if rozdiel < 0: rozdiel = rozdiel * (-1) while rozdiel > 10: self.mozna_vyska_uveru += 1000 self.bezna_splatka = (pmt( ((self.urokova_sadzba) / 100) / 12, 12 * self.doba_splatnosti_v_rokoch, self.mozna_vyska_uveru)) * (-1) self.zvysena_splatka = (pmt( ((self.urokova_sadzba + 2) / 100) / 12, 12 * self.doba_splatnosti_v_rokoch, self.mozna_vyska_uveru)) * (-1) rozdiel = self.zvysena_splatka - self.dsti_splatka if rozdiel < 0: rozdiel = rozdiel * (-1) if self.dti_vyska_uveru <= self.mozna_vyska_uveru: break return self.mozna_vyska_uveru, self.bezna_splatka
def _compute_fixed_amount(self): """ Computes the fixed amount in order to be used if round_on_end is checked. On fix-annuity interests are included and on fixed-principal and interests it isn't. :return: """ for record in self: if record.loan_type == "fixed-annuity": record.fixed_amount = -record.currency_id.round( numpy_financial.pmt( record.loan_rate() / 100, record.fixed_periods, record.fixed_loan_amount, -record.residual_amount, )) elif record.loan_type == "fixed-annuity-begin": record.fixed_amount = -record.currency_id.round( numpy_financial.pmt( record.loan_rate() / 100, record.fixed_periods, record.fixed_loan_amount, -record.residual_amount, when="begin", )) elif record.loan_type == "fixed-principal": record.fixed_amount = record.currency_id.round( (record.fixed_loan_amount - record.residual_amount) / record.fixed_periods) else: record.fixed_amount = 0.0
def PMT(rate: xltypes.XlNumber, nper: xltypes.XlNumber, pv: xltypes.XlNumber, fv: xltypes.XlNumber = 0, type: xltypes.XlNumber = 0) -> xltypes.XlNumber: """Calculates the payment for a loan based on constant payments and a constant interest rate. https://support.office.com/en-us/article/ pmt-function-0214da64-9a63-4996-bc20-214433fa6441 """ # WARNING fv & type not used yet - both are assumed to be their # defaults (0) # fv = args[3] # type = args[4] if xl.COMPATIBILITY == 'PYTHON': when = 'end' if type != 0: when = 'begin' return float( numpy_financial.pmt(float(rate), float(nper), float(pv), fv=float(fv), when=when)) # return -pv * rate / (1 - power(1 + rate, -nper)) return float( numpy_financial.pmt(float(rate), float(nper), float(pv), fv=float(fv), when='end'))
def test_pmt_decimal(self): res = npf.pmt(Decimal('0.08') / Decimal('12'), 5 * 12, 15000) tgt = Decimal('-304.1459143262052370338701494') assert_equal(res, tgt) # Test the edge case where rate == 0.0 res = npf.pmt(Decimal('0'), Decimal('60'), Decimal('15000')) tgt = -250 assert_equal(res, tgt) # Test the case where we use broadcast and # the arguments passed in are arrays. res = npf.pmt([[Decimal('0'), Decimal('0.8')], [Decimal('0.3'), Decimal('0.8')]], [Decimal('12'), Decimal('3')], [Decimal('2000'), Decimal('20000')]) tgt = numpy.array([[ Decimal('-166.6666666666666666666666667'), Decimal('-19311.25827814569536423841060') ], [ Decimal('-626.9081401700757748402586600'), Decimal('-19311.25827814569536423841060') ]]) # Cannot use the `assert_allclose` because it uses isfinite under # the covers which does not support the Decimal type # See issue: https://github.com/numpy/numpy/issues/9954 assert_equal(res[0][0], tgt[0][0]) assert_equal(res[0][1], tgt[0][1]) assert_equal(res[1][0], tgt[1][0]) assert_equal(res[1][1], tgt[1][1])
def test_pmt(self): res = npf.pmt(0.08 / 12, 5 * 12, 15000) tgt = -304.145914 assert_allclose(res, tgt) # Test the edge case where rate == 0.0 res = npf.pmt(0.0, 5 * 12, 15000) tgt = -250.0 assert_allclose(res, tgt) # Test the case where we use broadcast and # the arguments passed in are arrays. res = npf.pmt([[0.0, 0.8], [0.3, 0.8]], [12, 3], [2000, 20000]) tgt = numpy.array([[-166.66667, -19311.258], [-626.90814, -19311.258]]) assert_allclose(res, tgt)
def test_fixed_annuity_begin_loan(self): amount = 10000 periods = 24 loan = self.create_loan("fixed-annuity-begin", amount, 1, periods) self.assertTrue(loan.line_ids) self.assertEqual(len(loan.line_ids), periods) line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertAlmostEqual( -numpy_financial.pmt(1 / 100 / 12, 24, 10000, when="begin"), line.payment_amount, 2, ) self.assertEqual(line.long_term_principal_amount, 0) loan.long_term_loan_account_id = self.lt_loan_account loan.compute_lines() line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertGreater(line.long_term_principal_amount, 0) self.post(loan) self.assertTrue(loan.start_date) line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertTrue(line) self.assertFalse(line.move_ids) wzd = self.env["account.loan.generate.wizard"].create({}) action = wzd.run() self.assertTrue(action) self.assertFalse(wzd.run()) self.assertTrue(line.move_ids) self.assertIn(line.move_ids.id, action["domain"][0][2]) self.assertTrue(line.move_ids) self.assertEqual(line.move_ids.state, "posted") loan.rate = 2 loan.compute_lines() line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertAlmostEqual( -numpy_financial.pmt(1 / 100 / 12, periods, amount, when="begin"), line.payment_amount, 2, ) line = loan.line_ids.filtered(lambda r: r.sequence == 2) self.assertAlmostEqual( -numpy_financial.pmt(2 / 100 / 12, periods - 1, line.pending_principal_amount, when="begin"), line.payment_amount, 2, ) line = loan.line_ids.filtered(lambda r: r.sequence == 3) with self.assertRaises(UserError): line.view_process_values()
def calculate_typeA(self, data): data['monthly_amortization'] = npf.pmt(self.eair, data['loan_term'], -data['principal_amount']) data['sum_payments'] = data['monthly_amortization'] * data['loan_term'] data['total_interest'] = data['sum_payments'] - \ data['principal_amount'] return data
def model_payments(data: dict): hp = data["home"] rate = data["rate"] tax = data["tax"] hoa = data["hoa"] insr = data["insr"] term = float(data["term"] * 12) periodic_rate = (1 + rate)**(1 / 12) - 1 dp = np.arange(0.0, 110000, 10000) payments = {"DOWN_PMT": dp} for h in hp: mp = np.zeros(dp.shape) for i in range(len(dp)): loan = h - dp[i] mp[i] = -1 * npf.pmt(periodic_rate, term, loan) mp = mp + tax + hoa + insr payments[f"{str(int(h))}"] = mp data["payments"] = pd.DataFrame(payments) return data
def amort_cicle(loan, rate, term): payment = np.round(-nf.pmt(rate / 12, term, loan), 2) balance = loan df = pd.DataFrame({ 'month': [0], 'payment': [np.NaN], 'interest': [np.NaN], 'principal': [np.NaN], 'balance': [balance] }) for i in range(1, term + 1): interest = round(rate / 12 * balance, 2) principal = payment - interest balance -= principal df = df.append( pd.DataFrame({ 'month': [i], 'payment': [payment], 'interest': [interest], 'principal': [principal], 'balance': [balance] })) return (df)
def test_pay_amount_validation(self): amount = 10000 periods = 24 loan = self.create_loan("fixed-annuity", amount, 1, periods) self.assertTrue(loan.line_ids) self.assertEqual(len(loan.line_ids), periods) line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertAlmostEqual(-numpy_financial.pmt(1 / 100 / 12, 24, 10000), line.payment_amount, 2) self.assertEqual(line.long_term_principal_amount, 0) loan.long_term_loan_account_id = self.lt_loan_account loan.compute_lines() line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertGreater(line.long_term_principal_amount, 0) self.post(loan) self.assertTrue(loan.start_date) line = loan.line_ids.filtered(lambda r: r.sequence == 1) self.assertTrue(line) self.assertFalse(line.move_ids) wzd = self.env["account.loan.generate.wizard"].create({}) action = wzd.run() self.assertTrue(action) self.assertFalse(wzd.run()) self.assertTrue(line.move_ids) self.assertIn(line.move_ids.id, action["domain"][0][2]) self.assertTrue(line.move_ids) self.assertEqual(line.move_ids.state, "posted") with self.assertRaises(UserError): self.env["account.loan.pay.amount"].create({ "loan_id": loan.id, "amount": (amount - amount / periods) / 2, "fees": 100, "date": line.date + relativedelta(months=-1), }).run() with self.assertRaises(UserError): self.env["account.loan.pay.amount"].create({ "loan_id": loan.id, "amount": amount, "fees": 100, "date": line.date }).run() with self.assertRaises(UserError): self.env["account.loan.pay.amount"].create({ "loan_id": loan.id, "amount": 0, "fees": 100, "date": line.date }).run() with self.assertRaises(UserError): self.env["account.loan.pay.amount"].create({ "loan_id": loan.id, "amount": -100, "fees": 100, "date": line.date }).run()
def calc_parameter(ask_reply, input_string): """ calc_parameter is a calculator to calculate the final goal based on ino given by users. Parameters --------- Param1 : Dictionary The dictionary stores the float provided by user as value, stores corresponding terms as the key. Param2 : String The string is the specified goal for caculation. The string implies what the dictionary would be since each value is dependent to the remaining values. Returns ------ Return1 : Float The final result of requested value after caculation. """ user_fin_dict = ask_reply try: if (ask_reply['input_string']) == 'present value': output = abs( npf.pv(user_fin_dict["required rate per year"], user_fin_dict["required time period"], 0 - user_fin_dict["payment"], user_fin_dict["future value"])) elif (ask_reply['input_string']) == "future value": output = abs( npf.fv(user_fin_dict["required rate per year"], user_fin_dict["required time period"], 0 - user_fin_dict["payment"], 0 - user_fin_dict["present value"])) elif (ask_reply['input_string']) == "payment": output = abs( npf.pmt(user_fin_dict["required rate per year"], user_fin_dict["required time period"], 0 - user_fin_dict["present value"], user_fin_dict["future value"])) elif (ask_reply['input_string']) == "required rate per year": output = abs( npf.rate(user_fin_dict["required time period"], 0 - user_fin_dict["payment"], 0 - user_fin_dict["present value"], user_fin_dict["future value"])) elif (ask_reply['input_string']) == "required time period": output = abs( npf.nper(user_fin_dict["required rate per year"], 0 - user_fin_dict["payment"], 0 - user_fin_dict["present value"], user_fin_dict["future value"])) else: output = random.choice(unknown_input_reply) return output except KeyError: print("I'm dead because of you !") print("You should never have encountered this. What did you do?") return None
def mortgage_schedule(principal, interest_rate, months): monthly_interest_rate = pow(1 + interest_rate, (1 / 12)) - 1 monthlyPayment = -round(pmt(monthly_interest_rate, months, principal), 1) for i in range(0, months): interest = round(monthly_interest_rate * principal, 1) repayment = monthlyPayment - interest print(i, "\t", round(principal, 1), "\t", monthlyPayment, "\t", interest, "\t", round(principal - repayment, 1), "\t") principal = round(principal - repayment, 1)
def total_payment(data: dict): data['term'] = int(30 * 12) data['rate_periodic'] = (1 + data['rate'])**(1 / 12) - 1 data['loan'] = data['home'] - data['down'] data['periodic_payment'] = -1 * npf.pmt(data['rate_periodic'], data['term'], data['loan']) data['total_payment'] = data['periodic_payment'] + data['hoa'] + data[ 'tax'] + data['insur'] return data
def calcLoan(self, loan=0.6, interest=0.04, years=10): quantity = loan * self.CAPEX assert quantity > 0 assert interest >= 0 and interest <= 1 assert years > 1 self.loan_payment = pmt(interest, years, quantity) self.loan_interest = ipmt(interest, np.arange(years) + 1, years, quantity) self.loan_principal = ppmt(interest, np.arange(years) + 1, years, quantity)
def mezzanine_debt_assumptions(self): loan_amount = self.data.get("price") * 0 # J19 refinance_term = 300 # J20 refinance_rate = 0.043 # J21 monthly_payment = np.pmt( # J23 (refinance_rate / 12), refinance_term, -loan_amount, 0, ) return monthly_payment
def get_reg_pmt(self) -> float: self.reg_pmt = round( -pmt( self.rate / (100 * self.freq), self.freq * self.num_of_years, self.loan, when=self.pmt_when, ), 4, ) return self.reg_pmt
def __init__(self, principle_amount, interest_in_year, period_in_years,starting_date=datetime.now()): self.starting_date = starting_date self.principle_amount = principle_amount self.interest_in_year = interest_in_year self.period_in_years = period_in_years self.column_names = ["MONTH", "STARTING_AMOUNT", "EMI_AMOUNT", "INTEREST_PAID", "PRINCIPLE_PAID", "LEFTOVER_PRINCIPLE"] self.df = pd.DataFrame(columns = self.column_names) self.orginal_df = pd.DataFrame(columns = self.column_names) self.emi_amount = npf.pmt((interest_in_year/100)/12, period_in_years*12, -principle_amount,0) self.Principle_paid=0 self.Interest_paid=0 self.advancePayments=[]
def get_reg_wdr(self) -> float: self.reg_wdr = round( -pmt( self.rate / (100 * self.freq), self.freq * self.num_of_years, self.ret_fund, when=self.wdr_when, ), 2, ) return self.reg_wdr
def loan(self, prestamo, interest, years): """Compute annual payment of a loan. Inputs: quantity [monetary units] == investment which will be funded interest [as fraction of unity] == annual interest years == number of yeras to return the loan.""" quantity = prestamo * self.capex() assert quantity > 0 assert interest >= 0 and interest <= 1 assert years > 1 loan_payment = pmt(interest, years, quantity) loan_interest = ipmt(interest, np.arange(years) + 1, years, quantity) loan_principal = ppmt(interest, np.arange(years) + 1, years, quantity) return loan_payment, loan_interest, loan_principal
def compute_amount(self): """ Computes the payment amount :return: Amount to be payed on the annuity """ if self.sequence == self.loan_id.periods: return (self.pending_principal_amount + self.interests_amount - self.loan_id.residual_amount) if self.loan_type == "fixed-principal" and self.loan_id.round_on_end: return self.loan_id.fixed_amount + self.interests_amount if self.loan_type == "fixed-principal": return (self.pending_principal_amount - self.loan_id.residual_amount) / (self.loan_id.periods - self.sequence + 1) + self.interests_amount if self.loan_type == "interest": return self.interests_amount if self.loan_type == "fixed-annuity" and self.loan_id.round_on_end: return self.loan_id.fixed_amount if self.loan_type == "fixed-annuity": return self.currency_id.round(-numpy_financial.pmt( self.loan_id.loan_rate() / 100, self.loan_id.periods - self.sequence + 1, self.pending_principal_amount, -self.loan_id.residual_amount, )) if self.loan_type == "fixed-annuity-begin" and self.loan_id.round_on_end: return self.loan_id.fixed_amount if self.loan_type == "fixed-annuity-begin": return self.currency_id.round(-numpy_financial.pmt( self.loan_id.loan_rate() / 100, self.loan_id.periods - self.sequence + 1, self.pending_principal_amount, -self.loan_id.residual_amount, when="begin", ))
def calculate_loan(self): """Compute annual payment of a loan. Inputs: quantity [monetary units] == investment which will be funded interest [as fraction of unity] == annual interest years == number of yeras to return the loan.""" assert type(self) is Loan self.res_payment = pmt(self.interest, self.years, self.quantity) self.res_interest = ipmt(self.interest, np.arange(self.years) + 1, self.years, self.quantity) self.res_principal = ppmt(self.interest, np.arange(self.years) + 1, self.years, self.quantity)
def calculate_amortisation(interest_rate_curve, cpr, default_rate, default_curve, lgd, recovery_lag): """ Args: interest_rate_curve (str): name of the interest rate curve assumption (e.g., 3m_forward, up_stress) cpr (float): CPR -- value between 0 and 1 default_rate (float) cumulative default rate -- value between 0 and 1 default_curve (str): name of the default timing curve (e.g., Front_10yr') lgd (float): loss given default recovery_lag (int): number of months between default and recovery Returns: cf_df (pd.DataFrame): cash flow table - each row represents a period. The columns are: beg_bal, default, interest, scheduled_prin, prepay, end_bal """ period = 1 result = [] end_bal = orig_bal smm = 1 - (1 - cpr)**(1 / 12) while round(end_bal, 0) > 0 and period <= term: beg_bal = end_bal flt_coupon = (spread + sonia.loc[period, interest_rate_curve]) / 12 default = orig_bal * default_rate * default_curves.loc[period, default_curve] pmt_i = npf.pmt(rate=flt_coupon, nper=term - period + 1, pv=-(beg_bal - default)) interest = (beg_bal - default) * flt_coupon scheduled_prin = pmt_i - interest prepayment = max(0, (min(beg_bal - default - scheduled_prin, smm * (beg_bal - scheduled_prin)))) end_bal = beg_bal - default - scheduled_prin - prepayment result.append( Period_CF(period, beg_bal, default, interest, scheduled_prin, prepayment, end_bal)) period += 1 cf_df = pd.DataFrame(result) cf_df.set_index('period') cf_df['loss'] = cf_df['default'] * lgd cf_df['recovery'] = cf_df['default'] * (1 - lgd) cf_df['loss'] = cf_df['loss'].shift(recovery_lag).fillna(0) cf_df['recovery'] = cf_df['recovery'].shift(recovery_lag).fillna(0) return cf_df
def senior_debt_assumptions(self): # J13 interest_rate = 0.0375 # J10 loan_amount = 0 monthly_payment = 0 if self.debt_financing: loan_amount = (1 - self.down_payment_percent) * self.data.get( "price") # J9 monthly_payment = round((np.pmt( (interest_rate / 12), 360, -loan_amount, 0)), 0) return { "loan_amount": loan_amount, "monthly_payment": monthly_payment, "interest_rate": interest_rate, }
def bi_weekly_payment(self): """Payments required for a bi-weekly payment schedule. Takes APR as an input and compounds semi annually for AER. Canadian mortgages are dumb like that. Returns ------- pmt: float The amount of the monthly payment """ rate = (1 + (self.rate / 2))**2 - 1 periodic_interest_rate = (1 + rate)**(1 / 26) - 1 periods = self.years * 26 pmt = -round(npf.pmt(periodic_interest_rate, periods, self.principal), 2) return pmt
def get_reg_dep(self) -> float: _fv = (fv( self.rate / (100 * self.freq), self.freq * self.num_of_years, 0, self.ini_dep, self.dep_when, ) + self.fin_bal) self.reg_dep = -pmt( self.rate / (100 * self.freq), self.freq * self.num_of_years, 0, _fv, self.dep_when, ) return self.reg_dep
def poolCashFlows(size, sda, WAM, WAC, netC, last, lag, rr): rates = CIR(last, 0.089603, 0.039538, 0.00809439, WAM) #calibrated values balance = size interestCF = np.array([]) principalCF = np.array([]) defaultED = np.array([]) i = 0 while balance > 0: interest = balance * (netC/12) principal = -npf.pmt(netC/12, WAM-i, balance) - interest prepayment = (balance - principal) * RichardRoll(rates[i], 0.5, 0, WAC, 0.6, balance, size, i+1) default = (balance - (principal + prepayment)) * SDA(sda, i+1) if i > lag: recovery = defaultED[i-lag-1] * rr else: recovery = 0 if balance - principal - prepayment <0: break elif i < lag: balance = balance - principal - prepayment - default else: balance = balance - principal - prepayment - default - recovery interestCF = np.append(interestCF, interest) principalCF = np.append(principalCF, principal + prepayment + recovery) defaultED = np.append(defaultED, default) i += 1 #cash flows in the final period interest = balance * (netC/12) principal = balance recovery = defaultED[WAM-lag-2] * rr interestCF = np.append(interestCF, interest) principalCF = np.append(principalCF, principal + recovery) defaultED = np.append(defaultED, 0) totalCF = interestCF + principalCF return {'interest':interestCF, 'principal':principalCF, 'defaults':defaultED, 'total': totalCF}
def lcoe(annual_output, capital_cost, annual_operating_cost, discount_rate, lifetime): """Compute levelised cost of electricity Arguments --------- annual_output : float capital_cost : float annual_operating_cost : float discount_rate : float lifetime : int Returns ------- float """ annual_cost_capital = npf.pmt(discount_rate, lifetime, -capital_cost) total_annual_cost = annual_cost_capital + annual_operating_cost return total_annual_cost / annual_output
def amoritization(loan_amount, term, rate=.05): balance = [loan_amount] monthly_payment = [0] interest = [0] principal = [0] index = list(range(term + 1)) for i in range(len(index) - 1): monthly_payment.append(-npf.pmt(rate / 12, term, loan_amount)) #print(rate/12) interest.append((rate / 12) * (balance[i])) principal.append(monthly_payment[i + 1] - interest[i + 1]) balance.append(balance[i] - principal[i + 1]) df = pd.DataFrame( { 'Payment Amount': monthly_payment, 'Interest': interest, 'Principal': principal, 'Balance': balance }, index=index) return df
def amort(loan, rate, term): payment = np.round(-nf.pmt(rate / 12, term, loan), 2) balance = loan index = list(range(term + 1)) columns = ['month', 'payment', 'interest', 'principal', 'balance'] df = pd.DataFrame(index=index, columns=columns) df.iloc[0]['month'] = 0 df.iloc[0]['balance'] = balance for i in range(1, term + 1): interest = round(rate / 12 * balance, 2) principal = payment - interest balance -= principal df.iloc[i]['month'] = i df.iloc[i]['payment'] = payment df.iloc[i]['interest'] = interest df.iloc[i]['principal'] = principal df.iloc[i]['balance'] = balance return (df)
def test_pmt_decimal_broadcast(self): # Test the case where we use broadcast and # the arguments passed in are arrays. res = npf.pmt([[Decimal('0'), Decimal('0.8')], [Decimal('0.3'), Decimal('0.8')]], [Decimal('12'), Decimal('3')], [Decimal('2000'), Decimal('20000')]) tgt = numpy.array([[ Decimal('-166.6666666666666666666666667'), Decimal('-19311.25827814569536423841060') ], [ Decimal('-626.9081401700757748402586600'), Decimal('-19311.25827814569536423841060') ]]) # Cannot use the `assert_allclose` because it uses isfinite under # the covers which does not support the Decimal type # See issue: https://github.com/numpy/numpy/issues/9954 assert_equal(res[0][0], tgt[0][0]) assert_equal(res[0][1], tgt[0][1]) assert_equal(res[1][0], tgt[1][0]) assert_equal(res[1][1], tgt[1][1])