roi_calculator 0.1.6 → 2.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 +5 -5
- data/.ruby-version +1 -1
- data/bitbucket-pipelines.yml +21 -0
- data/lib/roi.rb +6 -4
- data/lib/roi/{financial_result.rb → gross_profit.rb} +21 -17
- data/lib/roi/rentability.rb +27 -27
- data/lib/roi/rentability_line.rb +10 -16
- data/lib/roi/rentability_periods.rb +28 -16
- data/lib/roi/version.rb +3 -1
- data/roi_calculator.gemspec +17 -15
- metadata +15 -16
- data/.ruby-gemset +0 -1
- data/circle.yml +0 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 04b1f92abea56c262e66f32551040c1ec5e6bed8e42ae60cf1867d98b36fa7e0
|
4
|
+
data.tar.gz: 1d6d9209fe7152a599be99b6effa158696692d0faefd0e089a2b8352d478eed5
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3ea5605bdbcdee6a856dc0c900db73c26d403ee2f75074fec8599abb481625021aa14c7bc1301a83f50956427677ce5547744bb6a2dc576615bf8058df1e814
|
7
|
+
data.tar.gz: 117182e61665f1550ca3676933f2ba97358eae87425ceb0cf0f2affbb9b21789ec95e5277f2234614c4eb21032f3af2a74953ae547ef8193c2a77f37cb71e7df
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
ruby-2.
|
1
|
+
ruby-2.5.0
|
@@ -0,0 +1,21 @@
|
|
1
|
+
image: ruby:2.5.0
|
2
|
+
|
3
|
+
pipelines:
|
4
|
+
default:
|
5
|
+
- step:
|
6
|
+
script:
|
7
|
+
- git archive --remote=git@bitbucket.org:guideinvestimentos/rails_defaults.git HEAD .rubocop.yml | tar -x
|
8
|
+
- bundle install
|
9
|
+
- gem install rubocop
|
10
|
+
- rspec -fdoc
|
11
|
+
- rubocop .
|
12
|
+
|
13
|
+
branches:
|
14
|
+
master:
|
15
|
+
- step:
|
16
|
+
script:
|
17
|
+
- gem build roi_calculator.gemspec
|
18
|
+
- mkdir -p ~/.gem
|
19
|
+
- curl -u $RUBYGEMS_USERNAME:$RUBYGEMS_PASSWORD https://rubygems.org/api/v1/api_key.yaml > ~/.gem/credentials
|
20
|
+
- chmod 0600 ~/.gem/credentials
|
21
|
+
- gem push $(ls *.gem)
|
data/lib/roi.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'roi/rentability'
|
4
|
+
require 'roi/rentability_line'
|
5
|
+
require 'roi/rentability_periods'
|
6
|
+
require 'roi/gross_profit'
|
5
7
|
|
6
8
|
module ROI
|
7
9
|
end
|
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'work_day'
|
4
|
+
require 'active_support'
|
5
|
+
require 'active_support/core_ext/date'
|
4
6
|
|
5
7
|
module ROI
|
6
|
-
class
|
8
|
+
class GrossProfit
|
7
9
|
attr_reader :start_date, :end_date, :rentabilities
|
8
10
|
|
9
11
|
def initialize(rentabilities, start_date, end_date)
|
@@ -14,7 +16,7 @@ module ROI
|
|
14
16
|
|
15
17
|
def current_month
|
16
18
|
scope_start = WorkDay.next_after(end_date.beginning_of_month, 0)
|
17
|
-
|
19
|
+
format_gross_profit(scope_start, end_date)
|
18
20
|
end
|
19
21
|
|
20
22
|
def months(amount)
|
@@ -24,41 +26,43 @@ module ROI
|
|
24
26
|
|
25
27
|
def current_year
|
26
28
|
scope_start = WorkDay.next_after(end_date.beginning_of_year, 0)
|
27
|
-
|
29
|
+
format_gross_profit(scope_start, end_date)
|
28
30
|
end
|
29
31
|
|
30
32
|
def years_ago(amount)
|
31
33
|
scope_end = (end_date - amount.year).end_of_year
|
32
34
|
scope_start = scope_end.beginning_of_year
|
33
|
-
|
35
|
+
format_gross_profit(scope_start, scope_end)
|
34
36
|
end
|
35
37
|
|
36
38
|
def portfolio
|
37
|
-
|
39
|
+
format_gross_profit(start_date, end_date)
|
38
40
|
end
|
39
41
|
|
40
42
|
private
|
43
|
+
|
41
44
|
def scoped_rentabilities(scope_start, scope_end)
|
42
45
|
rentabilities.values.select.each do |line|
|
43
|
-
line.
|
46
|
+
line.reference_date.between?(scope_start, scope_end)
|
44
47
|
end
|
45
48
|
end
|
46
49
|
|
47
|
-
def
|
50
|
+
def format_gross_profit(scope_start, scope_end)
|
48
51
|
return unless scope_start && scope_end
|
52
|
+
|
49
53
|
total = scoped_rentabilities(scope_start, scope_end).sum do |line|
|
50
|
-
line.try(:
|
54
|
+
line.try(:gross_profit) || 0
|
51
55
|
end.round(2)
|
52
|
-
total
|
56
|
+
total.zero? ? nil : total
|
53
57
|
end
|
54
58
|
|
55
59
|
def check_gaps_and_format(scope_start, scope_end)
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
format_financial(scope_start, scope_end)
|
60
|
+
return unless scope_start >= start_date
|
61
|
+
|
62
|
+
scoped_rentabilities(scope_start, scope_end).each do |line|
|
63
|
+
return nil if line.try(:have_position) == false
|
61
64
|
end
|
65
|
+
format_gross_profit(scope_start, scope_end)
|
62
66
|
end
|
63
67
|
end
|
64
68
|
end
|
data/lib/roi/rentability.rb
CHANGED
@@ -1,9 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'memoist'
|
4
|
+
require 'roi/gross_profit'
|
5
|
+
require 'roi/rentability_periods'
|
6
|
+
require 'math_util'
|
7
|
+
require 'active_support'
|
8
|
+
require 'active_support/core_ext'
|
7
9
|
|
8
10
|
module ROI
|
9
11
|
class Rentability
|
@@ -20,20 +22,20 @@ module ROI
|
|
20
22
|
post_initialize(options)
|
21
23
|
end
|
22
24
|
|
23
|
-
def post_initialize(options)
|
24
|
-
end
|
25
|
+
def post_initialize(options); end
|
25
26
|
|
26
27
|
def calculate
|
27
28
|
parse_rentabilities
|
28
|
-
if @rentabilities.count
|
29
|
+
if @rentabilities.count.positive?
|
29
30
|
dates = @rentabilities.keys
|
30
|
-
@start_date
|
31
|
+
@start_date = dates[0]
|
32
|
+
@end_date = dates[-1]
|
31
33
|
end
|
32
34
|
self
|
33
35
|
end
|
34
36
|
|
35
|
-
def
|
36
|
-
|
37
|
+
def gross_profit
|
38
|
+
GrossProfit.new(rentabilities, start_date, end_date)
|
37
39
|
end
|
38
40
|
|
39
41
|
def dates_with_position
|
@@ -45,15 +47,14 @@ module ROI
|
|
45
47
|
end_date ||= @end_date
|
46
48
|
|
47
49
|
filtered = @rentabilities.values.select do |val|
|
48
|
-
val.
|
50
|
+
val.reference_date.between?(start_date, end_date)
|
49
51
|
end
|
50
52
|
filtered.map(&:rentability).compact
|
51
53
|
end
|
52
54
|
|
53
55
|
def volatility(months_ago = nil)
|
54
|
-
|
55
|
-
|
56
|
-
(volatility_in_window(nil, _start).first || [])[1]
|
56
|
+
start = (end_date - months_ago.months + 1.month).beginning_of_month if months_ago
|
57
|
+
(volatility_in_window(nil, start).first || [])[1]
|
57
58
|
end
|
58
59
|
|
59
60
|
def volatility_in_window(days = nil, start_date = nil)
|
@@ -62,23 +63,21 @@ module ROI
|
|
62
63
|
|
63
64
|
0.upto(filtered.size - days).map do |low|
|
64
65
|
series = filtered.slice(low, days + 1)
|
65
|
-
|
66
|
-
|
67
|
-
[date,
|
66
|
+
date =
|
67
|
+
dates_with_position.fetch(low + days) { dates_with_position.last }
|
68
|
+
[date, MathUtil.volatility(series)] if date
|
68
69
|
end
|
69
70
|
end
|
70
71
|
|
71
72
|
def to_a
|
72
73
|
dates_with_position.map do |date|
|
73
|
-
if @rentabilities[date]
|
74
|
-
[date.to_time.to_i, @rentabilities[date].share]
|
75
|
-
end
|
74
|
+
[date.strftime('%Y-%m-%d'), @rentabilities[date].quota - 1] if @rentabilities[date]
|
76
75
|
end.compact
|
77
76
|
end
|
78
77
|
|
79
78
|
protected
|
80
|
-
|
81
|
-
end
|
79
|
+
|
80
|
+
def before_parse_rentabilities; end
|
82
81
|
|
83
82
|
def work_days
|
84
83
|
start_date && end_date ? WorkDay.between(start_date, end_date) : []
|
@@ -86,6 +85,7 @@ module ROI
|
|
86
85
|
memoize :work_days
|
87
86
|
|
88
87
|
private
|
88
|
+
|
89
89
|
def parse_rentabilities
|
90
90
|
@rentabilities = {}
|
91
91
|
before_parse_rentabilities
|
@@ -99,10 +99,10 @@ module ROI
|
|
99
99
|
last_value = rentabilities_source(last_date)
|
100
100
|
return rentabilities unless this_value && last_value
|
101
101
|
|
102
|
-
|
102
|
+
last_quota = rentabilities[last_date].try(:quota) || 1
|
103
103
|
rentability = (this_value / last_value - 1).round(8)
|
104
|
-
|
105
|
-
line = RentabilityLine.new(this_date, rentability,
|
104
|
+
new_quota = (last_quota * (1 + rentability)).round(8)
|
105
|
+
line = RentabilityLine.new(this_date, rentability, new_quota, true)
|
106
106
|
after_parse(this_date, last_date, rentabilities, line)
|
107
107
|
end
|
108
108
|
end
|
data/lib/roi/rentability_line.rb
CHANGED
@@ -1,21 +1,15 @@
|
|
1
|
-
|
2
|
-
class RentabilityLine < Struct.new(
|
3
|
-
:date, :rentability, :daily_result, :share, :have_position, :total_balance)
|
1
|
+
# frozen_string_literal: true
|
4
2
|
|
5
|
-
|
6
|
-
|
7
|
-
|
3
|
+
module ROI
|
4
|
+
class RentabilityLine
|
5
|
+
attr_reader :reference_date, :rentability,
|
6
|
+
:gross_profit, :quota, :have_position
|
8
7
|
|
9
|
-
def
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
line.rentability = line.daily_result / last_balance
|
15
|
-
line.share = (last_share * (1 + line.rentability)).round(8)
|
16
|
-
line.have_position = true
|
17
|
-
end
|
18
|
-
line
|
8
|
+
def initialize(reference_date, rentability, quota, have_position)
|
9
|
+
@reference_date = reference_date
|
10
|
+
@rentability = rentability
|
11
|
+
@quota = quota
|
12
|
+
@have_position = have_position
|
19
13
|
end
|
20
14
|
end
|
21
15
|
end
|
@@ -1,4 +1,6 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'work_day'
|
2
4
|
|
3
5
|
module ROI
|
4
6
|
module RentabilityPeriods
|
@@ -13,8 +15,9 @@ module ROI
|
|
13
15
|
end
|
14
16
|
|
15
17
|
def months(amount, date = end_date)
|
16
|
-
scoped_start =
|
17
|
-
|
18
|
+
scoped_start =
|
19
|
+
WorkDay.last_until((date - (amount + 1).month).end_of_month)
|
20
|
+
scoped_end = adjust_end_date((date - 1.month).end_of_month)
|
18
21
|
check_gaps_and_format(scoped_start, scoped_end)
|
19
22
|
end
|
20
23
|
|
@@ -34,32 +37,41 @@ module ROI
|
|
34
37
|
end
|
35
38
|
|
36
39
|
private
|
40
|
+
|
37
41
|
def adjust_start_date(date)
|
38
42
|
[start_date, date].compact.max
|
39
43
|
end
|
40
44
|
|
41
45
|
def adjust_end_date(date)
|
42
|
-
|
43
|
-
|
46
|
+
scoped_end =
|
47
|
+
if date.strftime('%Y-%m') == end_date.strftime('%Y-%m')
|
48
|
+
end_date
|
49
|
+
else
|
50
|
+
date.end_of_month
|
51
|
+
end
|
52
|
+
WorkDay.last_until(scoped_end)
|
44
53
|
end
|
45
54
|
|
46
55
|
def format(start_date, end_date)
|
47
56
|
scoped_start, scoped_end = rentabilities.values_at(start_date, end_date)
|
48
|
-
if scoped_start && scoped_end
|
49
|
-
((scoped_end.share / scoped_start.share - 1) * 100).round(8)
|
50
|
-
end
|
57
|
+
((scoped_end.quota / scoped_start.quota - 1) * 100).round(8) if scoped_start && scoped_end
|
51
58
|
end
|
52
59
|
|
53
60
|
def check_gaps_and_format(scoped_start, scoped_end)
|
54
|
-
|
55
|
-
return unless
|
56
|
-
if skip_on_gap
|
57
|
-
|
58
|
-
return if line.date.between?(_start.date, _end.date) &&
|
59
|
-
!line.have_position
|
60
|
-
end
|
61
|
-
end
|
61
|
+
local_start, local_end = rentabilities.values_at(scoped_start, scoped_end)
|
62
|
+
return unless local_start && local_end
|
63
|
+
return if skip_on_gap && gap?(local_start, local_end)
|
64
|
+
|
62
65
|
format(scoped_start, scoped_end)
|
63
66
|
end
|
67
|
+
|
68
|
+
def gap?(start_date, end_date)
|
69
|
+
gap = rentabilities.values.detect do |line|
|
70
|
+
line.reference_date.between?(
|
71
|
+
start_date.reference_date, end_date.reference_date
|
72
|
+
) && !line.have_position
|
73
|
+
end
|
74
|
+
!gap.nil?
|
75
|
+
end
|
64
76
|
end
|
65
77
|
end
|
data/lib/roi/version.rb
CHANGED
data/roi_calculator.gemspec
CHANGED
@@ -1,25 +1,27 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'roi/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name
|
8
|
-
spec.version
|
9
|
-
spec.authors
|
10
|
-
spec.email
|
8
|
+
spec.name = 'roi_calculator'
|
9
|
+
spec.version = ROI::VERSION
|
10
|
+
spec.authors = ['Adriano Bacha']
|
11
|
+
spec.email = ['abacha@gmail.com']
|
11
12
|
|
12
|
-
spec.summary
|
13
|
-
spec.license
|
13
|
+
spec.summary = 'Rentability and Gross Profit Calculations'
|
14
|
+
spec.license = 'MIT'
|
14
15
|
|
15
|
-
spec.files
|
16
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
17
|
f.match(%r{^(test|spec|features)/})
|
17
18
|
end
|
18
|
-
spec.require_paths
|
19
|
+
spec.require_paths = ['lib']
|
20
|
+
spec.required_ruby_version = '>= 2.5.0'
|
19
21
|
|
20
|
-
spec.add_development_dependency
|
21
|
-
spec.add_development_dependency
|
22
|
-
spec.add_runtime_dependency
|
23
|
-
spec.add_runtime_dependency
|
24
|
-
spec.add_runtime_dependency
|
22
|
+
spec.add_development_dependency 'bundler', '~> 1.13'
|
23
|
+
spec.add_development_dependency 'rspec', '~> 3.0'
|
24
|
+
spec.add_runtime_dependency 'math_util', '~> 0.1.0'
|
25
|
+
spec.add_runtime_dependency 'memoist', '~> 0.15'
|
26
|
+
spec.add_runtime_dependency 'work_day', '~> 1.0.0'
|
25
27
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: roi_calculator
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version:
|
4
|
+
version: 2.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Adriano Bacha
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2020-12-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: bundler
|
@@ -39,47 +39,47 @@ dependencies:
|
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '3.0'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: math_util
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version:
|
47
|
+
version: 0.1.0
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version:
|
54
|
+
version: 0.1.0
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: memoist
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
59
|
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: 0.
|
61
|
+
version: '0.15'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: 0.
|
68
|
+
version: '0.15'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: work_day
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
73
|
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: 0.
|
75
|
+
version: 1.0.0
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 0.
|
82
|
+
version: 1.0.0
|
83
83
|
description:
|
84
84
|
email:
|
85
85
|
- abacha@gmail.com
|
@@ -89,16 +89,15 @@ extra_rdoc_files: []
|
|
89
89
|
files:
|
90
90
|
- ".gitignore"
|
91
91
|
- ".rspec"
|
92
|
-
- ".ruby-gemset"
|
93
92
|
- ".ruby-version"
|
94
93
|
- ".travis.yml"
|
95
94
|
- Gemfile
|
96
95
|
- Gemfile.lock
|
97
96
|
- LICENSE.txt
|
98
97
|
- README.md
|
99
|
-
-
|
98
|
+
- bitbucket-pipelines.yml
|
100
99
|
- lib/roi.rb
|
101
|
-
- lib/roi/
|
100
|
+
- lib/roi/gross_profit.rb
|
102
101
|
- lib/roi/rentability.rb
|
103
102
|
- lib/roi/rentability_line.rb
|
104
103
|
- lib/roi/rentability_periods.rb
|
@@ -116,7 +115,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
116
115
|
requirements:
|
117
116
|
- - ">="
|
118
117
|
- !ruby/object:Gem::Version
|
119
|
-
version:
|
118
|
+
version: 2.5.0
|
120
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
121
120
|
requirements:
|
122
121
|
- - ">="
|
@@ -124,8 +123,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
124
123
|
version: '0'
|
125
124
|
requirements: []
|
126
125
|
rubyforge_project:
|
127
|
-
rubygems_version: 2.
|
126
|
+
rubygems_version: 2.7.6
|
128
127
|
signing_key:
|
129
128
|
specification_version: 4
|
130
|
-
summary: Rentability and
|
129
|
+
summary: Rentability and Gross Profit Calculations
|
131
130
|
test_files: []
|
data/.ruby-gemset
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
bigbang_services
|
data/circle.yml
DELETED