cotcube-bardata 0.1.15.2 → 0.1.16
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/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
|