interest_days 0.1.1 → 0.2.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 68382b7fbcf8795d417cef0017b8c77cf3169d0e7b14aad979afc82003f80a31
4
- data.tar.gz: 0e283cb94a33ec8d073ba0c3ea38b95309e8ca95c18a655b0c6d9772bce152bc
3
+ metadata.gz: fd70242df3cc611422eab114a361fa95159a2b38f80c1f36588f65bd42696eae
4
+ data.tar.gz: 1110b831429ac7ec6e544ac7122d020ee2cf0a3e2b815ce028dea04db218b34f
5
5
  SHA512:
6
- metadata.gz: 8b30317b93074457dd25bf20968a533d051d91fdb757a8de6db2a3e1b25c352a2f40ef6e91cc05b42457b58bde54167a408a2e62155d1f569ebb6f751ba17b25
7
- data.tar.gz: 3d4fbecfdd70fc6b051545d3c1cf6dc126ae3278f28ff276d999da7dc37060eefc6387f8df73e31e922121df1cf97207cd3a5410c5e508bfe0e61b0436c112e4
6
+ metadata.gz: b6f267d1f27967ab0e522b6b4e0854ffb4d4b56986ae848adbc535b826282380a20cbe9bde47dae5baa743ea9da4de0e5341d135cb161a53540d3e28325ae35a
7
+ data.tar.gz: 801180a7509c5e751d7a1d91ebfedb335d69c0f7d4d19ad3c05d7cba8c7c7d1d07ba0f4aacee1a87e9ae287b30d4e3f4317eac5a3d9267b2dce7dcbbcc5842f5
data/.rubocop.yml CHANGED
@@ -14,4 +14,7 @@ Layout/LineLength:
14
14
  Max: 120
15
15
 
16
16
  Naming/VariableNumber:
17
- EnforcedStyle: snake_case
17
+ EnforcedStyle: snake_case
18
+
19
+ Metrics/BlockLength:
20
+ Max: 50
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- interest_days (0.1.1)
4
+ interest_days (0.2.0)
5
5
 
6
6
  GEM
7
7
  remote: https://rubygems.org/
data/README.md CHANGED
@@ -1,6 +1,7 @@
1
1
  # InterestDays
2
2
 
3
3
  This gem provide interest day factor calculation based on ISDA conventions e.g. Isda Act 360.
4
+ Since version 0.2 interest_day gem support 30/360 US EOM and 30/360 Bond Basis conventions.
4
5
 
5
6
  ## Installation
6
7
 
@@ -22,14 +23,18 @@ Or install it yourself as:
22
23
 
23
24
  You can simple use the InterestDays::Calculator like:
24
25
 
25
- ’’’
26
- InterestDays::Calculator.new(start_date: start, end_date: end, strategy: :isda_act_360)
27
- ’’’
26
+ ```ruby
27
+ calculator = InterestDays::Calculator.new(start_date: start, end_date: end, strategy: :isda_act_360)
28
+
29
+ calculator.interest_day_count_factor
30
+ ```
28
31
 
29
- current there a three supported conventions:
32
+ currently there a three supported conventions:
30
33
  - :isda_act_360
31
34
  - :isda_act_365
32
35
  - :isda_30_e_360
36
+ - :us_eom_30_360
37
+ - :bond_basis_30_360
33
38
 
34
39
 
35
40
  ## Development
@@ -12,7 +12,7 @@ module InterestDays
12
12
  end
13
13
 
14
14
  def day_count_factor
15
- raise NotImplementedError, "#{self.class} has nit implemented method '#{__method__}"
15
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}"
16
16
  end
17
17
 
18
18
  private
@@ -3,25 +3,15 @@
3
3
  module InterestDays
4
4
  module Calculation
5
5
  # ISDA 30 E 360 Convention calculation
6
- class Isda30e360 < Base
7
- RELEVANT_DAYS_IN_YEAR = 360
8
-
9
- def day_count_factor
10
- (year_interval_in_days + month_interval_in_days + day_interval).fdiv(RELEVANT_DAYS_IN_YEAR)
11
- end
12
-
6
+ class Isda30e360 < ThirtyThreesixtyBase
13
7
  private
14
8
 
15
- def year_interval_in_days
16
- 360 * (@end_date.year - @start_date.year)
17
- end
18
-
19
- def month_interval_in_days
20
- 30 * (@end_date.month - @start_date.month)
9
+ def end_date_days
10
+ [@end_date.day, RELEVANT_DAY_IN_MONTH].min
21
11
  end
