finrb 0.0.1 → 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/finrb.gemspec CHANGED
@@ -2,97 +2,41 @@
2
2
 
3
3
  SPEC =
4
4
  Gem::Specification.new do |s|
5
- s.name = 'finrb'
6
- s.version = '0.0.1'
7
- s.authors = ['Nadir Cohen', 'Martin Bjeldbak Madsen', 'Bill Kranec']
8
- s.license = 'LGPL-3.0'
9
- s.email = ['nadircs11@gmail.com', 'me@martinbjeldbak.com', 'wkranec@gmail.com']
5
+ s.name = "finrb"
6
+ s.version = "0.1.0"
7
+ s.authors = ["Nadir Cohen", "Martin Bjeldbak Madsen", "Bill Kranec"]
8
+ s.license = "LGPL-3.0"
9
+ s.email = ["nadircs11@gmail.com", "me@martinbjeldbak.com", "wkranec@gmail.com"]
10
10
  s.platform = Gem::Platform::RUBY
11
- s.summary = 'Ruby gem for financial calculations/modeling'
11
+ s.summary = "Ruby gem for financial calculations/modeling"
12
12
 
13
13
  s.description = <<~EOF
14
- The finrb library (forked from the finance gem) provides a Ruby interface for financial calculations/modeling.
15
-
16
- - Working with interest rates
17
- - Mortgage amortization
18
- - Cashflows (NPV, IRR, etc.)
19
- - Computing bank discount yield (BDY) for a T-bill
20
- - Computing money market yield (MMY) for a T-bill
21
- - Cash ratio - Liquidity ratios measure the firm's ability to satisfy its short-term obligations as they come due.
22
- - Computing Coefficient of variation
23
- - Cost of goods sold and ending inventory under three methods (FIFO,LIFO,Weighted average)
24
- - Current ratio - Liquidity ratios measure the firm's ability to satisfy its short-term obligations as they come due.
25
- - Depreciation Expense Recognition - double-declining balance (DDB), the most common declining balance method, which applies two times the straight-line rate to the declining balance.
26
- - Debt ratio - Solvency ratios measure the firm's ability to satisfy its long-term obligations.
27
- - Diluted Earnings Per Share
28
- - Computing the rate of return for each period
29
- - Convert stated annual rate to the effective annual rate
30
- - Convert stated annual rate to the effective annual rate with continuous compounding
31
- - Bond-equivalent yield (BEY), 2 x the semiannual discount rate
32
- - Computing HPR, the holding period return
33
- - Equivalent/proportional Interest Rates
34
- - Basic Earnings Per Share
35
- - Financial leverage - Solvency ratios measure the firm's ability to satisfy its long-term obligations.
36
- - Estimate future value (fv)
37
- - Estimate future value of an annuity
38
- - Estimate future value (fv) of a single sum
39
- - Computing the future value of an uneven cash flow series
40
- - Geometric mean return
41
- - Gross profit margin - Evaluate a company's financial performance
42
- - Harmonic mean, average price
43
- - Computing HPR, the holding period return
44
- - Bond-equivalent yield (BEY), 2 x the semiannual discount rate
45
- - Convert holding period return to the effective annual rate
46
- - Computing money market yield (MMY) for a T-bill
47
- - Computing IRR, the internal rate of return
48
- - Calculate the net increase in common shares from the potential exercise of stock options or warrants
49
- - Long-term debt-to-equity - Solvency ratios measure the firm's ability to satisfy its long-term obligations.
50
- - Computing HPR, the holding period return
51
- - Estimate the number of periods
52
- - Net profit margin - Evaluate a company's financial performance
53
- - Computing NPV, the PV of the cash flows less the initial (time = 0) outlay
54
- - Estimate period payment
55
- - Estimate present value (pv)
56
- - Estimate present value (pv) of an annuity
57
- - Estimate present value of a perpetuity
58
- - Estimate present value (pv) of a single sum
59
- - Computing the present value of an uneven cash flow series
60
- - Quick ratio - Liquidity ratios measure the firm's ability to satisfy its short-term obligations as they come due.
61
- - Convert a given norminal rate to a continuous compounded rate
62
- - Convert a given continuous compounded rate to a norminal rate
63
- - Rate of return for a perpetuity
64
- - Computing Sampling error
65
- - Computing Roy's safety-first ratio
66
- - Computing Sharpe Ratio
67
- - Depreciation Expense Recognition - Straight-line depreciation (SL) allocates an equal amount of depreciation each year over the asset's useful life
68
- - Total debt-to-equity - Solvency ratios measure the firm's ability to satisfy its long-term obligations.
69
- - Computing TWRR, the time-weighted rate of return
70
- - Calculate weighted average shares - weighted average number of common shares
71
- - Weighted mean as a portfolio return
14
+ The finrb library (forked from the finance gem) provides a Ruby interface for financial calculations/modeling. Working with interest rates, Mortgage amortization, Cashflows (NPV, IRR, etc.) and other basic utilities.
72
15
 
