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 +4 -4
- data/CHANGELOG.md +20 -0
- data/VERSION +1 -1
- data/lib/cotcube-bardata.rb +2 -0
- data/lib/cotcube-bardata/cached.rb +7 -6
- data/lib/cotcube-bardata/daily.rb +94 -46
- data/lib/cotcube-bardata/provide.rb +9 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: dc417f9b8b33204bbc1b345ec28e2c5604b2a5f59c183a6a0a1ad15a6cf223b1
|
4
|
+
data.tar.gz: f631c5507dff588e4f2e19209aca5d135514e450ddc9b311e407b9733f539191
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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.
|
1
|
+
0.1.11
|
data/lib/cotcube-bardata.rb
CHANGED
@@ -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)
|
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
|
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[:
|
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[:
|
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
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
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
|
-
|
77
|
-
|
78
|
-
|
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
|
-
|
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
|
-
|
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
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
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
|
-
|
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 =
|
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 =
|
185
|
-
data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init)
|
186
|
-
|
187
|
-
|
188
|
-
|
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
|
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
|
-
|
211
|
-
|
212
|
-
|
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
|
-
|
224
|
-
|
225
|
-
|
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
|
-
|
228
|
-
|
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
|
-
|
234
|
-
|
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
|
-
|
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.
|
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-
|
11
|
+
date: 2021-03-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|