22
12
 
23
- def day_interval
24
- [@end_date.day, 30].min - [@start_date.day, 30].min
13
+ def start_date_days
14
+ [@start_date.day, RELEVANT_DAY_IN_MONTH].min
25
15
  end
26
16
  end
27
17
  end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InterestDays
4
+ module Calculation
5
+ # ISDA 30 E 360 Convention calculation
6
+ class ThirtyThreesixtyBase < Base
7
+ RELEVANT_DAYS_IN_YEAR = 360
8
+ RELEVANT_DAY_IN_MONTH = 30
9
+
10
+ def day_count_factor
11
+ (year_interval_in_days + month_interval_in_days + day_interval).fdiv(RELEVANT_DAYS_IN_YEAR)
12
+ end
13
+
14
+ private
15
+
16
+ def year_interval_in_days
17
+ RELEVANT_DAYS_IN_YEAR * (@end_date.year - @start_date.year)
18
+ end
19
+
20
+ def month_interval_in_days
21
+ RELEVANT_DAY_IN_MONTH * (@end_date.month - @start_date.month)
22
+ end
23
+
24
+ def day_interval
25
+ end_date_days - start_date_days
26
+ # [@end_date.day, 30].min - [@start_date.day, 30].min
27
+ end
28
+
29
+ def end_date_days
30
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}"
31
+ end
32
+
33
+ def start_date_days
34
+ raise NotImplementedError, "#{self.class} has not implemented method '#{__method__}"
35
+ end
36
+
37
+ def days_in_month_for(date)
38
+ Date.new(date.year, date.month, -1).day
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module InterestDays
4
+ module Calculation
5
+ # ISDA 30 E 360 Convention calculation
6
+ class UsEom30360 < ThirtyThreesixtyBase
7
+ private
8
+
9
+ # D2 day
10
+ def end_date_days
11
+ if ((@start_date.month == 2 && @start_date.date == days_in_month_for(@start_date)) &&
12
+ (@end_date.month == 2 && @end_date.date == days_in_month_for(@end_date))) ||
13
+ (@end_date.day == 31 && @start_date.day >= 30)
14
+ RELEVANT_DAY_IN_MONTH
15
+ else
16
+ @end_date.day
17
+ end
18
+ end
19
+
20
+ # D1 day
21
+ def start_date_days
22
+ if (@start_date.month == 2 && @start_date.date == days_in_month_for(@start_date)) || @start_date.day == 31
23
+ RELEVANT_DAY_IN_MONTH
24
+ else
25
+ @start_date.day
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -23,7 +23,9 @@ module InterestDays
23
23
  @strategies ||= {
24
24
  isda_act_360: InterestDays::Calculation::IsdaAct360,
25
25
  isda_act_365: InterestDays::Calculation::IsdaAct365,
26
- isda_30_e_360: InterestDays::Calculation::Isda30e360
26
+ isda_30_e_360: InterestDays::Calculation::Isda30e360,
27
+ bond_basis_30_360: InterestDays::Calculation::Isda30e360,
28
+ us_eom_30_360: InterestDays::Calculation::UsEom30360
27
29
  }
28
30
  end
29
31
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module InterestDays
4
- VERSION = "0.1.1"
4
+ VERSION = "0.2.0"
5
5
  end
data/lib/interest_days.rb CHANGED
@@ -3,6 +3,8 @@
3
3
  require_relative "interest_days/version"
4
4
  require "interest_days/calculator"
5
5
  require "interest_days/calculation/base"
6
+ require "interest_days/calculation/thirty_threesixty_base"
7
+ require "interest_days/calculation/us_eom_30_360"
6
8
  require "interest_days/calculation/isda_act_360"
7
9
  require "interest_days/calculation/isda_act_365"
8
10
  require "interest_days/calculation/isda_30_e_360"
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: interest_days
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Eugen Mueller
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2021-10-04 00:00:00.000000000 Z
11
+ date: 2021-10-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rspec
@@ -77,6 +77,8 @@ files:
77
77
  - lib/interest_days/calculation/isda_30_e_360.rb
78
78
  - lib/interest_days/calculation/isda_act_360.rb
79
79
  - lib/interest_days/calculation/isda_act_365.rb
80
+ - lib/interest_days/calculation/thirty_threesixty_base.rb
81
+ - lib/interest_days/calculation/us_eom_30_360.rb
80
82
  - lib/interest_days/calculator.rb
81
83
  - lib/interest_days/version.rb
82
84
  homepage: https://github.com/eugenmueller/interest_days