cotcube-bardata 0.1.8 → 0.1.11

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: a701303a258aaaf6050922e35eaacf53ce09fc43fc25778492ebb0b11fb9890c
4
- data.tar.gz: 389709153f639e14638832e701f19a295181e1b81e26a8aa2ba2baf5c0587ee9
3
+ metadata.gz: dc417f9b8b33204bbc1b345ec28e2c5604b2a5f59c183a6a0a1ad15a6cf223b1
4
+ data.tar.gz: f631c5507dff588e4f2e19209aca5d135514e450ddc9b311e407b9733f539191
5
5
  SHA512:
6
- metadata.gz: ee32360405d9597e82c6eb9d7678895ecd1c7db9872ed2ecdd8efbd4fc0cd2ec4cea21d2546e867a45af3655ab251a34d39855d7b7d7865458ea60ff8ba65811
7
- data.tar.gz: 7a4387b1834d811a61e9bd04fbe0a263f7f4a730b2a15cb928fb956929acefa5097a502fa548c26356f5ccac051d7f037344c42e320400a8a5eab55266119b81
6
+ metadata.gz: f5276bd185a561658226f65b92ce696774f1da7442bf0c10704925e4afd295566844d02bf866921575bf60cea6944555c7dd6abc28214ed5852ca8228553d2f3
7
+ data.tar.gz: c73f923b1bf4399bf6a9cea56e4adf2acc3aaeab770d4b56cc1daae7d5a4f7c4617f30baff58b03f9ced45a9987a4bf8106c709f12a1cfb17f0021cfe36a6d71
data/CHANGELOG.md CHANGED
@@ -1,3 +1,23 @@
1
+ ## 0.1.11 (March 07, 2021)
2
+ - daily.rb: added new technique 'caching in constants' to accelerate computation, also referring to continuous
3
+ - provide.rb: minor change, so disregarded contracts can be used in swapproximate
4
+
5
+ ## 0.1.10 (February 11, 2021)
6
+ - Daily.rb: Added measure parameters to continous_suite
7
+ - cached.rb: Minor fix in comparison
8
+
9
+ ## 0.1.9.3 (February 08, 2021)
10
+ - cached: minor change fixing problem to get yesterday in rth subsets
11
+
12
+ ## 0.1.9.2 (February 07, 2021)
13
+ - minor changes
14
+ - daily#continuous_table: introducing debuglevel
15
+
16
+ ## 0.1.9.1 (January 29, 2021)
17
+ - provide: added new interval 'synth', mixing available dailies with synthetic days based on quarters
18
+ - minor change / cleanup
19
+ - setting gemspec to use rake 13 and changing version spec to overcome warnings
20
+
1
21
  ## 0.1.8 (January 27, 2021)
2
22
  - in helpers, #extended_range_for_date: fixed comparison signs
3
23
  - range_matrix: applied cops, noted appearance of Cotcube::Helpers.simple_series_stats
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.8
1
+ 0.1.11
@@ -52,6 +52,8 @@ module Cotcube
52
52
  :continuous_actual_ml,
53
53
  # based on continuous, create list of when which contract was most liquid
54
54
  :continuous_overview,
55
+ # provider estimation of current ML usability
56
+ :continuous_table,
55
57
  # provide the list of quarters, possibly as hours or days.
56
58
  :provide_quarters,
57
59
  # some statistics to estimate daily volatility of specific contract
@@ -8,6 +8,7 @@ module Cotcube
8
8
  symbol: nil, id: nil,
9
9
  range: nil,
10
10
  config: init,
11
+ debug: false,
11
12
  timezone: Time.find_zone('America/Chicago'),
12
13
  filter: :full, # most probably either :full or :rth
13
14
  force_update: false, # force reloading via provide_quarters
@@ -59,9 +60,9 @@ module Cotcube
59
60
  end
60
61
  end
61
62
  return result
