cotcube-bardata 0.1.15.4 → 0.1.17
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/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
|