Class: Finance::Amortization
- Inherits:
-
Object
- Object
- Finance::Amortization
- Defined in:
- lib/finance/amortization.rb
Overview
There are two ways to create an amortization. The first example uses the amortize method for the Numeric class. The second calls Amortization.new directly.
the Amortization class provides an interface for working with loan amortizations.
Instance Attribute Summary collapse
-
#balance ⇒ DecNum
readonly
The balance of the loan at the end of the amortization period (usually zero).
-
#payment ⇒ DecNum
readonly
The required monthly payment.
-
#principal ⇒ DecNum
readonly
The principal amount of the loan.
-
#rates ⇒ Array
readonly
The interest rates used for calculating the amortization.
Class Method Summary collapse
-
.payment(principal, rate, periods) ⇒ DecNum
The periodic payment due on a loan.
Instance Method Summary collapse
-
#==(amortization) ⇒ Numeric
compare two Amortization instances.
-
#additional_payments ⇒ Array
The amount of any additional payments in each period.
-
#amortize(rate) ⇒ Object
private
amortize the balance of loan with the given interest rate.
-
#compute ⇒ Object
private
compute the amortization of the principal.
-
#duration ⇒ Integer
The time required to pay off the loan, in months.
-
#initialize(principal, *rates, &block) ⇒ Amortization
constructor
create a new Amortization instance.
- #inspect ⇒ Object
-
#interest ⇒ Array
The amount of interest charged in each period.
-
#payments ⇒ Array
The amount of the payment in each period.
Constructor Details
#initialize(principal, *rates, &block) ⇒ Amortization
create a new Amortization instance
132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/finance/amortization.rb', line 132 def initialize(principal, *rates, &block) @principal = Flt::DecNum.new(principal.to_s) @rates = rates @block = block # compute the total duration from all of the rates. @periods = (rates.collect { |r| r.duration }).sum @period = 0 compute end |
Instance Attribute Details
#balance ⇒ DecNum (readonly)
Returns the balance of the loan at the end of the amortization period (usually zero).
24 25 26 |
# File 'lib/finance/amortization.rb', line 24 def balance @balance end |
#payment ⇒ DecNum (readonly)
Returns the required monthly payment. For loans with more than one rate, returns nil.
27 28 29 |
# File 'lib/finance/amortization.rb', line 27 def payment @payment end |
#principal ⇒ DecNum (readonly)
Returns the principal amount of the loan.
30 31 32 |
# File 'lib/finance/amortization.rb', line 30 def principal @principal end |
#rates ⇒ Array (readonly)
Returns the interest rates used for calculating the amortization.
33 34 35 |
# File 'lib/finance/amortization.rb', line 33 def rates @rates end |
Class Method Details
.payment(principal, rate, periods) ⇒ DecNum
in most cases, you will probably want to use rate.monthly when calling this function outside of an Amortization instance.
Returns the periodic payment due on a loan.
174 175 176 177 178 179 180 181 |
# File 'lib/finance/amortization.rb', line 174 def Amortization.payment(principal, rate, periods) if rate.zero? # simplified formula to avoid division-by-zero when interest rate is zero return -(principal / periods).round(2) else return -(principal * (rate + (rate / ((1 + rate) ** periods - 1)))).round(2) end end |
Instance Method Details
#==(amortization) ⇒ Numeric
compare two Amortization instances
39 40 41 |
# File 'lib/finance/amortization.rb', line 39 def ==(amortization) self.principal == amortization.principal and self.rates == amortization.rates and self.payments == amortization.payments end |
#additional_payments ⇒ Array
Returns the amount of any additional payments in each period.
49 50 51 |
# File 'lib/finance/amortization.rb', line 49 def additional_payments @transactions.find_all(&:payment?).collect{ |p| p.difference } end |
#amortize(rate) ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
amortize the balance of loan with the given interest rate
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 |
# File 'lib/finance/amortization.rb', line 57 def amortize(rate) # For the purposes of calculating a payment, the relevant time # period is the remaining number of periods in the loan, not # necessarily the duration of the rate itself. periods = @periods - @period amount = Amortization.payment @balance, rate.monthly, periods pmt = Payment.new(amount, :period => @period) if @block then pmt.modify(&@block) end rate.duration.to_i.times do # Do this first in case the balance is zero already. if @balance.zero? then break end # Compute and record interest on the outstanding balance. int = (@balance * rate.monthly).round(2) interest = Interest.new(int, :period => @period) @balance += interest.amount @transactions << interest.dup # Record payment. Don't pay more than the outstanding balance. if pmt.amount.abs > @balance then pmt.amount = -@balance end @transactions << pmt.dup @balance += pmt.amount @period += 1 end end |
#compute ⇒ Object
This method is part of a private API. You should avoid using this method if possible, as it may be removed or be changed in the future.
compute the amortization of the principal
89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 |
# File 'lib/finance/amortization.rb', line 89 def compute @balance = @principal @transactions = [] @rates.each do |rate| amortize(rate) end # Add any remaining balance due to rounding error to the last payment. unless @balance.zero? @transactions.find_all(&:payment?)[-1].amount -= @balance @balance = 0 end if @rates.length == 1 @payment = self.payments[0] else @payment = nil end @transactions.freeze end |
#duration ⇒ Integer
Returns the time required to pay off the loan, in months.
122 123 124 |
# File 'lib/finance/amortization.rb', line 122 def duration self.payments.length end |
#inspect ⇒ Object
145 146 147 |
# File 'lib/finance/amortization.rb', line 145 def inspect "Amortization.new(#{@principal})" end |
#interest ⇒ Array
Returns the amount of interest charged in each period.
159 160 161 |
# File 'lib/finance/amortization.rb', line 159 def interest @transactions.find_all(&:interest?).collect{ |p| p.amount } end |
#payments ⇒ Array
Returns the amount of the payment in each period.
189 190 191 |
# File 'lib/finance/amortization.rb', line 189 def payments @transactions.find_all(&:payment?).collect{ |p| p.amount } end |