62
- elsif File.mtime(file) + 1.day > File.mtime(quarters_file)
63
- puts "CACHE #{File.mtime(file)}\t#{file}"
64
- puts "QUART #{File.mtime(quarters_file)}\t#{quarters_file}"
63
+ elsif File.mtime(file) - Time.now.beginning_of_day >= 0
64
+ puts "CACHE #{File.mtime(file)}\t#{file}" if debug
65
+ puts "QUART #{File.mtime(quarters_file)}\t#{quarters_file}" if debug
65
66
  result = if range.nil?
66
67
  base
67
68
  else
@@ -97,17 +98,17 @@ module Cotcube
97
98
  base = Cotcube::Helpers.reduce(bars: data, to: :days)
98
99
 
99
100
  # remove last day of result unless marked
100
- 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
101
102
 
102
103
  base.map do |x|
103
- x[:datetime] = x[:datetime].to_date
104
+ x[:date] = x[:datetime].to_date
104
105
  x[:type] = "#{filter}_day".to_sym
105
106
  x.delete(:day)
106
107
  end
107
108
  CSV.open(file, 'w') do |csv|
108
109
  base.each { |b| csv << b.values_at(*headers) }
109
110
  if contract_is_marked
110
- 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]
111
112
  csv << marker
112
113
  end
113
114
  end
@@ -61,29 +61,50 @@ module Cotcube
61
61
 
62
62
  # reads all files in bardata/daily/<id> and aggregates by date
63
63
  # (what is a pre-stage of a continuous based on daily bars)
64
- def continuous(symbol: nil, id: nil, config: init, date: nil)
64
+ def continuous(symbol: nil, id: nil, config: init, date: nil, measure: nil, force_rewrite: false)
65
+ raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
66
+ measuring = lambda {|c| puts "[continuous] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
67
+
68
+ measuring.call("Starting")
65
69
  sym = get_id_set(symbol: symbol, id: id)
66
70
  id = sym[:id]
67
71
  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
72
+ c_file = "#{id_path}/continuous.csv"
73
+
74
+ # instead of using the provide_daily methods above, for this bulk operation a 'continuous.csv' is created
75
+ # this boosts from 4.5sec to 0.3sec
76
+ rewriting = force_rewrite or not(File.exist?(c_file)) or (Time.now - File.mtime(c_file) > 8.days)
77
+ if rewriting
78
+ puts "In daily+continuous: Rewriting #{c_file} #{force_rewrite ? "forcibly" : "due to fileage"}.".light_yellow
79
+ `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}`
80
+ end
81
+ loading = lambda do
82
+ data = CSV.read(c_file).map do |row|
83
+ r = { contract: row[0],
84
+ date: row[1],
85
+ volume: row[2].to_i,
86
+ oi: row[3].to_i
87
+ }
88
+ end
89
+
90
+ measuring.call("Finished retrieving dailies.")
91
+ result = []
92
+ data.group_by { |x| x[:date] }.map do |k, v|
93
+ v.map { |x| x.delete(:date) }
94
+ result << {
95
+ date: k,
96
+ volume: v.map { |x| x[:volume] }.reduce(:+),
97
+ oi: v.map { |x| x[:oi] }.reduce(:+)
98
+ }
99
+ result.last[:contracts] = v
74
100
  end
75
101
  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
102
+ constname = "CONTINUOUS_#{symbol}".to_sym
103
+ if rewriting or not Cotcube::Bardata.const_defined?( constname)
104
+ Cotcube::Bardata.const_set constname, loading.call
85
105
  end
86
- date.nil? ? result : result.select { |x| x[:date] == date }.first
106
+ measuring.call("Finished processing")
107
+ date.nil? ? Cotcube::Bardata.const_get(constname) : Cotcube::Bardata.const_get(constname).find { |x| x[:date] == date }
87
108
  end
88
109
 
89
110
  def continuous_ml(symbol: nil, id: nil, base: nil)
@@ -116,20 +137,27 @@ module Cotcube
116
137
  config: init,
117
138
  selector: :volume,
118
139
  human: false,
140
+ measure: nil,
119
141
  filter: nil)
