cotcube-bardata 0.1.15.4 → 0.1.17
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/daily.rb +73 -0
- data/bin/eod.rb +18 -0
- data/bin/intra.rb +75 -0
- data/bin/sym.rb +16 -0
- data/bin/symbols.rb +11 -0
- data/cotcube-bardata.gemspec +1 -1
- data/lib/cotcube-bardata/cached.rb +1 -1
- data/lib/cotcube-bardata/daily.rb +120 -65
- data/lib/cotcube-bardata/eods.rb +8 -6
- 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 +10 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2bb98a590c08cbd0dafba80850aab164befd778fb6425e67e304a7fc909f9411
|
4
|
+
data.tar.gz: cc3ec5166d4610605c0afd14c16f07798e092c537c82b2ed19d9a3326c10b642
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8a85816eefa18b6b72d98c9f6642881784678a99d1b4e402129bdcbe613ee0827ffd389bf996da31408306bf6a2f3ba8fe3cbd992b462460362b935d3e24dde2
|
7
|
+
data.tar.gz: 0f227bf5199375e04cda8382787170e2654689278eb93ac59f0573523030aecde9771f9a035a1b321f626e500a040ab01c5a35199ea54a63293adbf97357f2a0
|
data/CHANGELOG.md
CHANGED
@@ -1,3 +1,20 @@
|
|
1
|
+
## 0.1.17 (December 06, 2021)
|
2
|
+
- changed parameter for building of continuous (in daily.rb)
|
3
|
+
- added bin/intra + symbols. improved bin/daily
|
4
|
+
- bin/*: created (sym, daily) and improved (eod) cmd wrappers
|
5
|
+
- daily.rb: improved silence in .continuous
|
6
|
+
|
7
|
+
## 0.1.16 (November 23, 2021)
|
8
|
+
- bin/eod.rb: little helper to display eod data in bash resp. in xinetdhttpservice
|
9
|
+
- eods.rb: minor change to adapt move of symbols to Helpers
|
10
|
+
- daily.rb: in continuous, changed default indicators to %i[ tr atr5 dist ]
|
11
|
+
|
12
|
+
## 0.1.15.6 (November 19, 2021)
|
13
|
+
- daily: added filter_series
|
14
|
+
|
15
|
+
## 0.1.15.5 (November 08, 2021)
|
16
|
+
- decommissioned .get_id_set in favor of Cotcube::Helpers.get_id_set
|
17
|
+
|
1
18
|
## 0.1.15.4 (October 26, 2021)
|
2
19
|
- daily: including the sourcing factor (:bcf) into provide_daily and continuous
|
3
20
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.17
|
data/bin/daily.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/cotcube-bardata'
|
4
|
+
require 'cotcube-level'
|
5
|
+
require 'cotcube-indicators'
|
6
|
+
CcI = Cotcube::Indicators
|
7
|
+
|
8
|
+
def exit_with_error(err)
|
9
|
+
msg = { error: 1, message: "#{err}" }
|
10
|
+
p msg.to_json
|
11
|
+
exit 1
|
12
|
+
end
|
13
|
+
|
14
|
+
|
15
|
+
contract = ARGV[0].nil? ? nil : ARGV[0].upcase
|
16
|
+
if contract.nil?
|
17
|
+
exit_with_error('No contract given')
|
18
|
+
end
|
19
|
+
|
20
|
+
output = true
|
21
|
+
|
22
|
+
sym = Cotcube::Helpers.get_id_set(symbol: contract[..1])
|
23
|
+
# TODO: apply daylight time pimped diff to all relevant datetimes in series
|
24
|
+
timediff = if %w[ NYBOT NYMEX ].include? sym[:exchange]
|
25
|
+
5.hours
|
26
|
+
elsif %w[ DTB ].include? sym[:exchane]
|
27
|
+
1.hour
|
28
|
+
else
|
29
|
+
6.hours
|
30
|
+
end
|
31
|
+
|
32
|
+
continuous = %w[currencies interest indices].include? sym[:type]
|
33
|
+
intraday = false
|
34
|
+
interval = intraday ? 30.minutes : 1.day
|
35
|
+
ema_period = 50
|
36
|
+
|
37
|
+
indicators = {
|
38
|
+
ema_high: CcI.ema(key: :high, length: ema_period, smoothing: 2),
|
39
|
+
ema_low: CcI.ema(key: :low, length: ema_period, smoothing: 2)
|
40
|
+
}
|
41
|
+
|
42
|
+
dailybase = []
|
43
|
+
stencil = nil
|
44
|
+
stencil = Cotcube::Level::EOD_Stencil.new( interval: :daily, swap_type: :full)
|
45
|
+
dailybase = if continuous
|
46
|
+
Cotcube::Bardata.continuous(symbol: contract[..1], indicators: indicators)[-300..].
|
47
|
+
map{ |z|
|
48
|
+
z[:datetime] = DateTime.parse(z[:date])
|
49
|
+
z.delete(:contracts)
|
50
|
+
z
|
51
|
+
}
|
52
|
+
else
|
53
|
+
Cotcube::Bardata.provide_daily(contract: contract, indicators: indicators)[-300..]
|
54
|
+
end
|
55
|
+
|
56
|
+
base = dailybase
|
57
|
+
base.select!{|z| z[:high]}
|
58
|
+
|
59
|
+
scaleBreaks = []
|
60
|
+
brb = stencil.base
|
61
|
+
brb.each_with_index.map{|z,i|
|
62
|
+
next if i.zero?
|
63
|
+
if brb[i][:datetime] - brb[i-1][:datetime] > (intraday ? 1 : 1.day) and brb[i][:datetime] > base.first[:datetime] and brb[i-1][:datetime] < base.last[:datetime]
|
64
|
+
scaleBreaks << { startValue: brb[i-1][:datetime] + 0.5 * interval, endValue: brb[i][:datetime] - 0.5 * interval }
|
65
|
+
end
|
66
|
+
} unless base.empty?
|
67
|
+
|
68
|
+
pkg = {
|
69
|
+
base: base,
|
70
|
+
breaks: scaleBreaks
|
71
|
+
}
|
72
|
+
|
73
|
+
puts pkg.to_json if output
|
data/bin/eod.rb
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require_relative '../lib/cotcube-bardata.rb'
|
4
|
+
|
5
|
+
symbol = ARGV[0].nil? ? nil : ARGV[0].upcase
|
6
|
+
json = ARGV.include? 'json'
|
7
|
+
|
8
|
+
begin
|
9
|
+
s = Cotcube::Bardata.provide_eods(threshold: 0.10, contracts_only: false, symbol: symbol, filter: :oi_part)
|
10
|
+
if json
|
11
|
+
p s.to_json
|
12
|
+
else
|
13
|
+
s.each {|x| puts x.values.to_csv}
|
14
|
+
end
|
15
|
+
rescue
|
16
|
+
msg = { error: 503, message: "Could not processes symbol '#{symbol}'." }
|
17
|
+
p msg.to_json
|
18
|
+
end
|
data/bin/intra.rb
ADDED
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'cotcube-bardata'
|
4
|
+
require 'cotcube-level'
|
5
|
+
require 'cotcube-indicators'
|
6
|
+
|
7
|
+
def exit_with_error(err)
|
8
|
+
msg = { error: 1, message: "#{err}" }
|
9
|
+
p msg.to_json
|
10
|
+
exit 1
|
11
|
+
end
|
12
|
+
|
13
|
+
|
14
|
+
contract = ARGV[0].nil? ? nil : ARGV[0].upcase
|
15
|
+
|
16
|
+
debug = ARGV.include? 'debug'
|
17
|
+
if contract.nil?
|
18
|
+
exit_with_error('No contract given')
|
19
|
+
end
|
20
|
+
|
21
|
+
sym = Cotcube::Helpers.get_id_set(symbol: contract[..1])
|
22
|
+
# TODO: apply daylight time pimped diff to all relevant datetimes in series
|
23
|
+
timediff = if %w[ NYBOT NYMEX ].include? sym[:exchange]
|
24
|
+
5.hours
|
25
|
+
elsif %w[ DTB ].include? sym[:exchane]
|
26
|
+
1.hour
|
27
|
+
else
|
28
|
+
6.hours
|
29
|
+
end
|
30
|
+
|
31
|
+
continuous = %w[currencies interest indices].include? sym[:type]
|
32
|
+
interval = 30.minutes
|
33
|
+
|
34
|
+
intrabase = []
|
35
|
+
istencil = []
|
36
|
+
collector_threads = []
|
37
|
+
|
38
|
+
collector_threads << Thread.new do
|
39
|
+
istencil = Cotcube::Level::Intraday_Stencil.new( interval: 30.minutes, swap_type: :full, asset: :full, weeks: 8)
|
40
|
+
end
|
41
|
+
|
42
|
+
collector_threads << Thread.new do
|
43
|
+
begin
|
44
|
+
intrabase = JSON.parse(Cotcube::Helpers::DataClient.new.get_historical(contract: contract, interval: :min30, duration: '3_W' ), symbolize_names: true)[:base].
|
45
|
+
map{ |z|
|
46
|
+
z[:datetime] = DateTime.parse(z[:time])
|
47
|
+
%i[time created_at wap trades].each{|k| z.delete(k)}
|
48
|
+
z
|
49
|
+
}
|
50
|
+
rescue
|
51
|
+
intrabase = []
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
collector_threads.each(&:join)
|
56
|
+
|
57
|
+
base = intrabase
|
58
|
+
base.select!{|z| z[:high]}
|
59
|
+
|
60
|
+
scaleBreaks = []
|
61
|
+
brb = istencil.base
|
62
|
+
brb.each_with_index.map{|z,i|
|
63
|
+
next if i.zero?
|
64
|
+
if brb[i][:datetime] - brb[i-1][:datetime] > (1) and brb[i][:datetime] > base.first[:datetime] and brb[i-1][:datetime] < base.last[:datetime]
|
65
|
+
scaleBreaks << { startValue: brb[i-1][:datetime] + 0.5 * interval, endValue: brb[i][:datetime] - 0.5 * interval }
|
66
|
+
end
|
67
|
+
} unless base.empty?
|
68
|
+
|
69
|
+
pkg = {
|
70
|
+
sym: sym,
|
71
|
+
base: base,
|
72
|
+
breaks: scaleBreaks
|
73
|
+
}
|
74
|
+
|
75
|
+
puts pkg.to_json
|
data/bin/sym.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'cotcube-level'
|
4
|
+
require 'cotcube-helpers'
|
5
|
+
include Cotcube::Helpers
|
6
|
+
require_relative '../lib/cotcube-bardata.rb'
|
7
|
+
|
8
|
+
contract = ARGV[0].nil? ? nil : ARGV[0].upcase
|
9
|
+
|
10
|
+
begin
|
11
|
+
s = Cotcube::Helpers.get_id_set(symbol: contract[..1])
|
12
|
+
p s.to_json
|
13
|
+
rescue
|
14
|
+
msg = { error: 503, message: "Could not process contract '#{contract}'." }
|
15
|
+
p msg.to_json
|
16
|
+
end
|
data/bin/symbols.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}"
|
@@ -33,7 +33,7 @@ module Cotcube
|
|
33
33
|
range = (range_begin..range_end)
|
34
34
|
end
|
35
35
|
|
36
|
-
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
36
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id, contract: contract)
|
37
37
|
contract = contract[2..4] if contract.to_s.size == 5
|
38
38
|
id = sym[:id]
|
39
39
|
id_path = "#{config[:data_path]}/daily/#{id}"
|
@@ -81,7 +81,8 @@ module Cotcube
|
|
81
81
|
end
|
82
82
|
data.map do |bar|
|
83
83
|
indicators.each do |k,v|
|
84
|
-
|
84
|
+
tmp = v.call(bar)
|
85
|
+
bar[k] = tmp.respond_to?(:round) ? tmp.round(rounding) : tmp
|
85
86
|
end
|
86
87
|
end unless indicators.empty?
|
87
88
|
if range.nil?
|
@@ -101,7 +102,7 @@ module Cotcube
|
|
101
102
|
measuring = lambda {|c| puts "[continuous] Time measured until '#{c}': #{(Time.now.to_f - measure.to_f).round(2)}sec" unless measure.nil? }
|
102
103
|
|
103
104
|
measuring.call("Starting")
|
104
|
-
sym = get_id_set(symbol: symbol, id: id)
|
105
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
105
106
|
id = sym[:id]
|
106
107
|
symbol = sym[:symbol]
|
107
108
|
ticksize = sym[:ticksize]
|
@@ -115,7 +116,7 @@ module Cotcube
|
|
115
116
|
# this boosts from 4.5sec to 0.3sec
|
116
117
|
rewriting = (force_rewrite or not(File.exist?(c_file)) or (Time.now - File.mtime(c_file) > 8.days))
|
117
118
|
if rewriting
|
118
|
-
puts "In daily+continuous: Rewriting #{c_file} #{force_rewrite ? "forcibly" : "due to fileage"}.".light_yellow
|
119
|
+
puts "In daily+continuous: Rewriting #{c_file} #{force_rewrite ? "forcibly" : "due to fileage"}.".light_yellow if debug
|
119
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}`
|
120
121
|
end
|
121
122
|
loading = lambda do
|
@@ -145,17 +146,13 @@ module Cotcube
|
|
145
146
|
|
146
147
|
measuring.call("Finished retrieving dailies.")
|
147
148
|
result = []
|
148
|
-
rounding = 8
|
149
|
+
rounding = 8
|
149
150
|
indicators ||= {
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
sma250_typ: Cotcube::Indicators.sma(key: :typical, length: 250),
|
154
|
-
dist: Cotcube::Indicators.calc(a: :high, b: :low, finalize: :to_i) {|high, low| ((high-low) / ticksize) },
|
151
|
+
tr: Cotcube::Indicators.true_range,
|
152
|
+
atr5: Cotcube::Indicators.ema(key: :tr, length: 5),
|
153
|
+
dist: Cotcube::Indicators.calc(a: :high, b: :low, finalize: :to_i) {|high, low| ((high-low) / ticksize) }
|
155
154
|
}
|
156
155
|
|
157
|
-
|
158
|
-
|
159
156
|
data.group_by { |x| x[:date] }.map do |k, v|
|
160
157
|
v.map { |x| x.delete(:date) }
|
161
158
|
avg_bar = {
|
@@ -175,12 +172,13 @@ module Cotcube
|
|
175
172
|
p avg_bar if debug
|
176
173
|
indicators.each do |k,v|
|
177
174
|
print format('%12s: ', k.to_s) if debug
|
178
|
-
|
175
|
+
tmp = v.call(avg_bar)
|
176
|
+
avg_bar[k] = tmp.respond_to?(:round) ? tmp.round(rounding) : tmp
|
179
177
|
puts avg_bar[k] if debug
|
180
178
|
end
|
181
|
-
|
182
|
-
|
183
|
-
}
|
179
|
+
#%i[tr atr5].each { |ind|
|
180
|
+
# avg_bar[ind] = (avg_bar[ind] / sym[:ticksize]).round.to_i unless avg_bar[ind].nil?
|
181
|
+
#}
|
184
182
|
result << avg_bar
|
185
183
|
result.last[:contracts] = v
|
186
184
|
end
|
@@ -196,6 +194,57 @@ module Cotcube
|
|
196
194
|
date.nil? ? Cotcube::Bardata.const_get(constname).map{|z| z.dup } : Cotcube::Bardata.const_get(constname).find { |x| x[:date] == date }
|
197
195
|
end
|
198
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
|
+
|
199
248
|
def continuous_ml(symbol: nil, id: nil, base: nil)
|
200
249
|
(base.nil? ? Cotcube::Bardata.continuous(symbol: symbol, id: id) : base).map do |x|
|
201
250
|
x[:ml] = x[:contracts].max_by { |z| z[:volume] }[:contract]
|
@@ -236,7 +285,7 @@ module Cotcube
|
|
236
285
|
%i[volume oi].include?(selector)
|
237
286
|
|
238
287
|
measuring.call("Starting")
|
239
|
-
sym = get_id_set(symbol: symbol, id: id)
|
288
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
240
289
|
id = sym[:id]
|
241
290
|
# noinspection RubyNilAnalysis
|
242
291
|
data = continuous(id: id, config: config, measure: measure).map do |x|
|
@@ -300,7 +349,7 @@ module Cotcube
|
|
300
349
|
%i[volume oi].include?(selector)
|
301
350
|
|
302
351
|
measuring.call("Entering function")
|
303
|
-
sym = get_id_set(symbol: symbol, id: id)
|
352
|
+
sym = Cotcube::Helpers.get_id_set(symbol: symbol, id: id)
|
304
353
|
if %w[R6 BJ GE].include? sym[:symbol]
|
305
354
|
puts "Rejecting to process symbol '#{sym[:symbol]}'.".light_red
|
306
355
|
return []
|
@@ -319,12 +368,14 @@ module Cotcube
|
|
319
368
|
.reject { |k, _| k[-2..].to_i >= date.year % 2000 }
|
320
369
|
.group_by { |k, _| k[2] }
|
321
370
|
measuring.call("Retrieved continous_overview")
|
322
|
-
output_sent = []
|
323
|
-
early_year=nil
|
324
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
|
+
|
325
375
|
data.keys.sort.each do |month|
|
326
376
|
puts "Processing #{sym[:symbol]}#{month}" if debuglevel > 1
|
327
377
|
v0 = data[month]
|
378
|
+
|
328
379
|
# ldays is the list of 'last days'
|
329
380
|
ldays = v0.map { |_, v1| Date.parse(v1.last[:date]).yday }
|
330
381
|
# fdays is the list of 'first days'
|
@@ -333,6 +384,23 @@ module Cotcube
|
|
333
384
|
ldays.map! { |x| x > 350 ? x - 366 : x } if ldays.min < 50
|
334
385
|
fday = fdays[fdays.size / 2]
|
335
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: lavg - 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
|
+
|
336
404
|
# a contract is proposed to use after fday - 1, but before ldays.min (green)
|
337
405
|
# it is warned to user after fday - 1 but before lavg - 1 (red)
|
338
406
|
# it is warned red >= lavg - 1 and <= lavg + 1
|
@@ -345,55 +413,42 @@ module Cotcube
|
|
345
413
|
else
|
346
414
|
:white
|
347
415
|
end
|
348
|
-
|
349
|
-
long_output << {
|
350
|
-
month: month,
|
351
|
-
first_ml: fday,
|
352
|
-
last_min: ldays.min,
|
353
|
-
last_avg: lavg,
|
354
|
-
last_max: ldays.max }
|
416
|
+
|
355
417
|
output = "#{sym[:symbol]
|
356
|
-
|
357
|
-
|
358
|
-
|
359
|
-
|
360
|
-
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
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
|
+
|
381
443
|
end
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
puts " Assuming late-year-processing.".light_yellow
|
387
|
-
puts early_year.light_green
|
388
|
-
end
|
389
|
-
when 1
|
390
|
-
# all ok
|
391
|
-
true
|
392
|
-
else
|
393
|
-
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
|
394
448
|
end
|
449
|
+
|
395
450
|
measuring.call("Finished processing")
|
396
|
-
|
451
|
+
return long_output
|
397
452
|
end
|
398
453
|
end
|
399
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}" }
|
@@ -78,12 +78,14 @@ module Cotcube
|
|
78
78
|
# l_symbol = l_sym[:symbol]
|
79
79
|
id_path = id_path_get.call(i)
|
80
80
|
data_file = "#{id_path}/#{d}.csv"
|
81
|
+
current_sym = Cotcube::Helpers.get_id_set(id: i, config: config)
|
81
82
|
raise "No data found for requested :id (#{id_path} does not exist)" unless Dir.exist?(id_path)
|
82
83
|
|
83
84
|
unless File.exist?(data_file)
|
84
85
|
unless quiet
|
85
|
-
puts 'WARNING: No data found for requested
|
86
|
-
|
86
|
+
puts 'WARNING: No data found for requested symbol'\
|
87
|
+
" #{current_sym[:symbol]} in #{id_path} for #{d}.".colorize(:light_yellow)
|
88
|
+
|
87
89
|
end
|
88
90
|
return []
|
89
91
|
end
|
@@ -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.17
|
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-12-06 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,11 @@ files:
|
|
164
164
|
- README.md
|
165
165
|
- Rakefile
|
166
166
|
- VERSION
|
167
|
+
- bin/daily.rb
|
168
|
+
- bin/eod.rb
|
169
|
+
- bin/intra.rb
|
170
|
+
- bin/sym.rb
|
171
|
+
- bin/symbols.rb
|
167
172
|
- cotcube-bardata.gemspec
|
168
173
|
- lib/cotcube-bardata.rb
|
169
174
|
- lib/cotcube-bardata/cached.rb
|
@@ -200,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
200
205
|
- !ruby/object:Gem::Version
|
201
206
|
version: '0'
|
202
207
|
requirements: []
|
203
|
-
rubygems_version: 3.1.
|
208
|
+
rubygems_version: 3.1.6
|
204
209
|
signing_key:
|
205
210
|
specification_version: 4
|
206
211
|
summary: Functions to provide bardata; and some simple time series aggregations
|