finance_rb 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +5 -0
- data/README.md +6 -4
- data/lib/finance/calculations.rb +46 -4
- data/lib/finance/loan.rb +16 -4
- data/lib/finance/version.rb +1 -1
- data/spec/finance/calculations_spec.rb +43 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 82235bcca3f51afff5ec345707da9d1ed2e8472a20488bb3847a4967baf6932c
|
4
|
+
data.tar.gz: '02029b9b9151d52ad860b1f985cc708199d734f8f210e574cda50fc7290f4231'
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 38348b526019d3124c6cff67c4cd39427600d7a52ea584ea9b583328bedcfceb6680783bbbfdb8f9b45b686ff612e6295e670f1a09d882e09f4540fcf23a3aea
|
7
|
+
data.tar.gz: 879a9b9b6e01efd654e32a1bbc77a9e07e8a9b1cebbbb1061f6d20f3e0aa723b8150fbf8a56e66dee87bf3eb69a14301dc4d9a51fd62f87e9414f69f47aab5d6
|
data/CHANGELOG.md
CHANGED
data/README.md
CHANGED
@@ -2,7 +2,9 @@
|
|
2
2
|
|
3
3
|
This package is a ruby native port of the numpy-financial package with some helpful additional functions.
|
4
4
|
|
5
|
-
The functions in this package are a scalar version of their vectorised counterparts in
|
5
|
+
The functions in this package are a scalar version of their vectorised counterparts in the [numpy-financial](https://github.com/numpy/numpy-financial) library.
|
6
|
+
|
7
|
+
[![Release](https://img.shields.io/github/v/release/wowinter13/finance_rb.svg?style=flat-square)](https://github.com/wowinter13/finance_rb/releases) [![PRs Welcome](https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square)](http://makeapullrequest.com)
|
6
8
|
|
7
9
|
Currently, only some functions are ported,
|
8
10
|
which are as follows:
|
@@ -15,7 +17,7 @@ which are as follows:
|
|
15
17
|
| ppmt | | Computes principal payment for a loan|
|
16
18
|
| nper | | Computes the number of periodic payments|
|
17
19
|
| pv | | Computes the present value of a payment|
|
18
|
-
| rate |
|
19
|
-
| irr |
|
20
|
+
| rate | | Computes the rate of interest per period|
|
21
|
+
| irr | ✅ | Computes the internal rate of return|
|
20
22
|
| npv | ✅ | Computes the net present value of a series of cash flow|
|
21
|
-
| mirr |
|
23
|
+
| mirr | ✅ | Computes the modified internal rate of return|
|
data/lib/finance/calculations.rb
CHANGED
@@ -35,6 +35,8 @@ module Finance
|
|
35
35
|
# @return [Float] Internal Rate of Return for periodic input values.
|
36
36
|
#
|
37
37
|
# @param [Array<Numeric>] :values Input cash flows per time period.
|
38
|
+
# At least, must contain one positive and one negative value.
|
39
|
+
# Otherwise, irr equals zero.
|
38
40
|
#
|
39
41
|
# @example
|
40
42
|
# require 'finance_rb'
|
@@ -44,10 +46,7 @@ module Finance
|
|
44
46
|
# @see L. J. Gitman, "Principles of Managerial Finance, Brief," 3rd ed.,
|
45
47
|
# Addison-Wesley, 2003, pg. 348.
|
46
48
|
def irr(values)
|
47
|
-
|
48
|
-
if inflows.empty? || outflows.empty?
|
49
|
-
return 0.0
|
50
|
-
end
|
49
|
+
return 0.0 unless correct_cashflows?(values)
|
51
50
|
|
52
51
|
func = BigDecimal.limit(100)
|
53
52
|
func = Function.new(values)
|
@@ -56,11 +55,54 @@ module Finance
|
|
56
55
|
rate[0].to_f
|
57
56
|
end
|
58
57
|
|
58
|
+
# MIRR computes the modified Rate of Interest.
|
59
|
+
#
|
60
|
+
# @return [Float] Modified Internal Rate of Return.
|
61
|
+
#
|
62
|
+
# @param [Array<Numeric>] :values
|
63
|
+
# At least, must contain one positive and one negative value.
|
64
|
+
# Otherwise, mirr equals zero.
|
65
|
+
# @param [Numeric] :rate Interest rate paid on the cash flows
|
66
|
+
# @param [Numeric] :reinvest_rate Interest rate received on the cash flows upon reinvestment
|
67
|
+
#
|
68
|
+
# @example
|
69
|
+
# require 'finance_rb'
|
70
|
+
# Finance::Calculations.mirr([100, 200, -50, 300, -200], 0.05, 0.06) => 0.2979256979689131
|
71
|
+
#
|
72
|
+
# @see https://en.wikipedia.org/wiki/Modified_internal_rate_of_return
|
73
|
+
def mirr(values, rate, reinvest_rate)
|
74
|
+
inflows = [];
|
75
|
+
outflows = [];
|
76
|
+
# We prefer manual enumeration over the partition
|
77
|
+
# because of the need to replace outflows with zeros.
|
78
|
+
values.each do |val|
|
79
|
+
if val >= 0
|
80
|
+
inflows << val
|
81
|
+
outflows << 0.0
|
82
|
+
else
|
83
|
+
outflows << val
|
84
|
+
inflows << 0.0
|
85
|
+
end
|
86
|
+
end
|
87
|
+
if outflows.all?(0.0) || inflows.all?(0.0)
|
88
|
+
return 0.0
|
89
|
+
end
|
90
|
+
fv = npv(reinvest_rate, inflows).abs
|
91
|
+
pv = npv(rate, outflows).abs
|
92
|
+
|
93
|
+
return (fv/pv) ** (1.0/(values.size - 1)) * (1 + reinvest_rate) - 1
|
94
|
+
end
|
95
|
+
|
59
96
|
alias net_present_value npv
|
60
97
|
alias internal_return_rate irr
|
61
98
|
|
62
99
|
private
|
63
100
|
|
101
|
+
def correct_cashflows?(values)
|
102
|
+
inflows, outflows = values.partition{ |i| i >= 0 }
|
103
|
+
!(inflows.empty? || outflows.empty?)
|
104
|
+
end
|
105
|
+
|
64
106
|
# Base class for working with Newton's Method.
|
65
107
|
# For more details, see Bigdecimal::Newton.
|
66
108
|
# @api private
|
data/lib/finance/loan.rb
CHANGED
@@ -2,12 +2,24 @@
|
|
2
2
|
|
3
3
|
module Finance
|
4
4
|
class Loan
|
5
|
-
def initialize
|
5
|
+
def initialize(**options)
|
6
|
+
end
|
6
7
|
|
7
|
-
def pmt
|
8
|
+
def pmt()
|
9
|
+
end
|
8
10
|
|
9
|
-
def ipmt
|
11
|
+
def ipmt()
|
12
|
+
end
|
10
13
|
|
11
|
-
def ppmt
|
14
|
+
def ppmt()
|
15
|
+
end
|
16
|
+
|
17
|
+
def fv();end
|
18
|
+
|
19
|
+
def pv();end
|
20
|
+
|
21
|
+
def nper();end
|
22
|
+
|
23
|
+
def rate();end
|
12
24
|
end
|
13
25
|
end
|
data/lib/finance/version.rb
CHANGED
@@ -26,7 +26,7 @@ RSpec.describe Finance::Calculations do
|
|
26
26
|
).to eq(0.14299344106053188)
|
27
27
|
end
|
28
28
|
|
29
|
-
it 'calculates zero
|
29
|
+
it 'calculates zero for cashflows w/o any inflows' do
|
30
30
|
expect(
|
31
31
|
Finance::Calculations.irr([100,500,200,50])
|
32
32
|
).to eq(0.0)
|
@@ -38,4 +38,46 @@ RSpec.describe Finance::Calculations do
|
|
38
38
|
).to eq(-0.09549583035161031)
|
39
39
|
end
|
40
40
|
end
|
41
|
+
|
42
|
+
describe '#mirr' do
|
43
|
+
it 'calculates correct mirr value' do
|
44
|
+
expect(
|
45
|
+
Finance::Calculations.mirr(
|
46
|
+
[-120000.0, 39000.0, 30000.0, 21000.0, 37000.0, 46000.0], 0.10, 0.12
|
47
|
+
)
|
48
|
+
).to eq(0.1260941303659051)
|
49
|
+
end
|
50
|
+
|
51
|
+
it 'calculates correct mirr value with integers' do
|
52
|
+
expect(
|
53
|
+
Finance::Calculations.mirr(
|
54
|
+
[-4500, -800, 800, 800, 600, 600, 800, 800, 700, 3000], 0.08, 0.055
|
55
|
+
)
|
56
|
+
).to eq(0.06659717503155349)
|
57
|
+
end
|
58
|
+
|
59
|
+
it 'calculates zero for cashflows w/o any outflows' do
|
60
|
+
expect(
|
61
|
+
Finance::Calculations.mirr(
|
62
|
+
[39000, 30000, 21000, 37000, 46000], 0.10, 0.12
|
63
|
+
)
|
64
|
+
).to eq(0.0)
|
65
|
+
end
|
66
|
+
|
67
|
+
it 'calculates zero for cashflows w/o any inflows' do
|
68
|
+
expect(
|
69
|
+
Finance::Calculations.mirr(
|
70
|
+
[-1000, -5000, -2000, -100, -50], 0.10, 0.12
|
71
|
+
)
|
72
|
+
).to eq(0.0)
|
73
|
+
end
|
74
|
+
|
75
|
+
it 'calculates correct mirr value for a shuffled order' do
|
76
|
+
expect(
|
77
|
+
Finance::Calculations.mirr(
|
78
|
+
[100, 200, -50, 300, -200], 0.05, 0.06
|
79
|
+
)
|
80
|
+
).to eq(0.3428233878421769)
|
81
|
+
end
|
82
|
+
end
|
41
83
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: finance_rb
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Vlad Dyachenko
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2021-03-
|
11
|
+
date: 2021-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies: []
|
13
13
|
description: A ruby port of numpy-financial functions. This library provides a Ruby
|
14
14
|
interface for working with interest rates, mortgage amortization, and cashflows
|