142
+
143
+ raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
144
+ measuring = lambda {|c| puts "[continuous_overview] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
145
+
120
146
  raise ArgumentError, 'Selector must be either :volume or :oi' unless selector.is_a?(Symbol) &&
121
- %i[volume oi].include?(selector)
147
+ %i[volume oi].include?(selector)
122
148
 
149
+ measuring.call("Starting")
123
150
  sym = get_id_set(symbol: symbol, id: id)
124
151
  id = sym[:id]
125
152
  # noinspection RubyNilAnalysis
126
- data = continuous(id: id, config: config).map do |x|
153
+ data = continuous(id: id, config: config, measure: measure).map do |x|
127
154
  {
128
155
  date: x[:date],
129
156
  volume: x[:contracts].sort_by { |z| - z[:volume] }[0..4].compact.reject { |z| z[:volume].zero? },
130
157
  oi: x[:contracts].sort_by { |z| - z[:oi] }[0..4].compact.reject { |z| z[:oi].zero? }
131
158
  }
132
159
  end
160
+ measuring.call("Retrieved continuous")
133
161
  data.reject! { |x| x[selector].empty? }
134
162
  result = data.group_by { |x| x[selector].first[:contract] }
135
163
  result.each_key do |key|
@@ -149,31 +177,44 @@ module Cotcube
149
177
  }\t#{v.last[:date]
150
178
  }\t#{format('%4d', (Date.parse(v.last[:date]) - Date.parse(v.first[:date])))
151
179
  }\t#{result[k].map do |x|
152
- x[:volume].select do
153
- x[:contract] == k
154
- end
155
- end.size
180
+ x[:volume].select do
181
+ x[:contract] == k
182
+ end
183
+ end.size
156
184
  }"
157
185
  # rubocop:enable Layout/ClosingParenthesisIndentation
158
186
  end
159
187
  end
188
+ measuring.call("Finished processing")
160
189
  result
161
190
  end
162
191
 
163
192
  def continuous_table(symbol: nil, id: nil,
164
193
  selector: :volume,
165
194
  filter: nil,
195
+ date: Date.today,
196
+ measure: nil,
197
+ debuglevel: 1,
166
198
  debug: false)
199
+ if debug.is_a?(Integer)
200
+ debuglevel = debug
201
+ debug = debuglevel > 0 ? true : false
202
+ end
203
+
204
+ raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
205
+ measuring = lambda {|c| puts "[continuous_table] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
206
+
167
207
  raise ArgumentError, 'Selector must be either :volume or :oi' unless selector.is_a?(Symbol) &&
168
- %i[volume oi].include?(selector)
208
+ %i[volume oi].include?(selector)
169
209
 
210
+ measuring.call("Entering function")
170
211
  sym = get_id_set(symbol: symbol, id: id)
171
212
  if %w[R6 BJ GE].include? sym[:symbol]
172
- puts "Rejecting to process symbol '#{sym[:symbol]}'."
173
- return
213
+ puts "Rejecting to process symbol '#{sym[:symbol]}'.".light_red
214
+ return []
174
215
  end
175
216
  id = sym[:id]
176
- dfm = lambda do |x, y = Date.today.year|
217
+ dfm = lambda do |x, y = date.year|
177
218
  k = Date.strptime("#{y} #{x.negative? ? x + 366 : x}", '%Y %j')
178
219
  k -= 1 while [0, 6].include?(k.wday)
179
220
  k.strftime('%a, %Y-%m-%d')
@@ -181,13 +222,15 @@ module Cotcube
181
222
  puts "#{sym[:symbol]}\t#{x}\t#{y}"
182
223
  end
183
224
 
184
- ytoday = Date.today.yday
185
- data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init)
186
- .reject { |k, _| k[-2..].to_i == Date.today.year % 2000 }
187
- .group_by { |k, _| k[2] }
188
- output_sent = 0
225
+ ytoday = date.yday
226
+ data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init, measure: measure)
227
+ .reject { |k, _| k[-2..].to_i == date.year % 2000 }
228
+ .group_by { |k, _| k[2] }
229
+ measuring.call("Retrieved continous_overview")
230
+ output_sent = []
231
+ early_year=nil
189
232
  data.keys.sort.each do |month|
