cotcube-bardata 0.1.9.2 → 0.1.13

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: 42d2c651e2e0cc53cbd35ea0ea824e82828930bee04d1bce9a52edf9b70c54f1
4
- data.tar.gz: 388c35d25810c30a73136e66e0e204473dd2646f2ea776c23a476b8cb769afb7
3
+ metadata.gz: 6b1f66885f510fbe8be92a8e543f7206220db76940825862115c60be6892d5d4
4
+ data.tar.gz: a12e509a14c41cc17e31d95fca73d09ab09c342b029e973baf30377ebe8f1d6a
5
5
  SHA512:
6
- metadata.gz: 705ded304d33270f8133a5e297a807a56288b7a710ac12f6aa2896f4971c2302f6e5a3a9b229c8c513489abb32bbe3079e0f60bdf094756935f19a6d84d7d276
7
- data.tar.gz: e36f72ffc6dbf098a86b647932f8d881016477ebb74223b8db12f75f3e9c58f4962eef7da5992838c72538d1e18545f647b4df104554e70727ba45694b55de59
6
+ metadata.gz: dc53284daf85e21387ba1d7b24b3e2518be8dae3d49f6b2893e6aa6442e082516be12f76f23001ad3f04aee3e3ae5601ae7e747fd8451d5d9a437c7ac2b45976
7
+ data.tar.gz: 3b496b4e75e73feee1dbc08fd355572471ba78eb1b692c91e81dd3b1f515eab510cab0d22bc712cabab84cfe621a536e91a81e0925ce897e8d48c05770b0b015
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## 0.1.13 (April 07, 2021)
2
+ - daily: fixed const_caching in continuous
3
+ - trade_dates: FIXING call with HTTParty must send Agent Header
4
+ - helpers/get_id_set: added support for params given as Symbols (:NG instead of 'NG')
5
+
6
+ ## 0.1.12 (March 13, 2021)
7
+ - range_matrix: adapted to accept block for range provision; added params :days_only and :last_n
8
+ - minor fix on previous patch
9
+
10
+ ## 0.1.11 (March 07, 2021)
11
+ - daily.rb: added new technique 'caching in constants' to accelerate computation, also referring to continuous
12
+ - provide.rb: minor change, so disregarded contracts can be used in swapproximate
13
+
14
+ ## 0.1.10 (February 11, 2021)
15
+ - Daily.rb: Added measure parameters to continous_suite
16
+ - cached.rb: Minor fix in comparison
17
+
18
+ ## 0.1.9.3 (February 08, 2021)
19
+ - cached: minor change fixing problem to get yesterday in rth subsets
20
+
1
21
  ## 0.1.9.2 (February 07, 2021)
2
22
  - minor changes
3
23
  - daily#continuous_table: introducing debuglevel
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.9.2
1
+ 0.1.13
@@ -60,7 +60,7 @@ module Cotcube
60
60
  end
61
61
  end
62
62
  return result
63
- elsif File.mtime(file) + 1.day > File.mtime(quarters_file)
63
+ elsif File.mtime(file) - Time.now.beginning_of_day >= 0
64
64
  puts "CACHE #{File.mtime(file)}\t#{file}" if debug
65
65
  puts "QUART #{File.mtime(quarters_file)}\t#{quarters_file}" if debug
66
66
  result = if range.nil?
@@ -98,17 +98,17 @@ module Cotcube
98
98
  base = Cotcube::Helpers.reduce(bars: data, to: :days)
99
99
 
100
100
  # remove last day of result unless marked
101
- base.pop unless contract_is_marked || force_recent
101
+ base.pop if base.last[:datetime].to_date == timezone.now.to_date and not force_recent
102
102
 
103
103
  base.map do |x|
104
- x[:datetime] = x[:datetime].to_date
104
+ x[:date] = x[:datetime].to_date
105
105
  x[:type] = "#{filter}_day".to_sym
106
106
  x.delete(:day)
107
107
  end
108
108
  CSV.open(file, 'w') do |csv|
109
109
  base.each { |b| csv << b.values_at(*headers) }
110
110
  if contract_is_marked
