class Financier::Amortization
Attributes
closing_date[R]
attr_reader :principal, :rate, :closing_date, :first_payment_due
first_payment_due[R]
attr_reader :principal, :rate, :closing_date, :first_payment_due
ledger[R]
attr_reader :principal, :rate, :closing_date, :first_payment_due
payment[R]
attr_reader :principal, :rate, :closing_date, :first_payment_due
Public Class Methods
interest(principal, rate)
click to toggle source
# File lib/financier/amortization.rb, line 12 def interest(principal, rate) (D(principal.to_s) * D(rate.to_s)) end
new(principal, rate, closing_date: nil, first_payment_due: nil)
click to toggle source
# File lib/financier/amortization.rb, line 20 def initialize(principal, rate, closing_date: nil, first_payment_due: nil) @principal = Flt::DecNum.new(principal.to_s) @rate = rate self.closing_date = closing_date || Time.now self.first_payment_due = first_payment_due || (@closing_date + 30.days) #@periods = rate.duration #@period = 0 compute end
payment(principal, rate, periods)
click to toggle source
# File lib/financier/amortization.rb, line 4 def payment(principal, rate, periods) principal, rate, periods = [D(principal.to_s), D(rate.to_s), D(periods.to_s)] return -(principal / periods).round(2) if rate.zero? -(principal * (rate + (rate / ((1 + rate) ** periods - 1)))).round(2) end
Public Instance Methods
amortize()
click to toggle source
# File lib/financier/amortization.rb, line 56 def amortize @payment = Amortization.payment(@principal + interim_interest, @rate.monthly, @rate.duration) @ledger = Ledger.new(@principal) current_date = @first_payment_due @rate.duration.to_i.times do |period| break if @ledger.balance.zero? int = @ledger.balance * @rate.monthly int += interim_interest * (1 + @rate.monthly) if period === 0 @ledger << Transaction.new(int.round(2), current_date) pmt = @payment.abs <= @ledger.balance ? @payment : -@ledger.balance @ledger << Transaction.new(pmt, current_date) current_date += 1.month end @ledger.debits.last.amount -= @ledger.balance unless @ledger.balance.zero? end
balance()
click to toggle source
# File lib/financier/amortization.rb, line 33 def balance return unless @ledger @ledger.balance end
closing_date=(value)
click to toggle source
# File lib/financier/amortization.rb, line 48 def closing_date=(value) @closing_date = Date[value] end
compute()
click to toggle source
# File lib/financier/amortization.rb, line 78 def compute amortize end
first_payment_due=(value)
click to toggle source
# File lib/financier/amortization.rb, line 52 def first_payment_due=(value) @first_payment_due = Date[value] end
interest()
click to toggle source
# File lib/financier/amortization.rb, line 43 def interest return unless @ledger @ledger.credits[1..(@ledger.credits.length - 1)] end
payments()
click to toggle source
# File lib/financier/amortization.rb, line 38 def payments return unless @ledger @ledger.debits end
schedule()
click to toggle source
# File lib/financier/amortization.rb, line 82 def schedule @schedule = {} @schedule[closing_date] = { payment: 0.0, interest: 0.0, principal: 0.0, balance: @principal.round(2).to_f } payments.each_with_index do |payment, index| interest = self.interest[index] pmt = payment.amount.abs.round(2).to_f int = interest.amount.abs.round(2).to_f princ = (pmt - int).round(2).to_f bal = @ledger.balance(before: payment.date + 1.day).round(2).to_f @schedule[payment.date] = { payment: pmt, interest: int, principal: princ, balance: bal } end @schedule end
Private Instance Methods
interim_days()
click to toggle source
# File lib/financier/amortization.rb, line 120 def interim_days return D('0') if @first_payment_due == @closing_date odd_days = (@first_payment_due - 30.days - @closing_date).to_i raise NotImplementedError, "Short periods are not yet implemented!" unless odd_days >= 0 odd_days.positive? ? odd_days : (30 + odd_days) - 30 end
interim_interest()
click to toggle source
# File lib/financier/amortization.rb, line 113 def interim_interest return D('0') if @closing_date == @first_payment_due return D('0') if @closing_date == (@first_payment_due - 30.days) Amortization.interest(@principal, @rate.daily) * interim_days end