finrb 0.1.0 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
data/lib/finrb/rates.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "decimal"
3
+ require_relative 'decimal'
4
4
 
5
5
  module Finrb
6
6
  # the Rate class provides an interface for working with interest rates.
@@ -8,6 +8,47 @@ module Finrb
8
8
  # @api public
9
9
  class Rate
10
10
  include Comparable
11
+ # Accepted rate types
12
+ TYPES = { apr: 'effective', apy: 'effective', effective: 'effective', nominal: 'nominal' }.freeze
13
+ public_constant :TYPES
14
+
15
+ # convert a nominal interest rate to an effective interest rate
16
+ # @return [Flt::DecNum] the effective interest rate
17
+ # @param [Numeric] rate the nominal interest rate
18
+ # @param [Numeric] periods the number of compounding periods per year
19
+ # @example
20
+ # Rate.to_effective(0.05, 4) #=> Flt::DecNum('0.05095')
21
+ # @api public
22
+ def self.to_effective(rate, periods)
23
+ rate = Flt::DecNum.new(rate.to_s)
24
+ periods = Flt::DecNum.new(periods.to_s)
25
+
26
+ if periods.infinite?
27
+ rate.exp - 1
28
+ else
29
+ (((rate / periods) + 1)**periods) - 1
30
+ end
31
+ end
32
+
33
+ # convert an effective interest rate to a nominal interest rate
34
+ # @return [Flt::DecNum] the nominal interest rate
35
+ # @param [Numeric] rate the effective interest rate
36
+ # @param [Numeric] periods the number of compounding periods per year
37
+ # @example
38
+ # Rate.to_nominal(0.06, 365) #=> Flt::DecNum('0.05827')
39
+ # @see https://www.miniwebtool.com/nominal-interest-rate-calculator/
40
+ # @api public
41
+ def self.to_nominal(rate, periods)
42
+ rate = Flt::DecNum.new(rate.to_s)
43
+ periods = Flt::DecNum.new(periods.to_s)
44
+
45
+ if periods.infinite?
46
+ (rate + 1).log
47
+ else
48
+ periods * (((rate + 1)**(1.to_f / periods)) - 1)
49
+ end
50
+ end
51
+
11
52
  # create a new Rate instance
12
53
  # @return [Rate]
13
54
  # @param [Numeric] rate the decimal value of the interest rate
@@ -26,33 +67,30 @@ module Finrb
26
67
 
27
68
  # Set optional attributes..
28
69
  opts.each do |key, value|
29
- send("#{key}=", value)
70
+ __send__("#{key}=", value)
30
71
  end
31
72
 
32
73
  # Set the rate in the proper way, based on the value of type.
33
74
  begin
34
- send("#{TYPES.fetch(type)}=", Flt::DecNum.new(rate.to_s))
75
+ __send__("#{TYPES.fetch(type)}=", Flt::DecNum.new(rate.to_s))
35
76
  rescue KeyError
36
77
  raise(ArgumentError, "type must be one of #{TYPES.keys.join(', ')}", caller)
37
78
  end
38
79
  end
39
80
 
40
- # Accepted rate types
41
- TYPES = { apr: "effective", apy: "effective", effective: "effective", nominal: "nominal" }.freeze
42
-
43
81
  # @return [Integer] the duration for which the rate is valid, in months
44
82
  # @api public
45
83
  attr_accessor :duration
46
- # @return [DecNum] the effective interest rate
84
+ # @return [Flt::DecNum] the effective interest rate
47
85
  # @api public
48
86
  attr_reader :effective
49
- # @return [DecNum] the nominal interest rate
87
+ # @return [Flt::DecNum] the nominal interest rate
50
88
  # @api public
51
89
  attr_reader :nominal
52
90
 
53
91
  # compare two Rates, using the effective rate
54
92
  # @return [Numeric] one of -1, 0, +1
55
- # @param [Rate] rate the comparison Rate
93
+ # @param [Rate] other the comparison Rate
56
94
  # @example Which is better, a nominal rate of 15% compounded monthly, or 15.5% compounded semiannually?
57
95
  # r1 = Rate.new(0.15, :nominal) #=> Rate.new(0.160755, :apr)
58
96
  # r2 = Rate.new(0.155, :nominal, :compounds => :semiannually) #=> Rate.new(0.161006, :apr)
@@ -95,7 +133,7 @@ module Finrb
95
133
 
96
134
  # set the effective interest rate