190
- puts "Processing #{sym[:symbol]}#{month}" if debug
233
+ puts "Processing #{sym[:symbol]}#{month}" if debuglevel > 1
191
234
  v0 = data[month]
192
235
  ydays = v0.map { |_, v1| Date.parse(v1.last[:date]).yday }
193
236
  fdays = v0.map { |_, v1| Date.parse(v1.first[:date]).yday }.sort
@@ -207,10 +250,9 @@ module Cotcube
207
250
  else
208
251
  :white
209
252
  end
210
- if debug || (color != :white)
211
- # rubocop:disable Layout/ClosingParenthesisIndentation
212
- puts "#{sym[:symbol]
213
- }#{month
253
+ # rubocop:disable Layout/ClosingParenthesisIndentation
254
+ output = "#{sym[:symbol]
255
+ }#{month
214
256
  }\t#{format '%12s', sym[:type]
215
257
  }\t#{ytoday
216
258
  }/#{fday
@@ -220,22 +262,27 @@ module Cotcube
220
262
  }: #{dfm.call(yavg)
221
263
  }\t#{format '%5d', ydays.max
222
264
  }: #{dfm.call(ydays.max)}".colorize(color)
223
- output_sent += 1
224
- end
225
- next unless debug
265
+ if debug || (color != :white)
266
+ puts output
267
+ output_sent << "#{sym[:symbol]}#{month}" unless color == :white
268
+ end
269
+ early_year ||= output
270
+ next unless (debug and debuglevel >= 2)
226
271
 
227
- v0.each do |contract, v1|
228
- puts "\t#{contract
272
+ v0.each do |contract, v1|
273
+ puts "\t#{contract
229
274
  }\t#{v1.first[:date]
230
275
  }\t#{Date.parse(v1.last[:date]).strftime('%a')
231
276
  }, #{v1.last[:date]
232
277
  } (#{Date.parse(v1.last[:date]).yday}"
233
- # rubocop:enable Layout/ClosingParenthesisIndentation
234
- end
278
+ # rubocop:enable Layout/ClosingParenthesisIndentation
279
+ end
235
280
  end
236
- case output_sent
281
+ case output_sent.size
237
282
  when 0
238
283
  puts "WARNING: No output was sent for symbol '#{sym[:symbol]}'.".colorize(:light_yellow)
284
+ puts " Assuming late-year-processing.".light_yellow
285
+ puts early_year.light_green
239
286
  when 1
240
287
  # all ok
241
288
  true
@@ -243,7 +290,8 @@ module Cotcube
243
290
  puts "---- #{output_sent} for #{sym[:symbol]} ---------------"
244
291
 
245
292
  end
246
- nil
293
+ measuring.call("Finished processing")
294
+ output_sent
247
295
  end
248
296
  end
249
297
  end
@@ -40,6 +40,15 @@ module Cotcube
40
40
  raise 'Missing implementation to reduce cached days to weeks or months'
41
41
  when :dailies, :daily
42
42
  provide_daily contract: contract, symbol: symbol, id: id, config: config, range: range
43
+ when :synth, :synthetic, :synthetic_days
44
+ days = provide_cached contract: contract, symbol: symbol, id: id, config: config, filter: filter,
45
+ range: range, force_recent: force_recent
46
+ dailies = provide_daily contract: contract, symbol: symbol, id: id, config: config, range: range
47
+ if ((days.last[:datetime] > dailies.last[:datetime]) rescue false)
48
+ dailies[..-2] + days.select { |d| d[:datetime] > dailies[-2][:datetime] }
49
+ else
50
+ dailies
51
+ end
43
52
  else
44
53
  raise ArgumentError, "Unsupported or unknown interval '#{interval}' in Bardata.provide"
45
54
  end
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.8
4
+ version: 0.1.11
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-01-27 00:00:00.000000000 Z
11
+ date: 2021-03-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activesupport