class FinancialCalculator::Rate

the Rate class provides an interface for working with interest rates. {render:Rate#new} @api public

Constants

TYPES

Accepted rate types

Attributes

duration[RW]

@return [Integer] the duration for which the rate is valid, in months @api public

effective[R]

@return [DecNum] the effective interest rate @api public

nominal[R]

@return [DecNum] the nominal interest rate @api public

Public Class Methods

new(rate, type, opts={}) click to toggle source

create a new Rate instance @return [Rate] @param [Numeric] rate the decimal value of the interest rate @param [Symbol] type a valid {TYPES rate type} @param [optional, Hash] opts set optional attributes @option opts [String] :duration a time interval for which the rate is valid @option opts [String] :compounds (:monthly) the number of compounding periods per year @example create a 3.5% APR rate

Rate.new(0.035, :apr) #=> Rate(0.035, :apr)

@see en.wikipedia.org/wiki/Effective_interest_rate @see en.wikipedia.org/wiki/Nominal_interest_rate @api public

# File lib/financial_calculator/rates.rb, line 88
def initialize(rate, type, opts={})
  # Default monthly compounding.
  opts = { :compounds => :monthly }.merge opts

  # Set optional attributes..
  opts.each do |key, value|
    send("#{key}=", value)
  end

  # Set the rate in the proper way, based on the value of type.
  begin
    send("#{TYPES.fetch(type)}=", Flt::DecNum.new(rate.to_s))
  rescue KeyError
    raise ArgumentError, "type must be one of #{TYPES.keys.join(', ')}", caller
  end
end
to_effective(rate, periods) click to toggle source

convert a nominal interest rate to an effective interest rate @return [DecNum] the effective interest rate @param [Numeric] rate the nominal interest rate @param [Numeric] periods the number of compounding periods per year @example

Rate.to_effective(0.05, 4) #=> DecNum('0.05095')

@api public

# File lib/financial_calculator/rates.rb, line 135
def Rate.to_effective(rate, periods)
  rate, periods = Flt::DecNum.new(rate.to_s), Flt::DecNum.new(periods.to_s)

  if periods.infinite?
    rate.exp - 1
  else
    (1 + rate / periods) ** periods - 1
  end
end
to_nominal(rate, periods) click to toggle source

convert an effective interest rate to a nominal interest rate @return [DecNum] the nominal interest rate @param [Numeric] rate the effective interest rate @param [Numeric] periods the number of compounding periods per year @example

Rate.to_nominal(0.06, 365) #=> DecNum('0.05827')

@see www.miniwebtool.com/nominal-interest-rate-calculator/ @api public

# File lib/financial_calculator/rates.rb, line 153
def Rate.to_nominal(rate, periods)
  rate, periods = Flt::DecNum.new(rate.to_s), Flt::DecNum.new(periods.to_s)

  if periods.infinite?
    (rate + 1).log
  else
    periods * ((1 + rate) ** (1 / periods) - 1)
  end
end

Public Instance Methods

<=>(rate) click to toggle source

compare two Rates, using the effective rate @return [Numeric] one of -1, 0, +1 @param [Rate] rate the comparison Rate @example Which is better, a nominal rate of 15% compounded monthly, or 15.5% compounded semiannually?

r1 = Rate.new(0.15, :nominal) #=> Rate.new(0.160755, :apr)
r2 = Rate.new(0.155, :nominal, :compounds => :semiannually) #=> Rate.new(0.161006, :apr)
r1 <=> r2 #=> -1

@api public

# File lib/financial_calculator/rates.rb, line 33
def <=>(rate)
  @effective <=> rate.effective
end
apr() click to toggle source

(see effective) @api public

# File lib/financial_calculator/rates.rb, line 39
def apr
  self.effective
end
apy() click to toggle source

(see effective) @api public

# File lib/financial_calculator/rates.rb, line 45
def apy
  self.effective
end
inspect() click to toggle source
# File lib/financial_calculator/rates.rb, line 105
def inspect
  "Rate.new(#{self.apr.round(6)}, :apr)"
end
monthly() click to toggle source

@return [DecNum] the monthly effective interest rate @example

rate = Rate.new(0.15, :nominal)
rate.apr.round(6) #=> DecNum('0.160755')
rate.monthly.round(6) #=> DecNum('0.013396')

@api public

# File lib/financial_calculator/rates.rb, line 115
def monthly
  (self.effective / 12).round(15)
end

Private Instance Methods

compounds=(input) click to toggle source

a convenience method which sets the value of @periods @return none @param [Symbol, Numeric] input the compounding frequency @raise [ArgumentError] if input is not an accepted keyword or Numeric @api private

# File lib/financial_calculator/rates.rb, line 54
def compounds=(input)
  @periods = case input
             when :annually     then Flt::DecNum.new(1)
             when :continuously then Flt::DecNum.infinity
             when :daily        then Flt::DecNum.new(365)
             when :monthly      then Flt::DecNum.new(12)
             when :quarterly    then Flt::DecNum.new(4)
             when :semiannually then Flt::DecNum.new(2)
             when Numeric       then Flt::DecNum.new(input.to_s)
             else raise ArgumentError
             end
end
effective=(rate) click to toggle source

set the effective interest rate @return none @param [DecNum] rate the effective interest rate @api private

# File lib/financial_calculator/rates.rb, line 71
def effective=(rate)
  @effective = rate
  @nominal = Rate.to_nominal(rate, @periods)
end
nominal=(rate) click to toggle source

set the nominal interest rate @return none @param [DecNum] rate the nominal interest rate @api private

# File lib/financial_calculator/rates.rb, line 123
def nominal=(rate)
  @nominal = rate
  @effective = Rate.to_effective(rate, @periods)
end