111
- marker = ["#{sym[:symbol]}#{contract}", base.last[:datetime] + 1.day, 0, 0, 0, 0, 0]
111
+ marker = ["#{sym[:symbol]}#{contract}", base.last[:date] + 1.day, 0, 0, 0, 0, 0]
112
112
  csv << marker
113
113
  end
114
114
  end
@@ -8,6 +8,7 @@ module Cotcube
8
8
  symbol: nil, id: nil,
9
9
  range: nil,
10
10
  timezone: Time.find_zone('America/Chicago'),
11
+ keep_last: false,
11
12
  config: init)
12
13
  contract = contract.to_s.upcase
13
14
  unless contract.is_a?(String) && [3, 5].include?(contract.size)
@@ -48,7 +49,7 @@ module Cotcube
48
49
  row[:type] = :daily
49
50
  row
50
51
  end
51
- data.pop if data.last[:high].zero?
52
+ data.pop if data.last[:high].zero? and not keep_last
52
53
  if range.nil?
53
54
  data
54
55
  else
@@ -61,29 +62,52 @@ module Cotcube
61
62
 
62
63
  # reads all files in bardata/daily/<id> and aggregates by date
63
64
  # (what is a pre-stage of a continuous based on daily bars)
64
- def continuous(symbol: nil, id: nil, config: init, date: nil)
65
+ def continuous(symbol: nil, id: nil, config: init, date: nil, measure: nil, force_rewrite: false)
66
+ raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
67
+ measuring = lambda {|c| puts "[continuous] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
68
+
69
+ measuring.call("Starting")
65
70
  sym = get_id_set(symbol: symbol, id: id)
66
71
  id = sym[:id]
72
+ symbol = sym[:symbol]
67
73
  id_path = "#{config[:data_path]}/daily/#{id}"
68
- available_contracts = Dir["#{id_path}/*.csv"].map { |x| x.split('/').last.split('.').first }
69
- available_contracts.sort_by! { |x| x[-7] }.sort_by! { |x| x[-6..-5] }
70
- data = []
71
- available_contracts.each do |c|
72
- provide_daily(id: id, config: config, contract: c).each do |x|
73
- data << x
74
+ c_file = "#{id_path}/continuous.csv"
75
+
76
+ # instead of using the provide_daily methods above, for this bulk operation a 'continuous.csv' is created
77
+ # this boosts from 4.5sec to 0.3sec
78
+ rewriting = force_rewrite or not(File.exist?(c_file)) or (Time.now - File.mtime(c_file) > 8.days)
79
+ if rewriting
80
+ puts "In daily+continuous: Rewriting #{c_file} #{force_rewrite ? "forcibly" : "due to fileage"}.".light_yellow
81
+ `rm #{c_file}; find #{id_path} | xargs cat 2>/dev/null | grep -v '0,0,0,0' | sort -t, -k2 | cut -d, -f1,2,7,8 > #{c_file}`
82
+ end
83
+ loading = lambda do
84
+ data = CSV.read(c_file).map do |row|
85
+ r = { contract: row[0],
86
+ date: row[1],
87
+ volume: row[2].to_i,
88
+ oi: row[3].to_i
89
+ }
74
90
  end
91
+
92
+ measuring.call("Finished retrieving dailies.")
93
+ result = []
94
+ data.group_by { |x| x[:date] }.map do |k, v|
95
+ v.map { |x| x.delete(:date) }
96
+ result << {
97
+ date: k,
98
+ volume: v.map { |x| x[:volume] }.reduce(:+),
99
+ oi: v.map { |x| x[:oi] }.reduce(:+)
100
+ }
101
+ result.last[:contracts] = v
102
+ end
103
+ result
75
104
  end
76
- result = []
77
- data.sort_by { |x| x[:date] }.group_by { |x| x[:date] }.map do |k, v|
78
- v.map { |x| x.delete(:date) }
79
- result << {
80
- date: k,
81
- volume: v.map { |x| x[:volume] }.reduce(:+),
82
- oi: v.map { |x| x[:oi] }.reduce(:+)
83
- }
84
- result.last[:contracts] = v
105
+ constname = "CONTINUOUS_#{symbol}".to_sym
106
+ if rewriting or not Cotcube::Bardata.const_defined?( constname)
107
+ Cotcube::Bardata.const_set constname, loading.call
85
108
  end
86
- date.nil? ? result : result.select { |x| x[:date] == date }.first
109
+ measuring.call("Finished processing")
110
+ date.nil? ? Cotcube::Bardata.const_get(constname) : Cotcube::Bardata.const_get(constname).find { |x| x[:date] == date }
87
111
  end
88
112
 
89
113
  def continuous_ml(symbol: nil, id: nil, base: nil)
@@ -116,20 +140,27 @@ module Cotcube
116
140
  config: init,
117
141
  selector: :volume,
118
142
  human: false,
143
+ measure: nil,
119
144
  filter: nil)
