cotcube-bardata 0.1.5 → 0.1.9.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 +23 -0
- data/VERSION +1 -1
- data/cotcube-bardata.gemspec +3 -2
- data/lib/cotcube-bardata.rb +5 -0
- data/lib/cotcube-bardata/cached.rb +54 -8
- data/lib/cotcube-bardata/daily.rb +134 -7
- data/lib/cotcube-bardata/helpers.rb +4 -4
- data/lib/cotcube-bardata/provide.rb +13 -7
- data/lib/cotcube-bardata/range_matrix.rb +42 -33
- data/lib/cotcube-bardata/trading_hours.rb +12 -10
- metadata +6 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 42d2c651e2e0cc53cbd35ea0ea824e82828930bee04d1bce9a52edf9b70c54f1
|
4
|
+
data.tar.gz: 388c35d25810c30a73136e66e0e204473dd2646f2ea776c23a476b8cb769afb7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 705ded304d33270f8133a5e297a807a56288b7a710ac12f6aa2896f4971c2302f6e5a3a9b229c8c513489abb32bbe3079e0f60bdf094756935f19a6d84d7d276
|
7
|
+
data.tar.gz: e36f72ffc6dbf098a86b647932f8d881016477ebb74223b8db12f75f3e9c58f4962eef7da5992838c72538d1e18545f647b4df104554e70727ba45694b55de59
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,26 @@
|
|
1
|
+
## 0.1.9.2 (February 07, 2021)
|
2
|
+
- minor changes
|
3
|
+
- daily#continuous_table: introducing debuglevel
|
4
|
+
|
5
|
+
## 0.1.9.1 (January 29, 2021)
|
6
|
+
- provide: added new interval 'synth', mixing available dailies with synthetic days based on quarters
|
7
|
+
- minor change / cleanup
|
8
|
+
- setting gemspec to use rake 13 and changing version spec to overcome warnings
|
9
|
+
|
10
|
+
## 0.1.8 (January 27, 2021)
|
11
|
+
- in helpers, #extended_range_for_date: fixed comparison signs
|
12
|
+
- range_matrix: applied cops, noted appearance of Cotcube::Helpers.simple_series_stats
|
13
|
+
- cached: Fixing wrong comparison sign
|
14
|
+
- daily: slimmed down results for #continuous_overview
|
15
|
+
|
16
|
+
## 0.1.7 (January 14, 2021)
|
17
|
+
- added :range parameter to :provide, hence to :provide_cached, :provide_daily
|
18
|
+
- added forgotten module_functions
|
19
|
+
|
20
|
+
## 0.1.6 (January 07, 2021)
|
21
|
+
- prefering datetime instead date (in helpers and daily)
|
22
|
+
- changed keyword :set to :filter in cached, provide and trading_hours
|
23
|
+
|
1
24
|
## 0.1.5 (January 02, 2021)
|
2
25
|
- applied some still missing cops
|
3
26
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.9.2
|
data/cotcube-bardata.gemspec
CHANGED
@@ -34,7 +34,8 @@ Gem::Specification.new do |spec|
|
|
34
34
|
spec.add_dependency 'parallel', '~> 1'
|
35
35
|
spec.add_dependency 'yaml', '~> 0.1'
|
36
36
|
|
37
|
-
|
37
|
+
# using ~> in favor of >= to overcome warning
|
38
|
+
spec.add_development_dependency 'rake', '~> 13'
|
38
39
|
spec.add_development_dependency 'rspec', '~>3.6'
|
39
|
-
spec.add_development_dependency 'yard',
|
40
|
+
spec.add_development_dependency 'yard', '~>0.9'
|
40
41
|
end
|
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
|
@@ -60,6 +62,9 @@ module Cotcube
|
|
60
62
|
:trading_hours,
|
61
63
|
# receive id / symbol information on an uncertain set of parameters
|
62
64
|
:get_id_set,
|
65
|
+
:select_specific_date,
|
66
|
+
:extended_select_for_range,
|
67
|
+
:provide_cached,
|
63
68
|
:compare,
|
64
69
|
:holidays,
|
65
70
|
:symbols # reads and provides the symbols file
|
@@ -6,12 +6,29 @@ module Cotcube
|
|
6
6
|
# send pre-created days based on quarters
|
7
7
|
def provide_cached(contract:, # rubocop:disable Metrics/ParameterLists
|
8
8
|
symbol: nil, id: nil,
|
9
|
+
range: nil,
|
9
10
|
config: init,
|
11
|
+
debug: false,
|
10
12
|
timezone: Time.find_zone('America/Chicago'),
|
11
13
|
filter: :full, # most probably either :full or :rth
|
12
14
|
force_update: false, # force reloading via provide_quarters
|
13
15
|
force_recent: false) #
|
14
16
|
|
17
|
+
unless range.nil? ||
|
18
|
+
range.is_a?(Range) &&
|
19
|
+
[Date, DateTime, ActiveSupport::TimeWithZone].map do |cl|
|
20
|
+
(range.begin.nil? || range.begin.is_a?(cl)) &&
|
21
|
+
(range.end.nil? || range.end.is_a?(cl))
|
22
|
+
end.reduce(:|)
|
23
|
+
raise ArgumentError, 'Range, if given, must be either (Integer..Integer) or (Timelike..Timelike)'
|
24
|
+
end
|
25
|
+
|
26
|
+
unless range.nil?
|
27
|
+
range_begin = range.begin.nil? ? nil : timezone.parse(range.begin.to_s)
|
28
|
+
range_end = range.end.nil? ? nil : timezone.parse(range.end.to_s)
|
29
|
+
range = (range_begin..range_end)
|
30
|
+
end
|
31
|
+
|
15
32
|
headers = %i[contract datetime open high low close volume]
|
16
33
|
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
17
34
|
contract = contract[-3..]
|
@@ -33,18 +50,40 @@ module Cotcube
|
|
33
50
|
if base.last[:high].zero?
|
34
51
|
# contract exists but is closed (has the CLOSED marker)
|
35
52
|
base.pop
|
36
|
-
|
37
|
-
|
38
|
-
|
53
|
+
# rubocop:disable Metrics/BlockNesting
|
54
|
+
result = if range.nil?
|
55
|
+
base
|
56
|
+
else
|
57
|
+
base.select do |x|
|
58
|
+
(range.begin.nil? ? true : x[:datetime] >= range.begin) and
|
59
|
+
(range.end.nil? ? true : x[:datetime] <= range.end)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
return result
|
63
|
+
elsif File.mtime(file) + 1.day > File.mtime(quarters_file)
|
64
|
+
puts "CACHE #{File.mtime(file)}\t#{file}" if debug
|
65
|
+
puts "QUART #{File.mtime(quarters_file)}\t#{quarters_file}" if debug
|
66
|
+
result = if range.nil?
|
67
|
+
base
|
68
|
+
else
|
69
|
+
base.select do |x|
|
70
|
+
(range.begin.nil? ? true : x[:datetime] >= range.begin) and
|
71
|
+
(range.end.nil? ? true : x[:datetime] <= range.end)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
# rubocop:enable Metrics/BlockNesting
|
75
|
+
return result
|
39
76
|
else
|
40
|
-
|
77
|
+
# write a (positive warning, that the cache needs to be updated, as cached value is older
|
78
|
+
# than one day but not closed
|
79
|
+
puts "File #{file} exists, but is neither closed nor current. Running update...".colorize(:light_green)
|
41
80
|
end
|
42
81
|
end
|
43
82
|
begin
|
44
83
|
data = provide_quarters(contract: contract, id: sym[:id], keep_marker: true)
|
45
84
|
rescue StandardError
|
46
85
|
puts "Cannot provide quarters for requested contract #{sym[:symbol]}:#{contract},"\
|
47
|
-
|
86
|
+
"returning '[ ]'".colorize(:light_red)
|
48
87
|
return []
|
49
88
|
end
|
50
89
|
|
@@ -52,13 +91,13 @@ module Cotcube
|
|
52
91
|
contract_is_marked = data.last[:high].zero?
|
53
92
|
data.pop if contract_is_marked
|
54
93
|
unless (filter == :full) || (data.size < 3)
|
55
|
-
requested_set = trading_hours(symbol: sym[:symbol],
|
94
|
+
requested_set = trading_hours(symbol: sym[:symbol], filter: filter)
|
56
95
|
data = data.select_within(ranges: requested_set, attr: :datetime) { |x| x.to_datetime.to_sssm }
|
57
96
|
end
|
58
97
|
|
59
98
|
base = Cotcube::Helpers.reduce(bars: data, to: :days)
|
60
99
|
|
61
|
-
# remove last day of result
|
100
|
+
# remove last day of result unless marked
|
62
101
|
base.pop unless contract_is_marked || force_recent
|
63
102
|
|
64
103
|
base.map do |x|
|
@@ -73,7 +112,14 @@ module Cotcube
|
|
73
112
|
csv << marker
|
74
113
|
end
|
75
114
|
end
|
76
|
-
|
115
|
+
if range.nil?
|
116
|
+
base
|
117
|
+
else
|
118
|
+
base.select do |x|
|
119
|
+
(range.begin.nil? ? true : x[:date] >= range.begin) and
|
120
|
+
(range.end.nil? ? true : x[:date] <= range.end)
|
121
|
+
end
|
122
|
+
end
|
77
123
|
end
|
78
124
|
end
|
79
125
|
end
|
@@ -4,14 +4,30 @@ module Cotcube
|
|
4
4
|
# Missing top level documentation comment
|
5
5
|
module Bardata
|
6
6
|
# just reads bardata/daily/<id>/<contract>.csv
|
7
|
-
def provide_daily(contract:,
|
7
|
+
def provide_daily(contract:, # rubocop:disable Metrics/ParameterLists
|
8
8
|
symbol: nil, id: nil,
|
9
|
+
range: nil,
|
9
10
|
timezone: Time.find_zone('America/Chicago'),
|
10
11
|
config: init)
|
11
12
|
contract = contract.to_s.upcase
|
12
13
|
unless contract.is_a?(String) && [3, 5].include?(contract.size)
|
13
14
|
raise ArgumentError, "Contract '#{contract}' is bogus, should be like 'M21' or 'ESM21'"
|
14
15
|
end
|
16
|
+
unless range.nil? ||
|
17
|
+
(range.is_a?(Range) &&
|
18
|
+
[Date, DateTime, ActiveSupport::TimeWithZone].map do |cl|
|
19
|
+
(range.begin.nil? || range.begin.is_a?(cl)) &&
|
20
|
+
(range.end.nil? || range.end.is_a?(cl))
|
21
|
+
end.reduce(:|))
|
22
|
+
|
23
|
+
raise ArgumentError, 'Range, if given, must be either (Integer..Integer) or (Timelike..Timelike)'
|
24
|
+
end
|
25
|
+
|
26
|
+
unless range.nil?
|
27
|
+
range_begin = range.begin.nil? ? nil : timezone.parse(range.begin.to_s)
|
28
|
+
range_end = range.end.nil? ? nil : timezone.parse(range.end.to_s)
|
29
|
+
range = (range_begin..range_end)
|
30
|
+
end
|
15
31
|
|
16
32
|
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
17
33
|
contract = contract[2..4] if contract.to_s.size == 5
|
@@ -28,12 +44,19 @@ module Cotcube
|
|
28
44
|
row[k] = row[k].to_f if %i[open high low close].include? k
|
29
45
|
row[k] = row[k].to_i if %i[volume oi].include? k
|
30
46
|
end
|
31
|
-
row[:datetime] = timezone.parse(row[:date])
|
47
|
+
row[:datetime] = timezone.parse(row[:date])
|
32
48
|
row[:type] = :daily
|
33
49
|
row
|
34
50
|
end
|
35
51
|
data.pop if data.last[:high].zero?
|
36
|
-
|
52
|
+
if range.nil?
|
53
|
+
data
|
54
|
+
else
|
55
|
+
data.select do |x|
|
56
|
+
(range.begin.nil? ? true : x[:datetime] >= range.begin) and
|
57
|
+
(range.end.nil? ? true : x[:datetime] <= range.end)
|
58
|
+
end
|
59
|
+
end
|
37
60
|
end
|
38
61
|
|
39
62
|
# reads all files in bardata/daily/<id> and aggregates by date
|
@@ -109,6 +132,13 @@ module Cotcube
|
|
109
132
|
end
|
110
133
|
data.reject! { |x| x[selector].empty? }
|
111
134
|
result = data.group_by { |x| x[selector].first[:contract] }
|
135
|
+
result.each_key do |key|
|
136
|
+
result[key].map! do |x|
|
137
|
+
x[:volume].select! { |z| z[:contract] == key }
|
138
|
+
x[:oi].select! { |z| z[:contract] == key }
|
139
|
+
x
|
140
|
+
end
|
141
|
+
end
|
112
142
|
if human
|
113
143
|
result.each do |k, v|
|
114
144
|
next unless filter.nil? || v.first[selector].first[:contract][2..4] =~ (/#{filter}/)
|
@@ -119,15 +149,112 @@ module Cotcube
|
|
119
149
|
}\t#{v.last[:date]
|
120
150
|
}\t#{format('%4d', (Date.parse(v.last[:date]) - Date.parse(v.first[:date])))
|
121
151
|
}\t#{result[k].map do |x|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
152
|
+
x[:volume].select do
|
153
|
+
x[:contract] == k
|
154
|
+
end
|
155
|
+
end.size
|
126
156
|
}"
|
127
157
|
# rubocop:enable Layout/ClosingParenthesisIndentation
|
128
158
|
end
|
129
159
|
end
|
130
160
|
result
|
131
161
|
end
|
162
|
+
|
163
|
+
def continuous_table(symbol: nil, id: nil,
|
164
|
+
selector: :volume,
|
165
|
+
filter: nil,
|
166
|
+
date: Date.today,
|
167
|
+
debuglevel: 1,
|
168
|
+
debug: false)
|
169
|
+
if debug.is_a?(Integer)
|
170
|
+
debuglevel = debug
|
171
|
+
debug = debuglevel > 0 ? true : false
|
172
|
+
end
|
173
|
+
raise ArgumentError, 'Selector must be either :volume or :oi' unless selector.is_a?(Symbol) &&
|
174
|
+
%i[volume oi].include?(selector)
|
175
|
+
|
176
|
+
sym = get_id_set(symbol: symbol, id: id)
|
177
|
+
if %w[R6 BJ GE].include? sym[:symbol]
|
178
|
+
puts "Rejecting to process symbol '#{sym[:symbol]}'."
|
179
|
+
return
|
180
|
+
end
|
181
|
+
id = sym[:id]
|
182
|
+
dfm = lambda do |x, y = date.year|
|
183
|
+
k = Date.strptime("#{y} #{x.negative? ? x + 366 : x}", '%Y %j')
|
184
|
+
k -= 1 while [0, 6].include?(k.wday)
|
185
|
+
k.strftime('%a, %Y-%m-%d')
|
186
|
+
rescue StandardError
|
187
|
+
puts "#{sym[:symbol]}\t#{x}\t#{y}"
|
188
|
+
end
|
189
|
+
|
190
|
+
ytoday = date.yday
|
191
|
+
data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init)
|
192
|
+
.reject { |k, _| k[-2..].to_i == date.year % 2000 }
|
193
|
+
.group_by { |k, _| k[2] }
|
194
|
+
output_sent = []
|
195
|
+
early_year=nil
|
196
|
+
data.keys.sort.each do |month|
|
197
|
+
puts "Processing #{sym[:symbol]}#{month}" if debuglevel > 1
|
198
|
+
v0 = data[month]
|
199
|
+
ydays = v0.map { |_, v1| Date.parse(v1.last[:date]).yday }
|
200
|
+
fdays = v0.map { |_, v1| Date.parse(v1.first[:date]).yday }.sort
|
201
|
+
# 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
|
203
|
+
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)
|
209
|
+
:light_red
|
210
|
+
elsif (ytoday > ydays.min) && (ytoday < yavg - 1)
|
211
|
+
:light_yellow
|
212
|
+
elsif (ytoday >= (fday > yavg ? 0 : fday - 5)) && (ytoday <= ydays.min)
|
213
|
+
:light_green
|
214
|
+
else
|
215
|
+
:white
|
216
|
+
end
|
217
|
+
# rubocop:disable Layout/ClosingParenthesisIndentation
|
218
|
+
output = "#{sym[:symbol]
|
219
|
+
}#{month
|
220
|
+
}\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)
|
235
|
+
|
236
|
+
v0.each do |contract, v1|
|
237
|
+
puts "\t#{contract
|
238
|
+
}\t#{v1.first[:date]
|
239
|
+
}\t#{Date.parse(v1.last[:date]).strftime('%a')
|
240
|
+
}, #{v1.last[:date]
|
241
|
+
} (#{Date.parse(v1.last[:date]).yday}"
|
242
|
+
# rubocop:enable Layout/ClosingParenthesisIndentation
|
243
|
+
end
|
244
|
+
end
|
245
|
+
case output_sent.size
|
246
|
+
when 0
|
247
|
+
puts "WARNING: No output was sent for symbol '#{sym[:symbol]}'.".colorize(:light_yellow)
|
248
|
+
puts " Assuming late-year-processing.".light_yellow
|
249
|
+
puts early_year.light_green
|
250
|
+
when 1
|
251
|
+
# all ok
|
252
|
+
true
|
253
|
+
else
|
254
|
+
puts "---- #{output_sent} for #{sym[:symbol]} ---------------"
|
255
|
+
|
256
|
+
end
|
257
|
+
output_sent
|
258
|
+
end
|
132
259
|
end
|
133
260
|
end
|
@@ -36,11 +36,11 @@ module Cotcube
|
|
36
36
|
' is assumed (starting 5 pm CT yesterday, ending 4 pm CT today)'.colorize(:light_yellow)
|
37
37
|
end
|
38
38
|
result = select_specific_date(date: starting, base: base)
|
39
|
-
result += base.select { |d| d[:datetime]
|
39
|
+
result += base.select { |d| d[:datetime] >= starting and d[:datetime] < ending.to_date }
|
40
40
|
result += select_specific_date(date: ending, base: base)
|
41
41
|
result.uniq!
|
42
42
|
else
|
43
|
-
result = base.select { |x| x[:datetime] >= starting and x[:datetime]
|
43
|
+
result = base.select { |x| x[:datetime] >= starting and x[:datetime] <= ending }
|
44
44
|
end
|
45
45
|
result
|
46
46
|
end
|
@@ -83,8 +83,8 @@ module Cotcube
|
|
83
83
|
full = provide(contract: contract, interval: :days, filter: :full)
|
84
84
|
rth = provide(contract: contract, interval: :days, filter: :rth)
|
85
85
|
rth_dates = rth.map { |x| x[:datetime] }
|
86
|
-
daily.select! { |x| rth_dates.include? x[:datetime] }
|
87
|
-
full.select! { |x| rth_dates.include? x[:datetime] }
|
86
|
+
daily.select! { |x| rth_dates.include? x[:datetime].to_datetime }
|
87
|
+
full.select! { |x| rth_dates.include? x[:datetime].to_datetime }
|
88
88
|
|
89
89
|
printer = lambda { |z|
|
90
90
|
# rubocop:disable Layout/ClosingParenthesisIndentation
|
@@ -10,7 +10,7 @@ module Cotcube
|
|
10
10
|
config: init,
|
11
11
|
# supported types are :quarters, :hours, :days, :rth, :dailies, :weeks, :months
|
12
12
|
interval: :days,
|
13
|
-
# supported filters are :
|
13
|
+
# supported filters are :full and :rth (and custom named, if provided as file)
|
14
14
|
filter: :full,
|
15
15
|
# TODO: for future compatibility and suggestion: planning to include a function to update
|
16
16
|
# with live data from broker
|
@@ -22,7 +22,7 @@ module Cotcube
|
|
22
22
|
when :quarters, :hours, :quarter, :hour
|
23
23
|
base = provide_quarters(contract: contract, symbol: symbol, id: id, config: config)
|
24
24
|
base = extended_select_for_range(range: range, base: base) if range
|
25
|
-
requested_set = trading_hours(symbol: sym[:symbol],
|
25
|
+
requested_set = trading_hours(symbol: sym[:symbol], filter: filter)
|
26
26
|
|
27
27
|
base = base.select_within(ranges: requested_set, attr: :datetime) { |x| x.to_datetime.to_sssm }
|
28
28
|
return base if %i[quarters quarter].include? interval
|
@@ -33,16 +33,22 @@ module Cotcube
|
|
33
33
|
|
34
34
|
when :days, :weeks, :months
|
35
35
|
base = provide_cached contract: contract, symbol: symbol, id: id, config: config, filter: filter,
|
36
|
-
force_recent: force_recent
|
37
|
-
base = extended_select_for_range(range: range, base: base) if range
|
36
|
+
range: range, force_recent: force_recent
|
38
37
|
return base if %i[day days].include? interval
|
39
38
|
|
40
39
|
# TODO: Missing implementation to reduce cached days to weeks or months
|
41
40
|
raise 'Missing implementation to reduce cached days to weeks or months'
|
42
41
|
when :dailies, :daily
|
43
|
-
|
44
|
-
|
45
|
-
|
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]
|
48
|
+
dailies[..-2] + days.select { |d| d[:datetime] > dailies[-2][:datetime] }
|
49
|
+
else
|
50
|
+
dailies
|
51
|
+
end
|
46
52
|
else
|
47
53
|
raise ArgumentError, "Unsupported or unknown interval '#{interval}' in Bardata.provide"
|
48
54
|
end
|
@@ -12,7 +12,7 @@ module Cotcube
|
|
12
12
|
# 2. avg:
|
13
13
|
# 3. lower: like median, but not at 1/2 but 1/4
|
14
14
|
# 4. median:
|
15
|
-
# 5. upper: like median,
|
15
|
+
# 5. upper: like median, but not at 1/2 but 3/4
|
16
16
|
# 6. max:
|
17
17
|
# and columns:
|
18
18
|
# 1.a) all days os the series
|
@@ -20,6 +20,8 @@ module Cotcube
|
|
20
20
|
# 1.c) the last 200 days
|
21
21
|
# 2.a-c) same with days reduced to weeks (c: 52 weeks)
|
22
22
|
# 3.a-c) same with days reduced to months (c: 12 months)
|
23
|
+
#
|
24
|
+
# NOTE: there is now a new method Cotcube::Helpers.simple_series_stats, that should be used in favor.
|
23
25
|
def range_matrix(symbol: nil, id: nil, print: false, dim: 0.05)
|
24
26
|
# rubocop:disable Style/MultilineBlockChain
|
25
27
|
sym = get_id_set(symbol: symbol, id: id)
|
@@ -38,36 +40,43 @@ module Cotcube
|
|
38
40
|
target[period][:all_size] = source[period].size
|
39
41
|
target[period][:all_avg] = (source[period].map { |x| x[:range] }.reduce(:+) / source[period].size).round
|
40
42
|
target[period][:all_lower] = source[period].sort_by do |x|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
x[:range]
|
44
|
+
end.map { |x| x[:range] }[ (source[period].size * 1 / 4).round ]
|
45
|
+
|
46
|
+
target[period][:all_median] = source[period].sort_by do |x|
|
47
|
+
x[:range]
|
48
|
+
end.map { |x| x[:range] }[ (source[period].size * 2 / 4).round ]
|
49
|
+
|
50
|
+
target[period][:all_upper] = source[period].sort_by do |x|
|
51
|
+
x[:range]
|
52
|
+
end.map { |x| x[:range] }[ (source[period].size * 3 / 4).round ]
|
53
|
+
|
49
54
|
target[period][:all_max] = source[period].map { |x| x[:range] }.max
|
50
55
|
target[period][:all_records] = source[period].sort_by do |x|
|
51
|
-
|
52
|
-
|
56
|
+
-x[:range]
|
57
|
+
end.map { |x| { contract: x[:contract], range: x[:range] } }.take(5)
|
53
58
|
|
54
59
|
tenth = (source[period].size * dim).round
|
55
60
|
custom = source[period].sort_by { |x| x[:range] }[tenth..source[period].size - tenth]
|
61
|
+
|
56
62
|
target[period][:dim_size] = custom.size
|
57
63
|
target[period][:dim_avg] = (custom.map { |x| x[:range] }.reduce(:+) / custom.size).round
|
58
64
|
target[period][:dim_lower] = custom.sort_by do |x|
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
65
|
+
x[:range]
|
66
|
+
end.map { |x| x[:range] }[ (custom.size * 1 / 4).round ]
|
67
|
+
|
68
|
+
target[period][:dim_median] = custom.sort_by do |x|
|
69
|
+
x[:range]
|
70
|
+
end.map { |x| x[:range] }[ (custom.size * 2 / 4).round ]
|
71
|
+
|
72
|
+
target[period][:dim_upper] = custom.sort_by do |x|
|
73
|
+
x[:range]
|
74
|
+
end.map { |x| x[:range] }[ (custom.size * 3 / 4).round ]
|
75
|
+
|
76
|
+
target[period][:dim_max] = custom.map { |x| x[:range] }.max
|
68
77
|
target[period][:dim_records] = custom.sort_by do |x|
|
69
|
-
|
70
|
-
|
78
|
+
-x[:range]
|
79
|
+
end.map { |x| { contract: x[:contract], range: x[:range] } }.take(5)
|
71
80
|
|
72
81
|
range = case period
|
73
82
|
when :months
|
@@ -83,18 +92,18 @@ module Cotcube
|
|
83
92
|
target[period][:rec_size] = custom.size
|
84
93
|
target[period][:rec_avg] = (custom.map { |x| x[:range] }.reduce(:+) / custom.size).round
|
85
94
|
target[period][:rec_lower] = custom.sort_by do |x|
|
86
|
-
|
87
|
-
|
88
|
-
target[period][:rec_median] =
|
89
|
-
|
90
|
-
|
91
|
-
target[period][:rec_upper]
|
92
|
-
|
93
|
-
|
94
|
-
target[period][:rec_max]
|
95
|
+
x[:range]
|
96
|
+
end.map { |x| x[:range] }[ (custom.size * 1 / 4).round ]
|
97
|
+
target[period][:rec_median] = custom.sort_by do |x|
|
98
|
+
x[:range]
|
99
|
+
end.map { |x| x[:range] }[ (custom.size * 2 / 4).round ]
|
100
|
+
target[period][:rec_upper] = custom.sort_by do |x|
|
101
|
+
x[:range]
|
102
|
+
end.map { |x| x[:range] }[ (custom.size * 3 / 4).round ]
|
103
|
+
target[period][:rec_max] = custom.map { |x| x[:range] }.max
|
95
104
|
target[period][:rec_records] = custom.sort_by do |x|
|
96
|
-
|
97
|
-
|
105
|
+
-x[:range]
|
106
|
+
end.map { |x| { contract: x[:contract], range: x[:range] } }.take(5)
|
98
107
|
end
|
99
108
|
|
100
109
|
if print
|
@@ -7,11 +7,13 @@ module Cotcube
|
|
7
7
|
# (as sunday is wday:0)
|
8
8
|
# according files are located in config[:data_path]/trading_hours and picked either
|
9
9
|
# by the symbol itself or by the assigned type
|
10
|
-
# commonly there are two
|
11
|
-
def trading_hours(symbol: nil, id: nil,
|
12
|
-
|
10
|
+
# commonly there are two filter for each symbol: :full and :rth, exceptions are e.g. meats
|
11
|
+
def trading_hours(symbol: nil, id: nil, # rubocop:disable Metrics/ParameterLists
|
12
|
+
filter: ,
|
13
|
+
force_filter: false, # with force_filter one would avoid falling back
|
14
|
+
# to the contract_type based range set
|
13
15
|
config: init, debug: false)
|
14
|
-
return (0...24 * 7 * 3600) if
|
16
|
+
return (0...24 * 7 * 3600) if filter.to_s =~ /24x7/
|
15
17
|
|
16
18
|
prepare = lambda do |f|
|
17
19
|
CSV.read(f, converters: :numeric)
|
@@ -22,23 +24,23 @@ module Cotcube
|
|
22
24
|
|
23
25
|
sym = get_id_set(symbol: symbol, id: id)
|
24
26
|
|
25
|
-
file = "#{config[:data_path]}/trading_hours/#{sym[:symbol]}_#{
|
26
|
-
puts "Trying to use #{file} for #{symbol} + #{
|
27
|
+
file = "#{config[:data_path]}/trading_hours/#{sym[:symbol]}_#{filter}.csv"
|
28
|
+
puts "Trying to use #{file} for #{symbol} + #{filter}" if debug
|
27
29
|
return prepare.call(file) if File.exist? file
|
28
30
|
|
29
31
|
file = "#{config[:data_path]}/trading_hours/#{sym[:symbol]}_full.csv"
|
30
32
|
puts "Failed. Trying to use #{file} now" if debug
|
31
|
-
return prepare.call(file) if File.exist?(file) && (not
|
33
|
+
return prepare.call(file) if File.exist?(file) && (not force_filter)
|
32
34
|
|
33
|
-
file = "#{config[:data_path]}/trading_hours/#{sym[:type]}_#{
|
35
|
+
file = "#{config[:data_path]}/trading_hours/#{sym[:type]}_#{filter}.csv"
|
34
36
|
puts "Failed. Trying to use #{file} now." if debug
|
35
37
|
return prepare.call(file) if File.exist? file
|
36
38
|
|
37
39
|
file = "#{config[:data_path]}/trading_hours/#{sym[:type]}_full.csv"
|
38
40
|
puts "Failed. Trying to use #{file} now." if debug
|
39
|
-
return prepare.call(file) if File.exist?(file) && (not
|
41
|
+
return prepare.call(file) if File.exist?(file) && (not force_filter)
|
40
42
|
|
41
|
-
puts "Finally failed to find range
|
43
|
+
puts "Finally failed to find range filter for #{symbol} + #{filter}, returning 24x7".colorize(:light_yellow)
|
42
44
|
(0...24 * 7 * 3600)
|
43
45
|
end
|
44
46
|
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.9.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-02-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -112,16 +112,16 @@ dependencies:
|
|
112
112
|
name: rake
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
|
-
- - "
|
115
|
+
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: '
|
117
|
+
version: '13'
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
|
-
- - "
|
122
|
+
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: '
|
124
|
+
version: '13'
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rspec
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|