73
16
  EOF
74
17
 
75
- s.homepage = 'https://rubygems.org/gems/finrb'
18
+ s.homepage = "https://rubygems.org/gems/finrb"
76
19
 
77
- s.required_ruby_version = '>= 3.0'
20
+ s.required_ruby_version = ">= 3.0"
78
21
 
79
- s.add_dependency('activesupport')
80
- s.add_dependency('business_time')
81
- s.add_dependency('flt')
22
+ s.add_dependency("activesupport")
23
+ s.add_dependency("business_time")
24
+ s.add_dependency("flt")
82
25
 
83
- s.add_development_dependency('minitest')
84
- s.add_development_dependency('pry')
85
- s.add_development_dependency('rake')
86
- s.add_development_dependency('rubocop')
87
- s.add_development_dependency('rubocop-minitest')
88
- s.add_development_dependency('rubocop-performance')
89
- s.add_development_dependency('rubocop-rake')
90
- s.add_development_dependency('semver')
91
- s.add_development_dependency('solargraph')
26
+ s.add_development_dependency("minitest")
27
+ s.add_development_dependency("pry")
28
+ s.add_development_dependency("rake")
29
+ s.add_development_dependency("rubocop")
30
+ s.add_development_dependency("rubocop-minitest")
31
+ s.add_development_dependency("rubocop-performance")
32
+ s.add_development_dependency("rubocop-packaging")
33
+ s.add_development_dependency("rubocop-rake")
34
+ s.add_development_dependency("semver")
35
+ s.add_development_dependency("solargraph")
92
36
 
