sqa 0.0.14 → 0.0.17

Sign up to get free protection for your applications and to get access to all the features.
data/lib/sqa/errors.rb CHANGED
@@ -1,6 +1,30 @@
1
1
  # lib/sqa/errors.rb
2
2
 
3
- module SQA
4
- # raised when an API contract is broken
5
- class BadParameterError < ArgumentError; end
3
+ # raised when a method is still in TODO state
4
+ class ApiError < RuntimeError
5
+ def self.raise(why)
6
+ puts "="*64
7
+ puts "== API Error"
8
+ puts why
9
+ puts
10
+ puts "Callback trace:"
11
+ puts caller
12
+ puts "="*64
13
+ super
14
+ end
6
15
  end
16
+
17
+ # raised when a method is still in TODO state
18
+ class NotImplemented < RuntimeError
19
+ def self.raise
20
+ puts "="*64
21
+ puts "== Not Yet Implemented"
22
+ puts "Callback trace:"
23
+ puts caller
24
+ puts "="*64
25
+ super
26
+ end
27
+ end
28
+
29
+ # raised when an API contract is broken
30
+ class BadParameterError < ArgumentError; end
data/lib/sqa/init.rb ADDED
@@ -0,0 +1,51 @@
1
+ # sqa/lib/sqa/init.rb
2
+
3
+ module SQA
4
+ class << self
5
+ @@config = nil
6
+ @@av = ApiKeyManager::RateLimited.new(
7
+ api_keys: ENV['AV_API_KEYS'],
8
+ delay: true,
9
+ rate_count: ENV['AV_RATE_CNT'] || 5,
10
+ rate_period: ENV['AV_RATE_PER'] || 60
11
+ )
12
+
13
+ # Initializes the SQA modules
14
+ # returns the configuration
15
+ #
16
+ def init(argv=ARGV)
17
+ if argv.is_a? String
18
+ argv = argv.split()
19
+ end
20
+
21
+
22
+ # Ran at SQA::Config elaboration time
23
+ # @@config = Config.new
24
+
25
+ if defined? CLI
26
+ CLI.run(argv)
27
+ else
28
+ # There are no real command line parameters
29
+ # because the sqa gem is being required within
30
+ # the context of a larger program.
31
+ end
32
+
33
+ config.data_dir = homify(config.data_dir)
34
+
35
+ config
36
+ end
37
+
38
+ def av() = @@av
39
+
40
+ def debug?() = @@config.debug?
41
+ def verbose?() = @@config.verbose?
42
+
43
+ def homify(filepath) = filepath.gsub(/^~/, Nenv.home)
44
+ def data_dir() = Pathname.new(config.data_dir)
45
+ def config() = @@config
46
+
47
+ def config=(an_object)
48
+ @@config = an_object
49
+ end
50
+ end
51
+ end
data/lib/sqa/stock.rb CHANGED
@@ -1,91 +1,148 @@
1
1
  # lib/sqa/stock.rb
2
2
 
3
- require 'active_support/core_ext/string' # for String#underscore
4
- require 'hashie' # for Hashie::Mash
5
-
6
3
 
7
4
  # SMELL: SQA::Stock is now pretty coupled to the Alpha Vantage
8
5
  # API service. Should that stuff be extracted into a
9
6
  # separate class and injected by the requiring program?
10
7
 
11
8
  class SQA::Stock
9
+ extend Forwardable
10
+
12
11
  CONNECTION = Faraday.new(url: "https://www.alphavantage.co")
13
12
 
14
- attr_accessor :company_name
15
- attr_accessor :df # The DataFrane
16
- attr_accessor :ticker
17
- attr_accessor :type # type of data store (default is CSV)
18
- attr_accessor :indicators
13
+ attr_accessor :data # General Info -- SQA::DataFrame::Data
14
+ attr_accessor :df # Historical Prices -- SQA::DataFrame::Data
15
+
16
+ attr_accessor :klass # class of historical and current prices
17
+ attr_accessor :transformers # procs for changing column values from String to Numeric
19
18
 