145
+
146
+ raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
147
+ measuring = lambda {|c| puts "[continuous_overview] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
148
+
120
149
  raise ArgumentError, 'Selector must be either :volume or :oi' unless selector.is_a?(Symbol) &&
121
- %i[volume oi].include?(selector)
150
+ %i[volume oi].include?(selector)
122
151
 
152
+ measuring.call("Starting")
123
153
  sym = get_id_set(symbol: symbol, id: id)
124
154
  id = sym[:id]
125
155
  # noinspection RubyNilAnalysis
126
- data = continuous(id: id, config: config).map do |x|
156
+ data = continuous(id: id, config: config, measure: measure).map do |x|
127
157
  {
128
158
  date: x[:date],
129
159
  volume: x[:contracts].sort_by { |z| - z[:volume] }[0..4].compact.reject { |z| z[:volume].zero? },
130
160
  oi: x[:contracts].sort_by { |z| - z[:oi] }[0..4].compact.reject { |z| z[:oi].zero? }
131
161
  }
132
162
  end
163
+ measuring.call("Retrieved continuous for #{sym[:symbol]}")
133
164
  data.reject! { |x| x[selector].empty? }
134
165
  result = data.group_by { |x| x[selector].first[:contract] }
135
166
  result.each_key do |key|
@@ -149,14 +180,15 @@ module Cotcube
149
180
  }\t#{v.last[:date]
150
181
  }\t#{format('%4d', (Date.parse(v.last[:date]) - Date.parse(v.first[:date])))
151
182
  }\t#{result[k].map do |x|
152
- x[:volume].select do
153
- x[:contract] == k
154
- end
155
- end.size
183
+ x[:volume].select do
184
+ x[:contract] == k
185
+ end
186
+ end.size
156
187
  }"
157
188
  # rubocop:enable Layout/ClosingParenthesisIndentation
158
189
  end
159
190
  end
191
+ measuring.call("Finished processing")
160
192
  result
161
193
  end
162
194
 
@@ -164,19 +196,26 @@ module Cotcube
164
196
  selector: :volume,
165
197
  filter: nil,
166
198
  date: Date.today,
199
+ short: true,
200
+ measure: nil,
167
201
  debuglevel: 1,
168
202
  debug: false)
169
203
  if debug.is_a?(Integer)
170
204
  debuglevel = debug
171
205
  debug = debuglevel > 0 ? true : false
172
206
  end
207
+
208
+ raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
209
+ measuring = lambda {|c| puts "[continuous_table] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
210
+
173
211
  raise ArgumentError, 'Selector must be either :volume or :oi' unless selector.is_a?(Symbol) &&
174
- %i[volume oi].include?(selector)
212
+ %i[volume oi].include?(selector)
175
213
 
214
+ measuring.call("Entering function")
176
215
  sym = get_id_set(symbol: symbol, id: id)
177
216
  if %w[R6 BJ GE].include? sym[:symbol]
178
- puts "Rejecting to process symbol '#{sym[:symbol]}'."
179
- return
217
+ puts "Rejecting to process symbol '#{sym[:symbol]}'.".light_red
218
+ return []
180
219
  end
181
220
  id = sym[:id]
182
221
  dfm = lambda do |x, y = date.year|
@@ -188,60 +227,69 @@ module Cotcube
188
227
  end
189
228
 
190
229
  ytoday = date.yday
191
- data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init)
230
+ data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init, measure: measure)
192
231
  .reject { |k, _| k[-2..].to_i == date.year % 2000 }