93
37
  s.files = `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
94
38
 
95
- s.extra_rdoc_files = ['README.md', 'COPYING', 'COPYING.LESSER', 'CHANGELOG.md']
39
+ s.extra_rdoc_files = ["README.md", "COPYING", "COPYING.LESSER", "CHANGELOG.md"]
96
40
 
97
- s.metadata['rubygems_mfa_required'] = 'true'
41
+ s.metadata["rubygems_mfa_required"] = "true"
98
42
  end
@@ -1,8 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'cashflows'
4
- require_relative 'decimal'
5
- require_relative 'transaction'
3
+ require_relative "cashflows"
4
+ require_relative "decimal"
5
+ require_relative "transaction"
6
6
 
7
7
  module Finrb
8
8
  # the Amortization class provides an interface for working with loan amortizations.
@@ -67,7 +67,7 @@ module Finrb
67
67
  # amt.additional_payments #=> [DecNum('-100.00'), DecNum('-100.00'), ... ]
68
68
  # @api public
69
69
  def additional_payments
70
- @transactions.select(&:payment?).map(&:difference)
70
+ @transactions.filter_map { |trans| trans.difference if trans.payment? }
71
71
  end
72
72
 
73
73
  # amortize the balance of loan with the given interest rate
@@ -155,7 +155,7 @@ module Finrb
155
155
  # amt.interest[0,6].sum #=> DecNum('5603.74')
156
156
  # @api public
157
157
  def interest
158
- @transactions.select(&:interest?).map(&:amount)
158
+ @transactions.filter_map { |trans| trans.amount if trans.interest? }
159
159
  end
160
160
 
161
161
  # @return [DecNum] the periodic payment due on a loan
@@ -167,7 +167,7 @@ module Finrb
167
167
  # rate = Rate.new(0.0375, :apr, :duration => (30 * 12))
168
168
  # rate.duration #=> 360
169
169
  # Amortization.payment(200000, rate.monthly, rate.duration) #=> DecNum('-926.23')
170
- # @see http://en.wikipedia.org/wiki/Amortization_calculator
170
+ # @see https://en.wikipedia.org/wiki/Amortization_calculator
171
171
  # @api public
172
172
  def self.payment(principal, rate, periods)
173
173
  if rate.zero?
@@ -185,7 +185,7 @@ module Finrb
185
185
  # amt.payments.sum #=> DecNum('-500163.94')
186
186
  # @api public
187
187
  def payments
188
- @transactions.select(&:payment?).map(&:amount)
188
+ @transactions.filter_map { |trans| trans.amount if trans.payment? }
189
189
  end
190
190
  end
191
191
  end
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'decimal'
4
- require_relative 'rates'
3
+ require_relative "decimal"
4
+ require_relative "rates"
5
5
 
6
- require 'bigdecimal'
7
- require 'bigdecimal/newton'
8
- require 'business_time'
6
+ require "bigdecimal"
7
+ require "bigdecimal/newton"
8
+ require "business_time"
9
9
  include Newton
10
10
 
11
11
  module Finrb
@@ -15,7 +15,7 @@ module Finrb
15
15
  # Base class for working with Newton's Method.
16
16
  # @api private
17
17
  class Function
18
- values = { eps: Finrb.config.eps, one: '1.0', two: '2.0', ten: '10.0', zero: '0.0' }
18
+ values = { eps: Finrb.config.eps, one: "1.0", two: "2.0", ten: "10.0", zero: "0.0" }
19
19
 
20
20
  values.each do |key, value|
21
21
  define_method key do
@@ -43,12 +43,12 @@ module Finrb
43
43
  # @param [Numeric] Initial guess rate, Defaults to 1.0
44
44
  # @example
45
45
  # [-4000,1200,1410,1875,1050].irr #=> 0.143
46
- # @see http://en.wikipedia.org/wiki/Internal_rate_of_return
46
+ # @see https://en.wikipedia.org/wiki/Internal_rate_of_return
47
47
  # @api public
48
48
  def irr(guess = nil)
49
49
  # Make sure we have a valid sequence of cash flows.
50
50
  positives, negatives = partition { |i| i >= 0 }
51
- raise(ArgumentError, 'Calculation does not converge.') if positives.empty? || negatives.empty?
51
+ raise(ArgumentError, "Calculation does not converge.") if positives.empty? || negatives.empty?
52
52
 
53
53
  func = Function.new(self, :npv)
54
54
  rate = [valid(guess)]
@@ -57,7 +57,7 @@ module Finrb
57
57
  end
58
58
 
59
59
  def method_missing(name, *args, &block)
60
- return sum if name.to_s == 'sum'
60
+ return sum if name.to_s == "sum"
61
61
 
62
62
  super
63
63
  end
@@ -67,7 +67,7 @@ module Finrb
67
67
  # @param [Numeric] rate the discount rate to be applied
68
68
  # @example
69
69
  # [-100.0, 60, 60, 60].npv(0.1) #=> 49.211
70
- # @see http://en.wikipedia.org/wiki/Net_present_value
70
+ # @see https://en.wikipedia.org/wiki/Net_present_value
71
71
  # @api public
72
72
  def npv(rate)
73
73
  cashflows = map { |entry| Flt::DecNum.new(entry.to_s) }
@@ -97,7 +97,7 @@ module Finrb
97
97
  if positives.empty? || negatives.empty?
98
98
  raise(
99
99
  ArgumentError,
100
- 'Calculation does not converge. Cashflow needs to have a least one positive and one negative value.'
100
+ "Calculation does not converge. Cashflow needs to have a least one positive and one negative value."
101
101
  )
102
102
  end
103
103
 
@@ -125,44 +125,43 @@ module Finrb
125
125
  end
126
126
 
127
127
  private
128
-
129
- def date_diff(from, to)
130
- if Finrb.config.business_days
131
- from.to_date.business_days_until(to)
132
- else
133
- to - from
128
+ def date_diff(from, to)
129
+ if Finrb.config.business_days
130
+ from.to_date.business_days_until(to)
131
+ else
132
+ to - from
133
+ end
134
134
  end
135
- end
136
135
 
137
- def days_in_period
138
- if Finrb.config.periodic_compound && Finrb.config.business_days
139
- start.to_date.business_days_until(stop).to_f
140
- else
141
- Flt::DecNum.new(365.days.to_s)
136
+ def days_in_period
137
+ if Finrb.config.periodic_compound && Finrb.config.business_days
138
+ start.to_date.business_days_until(stop).to_f
139
+ else
140
+ Flt::DecNum.new(365.days.to_s)
141
+ end
142
142
  end
143
- end
144
143
 
145
- def start
146
- @start ||= self[0].date
147
- end
144
+ def start
145
+ @start ||= self[0].date
146
+ end
148
147
 
149
- def stop
150
- @stop ||= self[-1].date.to_date
151
- end
148
+ def stop
149
+ @stop ||= self[-1].date.to_date
150
+ end
152
151
 
153
- def valid(guess)
154
- if guess.nil?
155
- unless Finrb.config.guess.is_a?(Numeric)
156
- raise(ArgumentError, 'Invalid Guess. Default guess should be a [Numeric] value.')
157
- end
152
+ def valid(guess)
153
+ if guess.nil?
154
+ unless Finrb.config.guess.is_a?(Numeric)
155
+ raise(ArgumentError, "Invalid Guess. Default guess should be a [Numeric] value.")
156
+ end
158
157
 
159
- Finrb.config.guess
160
- else
161
- raise(ArgumentError, 'Invalid Guess. Use a [Numeric] value.') unless guess.is_a?(Numeric)
158
+ Finrb.config.guess
159
+ else
160
+ raise(ArgumentError, "Invalid Guess. Use a [Numeric] value.") unless guess.is_a?(Numeric)
162
161
 
163
- guess
164
- end.to_f
165
- end
162
+ guess
163
+ end.to_f
164
+ end
166
165
  end
167
166
  end
168
167
 
data/lib/finrb/config.rb CHANGED
@@ -3,7 +3,7 @@
3
3
  module Finrb
4
4
  include ActiveSupport::Configurable
5
5
 
6
- default_values = { eps: '1.0e-16', guess: 1.0, business_days: false, periodic_compound: false }
6
+ default_values = { eps: "1.0e-16", guess: 1.0, business_days: false, periodic_compound: false }
7
7
 
8
8
  default_values.each do |key, value|
9
9
  config.send("#{key.to_sym}=", value)
data/lib/finrb/decimal.rb CHANGED
@@ -1,7 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'rubygems'
4
- require 'flt'
3
+ require "rubygems"
4
+ require "flt"
5
5
  include Flt
6
6
 
7
7
  DecNum.context.define_conversion_from(BigDecimal) do |x, _context|
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.
@@ -17,8 +17,8 @@ module Finrb
17
17
  # @option opts [String] :compounds (:monthly) the number of compounding periods per year
18
18
  # @example create a 3.5% APR rate
19
19
  # Rate.new(0.035, :apr) #=> Rate(0.035, :apr)
20
- # @see http://en.wikipedia.org/wiki/Effective_interest_rate
21
- # @see http://en.wikipedia.org/wiki/Nominal_interest_rate
20
+ # @see https://en.wikipedia.org/wiki/Effective_interest_rate
21
+ # @see https://en.wikipedia.org/wiki/Nominal_interest_rate
22
22
  # @api public
23
23
  def initialize(rate, type, opts = {})
24
24
  # Default monthly compounding.
@@ -38,7 +38,7 @@ module Finrb
38
38
  end
39
39
 
40
40
  # Accepted rate types
41
- TYPES = { apr: 'effective', apy: 'effective', effective: 'effective', nominal: 'nominal' }.freeze
41
+ TYPES = { apr: "effective", apy: "effective", effective: "effective", nominal: "nominal" }.freeze
42
42
 
43
43
  # @return [Integer] the duration for which the rate is valid, in months
44
44
  # @api public
@@ -149,7 +149,7 @@ module Finrb
149
149
  # @param [Numeric] periods the number of compounding periods per year
150
150
  # @example
151
151
  # Rate.to_nominal(0.06, 365) #=> DecNum('0.05827')
152
- # @see http://www.miniwebtool.com/nominal-interest-rate-calculator/
152
+ # @see https://www.miniwebtool.com/nominal-interest-rate-calculator/
153
153
  # @api public
154
154
  def self.to_nominal(rate, periods)
155
155
  rate = Flt::DecNum.new(rate.to_s)
@@ -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 Transaction class provides a general interface for working with individual cash flows.