20
19
  def initialize(
21
20
  ticker:,
22
- source: :alpha_vantage,
23
- type: :csv
21
+ source: :alpha_vantage
24
22
  )
23
+
24
+ @ticker = ticker.downcase
25
+ @source = source
26
+
25
27
  raise "Invalid Ticker #{ticker}" unless SQA::Ticker.valid?(ticker)
26
28
 
27
- # TODO: Change API on lookup to return array instead of hash
28
- # Could this also incorporate the validation process to
29
- # save an additiona hash lookup?
29
+ @data_path = SQA.data_dir + "#{@ticker}.json"
30
+ @df_path = SQA.data_dir + "#{@ticker}.csv"
30
31
 
31
- entry = SQA::Ticker.lookup(ticker)
32
+ @klass = "SQA::DataFrame::#{@source.to_s.camelize}".constantize
33
+ @transformers = "SQA::DataFrame::#{@source.to_s.camelize}::TRANSFORMERS".constantize
32
34
 
33
- @ticker = ticker.downcase
34
- @company_name = entry[:name]
35
- @exchange = entry[:exchange]
36
- @klass = "SQA::DataFrame::#{source.to_s.camelize}".constantize
37
- @type = type
38
- @indicators = OpenStruct.new
35
+ if @data_path.exist?
36
+ load
37
+ else
38
+ create
39
+ update
40
+ save
41
+ end
39
42
 
40
43
  update_the_dataframe
41
44
  end
42
45
 
43
46
 
44
- def update_the_dataframe
45
- df1 = @klass.load(@ticker, type)
46
- df2 = @klass.recent(@ticker)
47
+ def load
48
+ @data = SQA::DataFrame::Data.new(
49
+ JSON.parse(@data_path.read)
50
+ )
51
+ end
52
+
53
+
54
+ def create
55
+ @data =
56
+ SQA::DataFrame::Data.new(
57
+ {
58
+ ticker: @ticker,
59
+ source: @source,
60
+ indicators: { xyzzy: "Magic" },
61
+ }
62
+ )
63
+ end
64
+
65
+
66
+ def update
67
+ merge_overview
68
+ end
69
+
70
+
71
+ def save
72
+ @data_path.write @data.to_json
73
+ end
74
+
75
+
76
+ def_delegator :@data, :ticker, :ticker
77
+ def_delegator :@data, :name, :name
78
+ def_delegator :@data, :exchange, :exchange
79
+ def_delegator :@data, :source, :source
80
+ def_delegator :@data, :indicators, :indicators
81
+ def_delegator :@data, :indicators=, :indicators=
82
+ def_delegator :@data, :overview, :overview
47
83
 
48
- df1_nrows = df1.nrows
49
- @df = @klass.append(df1, df2)
50
84
 
51
- if @df.nrows > df1_nrows
52
- @df.send("to_#{@type}", SQA.data_dir + "#{ticker}.csv")
85
+
86
+ def update_the_dataframe
87
+ if @df_path.exist?
88
+ @df = SQA::DataFrame.load(
89
+ source: @df_path,
90
+ transformers: @transformers
91
+ )
92
+ else
93
+ @df = klass.recent(@ticker, full: true)
94
+ @df.to_csv(@df_path)
95
+ return
53
96
  end
54
97
 
55
- # Adding a ticker vector in case I want to do
56
- # some multi-stock analysis in the same data frame.
57
- # For example to see how one stock coorelates with another.
58
- @df[:ticker] = @ticker
98
+ from_date = Date.parse(@df.timestamp.last) + 1
99
+ df2 = klass.recent(@ticker, from_date: from_date)
100
+
101
+ return if df2.nil? # CSV file is up to date.
102
+
103
+ df_nrows = @df.nrows
104
+ @df.append(df2)
105
+
106
+ if @df.nrows > df_nrows
107
+ @df.to_csv(file_path)
108
+ end
59
109
  end
60
110
 
111
+
61
112
  def to_s
62
113
  "#{ticker} with #{@df.size} data points from #{@df.timestamp.first} to #{@df.timestamp.last}"
63
114
  end
115
+ alias_method :inspect, :to_s
64
116
 
65
- # TODO: Turn this into a class Stock::Overview
66
- # which is a sub-class of Hashie::Dash
67
- def overview
68
- return @overview unless @overview.nil?
69
117
 
118
+ def merge_overview
70
119
  temp = JSON.parse(
71
- CONNECTION.get("/query?function=OVERVIEW&symbol=#{@ticker.upcase}&apikey=#{Nenv.av_api_key}")
120
+ CONNECTION.get("/query?function=OVERVIEW&symbol=#{ticker.upcase}&apikey=#{SQA.av.key}")
72
121
  .to_hash[:body]
73
122
  )
74
123
 
124
+ if temp.has_key? "Information"
125
+ ApiError.raise(temp["Information"])
126
+ end
127
+
75
128
  # TODO: CamelCase hash keys look common in Alpha Vantage
76
129
  # JSON; look at making a special Hashie-based class
77
130
  # to convert the keys to normal Ruby standards.
78
131
 
79
132
  temp2 = {}
80
133
 
81
- string_values = %w[ address asset_type cik country currency description dividend_date ex_dividend_date exchange fiscal_year_end industry latest_quarter name sector symbol ]
134
+ string_values = %w[ address asset_type cik country currency
135
+ description dividend_date ex_dividend_date
136
+ exchange fiscal_year_end industry latest_quarter
137
+ name sector symbol
138
+ ]
82
139
 
83
140
  temp.keys.each do |k|
84
141
  new_k = k.underscore
85
142
  temp2[new_k] = string_values.include?(new_k) ? temp[k] : temp[k].to_f
86
143
  end
87
144
 
88
- @overview = Hashie::Mash.new temp2
145
+ @data.overview = temp2
89
146
  end
90
147
 
91
148
 
@@ -101,13 +158,13 @@ class SQA::Stock
101
158
  def top
102
159
  return @@top unless @@top.nil?
103
160
 
104
- mash = Hashie::Mash.new(
105
- JSON.parse(
106
- CONNECTION.get(
107
- "/query?function=TOP_GAINERS_LOSERS&apikey=#{Nenv.av_api_key}"
108
- ).to_hash[:body]
109
- )
110
- )
161
+ a_hash = JSON.parse(
162
+ CONNECTION.get(
163
+ "/query?function=TOP_GAINERS_LOSERS&apikey=#{SQA.av.key}"
164
+ ).to_hash[:body]
165
+ )
166
+
167
+ mash = Hashie::Mash.new(a_hash)
111
168
 
112
169
  keys = mash.top_gainers.first.keys
113
170
 
data/lib/sqa/strategy.rb CHANGED
@@ -8,7 +8,7 @@ class SQA::Strategy
8
8
  end
9
9
 
10
10
  def add(a_strategy)
11
- raise SQA::BadParameterError unless [Class, Method].include? a_strategy.class
11
+ raise BadParameterError unless [Class, Method].include? a_strategy.class
12
12
 
13
13
  a_proc = if Class == a_strategy.class
14
14
  a_strategy.method(:trade)
data/lib/sqa/version.rb CHANGED
@@ -1,10 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'sem_version'
4
- require 'sem_version/core_ext'
5
-
6
3
  module SQA
7
- VERSION = "0.0.14"
4
+ VERSION = "0.0.17"
8
5
 
9
6
  class << self
10
7
  def version
data/lib/sqa/web.rb CHANGED
@@ -1,6 +1,6 @@
1
1
  # lib/sqa/command/web.rb
2
2
 
3
- require 'tty-option'
3
+ # require 'tty-option'
4
4
 
5
5
 
6
6
  module SQA
data/lib/sqa.rb CHANGED
@@ -1,77 +1,56 @@
1
1
  # lib/sqa.rb
2
2
  # frozen_string_literal: true
3
3
 
4
- require 'active_support'
5
- require 'active_support/core_ext/string'
6
- require 'amazing_print'
7
- require 'daru'
8
- require 'date'
9
- require 'descriptive_statistics'
10
- require 'nenv'
11
- require 'pathname'
4
+ # TODO: Create a new gem for the dumbstockapi website
12
5
 
13
- require_relative "sqa/version"
14
- require_relative "sqa/errors"
6
+ #############################################
7
+ ## Standard Libraries
15
8
 
9
+ require 'date'
10
+ require 'pathname'
16
11
 
17
12
  unless defined?(HOME)
18
- HOME = Pathname.new(Nenv.home)
13
+ HOME = Pathname.new(ENV['HOME'])
19
14
  end
20
15
 
16
+ #############################################
17
+ ## Additional Libraries
21
18
 
22
- module SQA
23
- class << self
24
- @@config = nil
25
-
26
- # Initializes the SQA modules
27
- # returns the configuration
28
- #
29
- def init(argv=ARGV)
30
- if argv.is_a? String
31
- argv = argv.split()
32
- end
33
-
34
-
35
- # Ran at SQA::Config elaboration time
36
- # @@config = Config.new
37
-
38
- if defined? CLI
39
- CLI.run(argv)
40
- else
41
- # There are no real command line parameters
42
- # because the sqa gem is being required within
43
- # the context of a larger program.
44
- end
45
-
46
- config.data_dir = homify(config.data_dir)
19
+ require 'active_support/core_ext/string'
20
+ require 'alphavantage' # TODO: add rate limiter to it; ** PR submitted! **
21
+ require 'api_key_manager'
22
+ require 'amazing_print'
23
+ require 'descriptive_statistics'
24
+ require 'faraday'
25
+ require 'hashie'
26
+ require 'nenv'
27
+ require 'sem_version'
28
+ require 'sem_version/core_ext'
29
+ require 'tty-option'
30
+ require 'tty-table'
47
31
 
48
- Daru.lazy_update = config.lazy_update
49
- Daru.plotting_library = config.plotting_library
50
32
 
51
- config
52
- end
33
+ #############################################
34
+ ## SQA soecufuc code
53
35
 
54
- def debug?() = @@config.debug?
55
- def verbose?() = @@config.verbose?
36
+ require_relative "sqa/version"
37
+ require_relative "sqa/errors"
56
38
 
57
- def homify(filepath) = filepath.gsub(/^~/, Nenv.home)
58
- def data_dir() = Pathname.new(config.data_dir)
59
- def config() = @@config
39
+ require_relative 'sqa/init.rb'
60
40
 
61
- def config=(an_object)
62
- @@config = an_object
63
- end
64
- end
65
- end
66
41
 
67
- # require_relative "patches/daru" # TODO: extract Daru::DataFrame in new gem sqa-data_frame
42
+ # TODO: Some of these components make direct calls to the
43
+ # Alpha Vantage API. Convert them to use the
44
+ # alphavantage gem.
68
45
 
69
46
  require_relative "sqa/config"
70
- require_relative "sqa/constants"
71
- require_relative "sqa/data_frame"
47
+ require_relative "sqa/constants" # SMELL: more app than gem
48
+ require_relative "sqa/data_frame" # TODO: drop the daru gem
72
49
  require_relative "sqa/indicator"
73
50
  require_relative "sqa/portfolio"
74
51
  require_relative "sqa/strategy"
75
52
  require_relative "sqa/stock"
76
53
  require_relative "sqa/ticker"
77
- require_relative "sqa/trade"
54
+ require_relative "sqa/trade" # SMELL: Not really a core gem; more of an application thing
55
+
56
+
metadata CHANGED
@@ -1,45 +1,31 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sqa
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.14
4
+ version: 0.0.17
5
5
  platform: ruby
6
6
  authors:
7
7
  - Dewayne VanHoozer
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-09-23 00:00:00.000000000 Z
11
+ date: 2023-10-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ">="
18
- - !ruby/object:Gem::Version
19
- version: '0'
20
- type: :runtime
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: daru
29
- requirement: !ruby/object:Gem::Requirement
30
- requirements:
31
- - - ">="
17
+ - - '='
32
18
  - !ruby/object:Gem::Version
33
- version: '0'
19
+ version: 7.0.6
34
20
  type: :runtime
35
21
  prerelease: false
36
22
  version_requirements: !ruby/object:Gem::Requirement
37
23
  requirements:
