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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 46f85dd103fd911ba475b347f14002f1402eda630b79ded6a161969a1df487db
4
- data.tar.gz: 72f66b63600041d28131df575036d0295f8ab206e132fcd69c2ea84109194505
3
+ metadata.gz: aa52a5fd519f8351f712e30495d4dda59bb37a4d4b588c84904d1971d7ad734c
4
+ data.tar.gz: b1eaacc5e75d13d84edf8c095cdaebc7ec588fe0e61ef6dc764d2a5633fedece
5
5
  SHA512:
6
- metadata.gz: 29271f6f4b5dba379bb19e81846d52f1d2995bd010f35b7e80bad3256ae415c841eeead6a84034ce72d29cd6b3746d4d62fb182347abca1fa6d78fd0c3bfb6a7
7
- data.tar.gz: 5cb42e0fbd5ae2124edb7ede368047e72c8fe68b99ed928727d8e47859a5c94470bab989a032f0689e63058dd01b190936d02f22d8be7fca3cd61f3240a40a1c
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.15.2
1
+ 0.1.16
data/bin/eod.rb ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/cotcube-bardata.rb'
4
+
5
+ symbol = ARGV[0].nil? ? nil : ARGV[0].upcase
6
+
7
+ s = Cotcube::Bardata.provide_eods(threshold: 0.10, contracts_only: false, symbol: symbol, filter: :oi_part)
8
+ s.each {|x| puts x.values.to_csv}
@@ -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.1'
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
- row[k] = row[k].to_f if %i[open high low close].include? k
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 # sym[:format].split('.').last.to_i rescue 6
149
+ rounding = 8
135
150
  indicators ||= {
136
- typical: Cotcube::Indicators.calc(a: :high, b: :low, c: :close) {|high, low, close| (high + low + close) / 3 },
137
- sma250_high: Cotcube::Indicators.sma(key: :high, length: 250),
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
- avg_bar[k] = v.call(avg_bar).round(rounding)
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
- %i[tr atr5].each { |ind|
192
- avg_bar[ind] = (avg_bar[ind] / sym[:ticksize]).round.to_i unless avg_bar[ind].nil?
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 == date.year % 2000 }
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
- # rubocop:disable Layout/ClosingParenthesisIndentation
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
- }#{month
366
- }\t#{format '%12s', sym[:type]
367
- }\ttoday is #{ytoday
368
- } -- median of first is #{fday
369
- }\tlast ranges from #{format '%5d', ldays.min
370
- }: #{dfm.call(ldays.min)
371
- }\t#{format '%5d', lavg
372
- }: #{dfm.call(lavg)
373
- }\tto #{format '%5d', ldays.max
374
- }: #{dfm.call(ldays.max)}".colorize(color)
375
- if debug || (color != :white)
376
- puts output unless silent
377
- output_sent << "#{sym[:symbol]}#{month}" unless color == :white
378
- end
379
- early_year ||= output
380
- next if silent or not (debug and debuglevel >= 2)
381
-
382
- v0.each do |contract, v1|
383
- puts "\t#{contract
384
- }\t#{v1.first[:date]
385
- } (#{format '%3d', Date.parse(v1.first[:date]).yday
386
- })\t#{Date.parse(v1.last[:date]).strftime('%a, %Y-%m-%d')
387
- } (#{Date.parse(v1.last[:date]).yday})" unless silent
388
- # rubocop:enable Layout/ClosingParenthesisIndentation
389
- end
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
- case output_sent.size
392
- when 0
393
- unless silent
394
- puts "WARNING: No output was sent for symbol '#{sym[:symbol]}'.".colorize(:light_yellow)
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
- short ? output_sent : long_output
451
+ return long_output
406
452
  end
407
453
  end
408
454
  end
@@ -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
@@ -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.15.2
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-08-04 00:00:00.000000000 Z
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.1'
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.1'
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.2
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