wi_xirr 1.0.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 2a708d7a6f079f706dfd6cfee92d5e8cc26f72c68750d0d007230a54de6e84ad
4
+ data.tar.gz: 8326f713285bcaf625d3f42720c17a6546df93279d9832eb209227cbea240533
5
+ SHA512:
6
+ metadata.gz: bed4a43e9a742bedba1eff69ba81b5b4e335e285dcd76c3a39ef2b0904d63d76dfbfc80be290d8cbd9d2315ab61297eac822156094291bbf8d9cf99b0cffd990
7
+ data.tar.gz: 99628d325724ca1e5356afba0891bfa0c474926167a5ee15a9e20191431cbecf0c67378e17571b6317afdc95029c17b01c67682241238d4a18c6bff1c7e89fd0
@@ -0,0 +1,4 @@
1
+ require "mkmf"
2
+ extension_name = "wi_xirr"
3
+ dir_config(extension_name)
4
+ create_makefile("wi_xirr/wi_xirr")
@@ -0,0 +1,84 @@
1
+ # include <math.h>
2
+ # include <time.h>
3
+ # include <stdio.h>
4
+ # include <ruby.h>
5
+
6
+ VALUE WiXirr = Qnil;
7
+
8
+ void Init_wi_xirr();
9
+ VALUE calculate(VALUE self, VALUE rb_amounts, VALUE rb_dates, VALUE guess, VALUE maximum_iterations);
10
+ double get_fx(double x, double amounts[], double investmentPreiods[], int numberOfTransactions);
11
+ double get_derivative_for_x(double x, double amounts[], double investmentPreiods[], int numberOfTransactions);
12
+
13
+ void Init_wi_xirr() {
14
+ WiXirr = rb_const_get(rb_cObject, rb_intern("WiXirr"));
15
+ rb_define_module_function(WiXirr, "calculate", calculate, 4);
16
+ }
17
+
18
+ VALUE calculate(VALUE self, VALUE rb_amounts, VALUE rb_dates, VALUE guess, VALUE maximum_iterations) {
19
+ // Fixed variables
20
+ int max_iterations = NUM2INT(maximum_iterations);
21
+ int length = (int)RARRAY_LEN(rb_amounts);
22
+ double delta = 1E-8;
23
+ double investment_periods[length], amounts[length], dates[length];
24
+ double min_date = 34028235E38;
25
+ // Find min and max date and initialize c arrays
26
+ for(int i = 0; i < length; i++) {
27
+ amounts[i] = NUM2DBL(rb_ary_entry(rb_amounts, i));
28
+ // Dates is the array containing the number of days since epoch
29
+ dates[i] = floor(NUM2DBL(rb_ary_entry(rb_dates, i)) / 86400);
30
+ if (dates[i] < min_date)
31
+ min_date = dates[i];
32
+ }
33
+ // Find investment_periods
34
+ for(int i = 0; i < length; i++)
35
+ investment_periods[i] = (dates[i] - min_date);
36
+
37
+ // Solving for 0 npv by Newton's Method
38
+ double init_guess = NUM2DBL(guess);
39
+ double irr = init_guess, delta_x = 0.0;
40
+ int number_of_iterations = 0;
41
+ do {
42
+ irr -= delta_x;
43
+ if (irr == -1.0) {
44
+ break;
45
+ }
46
+ double fx = get_fx(irr, amounts, investment_periods, length);
47
+ double derivative_at_x = get_derivative_for_x(irr, amounts, investment_periods, length);
48
+ if (derivative_at_x == 0.0) {
49
+ irr = -1;
50
+ break;
51
+ }
52
+ delta_x = fx / derivative_at_x;
53
+ number_of_iterations += 1;
54
+ } while((fabs(delta_x) > delta) && (number_of_iterations < max_iterations));
55
+ if (number_of_iterations >= max_iterations) {
56
+ irr = -1;
57
+ }
58
+ return DBL2NUM(pow(1 + irr, 365) - 1);
59
+ }
60
+
61
+ double get_fx(double x, double amounts[], double investmentPreiods[], int numberOfTransactions) {
62
+ double fx = 0.0;
63
+ for(int i = 0; i < numberOfTransactions; i++)
64
+ fx += (amounts[i] / pow(1 + x, investmentPreiods[i]));
65
+ return fx;
66
+ }
67
+
68
+ double get_derivative_for_x(double x, double amounts[], double investmentPreiods[], int numberOfTransactions) {
69
+ double f_dash_x = 0.0;
70
+ for(int i = 0; i < numberOfTransactions; i++)
71
+ f_dash_x += (amounts[i] * investmentPreiods[i]) / pow(1 + x, investmentPreiods[i]);
72
+ return -f_dash_x;
73
+ }
74
+
75
+ // Solving for 0 npv by bisection method
76
+ // double left_guess = -49.99/365.0, right_guess = 49.99/365.0;
77
+ // while((right_guess - left_guess) > (2 * delta)) {
78
+ // double mid = (right_guess + left_guess) / 2;
79
+ // if (get_fx(left_guess, amounts, investment_periods, length) * get_fx(mid, amounts, investment_periods, length) > 0)
80
+ // left_guess = mid;
81
+ // else
82
+ // right_guess = mid;
83
+ // }
84
+ // double irr = (left_guess + right_guess) / 2.0;
@@ -0,0 +1,4 @@
1
+ module WiXirr
2
+ end
3
+
4
+ require 'wi_xirr/wi_xirr'
@@ -0,0 +1,3 @@
1
+ module WiXirr
2
+ VERSION = '1.0.0'
3
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wi_xirr
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Mahadevan K, Shaunak Dey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-18 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rake-compiler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: byebug
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Fast Newtonian method XIRR calculator for Ruby, matches Excel implementation
56
+ of XIRR formula
57
+ email:
58
+ executables: []
59
+ extensions:
60
+ - ext/wi_xirr/extconf.rb
61
+ extra_rdoc_files: []
62
+ files:
63
+ - ext/wi_xirr/extconf.rb
64
+ - ext/wi_xirr/wi_xirr.c
65
+ - lib/wi_xirr.rb
66
+ - lib/wi_xirr/version.rb
67
+ homepage: https://github.com/planarinvestments/wi_xirr
68
+ licenses:
69
+ - MIT
70
+ metadata: {}
71
+ post_install_message:
72
+ rdoc_options: []
73
+ require_paths:
74
+ - lib
75
+ required_ruby_version: !ruby/object:Gem::Requirement
76
+ requirements:
77
+ - - ">="
78
+ - !ruby/object:Gem::Version
79
+ version: '0'
80
+ required_rubygems_version: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - ">="
83
+ - !ruby/object:Gem::Version
84
+ version: '0'
85
+ requirements: []
86
+ rubygems_version: 3.1.2
87
+ signing_key:
88
+ specification_version: 4
89
+ summary: Fast Newtonian method XIRR calculator for Ruby
90
+ test_files: []