193
- .group_by { |k, _| k[2] }
232
+ .group_by { |k, _| k[2] }
233
+ measuring.call("Retrieved continous_overview")
194
234
  output_sent = []
195
235
  early_year=nil
236
+ long_output = []
196
237
  data.keys.sort.each do |month|
238
+ current_long = { month: month }
197
239
  puts "Processing #{sym[:symbol]}#{month}" if debuglevel > 1
198
240
  v0 = data[month]
199
- ydays = v0.map { |_, v1| Date.parse(v1.last[:date]).yday }
241
+ ldays = v0.map { |_, v1| Date.parse(v1.last[:date]).yday }
200
242
  fdays = v0.map { |_, v1| Date.parse(v1.first[:date]).yday }.sort
201
243
  # if the last ml day nears the end of the year, we must fix
202
- ydays.map! { |x| x > 350 ? x - 366 : x } if ydays.min < 50
244
+ ldays.map! { |x| x > 350 ? x - 366 : x } if ldays.min < 50
203
245
  fday = fdays[fdays.size / 2]
204
- yavg = ydays.reduce(:+) / ydays.size
205
- # a contract is proposed to use after fday - 1, but before ydays.min (green)
206
- # it is warned to user after fday - 1 but before yavg - 1 (red)
207
- # it is warned red >= yavg - 1 and <= yavg + 1
208
- color = if (ytoday >= yavg - 1) && (ytoday <= yavg + 1)
246
+ lavg = ldays.reduce(:+) / ldays.size
247
+ # a contract is proposed to use after fday - 1, but before ldays.min (green)
248
+ # it is warned to user after fday - 1 but before lavg - 1 (red)
249
+ # it is warned red >= lavg - 1 and <= lavg + 1
250
+ color = if (ytoday >= lavg - 1) && (ytoday <= lavg + 1)
209
251
  :light_red
210
- elsif (ytoday > ydays.min) && (ytoday < yavg - 1)
252
+ elsif (ytoday > ldays.min) && (ytoday < lavg - 1)
211
253
  :light_yellow
212
- elsif (ytoday >= (fday > yavg ? 0 : fday - 5)) && (ytoday <= ydays.min)
254
+ elsif (ytoday >= (fday > lavg ? 0 : fday - 5)) && (ytoday <= ldays.min)
213
255
  :light_green
214
256
  else
215
257
  :white
216
258
  end
217
259
  # rubocop:disable Layout/ClosingParenthesisIndentation
260
+ long_output << {
261
+ month: month,
262
+ first_ml: fday,
263
+ last_min: ldays.min,
264
+ last_avg: lavg,
265
+ last_max: ldays.max }
218
266
  output = "#{sym[:symbol]
219
267
  }#{month
220
268
  }\t#{format '%12s', sym[:type]
221
- }\t#{ytoday
222
- }/#{fday
223
- }\t#{format '%5d', ydays.min
224
- }: #{dfm.call(ydays.min)
225
- }\t#{format '%5d', yavg
226
- }: #{dfm.call(yavg)
227
- }\t#{format '%5d', ydays.max
228
- }: #{dfm.call(ydays.max)}".colorize(color)
229
- if debug || (color != :white)
230
- puts output
231
- output_sent << "#{sym[:symbol]}#{month}" unless color == :white
232
- end
233
- early_year ||= output
234
- next unless (debug and debuglevel >= 2)
269
+ }\ttoday is #{ytoday
270
+ } -- median of first is #{fday
271
+ }\tlast ranges from #{format '%5d', ldays.min
272
+ }: #{dfm.call(ldays.min)
273
+ }\t#{format '%5d', lavg
274
+ }: #{dfm.call(lavg)
275
+ }\tto #{format '%5d', ldays.max
276
+ }: #{dfm.call(ldays.max)}".colorize(color)
277
+ if debug || (color != :white)
278
+ puts output
279
+ output_sent << "#{sym[:symbol]}#{month}" unless color == :white
280
+ end
281
+ early_year ||= output
282
+ next unless (debug and debuglevel >= 2)
235
283
 
