Skip to content

Instantly share code, notes, and snippets.

@davidrichards
Created July 24, 2012 07:47
Show Gist options
  • Save davidrichards/3168646 to your computer and use it in GitHub Desktop.
Save davidrichards/3168646 to your computer and use it in GitHub Desktop.
Just so I don't forget and have to re-figure this another time in my life. This isn't optimized and does nothing to handle rounding errors.
class AmortizationTable
Transaction = Struct.new(:payment, :interest, :principle, :balance)
attr_reader :amount, :rate, :n
def initialize(opts={})
@amount = opts.fetch(:amount, 25_000)
@rate = opts.fetch(:rate, (0.06 / 36))
@n = opts.fetch(:n, 36)
end
def table
@table ||= n.times.inject({}) do |hash, i|
last_payment = hash[i - 1]
last_balance = last_payment ? last_payment.balance : amount
new_interest = last_balance * rate
new_principle = payment - new_interest
new_balance = last_balance - new_principle
new_payment = last_balance < payment ? last_balance : payment
hash[i] = Transaction.new(new_payment, new_interest, new_principle, new_balance)
hash
end
end
def payment
amount * ((((1 + rate)**n) * rate) / (((1 + rate) ** n) - 1))
end
def interest(month)
index = month - 1
table[index] ? table[index].interest : 0
end
def principle(month)
index = month - 1
table[index] ? table[index].principle : 0
end
def balance(month)
index = month - 1
table[index] ? table[index].balance : 0
end
def inspect
"AmortizationTable amount: #{amount}, rate: #{rate}, n: #{n}"
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment