finrb 0.0.1 → 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
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.