236
- v0.each do |contract, v1|
237
- puts "\t#{contract
284
+ v0.each do |contract, v1|
285
+ puts "\t#{contract
238
286
  }\t#{v1.first[:date]
239
- }\t#{Date.parse(v1.last[:date]).strftime('%a')
240
- }, #{v1.last[:date]
241
- } (#{Date.parse(v1.last[:date]).yday}"
287
+ } (#{format '%3d', Date.parse(v1.first[:date]).yday
288
+ })\t#{Date.parse(v1.last[:date]).strftime('%a, %Y-%m-%d')
289
+ } (#{Date.parse(v1.last[:date]).yday})"
242
290
  # rubocop:enable Layout/ClosingParenthesisIndentation
291
+ end
243
292
  end
244
- end
245
293
  case output_sent.size
246
294
  when 0
247
295
  puts "WARNING: No output was sent for symbol '#{sym[:symbol]}'.".colorize(:light_yellow)
@@ -251,10 +299,10 @@ module Cotcube
251
299
  # all ok
252
300
  true
253
301
  else
254
- puts "---- #{output_sent} for #{sym[:symbol]} ---------------"
255
-
302
+ puts "Continuous table show #{output_sent.size} active contracts ( #{output_sent} ) for #{sym[:symbol]} ---------------"
256
303
  end
257
- output_sent
304
+ measuring.call("Finished processing")
305
+ short ? output_sent : long_output
258
306
  end
259
307
  end
260
308
  end
@@ -46,6 +46,10 @@ module Cotcube
46
46
  end
47
47
 
48
48
  def get_id_set(symbol: nil, id: nil, contract: nil, config: init)
49
+ contract = contract.to_s.upcase if contract.is_a? Symbol
50
+ id = id.to_s.upcase if id.is_a? Symbol
51
+ symbol = symbol.to_s.upcase if symbol.is_a? Symbol
52
+
49
53
  if contract.is_a?(String) && (contract.length == 5)
50
54
  c_symbol = contract[0..1]
51
55
  if (not symbol.nil?) && (symbol != c_symbol)
@@ -8,9 +8,9 @@ module Cotcube
8
8
  SYMBOL_EXAMPLES
9
9
  else
10
10
  CSV
11
- .read(config[:symbols_file], headers: %i[id symbol ticksize power months type bcf reports name])
11
+ .read(config[:symbols_file], headers: %i[id symbol ticksize power months type bcf reports format name])
12
12
  .map(&:to_h)
13
- .map { |row| %i[ticksize power bcf].each { |z| row[z] = row[z].to_f }; row } # rubocop:disable Style/Semicolon
13
+ .map { |row| %i[ticksize power bcf].each { |z| row[z] = row[z].to_f }; row[:format] = "%#{row[:format]}f"; row } # rubocop:disable Style/Semicolon
14
14
  .reject { |row| row[:id].nil? }
15
15
  .tap { |all| all.select! { |x| x[:type] == type } unless type.nil? }
16
16
  .tap { |all| all.select! { |x| x[:symbol] == symbol } unless symbol.nil? }
@@ -44,7 +44,7 @@ module Cotcube
44
44
  days = provide_cached contract: contract, symbol: symbol, id: id, config: config, filter: filter,
45
45
  range: range, force_recent: force_recent
46
46
  dailies = provide_daily contract: contract, symbol: symbol, id: id, config: config, range: range
47
- if days.last[:datetime] > dailies.last[:datetime]
47
+ if ((days.last[:datetime] > dailies.last[:datetime]) rescue false)
48
48
  dailies[..-2] + days.select { |d| d[:datetime] > dailies[-2][:datetime] }
49
49
  else
50
50
  dailies
@@ -5,7 +5,6 @@ module Cotcube
5
5
  module Bardata
6
6
  # this is an analysis tool to investigate actual ranges of an underlying symbol
7
7
  # it is in particular no true range or average true range, as a 'true range' can only be applied to
8
- # a steady series, what changing contracts definitely aren't
9
8
  #
10
9
  # The result printed / returned is a table, containing a matrix of rows:
11
10
  # 1. size: the amount of values evaluated
@@ -22,18 +21,25 @@ module Cotcube
22
21
  # 3.a-c) same with days reduced to months (c: 12 months)
23
22
  #
24
23
  # NOTE: there is now a new method Cotcube::Helpers.simple_series_stats, that should be used in favor.
25
- def range_matrix(symbol: nil, id: nil, print: false, dim: 0.05)
24
+ def range_matrix(symbol: nil, id: nil, base: nil, print: false, dim: 0.05, days_only: false, last_n: 60, &block)
26
25
  # rubocop:disable Style/MultilineBlockChain
26
+ symbol ||= base.last[:contract][0..1] if id.nil?
27
27
  sym = get_id_set(symbol: symbol, id: id)
28
28
  source = {}
29
29
  target = {}
30
- source[:days] = Cotcube::Bardata.continuous_actual_ml symbol: symbol
30
+ if base.nil?
31
+ ml = (Cotcube::Bardata.continuous_actual_ml symbol: symbol)&.last[:contract]
32
+ source[:days] = Cotcube::Bardata.provide contract: ml
33
+ else
34
+ source[:days] = base
35
+ end
31
36
  source[:weeks] = Cotcube::Helpers.reduce bars: source[:days], to: :weeks
32
37
  source[:months] = Cotcube::Helpers.reduce bars: source[:days], to: :months
33
38
 
34
39
  %i[days weeks months].each do |period|
40
+ next if days_only and %i[weeks months].include? period
35
41
  source[period].map! do |x|
36
- x[:range] = ((x[:high] - x[:low]) / sym[:ticksize]).round
42
+ x[:range] = block_given? ? yield(x) : (((x[:high] - x[:low]) / sym[:ticksize]).round)
37
43
  x
38
44
  end
39
45
  target[period] = {}
@@ -80,14 +86,18 @@ module Cotcube
80
86
 
81
87
  range = case period
82
88
  when :months
83
- -13..-2
89
+ -(last_n/15)..-2
84
90
  when :weeks
85
- -53..-2
91
+ -(last_n/4)..-2
86
92
  when :days
87
- -200..-1
93
+ -last_n..-1
88
94
  else
89
95
  raise ArgumentError, "Unsupported period: '#{period}'"
90
96
  end
97
+ if range.begin.abs > source[period].size
98
+ puts "WARNING: requested last_n = #{last_n} exceeds actual size (#{source[period].size}), adjusting...".light_yellow
99
+ range = (-source[period].size..range.end)
100
+ end
91
101
  custom = source[period][range]
92
102
  target[period][:rec_size] = custom.size
93
103
  target[period][:rec_avg] = (custom.map { |x| x[:range] }.reduce(:+) / custom.size).round
@@ -110,6 +120,7 @@ module Cotcube
110
120
  %w[size avg lower median upper max].each do |a|
111
121
  print "#{'%10s' % a} | " # rubocop:disable Style/FormatString
112
122
  %i[days weeks months].each do |b|
123
+ next if days_only and %i[weeks months].include? b
113
124
  %w[all dim rec].each do |c|
114
125
  print ('%8d' % target[b]["#{c}_#{a}".to_sym]).to_s # rubocop:disable Style/FormatString
115
126
  end
@@ -8,7 +8,7 @@ module Cotcube
8
8
  def last_trade_date
9
9
  uri = 'https://www.cmegroup.com/CmeWS/mvc/Volume/TradeDates?exchange=CME'
10
10
  begin
11
- HTTParty.get(uri)
11
+ HTTParty.get(uri, headers: { "User-Agent" => "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"})
12
12
  .parsed_response
13
13
  .map do |x|
14
14
  a = x['tradeDate'].chars.each_slice(2).map(&:join)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cotcube-bardata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.9.2
4
+ version: 0.1.13
5
5
  platform: ruby
6
6
  authors:
7
7
  - Benjamin L. Tischendorf
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-02-07 00:00:00.000000000 Z
11
+ date: 2021-04-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport