lib/finrb/amortization.rb in finrb-0.1.0 vs lib/finrb/amortization.rb in finrb-0.1.1
- old
+ new
@@ -1,10 +1,10 @@
# frozen_string_literal: true
-require_relative "cashflows"
-require_relative "decimal"
-require_relative "transaction"
+require_relative 'cashflows'
+require_relative 'decimal'
+require_relative 'transaction'
module Finrb
# the Amortization class provides an interface for working with loan amortizations.
# @note There are _two_ ways to create an amortization. The first
# example uses the amortize method for the Numeric class. The second
@@ -32,10 +32,30 @@
attr_reader :principal
# @return [Array] the interest rates used for calculating the amortization
# @api public
attr_reader :rates
+ # @return [DecNum] the periodic payment due on a loan
+ # @param [DecNum] principal the initial amount of the loan or investment
+ # @param [Rate] rate the applicable interest rate (per period)
+ # @param [Integer] periods the number of periods needed for repayment
+ # @note in most cases, you will probably want to use rate.monthly when calling this function outside of an Amortization instance.
+ # @example
+ # rate = Rate.new(0.0375, :apr, :duration => (30 * 12))
+ # rate.duration #=> 360
+ # Amortization.payment(200000, rate.monthly, rate.duration) #=> DecNum('-926.23')
+ # @see https://en.wikipedia.org/wiki/Amortization_calculator
+ # @api public
+ def self.payment(principal, rate, periods)
+ if rate.zero?
+ # simplified formula to avoid division-by-zero when interest rate is zero
+ -(principal / periods).round(2)
+ else
+ -(principal * (rate + (rate / (((rate + 1)**periods) - 1)))).round(2)
+ end
+ end
+
# create a new Amortization instance
# @return [Amortization]
# @param [DecNum] principal the initial amount of the loan or investment
# @param [Rate] rates the applicable interest rates
# @param [Proc] block
@@ -52,11 +72,11 @@
compute
end
# compare two Amortization instances
# @return [Numeric] -1, 0, or +1
- # @param [Amortization]
+ # @param [Amortization] other
# @api public
def ==(other)
(principal == other.principal) && (rates == other.rates) && (payments == other.payments)
end
@@ -154,29 +174,9 @@
# amt = 300000.amortize(rate)
# amt.interest[0,6].sum #=> DecNum('5603.74')
# @api public
def interest
@transactions.filter_map { |trans| trans.amount if trans.interest? }
- end
-
- # @return [DecNum] the periodic payment due on a loan
- # @param [DecNum] principal the initial amount of the loan or investment
- # @param [Rate] rate the applicable interest rate (per period)
- # @param [Integer] periods the number of periods needed for repayment
- # @note in most cases, you will probably want to use rate.monthly when calling this function outside of an Amortization instance.
- # @example
- # rate = Rate.new(0.0375, :apr, :duration => (30 * 12))
- # rate.duration #=> 360
- # Amortization.payment(200000, rate.monthly, rate.duration) #=> DecNum('-926.23')
- # @see https://en.wikipedia.org/wiki/Amortization_calculator
- # @api public
- def self.payment(principal, rate, periods)
- if rate.zero?
- # simplified formula to avoid division-by-zero when interest rate is zero
- -(principal / periods).round(2)
- else
- -(principal * (rate + (rate / (((1 + rate)**periods) - 1)))).round(2)
- end
end
# @return [Array] the amount of the payment in each period
# @example find the total payments for a loan
# rate = Rate.new(0.0375, :apr, :duration => (30 * 12))