cotcube-bardata 0.1.15.2 → 0.1.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +17 -0
- data/VERSION +1 -1
- data/bin/eod.rb +8 -0
- data/cotcube-bardata.gemspec +1 -1
- data/lib/cotcube-bardata/cached.rb +1 -1
- data/lib/cotcube-bardata/daily.rb +146 -100
- data/lib/cotcube-bardata/eods.rb +4 -4
- data/lib/cotcube-bardata/helpers.rb +0 -36
- data/lib/cotcube-bardata/provide.rb +1 -1
- data/lib/cotcube-bardata/quarters.rb +1 -1
- data/lib/cotcube-bardata/range_matrix.rb +1 -1
- data/lib/cotcube-bardata/trading_hours.rb +1 -1
- data/lib/cotcube-bardata.rb +2 -4
- metadata +6 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: aa52a5fd519f8351f712e30495d4dda59bb37a4d4b588c84904d1971d7ad734c
|
4
|
+
data.tar.gz: b1eaacc5e75d13d84edf8c095cdaebc7ec588fe0e61ef6dc764d2a5633fedece
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1798e058b377f50f2efe78f8f6b0936763ce29686a639f10e893914202ca27f4469665d9520d7adcda4df5f4346e5f9f87e8ce229c389ac78dde666335f1efd3
|
7
|
+
data.tar.gz: 8e245ebcea3acdde99f7c5673f97024432648938e530fd9ae11dae4b7f67091a5128536fa70c0e4ba0cb372d85f7c713460249da574278501e60f4bf66ebf1ac
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
## 0.1.16 (November 23, 2021)
|
2
|
+
- bin/eod.rb: little helper to display eod data in bash resp. in xinetdhttpservice
|
3
|
+
- eods.rb: minor change to adapt move of symbols to Helpers
|
4
|
+
- daily.rb: in continuous, changed default indicators to %i[ tr atr5 dist ]
|
5
|
+
|
6
|
+
## 0.1.15.6 (November 19, 2021)
|
7
|
+
- daily: added filter_series
|
8
|
+
|
9
|
+
## 0.1.15.5 (November 08, 2021)
|
10
|
+
- decommissioned .get_id_set in favor of Cotcube::Helpers.get_id_set
|
11
|
+
|
12
|
+
## 0.1.15.4 (October 26, 2021)
|
13
|
+
- daily: including the sourcing factor (:bcf) into provide_daily and continuous
|
14
|
+
|
15
|
+
## 0.1.15.3 (August 04, 2021)
|
16
|
+
- daily.rb: Hotfixing
|
17
|
+
|
1
18
|
## 0.1.15.2 (August 04, 2021)
|
2
19
|
- fixed leftover debug setting
|
3
20
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.16
|
data/bin/eod.rb
ADDED
data/cotcube-bardata.gemspec
CHANGED
@@ -28,7 +28,7 @@ Gem::Specification.new do |spec|
|
|
28
28
|
|
29
29
|
spec.add_dependency 'activesupport', '~> 6'
|
30
30
|
spec.add_dependency 'colorize', '~> 0.8'
|
31
|
-
spec.add_dependency 'cotcube-helpers', '~> 0.
|
31
|
+
spec.add_dependency 'cotcube-helpers', '~> 0.2'
|
32
32
|
spec.add_dependency 'cotcube-indicators', '~> 0.1'
|
33
33
|
spec.add_dependency 'httparty', '~> 0.18'
|
34
34
|
spec.add_dependency 'parallel', '~> 1'
|
@@ -30,7 +30,7 @@ module Cotcube
|
|
30
30
|
end
|
31
31
|
|
32
32
|
headers = %i[contract datetime open high low close volume]
|
33
|
-
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
33
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, contract: contract)
|
34
34
|
contract = contract[-3..]
|
35
35
|
dir = "#{config[:data_path]}/cached/#{sym[:id]}_#{filter.to_s.downcase}"
|
36
36
|
symlink = "#{config[:data_path]}/cached/#{sym[:symbol]}_#{filter.to_s.downcase}"
|
@@ -10,8 +10,10 @@ module Cotcube
|
|
10
10
|
timezone: Time.find_zone('America/Chicago'),
|
11
11
|
keep_last: false,
|
12
12
|
add_eods: true,
|
13
|
+
indicators: {},
|
13
14
|
config: init)
|
14
15
|
contract = contract.to_s.upcase
|
16
|
+
rounding = 8
|
15
17
|
unless contract.is_a?(String) && [3, 5].include?(contract.size)
|
16
18
|
raise ArgumentError, "Contract '#{contract}' is bogus, should be like 'M21' or 'ESM21'"
|
17
19
|
end
|
@@ -31,7 +33,7 @@ module Cotcube
|
|
31
33
|
range = (range_begin..range_end)
|
32
34
|
end
|
33
35
|
|
34
|
-
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
36
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, contract: contract)
|
35
37
|
contract = contract[2..4] if contract.to_s.size == 5
|
36
38
|
id = sym[:id]
|
37
39
|
id_path = "#{config[:data_path]}/daily/#{id}"
|
@@ -43,7 +45,10 @@ module Cotcube
|
|
43
45
|
data = CSV.read(data_file, headers: %i[contract date open high low close volume oi]).map do |row|
|
44
46
|
row = row.to_h
|
45
47
|
row.each do |k, _|
|
46
|
-
|
48
|
+
if %i[open high low close].include? k
|
49
|
+
row[k] = row[k].to_f
|
50
|
+
row[k] = (row[k] * sym[:bcf]).round(8) unless sym[:bcf] == 1.0
|
51
|
+
end
|
47
52
|
row[k] = row[k].to_i if %i[volume oi].include? k
|
48
53
|
end
|
49
54
|
row[:datetime] = timezone.parse(row[:date])
|
@@ -57,19 +62,29 @@ module Cotcube
|
|
57
62
|
today = Date.today
|
58
63
|
eods = [ ]
|
59
64
|
while today.strftime('%Y-%m-%d') > data.last[:date]
|
60
|
-
eods << provide_eods(symbol: sym[:symbol], dates: today, contracts_only: false)
|
65
|
+
eods << provide_eods(symbol: sym[:symbol], dates: today, contracts_only: false, quiet: true)
|
61
66
|
today -= 1
|
62
67
|
end
|
63
68
|
eods.flatten!.map!{|x| x.tap {|y| %i[ volume_part oi_part ].map{|z| y.delete(z)} } }
|
64
|
-
eods.select{|x| x[:contract] == contract }
|
69
|
+
eods.select!{|x| x[:contract] == "#{sym[:symbol]}#{contract}" }
|
65
70
|
eods.map!{|x| x.tap{|y|
|
71
|
+
if sym[:bcf] != 1.0
|
72
|
+
%i[open high low close].map{|k|
|
73
|
+
y[k] = (y[k] * sym[:bcf]).round(8)
|
74
|
+
}
|
75
|
+
end
|
66
76
|
y[:datetime] = timezone.parse(y[:date])
|
67
77
|
y[:dist] = ((y[:high] - y[:low]) / sym[:ticksize] ).to_i
|
68
78
|
y[:type] = :eod
|
69
79
|
} }
|
70
80
|
data += eods.reverse
|
71
|
-
|
72
81
|
end
|
82
|
+
data.map do |bar|
|
83
|
+
indicators.each do |k,v|
|
84
|
+
tmp = v.call(bar)
|
85
|
+
bar[k] = tmp.respond_to?(:round) ? tmp.round(rounding) : tmp
|
86
|
+
end
|
87
|
+
end unless indicators.empty?
|
73
88
|
if range.nil?
|
74
89
|
data
|
75
90
|
else
|
@@ -82,12 +97,12 @@ module Cotcube
|
|
82
97
|
|
83
98
|
# reads all files in bardata/daily/<id> and aggregates by date
|
84
99
|
# (what is a pre-stage of a continuous based on daily bars)
|
85
|
-
def continuous(symbol: nil, id: nil, config: init, date: nil, measure: nil, force_rewrite: false, selector: nil, debug: false, add_eods: true)
|
100
|
+
def continuous(symbol: nil, id: nil, config: init, date: nil, measure: nil, force_rewrite: false, selector: nil, debug: false, add_eods: true, indicators: nil)
|
86
101
|
raise ArgumentError, ':measure, if given, must be a Time object (e.g. Time.now)' unless [NilClass, Time].include? measure.class
|
87
102
|
measuring = lambda {|c| puts "[continuous] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
|
88
103
|
|
89
104
|
measuring.call("Starting")
|
90
|
-
sym = get_id_set(symbol: symbol, id: id)
|
105
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
91
106
|
id = sym[:id]
|
92
107
|
symbol = sym[:symbol]
|
93
108
|
ticksize = sym[:ticksize]
|
@@ -99,7 +114,7 @@ module Cotcube
|
|
99
114
|
|
100
115
|
# instead of using the provide_daily methods above, for this bulk operation a 'continuous.csv' is created
|
101
116
|
# this boosts from 4.5sec to 0.3sec
|
102
|
-
rewriting = force_rewrite or not(File.exist?(c_file)) or (Time.now - File.mtime(c_file) > 8.days)
|
117
|
+
rewriting = (force_rewrite or not(File.exist?(c_file)) or (Time.now - File.mtime(c_file) > 8.days))
|
103
118
|
if rewriting
|
104
119
|
puts "In daily+continuous: Rewriting #{c_file} #{force_rewrite ? "forcibly" : "due to fileage"}.".light_yellow
|
105
120
|
`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}`
|
@@ -113,62 +128,31 @@ module Cotcube
|
|
113
128
|
low: row[4],
|
114
129
|
close: row[5],
|
115
130
|
volume: row[6].to_i,
|
116
|
-
oi: row[7].to_i
|
131
|
+
oi: row[7].to_i,
|
132
|
+
type: :cont
|
117
133
|
}
|
118
134
|
end
|
119
135
|
if add_eods
|
120
136
|
today = Date.today
|
121
137
|
eods = [ ]
|
122
138
|
while today.strftime('%Y-%m-%d') > data.last[:date]
|
123
|
-
eods << provide_eods(symbol: symbol, dates: today, contracts_only: false)
|
139
|
+
eods << provide_eods(symbol: symbol, dates: today, contracts_only: false, quiet: true)
|
124
140
|
today -= 1
|
125
141
|
end
|
126
142
|
eods.flatten!.map!{|x| x.tap {|y| %i[ volume_part oi_part ].map{|z| y.delete(z)} } }
|
127
143
|
eods.delete_if { |elem| elem.flatten.empty? }
|
128
144
|
data += eods.reverse
|
129
|
-
|
130
145
|
end
|
131
146
|
|
132
147
|
measuring.call("Finished retrieving dailies.")
|
133
148
|
result = []
|
134
|
-
rounding = 8
|
149
|
+
rounding = 8
|
135
150
|
indicators ||= {
|
136
|
-
|
137
|
-
|
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}
|
151
|
+
tr: Cotcube::Indicators.true_range,
|
152
|
+
atr5: Cotcube::Indicators.ema(key: :tr, length: 5),
|
166
153
|
dist: Cotcube::Indicators.calc(a: :high, b: :low, finalize: :to_i) {|high, low| ((high-low) / ticksize) }
|
167
|
-
|
168
154
|
}
|
169
155
|
|
170
|
-
|
171
|
-
|
172
156
|
data.group_by { |x| x[:date] }.map do |k, v|
|
173
157
|
v.map { |x| x.delete(:date) }
|
174
158
|
avg_bar = {
|
@@ -177,20 +161,24 @@ module Cotcube
|
|
177
161
|
open: nil, high: nil, low: nil, close: nil,
|
178
162
|
volume: v.map { |x| x[:volume] }.reduce(:+),
|
179
163
|
oi: v.map { |x| x[:oi] }.reduce(:+),
|
164
|
+
type: :cont_eod
|
180
165
|
}
|
181
166
|
|
182
167
|
%i[ open high low close ].each do |ohlc|
|
183
168
|
avg_bar[ohlc] = (v.map{|x| x[ohlc].to_f * x[effective_selector] }.reduce(:+) / avg_bar[effective_selector]).round(rounding)
|
169
|
+
avg_bar[ohlc] = (avg_bar[ohlc] * sym[:bcf]).round(8) unless sym[:bcf] == 1.0
|
170
|
+
|
184
171
|
end
|
185
172
|
p avg_bar if debug
|
186
173
|
indicators.each do |k,v|
|
187
174
|
print format('%12s: ', k.to_s) if debug
|
188
|
-
|
175
|
+
tmp = v.call(avg_bar)
|
176
|
+
avg_bar[k] = tmp.respond_to?(:round) ? tmp.round(rounding) : tmp
|
189
177
|
puts avg_bar[k] if debug
|
190
178
|
end
|
191
|
-
|
192
|
-
|
193
|
-
}
|
179
|
+
#%i[tr atr5].each { |ind|
|
180
|
+
# avg_bar[ind] = (avg_bar[ind] / sym[:ticksize]).round.to_i unless avg_bar[ind].nil?
|
181
|
+
#}
|
194
182
|
result << avg_bar
|
195
183
|
result.last[:contracts] = v
|
196
184
|
end
|
@@ -206,6 +194,57 @@ module Cotcube
|
|
206
194
|
date.nil? ? Cotcube::Bardata.const_get(constname).map{|z| z.dup } : Cotcube::Bardata.const_get(constname).find { |x| x[:date] == date }
|
207
195
|
end
|
208
196
|
|
197
|
+
# the filter series is an indicator based on the Cotcube::Bardata.continuous of the asset price.
|
198
|
+
# current default filter is the ema50
|
199
|
+
def filter_series(ema_length: 50, symbol: , print_range: nil)
|
200
|
+
ema_high_n = "ema#{ema_length}_high".to_sym
|
201
|
+
ema_low_n = "ema#{ema_length}_low".to_sym
|
202
|
+
ema_filter = "ema#{ema_length}_filter".to_sym
|
203
|
+
indicators = {
|
204
|
+
ema_high_n => Cotcube::Indicators.ema(key: :high, length: ema_length, smoothing: 2),
|
205
|
+
ema_low_n => Cotcube::Indicators.ema(key: :low, length: ema_length, smoothing: 2),
|
206
|
+
# NOTE: TR / ATR5 are in default set of continuous
|
207
|
+
:tr => Cotcube::Indicators.true_range,
|
208
|
+
:atr5 => Cotcube::Indicators.ema(key: :tr, length: 5, smoothing: 2),
|
209
|
+
ema_filter => Cotcube::Indicators.calc(a: :high, b: :low, c: :close,
|
210
|
+
d: ema_high_n, e: ema_low_n, f: :atr5,
|
211
|
+
finalize: :to_i) do |high, low, close, ema_high, ema_low, atr5|
|
212
|
+
|
213
|
+
if close > ema_high and (low - ema_high).abs <= atr5 / 5.0; 3 # :bullish_tipped
|
214
|
+
elsif low > ema_high and (low - ema_high).abs >= atr5 * 3.0; 5 # :bullish_away
|
215
|
+
elsif low > ema_high and (low - ema_high).abs <= atr5 / 1.5; 2 # :bullish_nearby
|
216
|
+
elsif low > ema_high; 4 # :bullish
|
217
|
+
|
218
|
+
elsif close < ema_low and (high - ema_low).abs <= atr5 / 5.0; -3 # :bearish_tipped
|
219
|
+
elsif high < ema_low and (high - ema_low).abs >= atr5 * 3.0; -5 # :bearish_away
|
220
|
+
elsif high < ema_low and (high - ema_low).abs <= atr5 / 1.5; -2 # :bearish_nearby
|
221
|
+
elsif high < ema_low; -4 # :bearish
|
222
|
+
|
223
|
+
elsif close >= ema_high and (close - ema_high).abs > atr5 ; 2 # :bullish_closed
|
224
|
+
elsif close <= ema_low and (close - ema_low ).abs > atr5 ; -2 # :bearish_closed
|
225
|
+
elsif close >= ema_high; 1 # :bullish_weak
|
226
|
+
elsif close <= ema_low; -1 # :bearish_weak
|
227
|
+
elsif close > ema_low and close < ema_high; 0 # :ambigue
|
228
|
+
else
|
229
|
+
raise RuntimeError, "Unconsidered Indicator value with #{high}, #{low}, #{close}, #{ema_high}, #{ema_low}, #{atr5}"
|
230
|
+
|
231
|
+
end
|
232
|
+
end
|
233
|
+
}
|
234
|
+
filter = Cotcube::Bardata.continuous(symbol: symbol, indicators: indicators).
|
235
|
+
map{ |z| z[:datetime] = DateTime.parse(z[:date]); z[:datetime] += z[:datetime].wday == 5 ? 3 : 1; z.slice(:datetime, ema_filter) }.
|
236
|
+
group_by{ |z| z[:datetime] }.
|
237
|
+
map{ |k,v| [ k, v[0][ema_filter] ] }.
|
238
|
+
to_h.
|
239
|
+
tap{ |z|
|
240
|
+
z.to_a[print_range].each { |v|
|
241
|
+
puts "#{symbol} #{v[0].strftime('%Y-%m-%d')
|
242
|
+
} #{format '%2d', v[1]
|
243
|
+
}".colorize(v[1] > 3 ? :light_green : v[1] > 1 ? :green : v[1] < -3 ? :light_red : v[1] < -1 ? :red : :white )
|
244
|
+
} if print_range.is_a? Range
|
245
|
+
}
|
246
|
+
end
|
247
|
+
|
209
248
|
def continuous_ml(symbol: nil, id: nil, base: nil)
|
210
249
|
(base.nil? ? Cotcube::Bardata.continuous(symbol: symbol, id: id) : base).map do |x|
|
211
250
|
x[:ml] = x[:contracts].max_by { |z| z[:volume] }[:contract]
|
@@ -246,7 +285,7 @@ module Cotcube
|
|
246
285
|
%i[volume oi].include?(selector)
|
247
286
|
|
248
287
|
measuring.call("Starting")
|
249
|
-
sym = get_id_set(symbol: symbol, id: id)
|
288
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
250
289
|
id = sym[:id]
|
251
290
|
# noinspection RubyNilAnalysis
|
252
291
|
data = continuous(id: id, config: config, measure: measure).map do |x|
|
@@ -310,7 +349,7 @@ module Cotcube
|
|
310
349
|
%i[volume oi].include?(selector)
|
311
350
|
|
312
351
|
measuring.call("Entering function")
|
313
|
-
sym = get_id_set(symbol: symbol, id: id)
|
352
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
314
353
|
if %w[R6 BJ GE].include? sym[:symbol]
|
315
354
|
puts "Rejecting to process symbol '#{sym[:symbol]}'.".light_red
|
316
355
|
return []
|
@@ -326,22 +365,42 @@ module Cotcube
|
|
326
365
|
|
327
366
|
ytoday = date.yday
|
328
367
|
data = continuous_overview(id: id, selector: selector, filter: filter, human: false, config: init, measure: measure)
|
329
|
-
.reject { |k, _| k[-2..].to_i
|
368
|
+
.reject { |k, _| k[-2..].to_i >= date.year % 2000 }
|
330
369
|
.group_by { |k, _| k[2] }
|
331
370
|
measuring.call("Retrieved continous_overview")
|
332
|
-
output_sent = []
|
333
|
-
early_year=nil
|
334
371
|
long_output = []
|
372
|
+
|
373
|
+
toydate = -> (z,y=2021) { str = "#{z>365 ? y+1 : y} #{z>365 ? z-365 : z}"; DateTime.strptime(str, '%Y %j').strftime('%Y-%m-%d') }
|
374
|
+
|
335
375
|
data.keys.sort.each do |month|
|
336
|
-
current_long = { month: month }
|
337
376
|
puts "Processing #{sym[:symbol]}#{month}" if debuglevel > 1
|
338
377
|
v0 = data[month]
|
378
|
+
|
379
|
+
# ldays is the list of 'last days'
|
339
380
|
ldays = v0.map { |_, v1| Date.parse(v1.last[:date]).yday }
|
381
|
+
# fdays is the list of 'first days'
|
340
382
|
fdays = v0.map { |_, v1| Date.parse(v1.first[:date]).yday }.sort
|
341
383
|
# if the last ml day nears the end of the year, we must fix
|
342
384
|
ldays.map! { |x| x > 350 ? x - 366 : x } if ldays.min < 50
|
343
385
|
fday = fdays[fdays.size / 2]
|
344
386
|
lavg = ldays.reduce(:+) / ldays.size
|
387
|
+
|
388
|
+
# rubocop:disable Layout/ClosingParenthesisIndentation
|
389
|
+
current = {
|
390
|
+
month: month,
|
391
|
+
contract: "#{sym[:symbol]}#{month}",
|
392
|
+
first_ml: fday,
|
393
|
+
last_min: ldays.min,
|
394
|
+
last_avg: lavg,
|
395
|
+
last_max: ldays.max,
|
396
|
+
until_start: fday - ytoday,
|
397
|
+
until_end: ldays.min - ytoday
|
398
|
+
}
|
399
|
+
current[:until_end] += 365 if current[:until_end] - current[:until_start] < 0
|
400
|
+
current[:until_end] -= 365 if current[:until_end] > 365
|
401
|
+
|
402
|
+
long_output << current
|
403
|
+
|
345
404
|
# a contract is proposed to use after fday - 1, but before ldays.min (green)
|
346
405
|
# it is warned to user after fday - 1 but before lavg - 1 (red)
|
347
406
|
# it is warned red >= lavg - 1 and <= lavg + 1
|
@@ -354,55 +413,42 @@ module Cotcube
|
|
354
413
|
else
|
355
414
|
:white
|
356
415
|
end
|
357
|
-
|
358
|
-
long_output << {
|
359
|
-
month: month,
|
360
|
-
first_ml: fday,
|
361
|
-
last_min: ldays.min,
|
362
|
-
last_avg: lavg,
|
363
|
-
last_max: ldays.max }
|
416
|
+
|
364
417
|
output = "#{sym[:symbol]
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
418
|
+
}#{month
|
419
|
+
}\t#{format '%12s', sym[:type]
|
420
|
+
}\ttoday is #{ytoday
|
421
|
+
} -- median of first is #{fday
|
422
|
+
}\tlast ranges from #{format '%5d', ldays.min
|
423
|
+
}: #{dfm.call(ldays.min)
|
424
|
+
}\t#{format '%5d', lavg
|
425
|
+
}: #{dfm.call(lavg)
|
426
|
+
}\tto #{format '%5d', ldays.max
|
427
|
+
}: #{dfm.call(ldays.max)}".colorize(color)
|
428
|
+
|
429
|
+
if debug || (color != :white)
|
430
|
+
puts output unless silent
|
431
|
+
end
|
432
|
+
next if silent or not (debug and debuglevel >= 2)
|
433
|
+
|
434
|
+
v0.each do |contract, v1|
|
435
|
+
puts "\t#{contract
|
436
|
+
}\t#{v1.first[:date]
|
437
|
+
} (#{format '%3d', Date.parse(v1.first[:date]).yday
|
438
|
+
})\t#{Date.parse(v1.last[:date]).strftime('%a, %Y-%m-%d')
|
439
|
+
} (#{Date.parse(v1.last[:date]).yday})" unless silent
|
440
|
+
# rubocop:enable Layout/ClosingParenthesisIndentation
|
441
|
+
end
|
442
|
+
|
390
443
|
end
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
puts " Assuming late-year-processing.".light_yellow
|
396
|
-
puts early_year.light_green
|
397
|
-
end
|
398
|
-
when 1
|
399
|
-
# all ok
|
400
|
-
true
|
401
|
-
else
|
402
|
-
puts "Continuous table show #{output_sent.size} active contracts ( #{output_sent} ) for #{sym[:symbol]} ---------------" unless silent
|
444
|
+
long_output.sort_by!{|z| z[:until_end] + (z[:until_end].negative? ? 365 : 0)}
|
445
|
+
|
446
|
+
if short
|
447
|
+
return ([long_output.first] + long_output.select{|z| z[:until_start].positive? and z[:until_start] < 10 }).map{|z| z[:contract] }.uniq
|
403
448
|
end
|
449
|
+
|
404
450
|
measuring.call("Finished processing")
|
405
|
-
|
451
|
+
return long_output
|
406
452
|
end
|
407
453
|
end
|
408
454
|
end
|
data/lib/cotcube-bardata/eods.rb
CHANGED
@@ -4,7 +4,7 @@ module Cotcube
|
|
4
4
|
# Missing top level documentation
|
5
5
|
module Bardata
|
6
6
|
def most_liquid_for(symbol: nil, id: nil, date: last_trade_date, config: init)
|
7
|
-
id = get_id_set(symbol: symbol, id: id, config: config)[:id]
|
7
|
+
id = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, config: config)[:id]
|
8
8
|
provide_eods(id: id, dates: date, contracts_only: true).first
|
9
9
|
end
|
10
10
|
|
@@ -15,7 +15,7 @@ module Cotcube
|
|
15
15
|
date: last_trade_date,
|
16
16
|
filter: :volume_part,
|
17
17
|
age: 1.hour)
|
18
|
-
sym = get_id_set(symbol: symbol, id: id) if symbol || id
|
18
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id) if symbol || id
|
19
19
|
# noinspection RubyScope
|
20
20
|
eods = provide_eods(id: sym.nil? ? nil : sym[:id], config: config, dates: date, filter: filter)
|
21
21
|
result = []
|
@@ -62,13 +62,13 @@ module Cotcube
|
|
62
62
|
end
|
63
63
|
|
64
64
|
symbol = contract[0..1] if contract.to_s.size == 5
|
65
|
-
sym = get_id_set(symbol: symbol, id: id, config: config) if symbol || id
|
65
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, config: config) if symbol || id
|
66
66
|
# if no id can be clarified from given arguments, return all matching contracts from all available symbols
|
67
67
|
# raise ArgumentError, "Could not guess :id or :symbol from 'contract: #{contract}', please clarify." if id.nil?
|
68
68
|
raise ArgumentError, ':filter must be in [:volume_part, :oi_part]' unless %i[volume_part oi_part].include? filter
|
69
69
|
|
70
70
|
# noinspection RubyScope
|
71
|
-
ids = sym.nil? ? symbols.map { |x| x[:id] } : [sym[:id]]
|
71
|
+
ids = sym.nil? ? Cotcube::Helpers.symbols.map { |x| x[:id] } : [sym[:id]]
|
72
72
|
dates = [dates] unless dates.is_a?(Array) || dates.nil?
|
73
73
|
|
74
74
|
id_path_get = ->(local_id) { "#{config[:data_path]}/eods/#{local_id}" }
|
@@ -45,42 +45,6 @@ module Cotcube
|
|
45
45
|
result
|
46
46
|
end
|
47
47
|
|
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
|
-
|
53
|
-
if contract.is_a?(String) && (contract.length == 5)
|
54
|
-
c_symbol = contract[0..1]
|
55
|
-
if (not symbol.nil?) && (symbol != c_symbol)
|
56
|
-
raise ArgumentError,
|
57
|
-
"Mismatch between given symbol #{symbol} and contract #{contract}"
|
58
|
-
end
|
59
|
-
|
60
|
-
symbol = c_symbol
|
61
|
-
end
|
62
|
-
|
63
|
-
unless symbol.nil?
|
64
|
-
sym = symbols.select { |s| s[:symbol] == symbol.to_s.upcase }.first
|
65
|
-
if sym.nil? || sym[:id].nil?
|
66
|
-
raise ArgumentError,
|
67
|
-
"Could not find match in #{config[:symbols_file]} for given symbol #{symbol}"
|
68
|
-
end
|
69
|
-
raise ArgumentError, "Mismatching symbol #{symbol} and given id #{id}" if (not id.nil?) && (sym[:id] != id)
|
70
|
-
|
71
|
-
return sym
|
72
|
-
end
|
73
|
-
unless id.nil?
|
74
|
-
sym = symbols.select { |s| s[:id] == id.to_s }.first
|
75
|
-
if sym.nil? || sym[:id].nil?
|
76
|
-
raise ArgumentError,
|
77
|
-
"Could not find match in #{config[:symbols_file]} for given id #{id}"
|
78
|
-
end
|
79
|
-
return sym
|
80
|
-
end
|
81
|
-
raise ArgumentError, 'Need :id, :symbol or valid :contract '
|
82
|
-
end
|
83
|
-
|
84
48
|
def compare(contract:, format: '%5.2f')
|
85
49
|
format = "%#{format}" unless format[0] == '%'
|
86
50
|
daily = provide(contract: contract, interval: :daily)
|
@@ -17,7 +17,7 @@ module Cotcube
|
|
17
17
|
force_update: false,
|
18
18
|
force_recent: false)
|
19
19
|
|
20
|
-
sym = get_id_set(symbol: symbol, id: id, contract: contract, config: config)
|
20
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, contract: contract, config: config)
|
21
21
|
|
22
22
|
case interval
|
23
23
|
when :quarters, :hours, :quarter, :hour
|
@@ -16,7 +16,7 @@ module Cotcube
|
|
16
16
|
raise ArgumentError, "Contract '#{contract}' is bogus, should be like 'M21' or 'ESM21'"
|
17
17
|
end
|
18
18
|
|
19
|
-
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
19
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, contract: contract)
|
20
20
|
|
21
21
|
contract = contract[2..4] if contract.to_s.size == 5
|
22
22
|
id = sym[:id]
|
@@ -24,7 +24,7 @@ module Cotcube
|
|
24
24
|
def range_matrix(symbol: nil, id: nil, base: nil, print: false, dim: 0.05, days_only: false, last_n: 60, &block)
|
25
25
|
# rubocop:disable Style/MultilineBlockChain
|
26
26
|
symbol ||= base.last[:contract][0..1] if id.nil?
|
27
|
-
sym = get_id_set(symbol: symbol, id: id)
|
27
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
28
28
|
source = {}
|
29
29
|
target = {}
|
30
30
|
if base.nil?
|
@@ -28,7 +28,7 @@ module Cotcube
|
|
28
28
|
end
|
29
29
|
end
|
30
30
|
|
31
|
-
sym = get_id_set(symbol: symbol, id: id)
|
31
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
32
32
|
|
33
33
|
file = "#{config[:data_path]}/trading_hours/#{sym[:symbol]}_#{filter}.csv"
|
34
34
|
puts "Trying to use #{file} for #{symbol} + #{filter}" if debug
|
data/lib/cotcube-bardata.rb
CHANGED
@@ -56,16 +56,14 @@ module Cotcube
|
|
56
56
|
:continuous_overview,
|
57
57
|
# provider estimation of current ML usability
|
58
58
|
:continuous_table,
|
59
|
+
# provide a simple filter series
|
60
|
+
:filter_series,
|
59
61
|
# provide the list of quarters, possibly as hours or days.
|
60
62
|
:provide_quarters,
|
61
63
|
# some statistics to estimate daily volatility of specific contract
|
62
64
|
:range_matrix,
|
63
65
|
# create an array of ranges based on specified source data
|
64
66
|
:trading_hours,
|
65
|
-
# receive id / symbol information on an uncertain set of parameters
|
66
|
-
# TODO: decommision sppearance of get_id_set and symbols in cotcube::bardata
|
67
|
-
:get_id_set,
|
68
|
-
:symbols,
|
69
67
|
#
|
70
68
|
:select_specific_date,
|
71
69
|
:extended_select_for_range,
|
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.16
|
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-11-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -44,14 +44,14 @@ dependencies:
|
|
44
44
|
requirements:
|
45
45
|
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0.
|
47
|
+
version: '0.2'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0.
|
54
|
+
version: '0.2'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
56
|
name: cotcube-indicators
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
@@ -164,6 +164,7 @@ files:
|
|
164
164
|
- README.md
|
165
165
|
- Rakefile
|
166
166
|
- VERSION
|
167
|
+
- bin/eod.rb
|
167
168
|
- cotcube-bardata.gemspec
|
168
169
|
- lib/cotcube-bardata.rb
|
169
170
|
- lib/cotcube-bardata/cached.rb
|
@@ -200,7 +201,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
201
|
- !ruby/object:Gem::Version
|
201
202
|
version: '0'
|
202
203
|
requirements: []
|
203
|
-
rubygems_version: 3.1.
|
204
|
+
rubygems_version: 3.1.6
|
204
205
|
signing_key:
|
205
206
|
specification_version: 4
|
206
207
|
summary: Functions to provide bardata; and some simple time series aggregations
|