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 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