97
135
  # @return none
98
- # @param [DecNum] rate the effective interest rate
136
+ # @param [Flt::DecNum] rate the effective interest rate
99
137
  # @api private
100
138
  def effective=(rate)
101
139
  @effective = rate
@@ -106,11 +144,11 @@ module Finrb
106
144
  "Rate.new(#{apr.round(6)}, :apr)"
107
145
  end
108
146
 
109
- # @return [DecNum] the monthly effective interest rate
147
+ # @return [Flt::DecNum] the monthly effective interest rate
110
148
  # @example
111
149
  # rate = Rate.new(0.15, :nominal)
112
- # rate.apr.round(6) #=> DecNum('0.160755')
113
- # rate.monthly.round(6) #=> DecNum('0.013396')
150
+ # rate.apr.round(6) #=> Flt::DecNum('0.160755')
151
+ # rate.monthly.round(6) #=> Flt::DecNum('0.013396')
114
152
  # @api public
115
153
  def monthly
116
154
  (effective / 12).round(15)
@@ -118,50 +156,13 @@ module Finrb
118
156
 
119
157
  # set the nominal interest rate
120
158
  # @return none
121
- # @param [DecNum] rate the nominal interest rate
159
+ # @param [Flt::DecNum] rate the nominal interest rate
122
160
  # @api private
123
161
  def nominal=(rate)
124
162
  @nominal = rate
125
163
  @effective = Rate.to_effective(rate, @periods)
126
164
  end
127
165
 
128
- # convert a nominal interest rate to an effective interest rate
129
- # @return [DecNum] the effective interest rate
130
- # @param [Numeric] rate the nominal interest rate
131
- # @param [Numeric] periods the number of compounding periods per year
132
- # @example
133
- # Rate.to_effective(0.05, 4) #=> DecNum('0.05095')
134
- # @api public
135
- def self.to_effective(rate, periods)
136
- rate = Flt::DecNum.new(rate.to_s)
137
- periods = Flt::DecNum.new(periods.to_s)
138
-
139
- if periods.infinite?
140
- rate.exp - 1
141
- else
142
- ((1 + (rate / periods))**periods) - 1
143
- end
144
- end
145
-
146
- # convert an effective interest rate to a nominal interest rate
147
- # @return [DecNum] the nominal interest rate
148
- # @param [Numeric] rate the effective interest rate
149
- # @param [Numeric] periods the number of compounding periods per year
150
- # @example
151
- # Rate.to_nominal(0.06, 365) #=> DecNum('0.05827')
152
- # @see https://www.miniwebtool.com/nominal-interest-rate-calculator/
153
- # @api public
154
- def self.to_nominal(rate, periods)
155
- rate = Flt::DecNum.new(rate.to_s)
156
- periods = Flt::DecNum.new(periods.to_s)
157
-
158
- if periods.infinite?
159
- (rate + 1).log
160
- else
161
- periods * (((1 + rate)**(1 / periods)) - 1)
162
- end
163
- end
164
-
165
166
  private :compounds=, :effective=, :nominal=
166
167
  end
167
168
  end
@@ -1,12 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative "decimal"
3
+ require_relative 'decimal'
4
4
 
5
5
  module Finrb
6
6
  # the Transaction class provides a general interface for working with individual cash flows.
7
7
  # @api public
8
8
  class Transaction
9
- # @return [DecNum] the cash value of the transaction
9
+ # @return [Flt::DecNum] the cash value of the transaction
10
10
  # @api public
11
11
  attr_reader :amount
12
12
  # @return [Integer] the period number of the transaction
@@ -33,7 +33,7 @@ module Finrb
33
33
 
34
34
  # Set optional attributes..
35
35
  opts.each do |key, value|
36
- send("#{key}=", value)
36
+ __send__("#{key}=", value)
37
37
  end
38
38
  end
39
39
 
@@ -49,12 +49,12 @@ module Finrb
49
49
  @amount = Flt::DecNum.new(value.to_s) || 0
50
50
  end
51
51
 
52
- # @return [DecNum] the difference between the original transaction
52
+ # @return [Flt::DecNum] the difference between the original transaction
53
53
  # amount and the current amount
54
54
  # @example
55
55
  # t = Transaction.new(500)
56
56
  # t.amount = 750
57
- # t.difference #=> DecNum('250')
57
+ # t.difference #=> Flt::DecNum('250')
58
58
  # @api public
59
59
  def difference
60
60
  @amount - @original