cotcube-bardata 0.1.14 → 0.1.15.2
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 +17 -0
- data/README.md +1 -1
- data/VERSION +1 -1
- data/cotcube-bardata.gemspec +1 -1
- data/lib/cotcube-bardata.rb +1 -0
- data/lib/cotcube-bardata/cached.rb +2 -1
- data/lib/cotcube-bardata/daily.rb +114 -16
- data/lib/cotcube-bardata/provide.rb +6 -0
- data/lib/cotcube-bardata/quarters.rb +1 -0
- data/lib/cotcube-bardata/suggest.rb +1 -1
- data/lib/cotcube-bardata/trade_dates.rb +38 -12
- data/lib/cotcube-bardata/trading_hours.rb +10 -4
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 46f85dd103fd911ba475b347f14002f1402eda630b79ded6a161969a1df487db
|
4
|
+
data.tar.gz: 72f66b63600041d28131df575036d0295f8ab206e132fcd69c2ea84109194505
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 29271f6f4b5dba379bb19e81846d52f1d2995bd010f35b7e80bad3256ae415c841eeead6a84034ce72d29cd6b3746d4d62fb182347abca1fa6d78fd0c3bfb6a7
|
7
|
+
data.tar.gz: 5cb42e0fbd5ae2124edb7ede368047e72c8fe68b99ed928727d8e47859a5c94470bab989a032f0689e63058dd01b190936d02f22d8be7fca3cd61f3240a40a1c
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
## 0.1.15.2 (August 04, 2021)
|
2
|
+
- fixed leftover debug setting
|
3
|
+
|
4
|
+
## 0.1.15.1 (August 04, 2021)
|
5
|
+
- fixed license mismatch
|
6
|
+
|
7
|
+
## 0.1.15 (August 04, 2021)
|
8
|
+
- daily.rb: added support to add eod data on incomplete dailies
|
9
|
+
- adding dep: cotcube-indicators
|
10
|
+
- provide: new method :determine_significant_volume
|
11
|
+
- suggest: adding silence
|
12
|
+
- cached: Adding :dist
|
13
|
+
- daily: new method :determine_significant_volume
|
14
|
+
- added :dist generically to quarters
|
15
|
+
- trading_hours: added param to return headers only
|
16
|
+
- last_trade_date: Enabled caching instead of fetching each time
|
17
|
+
|
1
18
|
## 0.1.14 (May 07, 2021)
|
2
19
|
- few changes in provide / cached / daily for a more straigtforward forcing of cache renewal
|
3
20
|
- suggest: new method to suggest a contract for given symbol and date
|
data/README.md
CHANGED
@@ -90,5 +90,5 @@ Bug reports and pull requests are welcome on GitHub at https://github.com/donkey
|
|
90
90
|
|
91
91
|
## License
|
92
92
|
|
93
|
-
The gem is available as open source under the terms of the [
|
93
|
+
The gem is available as open source under the terms of the [BSD-3-Clause-License](https://opensource.org/licenses/BSD-3-Clause).
|
94
94
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.15.2
|
data/cotcube-bardata.gemspec
CHANGED
@@ -10,7 +10,7 @@ Gem::Specification.new do |spec|
|
|
10
10
|
spec.description = 'Functions to provide bardata; and some simple time series aggregations '
|
11
11
|
|
12
12
|
spec.homepage = "https://github.com/donkeybridge/#{spec.name}"
|
13
|
-
spec.license = 'BSD-
|
13
|
+
spec.license = 'BSD-3-Clause'
|
14
14
|
spec.required_ruby_version = Gem::Requirement.new('~> 2.7')
|
15
15
|
|
16
16
|
spec.metadata['homepage_uri'] = spec.homepage
|
data/lib/cotcube-bardata.rb
CHANGED
@@ -40,12 +40,13 @@ module Cotcube
|
|
40
40
|
quarters_file = "#{config[:data_path]}/quarters/#{sym[:id]}/#{contract[-3..]}.csv"
|
41
41
|
if File.exist?(file) && (not force_update)
|
42
42
|
puts "Working with existing #{file}, no update was forced" if debug
|
43
|
-
puts " Using quarters from #{quarters_file}"
|
43
|
+
puts " Using quarters from #{quarters_file}" if debug
|
44
44
|
base = CSV.read(file, headers: headers).map do |x|
|
45
45
|
x = x.to_h
|
46
46
|
x[:datetime] = timezone.parse(x[:datetime])
|
47
47
|
%i[open high low close].each { |z| x[z] = x[z].to_f.round(9) }
|
48
48
|
x[:volume] = x[:volume].to_i
|
49
|
+
x[:dist] = ((x[:high] - x[:low]) / sym[:ticksize] ).to_i
|
49
50
|
x[:type] = "#{filter.to_s.downcase}_day".to_sym
|
50
51
|
x
|
51
52
|
end
|
@@ -9,6 +9,7 @@ module Cotcube
|
|
9
9
|
range: nil,
|
10
10
|
timezone: Time.find_zone('America/Chicago'),
|
11
11
|
keep_last: false,
|
12
|
+
add_eods: true,
|
12
13
|
config: init)
|
13
14
|
contract = contract.to_s.upcase
|
14
15
|
unless contract.is_a?(String) && [3, 5].include?(contract.size)
|
@@ -46,10 +47,29 @@ module Cotcube
|
|
46
47
|
row[k] = row[k].to_i if %i[volume oi].include? k
|
47
48
|
end
|
48
49
|
row[:datetime] = timezone.parse(row[:date])
|
50
|
+
row[:dist] = ((row[:high] - row[:low]) / sym[:ticksize] ).to_i
|
49
51
|
row[:type] = :daily
|
50
52
|
row
|
51
53
|
end
|
52
|
-
|
54
|
+
contract_expired = data.last[:high].zero?
|
55
|
+
data.pop if contract_expired and not keep_last
|
56
|
+
if not contract_expired and add_eods
|
57
|
+
today = Date.today
|
58
|
+
eods = [ ]
|
59
|
+
while today.strftime('%Y-%m-%d') > data.last[:date]
|
60
|
+
eods << provide_eods(symbol: sym[:symbol], dates: today, contracts_only: false)
|
61
|
+
today -= 1
|
62
|
+
end
|
63
|
+
eods.flatten!.map!{|x| x.tap {|y| %i[ volume_part oi_part ].map{|z| y.delete(z)} } }
|
64
|
+
eods.select{|x| x[:contract] == contract }
|
65
|
+
eods.map!{|x| x.tap{|y|
|
66
|
+
y[:datetime] = timezone.parse(y[:date])
|
67
|
+
y[:dist] = ((y[:high] - y[:low]) / sym[:ticksize] ).to_i
|
68
|
+
y[:type] = :eod
|
69
|
+
} }
|
70
|
+
data += eods.reverse
|
71
|
+
|
72
|
+
end
|
53
73
|
if range.nil?
|
54
74
|
data
|
55
75
|
else
|
@@ -62,7 +82,7 @@ module Cotcube
|
|
62
82
|
|
63
83
|
# reads all files in bardata/daily/<id> and aggregates by date
|
64
84
|
# (what is a pre-stage of a continuous based on daily bars)
|
65
|
-
def continuous(symbol: nil, id: nil, config: init, date: nil, measure: nil, force_rewrite: false)
|
85
|
+
def continuous(symbol: nil, id: nil, config: init, date: nil, measure: nil, force_rewrite: false, selector: nil, debug: false, add_eods: true)
|
66
86
|
raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
|
67
87
|
measuring = lambda {|c| puts "[continuous] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
|
68
88
|
|
@@ -70,41 +90,117 @@ module Cotcube
|
|
70
90
|
sym = get_id_set(symbol: symbol, id: id)
|
71
91
|
id = sym[:id]
|
72
92
|
symbol = sym[:symbol]
|
93
|
+
ticksize = sym[:ticksize]
|
94
|
+
effective_selector = selector || :volume
|
95
|
+
raise ArgumentError, 'selector must be in %i[ nil :volume ;oi].' unless [ nil, :volume, :oi ].include? selector
|
73
96
|
id_path = "#{config[:data_path]}/daily/#{id}"
|
74
97
|
c_file = "#{id_path}/continuous.csv"
|
98
|
+
puts "Using file #{c_file}" if debug
|
75
99
|
|
76
100
|
# instead of using the provide_daily methods above, for this bulk operation a 'continuous.csv' is created
|
77
101
|
# this boosts from 4.5sec to 0.3sec
|
78
102
|
rewriting = force_rewrite or not(File.exist?(c_file)) or (Time.now - File.mtime(c_file) > 8.days)
|
79
103
|
if rewriting
|
80
104
|
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 '
|
105
|
+
`rm #{c_file}; find #{id_path} | xargs cat 2>/dev/null | grep -v ',0,' | grep -v ',0$'| sort -t, -k2 | cut -d, -f1-8 | grep ',.*,' | uniq > #{c_file}`
|
82
106
|
end
|
83
107
|
loading = lambda do
|
84
108
|
data = CSV.read(c_file).map do |row|
|
85
109
|
r = { contract: row[0],
|
86
110
|
date: row[1],
|
87
|
-
|
88
|
-
|
111
|
+
open: row[2],
|
112
|
+
high: row[3],
|
113
|
+
low: row[4],
|
114
|
+
close: row[5],
|
115
|
+
volume: row[6].to_i,
|
116
|
+
oi: row[7].to_i
|
89
117
|
}
|
90
118
|
end
|
119
|
+
if add_eods
|
120
|
+
today = Date.today
|
121
|
+
eods = [ ]
|
122
|
+
while today.strftime('%Y-%m-%d') > data.last[:date]
|
123
|
+
eods << provide_eods(symbol: symbol, dates: today, contracts_only: false)
|
124
|
+
today -= 1
|
125
|
+
end
|
126
|
+
eods.flatten!.map!{|x| x.tap {|y| %i[ volume_part oi_part ].map{|z| y.delete(z)} } }
|
127
|
+
eods.delete_if { |elem| elem.flatten.empty? }
|
128
|
+
data += eods.reverse
|
129
|
+
|
130
|
+
end
|
91
131
|
|
92
132
|
measuring.call("Finished retrieving dailies.")
|
93
133
|
result = []
|
134
|
+
rounding = 8 # sym[:format].split('.').last.to_i rescue 6
|
135
|
+
indicators ||= {
|
136
|
+
typical: Cotcube::Indicators.calc(a: :high, b: :low, c: :close) {|high, low, close| (high + low + close) / 3 },
|
137
|
+
sma250_high: Cotcube::Indicators.sma(key: :high, length: 250),
|
138
|
+
sma250_low: Cotcube::Indicators.sma(key: :low, length: 250),
|
139
|
+
sma250_typ: Cotcube::Indicators.sma(key: :typical, length: 250),
|
140
|
+
# sma60_typ: Cotcube::Indicators.sma(key: :typical, length: short),
|
141
|
+
# tr: Cotcube::Indicators.true_range,
|
142
|
+
# atr5: Cotcube::Indicators.sma(key: :tr, length: 5),
|
143
|
+
# dist_abs: Cotcube::Indicators.calc(a: :sma250_high, b: :sma250_low, c: :high, d: :low) do |sma_high, sma_low, high, low|
|
144
|
+
# if high > sma_high
|
145
|
+
# high - sma_high
|
146
|
+
# elsif sma_low > low
|
147
|
+
# low - sma_low
|
148
|
+
# else
|
149
|
+
# 0
|
150
|
+
# end
|
151
|
+
#end,
|
152
|
+
#dist_sma: Cotcube::Indicators.calc(a: :sma250_typ, b: :sma60_typ) do |sma250, sma60|
|
153
|
+
# sma60 - sma250
|
154
|
+
#end,
|
155
|
+
#dist_index: Cotcube::Indicators.index(key: :dist_abs, length: 60, abs: true),
|
156
|
+
#dev250_squared: Cotcube::Indicators.calc(a: :sma250_typ, b: :typical) {|sma, x| (sma - x) ** 2 },
|
157
|
+
#var250: Cotcube::Indicators.sma(key: :dev250_squared, length: long),
|
158
|
+
#sig250: Cotcube::Indicators.calc(a: :var250) {|var| Math.sqrt(var)},
|
159
|
+
#boll250_high: Cotcube::Indicators.calc(a: :sig250, b: :sma250_typ) {|sig, typ| (typ + sig * bollinger_factor) rescue nil},
|
160
|
+
#boll250_low: Cotcube::Indicators.calc(a: :sig250, b: :sma250_typ) {|sig, typ| (typ - sig * bollinger_factor) rescue nil},
|
161
|
+
#dev60_squared: Cotcube::Indicators.calc(a: :sma60_typ, b: :typical) {|sma, x| (sma - x) ** 2 },
|
162
|
+
#var60: Cotcube::Indicators.sma(key: :dev60_squared, length: short),
|
163
|
+
#sig60: Cotcube::Indicators.calc(a: :var60) {|var| Math.sqrt(var)},
|
164
|
+
#boll60_high: Cotcube::Indicators.calc(a: :sig60, b: :sma60_typ) {|sig, typ| (typ + sig * bollinger_factor) rescue nil},
|
165
|
+
#boll60_low: Cotcube::Indicators.calc(a: :sig60, b: :sma60_typ) {|sig, typ| (typ - sig * bollinger_factor) rescue nil}
|
166
|
+
dist: Cotcube::Indicators.calc(a: :high, b: :low, finalize: :to_i) {|high, low| ((high-low) / ticksize) }
|
167
|
+
|
168
|
+
}
|
169
|
+
|
170
|
+
|
171
|
+
|
94
172
|
data.group_by { |x| x[:date] }.map do |k, v|
|
95
173
|
v.map { |x| x.delete(:date) }
|
96
|
-
|
174
|
+
avg_bar = {
|
97
175
|
date: k,
|
98
|
-
|
99
|
-
|
176
|
+
contract: v.max_by{|x| x[:oi] }[:contract],
|
177
|
+
open: nil, high: nil, low: nil, close: nil,
|
178
|
+
volume: v.map { |x| x[:volume] }.reduce(:+),
|
179
|
+
oi: v.map { |x| x[:oi] }.reduce(:+),
|
180
|
+
}
|
181
|
+
|
182
|
+
%i[ open high low close ].each do |ohlc|
|
183
|
+
avg_bar[ohlc] = (v.map{|x| x[ohlc].to_f * x[effective_selector] }.reduce(:+) / avg_bar[effective_selector]).round(rounding)
|
184
|
+
end
|
185
|
+
p avg_bar if debug
|
186
|
+
indicators.each do |k,v|
|
187
|
+
print format('%12s: ', k.to_s) if debug
|
188
|
+
avg_bar[k] = v.call(avg_bar).round(rounding)
|
189
|
+
puts avg_bar[k] if debug
|
190
|
+
end
|
191
|
+
%i[tr atr5].each { |ind|
|
192
|
+
avg_bar[ind] = (avg_bar[ind] / sym[:ticksize]).round.to_i unless avg_bar[ind].nil?
|
100
193
|
}
|
194
|
+
result << avg_bar
|
101
195
|
result.last[:contracts] = v
|
102
196
|
end
|
103
197
|
result
|
104
198
|
end
|
105
|
-
constname = "CONTINUOUS_#{symbol}".to_sym
|
199
|
+
constname = "CONTINUOUS_#{symbol}#{selector.nil? ? '' : ('_' + selector.to_s)}".to_sym
|
106
200
|
if rewriting or not Cotcube::Bardata.const_defined?( constname)
|
201
|
+
old = $VERBOSE; $VERBOSE = nil
|
107
202
|
Cotcube::Bardata.const_set constname, loading.call
|
203
|
+
$VERBOSE = old
|
108
204
|
end
|
109
205
|
measuring.call("Finished processing")
|
110
206
|
date.nil? ? Cotcube::Bardata.const_get(constname).map{|z| z.dup } : Cotcube::Bardata.const_get(constname).find { |x| x[:date] == date }
|
@@ -277,7 +373,7 @@ module Cotcube
|
|
277
373
|
}\tto #{format '%5d', ldays.max
|
278
374
|
}: #{dfm.call(ldays.max)}".colorize(color)
|
279
375
|
if debug || (color != :white)
|
280
|
-
puts output
|
376
|
+
puts output unless silent
|
281
377
|
output_sent << "#{sym[:symbol]}#{month}" unless color == :white
|
282
378
|
end
|
283
379
|
early_year ||= output
|
@@ -288,20 +384,22 @@ module Cotcube
|
|
288
384
|
}\t#{v1.first[:date]
|
289
385
|
} (#{format '%3d', Date.parse(v1.first[:date]).yday
|
290
386
|
})\t#{Date.parse(v1.last[:date]).strftime('%a, %Y-%m-%d')
|
291
|
-
} (#{Date.parse(v1.last[:date]).yday})"
|
387
|
+
} (#{Date.parse(v1.last[:date]).yday})" unless silent
|
292
388
|
# rubocop:enable Layout/ClosingParenthesisIndentation
|
293
389
|
end
|
294
|
-
|
390
|
+
end
|
295
391
|
case output_sent.size
|
296
392
|
when 0
|
297
|
-
|
298
|
-
|
299
|
-
|
393
|
+
unless silent
|
394
|
+
puts "WARNING: No output was sent for symbol '#{sym[:symbol]}'.".colorize(:light_yellow)
|
395
|
+
puts " Assuming late-year-processing.".light_yellow
|
396
|
+
puts early_year.light_green
|
397
|
+
end
|
300
398
|
when 1
|
301
399
|
# all ok
|
302
400
|
true
|
303
401
|
else
|
304
|
-
puts "Continuous table show #{output_sent.size} active contracts ( #{output_sent} ) for #{sym[:symbol]} ---------------"
|
402
|
+
puts "Continuous table show #{output_sent.size} active contracts ( #{output_sent} ) for #{sym[:symbol]} ---------------" unless silent
|
305
403
|
end
|
306
404
|
measuring.call("Finished processing")
|
307
405
|
short ? output_sent : long_output
|
@@ -54,5 +54,11 @@ module Cotcube
|
|
54
54
|
raise ArgumentError, "Unsupported or unknown interval '#{interval}' in Bardata.provide"
|
55
55
|
end
|
56
56
|
end
|
57
|
+
|
58
|
+
def determine_significant_volume(base: , contract: )
|
59
|
+
set = Cotcube::Bardata.trading_hours(symbol: contract[0..1], filter: :rth)
|
60
|
+
prod = base - base.select_within(ranges: set ,attr: :datetime) {|x| x.to_datetime.to_sssm }
|
61
|
+
prod.group_by{|x| x[:volume] / 500 }
|
62
|
+
end
|
57
63
|
end
|
58
64
|
end
|
@@ -33,6 +33,7 @@ module Cotcube
|
|
33
33
|
%i[open high low close].map { |x| row[x] = row[x].to_f }
|
34
34
|
%i[volume day].map { |x| row[x] = row[x].to_i }
|
35
35
|
row[:datetime] = timezone.parse(row[:datetime])
|
36
|
+
row[:dist] = ((row[:high] - row[:low]) / sym[:ticksize] ).to_i
|
36
37
|
row[:type] = :quarter
|
37
38
|
row
|
38
39
|
end
|
@@ -5,7 +5,7 @@ module Cotcube
|
|
5
5
|
module Bardata
|
6
6
|
# based on day(of year) and symbol, suggest best fitting contract
|
7
7
|
def suggest_contract_for symbol:, date: Date.today, warnings: true
|
8
|
-
ml = Cotcube::Bardata.continuous_table symbol: symbol, date: date
|
8
|
+
ml = Cotcube::Bardata.continuous_table symbol: symbol, date: date, silent: true
|
9
9
|
if ml.size != 1
|
10
10
|
puts "WARNING: No or no unique most liquid found for #{date}. please give :contract parameter".light_yellow if warnings
|
11
11
|
if ml.size > 1
|
@@ -5,19 +5,45 @@ module Cotcube
|
|
5
5
|
module Bardata
|
6
6
|
# fetching official trade dates from CME
|
7
7
|
# it returns the current trade date or, if today isn't a trading day, the last trade date.
|
8
|
-
def last_trade_date
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
"
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
8
|
+
def last_trade_date(force_update: false)
|
9
|
+
const_LTD = :LAST_TRADE_DATE
|
10
|
+
const_LTDU = :LAST_TRADE_DATE_UPDATE
|
11
|
+
if force_update or not Object.const_defined?(const_LTD) or Object.const_get(const_LTD).nil? or Time.now - Object.const_get(const_LTDU) > 2.hours
|
12
|
+
result = nil
|
13
|
+
uri = 'https://www.cmegroup.com/CmeWS/mvc/Volume/TradeDates?exchange=CME'
|
14
|
+
headers = { "Accept" => "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
|
15
|
+
"Accept-Encoding" => "gzip, deflate, br",
|
16
|
+
"Accept-Language" => "en-US,en;q=0.9",
|
17
|
+
"Cache-Control" => "max-age=0",
|
18
|
+
"Connection" => "keep-alive",
|
19
|
+
# Cookie: ak_bmsc=602078F6DE40954BAA8C7E7D3815102CACE82AAFD237000084B5A460F4FBCA68~pluz010T49Xag3sXquUZtVJmFX701dzEgt5v6Ht1EZSLKE4HL+bgg1L9ePnL5I0mm7QWXe1qaLhUbX1IPrL/f20trRMMRlkC3UWXk27DY/EBCP4mRno8QQygLCwgs2B2AQHJyb63WwRihCko8UYUiIhb89ArPZM5OPraoKy3JU9oE9e+iERdARNZHLHqRiB1GnmbKUvQqos3sXaEe3GpoiTszzk8sHZs4ZKuoO/rvFHko=",
|
20
|
+
"Host" => "www.cmegroup.com",
|
21
|
+
"sec-ch-ua" => %q[" Not A;Brand";v="99", "Chromium";v="90", "Google Chrome";v="90"],
|
22
|
+
"sec-ch-ua-mobile" => "?0",
|
23
|
+
"Sec-Fetch-Dest" => "document",
|
24
|
+
"Sec-Fetch-Mode" => "navigate",
|
25
|
+
"Sec-Fetch-Site" => "none",
|
26
|
+
"Sec-Fetch-User" => "?1",
|
27
|
+
"Upgrade-Insecure-Requests" => "1",
|
28
|
+
"User-Agent" => "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36" }
|
29
|
+
begin
|
30
|
+
# HTTParty.get(uri, headers: { "User-Agent" => "Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/81.0"})
|
31
|
+
result = HTTParty.get(uri, headers: headers)
|
32
|
+
.parsed_response
|
33
|
+
.map do |x|
|
34
|
+
a = x['tradeDate'].chars.each_slice(2).map(&:join)
|
35
|
+
"#{a[0]}#{a[1]}-#{a[2]}-#{a[3]}"
|
36
|
+
end
|
37
|
+
.first
|
38
|
+
rescue StandardError
|
39
|
+
result = nil
|
40
|
+
end
|
41
|
+
oldverbose = $VERBOSE; $VERBOSE = nil
|
42
|
+
Object.const_set(const_LTD, result)
|
43
|
+
Object.const_set(const_LTDU, Time.now) unless result.nil?
|
44
|
+
$VERBOSE = oldverbose
|
20
45
|
end
|
46
|
+
Object.const_get(const_LTD)
|
21
47
|
end
|
22
48
|
|
23
49
|
def holidays(config: init)
|
@@ -12,14 +12,20 @@ module Cotcube
|
|
12
12
|
filter: ,
|
13
13
|
force_filter: false, # with force_filter one would avoid falling back
|
14
14
|
# to the contract_type based range set
|
15
|
+
headers_only: false, # return only headers instead of ranges
|
15
16
|
config: init, debug: false)
|
16
17
|
return (0...24 * 7 * 3600) if filter.to_s =~ /24x7/
|
17
18
|
|
18
19
|
prepare = lambda do |f|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
20
|
+
if headers_only
|
21
|
+
CSV.read(f)
|
22
|
+
.first
|
23
|
+
else
|
24
|
+
CSV.read(f, converters: :numeric)
|
25
|
+
.map(&:to_a)
|
26
|
+
.tap { |x| x.shift unless x.first.first.is_a?(Numeric) }
|
27
|
+
.map { |x| (x.first...x.last) }
|
28
|
+
end
|
23
29
|
end
|
24
30
|
|
25
31
|
sym = get_id_set(symbol: symbol, id: id)
|
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.15.2
|
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-08-04 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -180,7 +180,7 @@ files:
|
|
180
180
|
- lib/cotcube-bardata/trading_hours.rb
|
181
181
|
homepage: https://github.com/donkeybridge/cotcube-bardata
|
182
182
|
licenses:
|
183
|
-
- BSD-
|
183
|
+
- BSD-3-Clause
|
184
184
|
metadata:
|
185
185
|
homepage_uri: https://github.com/donkeybridge/cotcube-bardata
|
186
186
|
source_code_uri: https://github.com/donkeybridge/cotcube-bardata
|