38
- - - ">="
24
+ - - '='
39
25
  - !ruby/object:Gem::Version
40
- version: '0'
26
+ version: 7.0.6
41
27
  - !ruby/object:Gem::Dependency
42
- name: descriptive_statistics
28
+ name: alphavantage
43
29
  requirement: !ruby/object:Gem::Requirement
44
30
  requirements:
45
31
  - - ">="
@@ -53,7 +39,7 @@ dependencies:
53
39
  - !ruby/object:Gem::Version
54
40
  version: '0'
55
41
  - !ruby/object:Gem::Dependency
56
- name: hashie
42
+ name: api_key_manager
57
43
  requirement: !ruby/object:Gem::Requirement
58
44
  requirements:
59
45
  - - ">="
@@ -67,35 +53,7 @@ dependencies:
67
53
  - !ruby/object:Gem::Version
68
54
  version: '0'
69
55
  - !ruby/object:Gem::Dependency
70
- name: nenv
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - ">="
74
- - !ruby/object:Gem::Version
75
- version: '0'
76
- type: :runtime
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - ">="
81
- - !ruby/object:Gem::Version
82
- version: '0'
83
- - !ruby/object:Gem::Dependency
84
- name: tty-logger
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - ">="
88
- - !ruby/object:Gem::Version
89
- version: '0'
90
- type: :runtime
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - ">="
95
- - !ruby/object:Gem::Version
96
- version: '0'
97
- - !ruby/object:Gem::Dependency
98
- name: tty-markdown
56
+ name: descriptive_statistics
99
57
  requirement: !ruby/object:Gem::Requirement
100
58
  requirements:
101
59
  - - ">="
@@ -109,7 +67,7 @@ dependencies:
109
67
  - !ruby/object:Gem::Version
110
68
  version: '0'
111
69
  - !ruby/object:Gem::Dependency
112
- name: tty-option
70
+ name: faraday
113
71
  requirement: !ruby/object:Gem::Requirement
114
72
  requirements:
115
73
  - - ">="
@@ -123,21 +81,21 @@ dependencies:
123
81
  - !ruby/object:Gem::Version
124
82
  version: '0'
125
83
  - !ruby/object:Gem::Dependency
126
- name: tty-progressbar
84
+ name: hashie
127
85
  requirement: !ruby/object:Gem::Requirement
128
86
  requirements:
129
- - - ">="
87
+ - - "~>"
130
88
  - !ruby/object:Gem::Version
131
- version: '0'
89
+ version: 4.1.0
132
90
  type: :runtime
133
91
  prerelease: false
134
92
  version_requirements: !ruby/object:Gem::Requirement
135
93
  requirements:
136
- - - ">="
94
+ - - "~>"
137
95
  - !ruby/object:Gem::Version
138
- version: '0'
96
+ version: 4.1.0
139
97
  - !ruby/object:Gem::Dependency
140
- name: tty-prompt
98
+ name: nenv
141
99
  requirement: !ruby/object:Gem::Requirement
142
100
  requirements:
143
101
  - - ">="
@@ -151,7 +109,7 @@ dependencies:
151
109
  - !ruby/object:Gem::Version
152
110
  version: '0'
153
111
  - !ruby/object:Gem::Dependency
154
- name: tty-reader
112
+ name: sem_version
155
113
  requirement: !ruby/object:Gem::Requirement
156
114
  requirements:
157
115
  - - ">="
@@ -165,7 +123,7 @@ dependencies:
165
123
  - !ruby/object:Gem::Version
166
124
  version: '0'
167
125
  - !ruby/object:Gem::Dependency
168
- name: tty-spinner
126
+ name: tty-option
169
127
  requirement: !ruby/object:Gem::Requirement
170
128
  requirements:
171
129
  - - ">="
@@ -282,7 +240,8 @@ files:
282
240
  - checksums/sqa-0.0.11.gem.sha512
283
241
  - checksums/sqa-0.0.12.gem.sha512
284
242
  - checksums/sqa-0.0.13.gem.sha512
285
- - checksums/sqa-0.0.14.gem.sha512
243
+ - checksums/sqa-0.0.15.gem.sha512
244
+ - checksums/sqa-0.0.17.gem.sha512
286
245
  - checksums/sqa-0.0.2.gem.sha512
287
246
  - checksums/sqa-0.0.3.gem.sha512
288
247
  - checksums/sqa-0.0.4.gem.sha512
@@ -293,6 +252,7 @@ files:
293
252
  - checksums/sqa-0.0.9.gem.sha512
294
253
  - docs/.gitignore
295
254
  - docs/README.md
255
+ - docs/alpha_vantage_technical_indicators.md
296
256
  - docs/average_true_range.md
297
257
  - docs/bollinger_bands.md
298
258
  - docs/candlestick_pattern_recognizer.md
@@ -316,14 +276,6 @@ files:
316
276
  - docs/stochastic_oscillator.md
317
277
  - docs/strategy.md
318
278
  - docs/true_range.md
319
- - lib/patches/daru.rb
320
- - lib/patches/daru/category.rb
321
- - lib/patches/daru/data_frame.rb
322
- - lib/patches/daru/plotting/svg-graph.rb
323
- - lib/patches/daru/plotting/svg-graph/category.rb
324
- - lib/patches/daru/plotting/svg-graph/dataframe.rb
325
- - lib/patches/daru/plotting/svg-graph/vector.rb
326
- - lib/patches/daru/vector.rb
327
279
  - lib/sqa.rb
328
280
  - lib/sqa/activity.rb
329
281
  - lib/sqa/analysis.rb
@@ -356,6 +308,7 @@ files:
356
308
  - lib/sqa/indicator/simple_moving_average_trend.rb
357
309
  - lib/sqa/indicator/stochastic_oscillator.rb
358
310
  - lib/sqa/indicator/true_range.rb
311
+ - lib/sqa/init.rb
359
312
  - lib/sqa/portfolio.rb
360
313
  - lib/sqa/stock.rb
361
314
  - lib/sqa/strategy.rb
@@ -379,7 +332,8 @@ licenses:
379
332
  metadata:
380
333
  allowed_push_host: https://rubygems.org
381
334
  homepage_uri: https://github.com/MadBomber/sqa
382
- source_code_uri: https://github.com/MadBomber/sta
335
+ source_code_uri: https://github.com/MadBomber/sqa
336
+ changelog_uri: https://github.com/MadBomber/sqa
383
337
  post_install_message:
384
338
  rdoc_options: []
385
339
  require_paths:
@@ -395,7 +349,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
395
349
  - !ruby/object:Gem::Version
396
350
  version: '0'
397
351
  requirements: []
398
- rubygems_version: 3.4.19
352
+ rubygems_version: 3.4.20
399
353
  signing_key:
400
354
  specification_version: 4
401
355
  summary: sqa - Stock Qualitative Analysis
@@ -1 +0,0 @@
1
- c5eea4fb74e6ab7b7b1715a81598585ec540a3eb1e9b902ca339ff0a2ba9cc7624ae3f43e00b5fbbad1d3d510ed938e8f91154c0bee2e14d6503564b1b0ccfb1
@@ -1,19 +0,0 @@
1
- # lib/patches/daru/category.rb
2
-
3
- module Daru
4
- module Category
5
-
6
- def plotting_lig lib
7
- if :svg_graph = lib
8
- @plotting_library = lib
9
- if Daru.send("has_#{lib}?".to_sym)
10
- extend Module.const_get(
11
- "Daru::Plotting::Category::#{lib.to_s.capitalize}Library"
12
- )
13
- end
14
- else
15
- super
16
- end
17
- end
18
- end
19
- end
@@ -1,19 +0,0 @@
1
- # lib/patches/daru/data_frame.rb
2
-
3
- module Daru
4
- module DataFrame
5
-
6
- def plotting_lig lib
7
- if :svg_graph = lib
8
- @plotting_library = lib
9
- if Daru.send("has_#{lib}?".to_sym)
10
- extend Module.const_get(
11
- "Daru::Plotting::DataFrame::#{lib.to_s.capitalize}Library"
12
- )
13
- end
14
- else
15
- super
16
- end
17
- end
18
- end
19
- end