cotcube-bardata 0.1.2 → 0.1.7

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: 7cc8f5a19330f55ec26073d90b2c7da30547b61903daa93f8b2977c05ad308f8
4
- data.tar.gz: 3dac9e49fb0143d8dd91a86f5a7779dcb25a5c8fca719de5b23a46a5e742380f
3
+ metadata.gz: 7db21286fcb1a011326db3d27333b3417ec497db6c5b005250e0dcc11d355839
4
+ data.tar.gz: 1eca29b839ae84d43c601f793501237cabc5de25363ea1bd55f6c707393d98ba
5
5
  SHA512:
6
- metadata.gz: aafb4160d474f4f4d0694faee22821f1e8a65a510dcc2c84999acce0e0f3b7511dc52cd2d28cb21856162fbed9c5fa2e9b8e65b8065b7c1603128f8ef1cdea75
7
- data.tar.gz: 51ba4678419a6daf9f4d2a18810432f2f3c93c7a6417e8d0e7beae822e76ad9214450bfb1bf4479fc30c4032b51e4504c923e707f6ea8feff295f16071040df3
6
+ metadata.gz: 3b46cbfbd3bf8117a5076691d9eaa8985ea551d822838e69cf4336a97161e77d3c0ab5b9427f957a08a219a19290d76832527cadbf2956d16053762443e8f25b
7
+ data.tar.gz: b082544cd2ac1c4a36a5e23a7ce2da9764fd9ce4fa7f09a72b28a579301eb007fda3ea8c8856cb5f9a9fea6756d2c6ee2a4d84224195840793ff49d1c7985855
data/.irbrc.rb CHANGED
@@ -1,5 +1,7 @@
1
+ # frozen_string_literal: true
2
+
1
3
  def verbose_toggle
2
- irb_context.echo ? irb_context.echo = false : irb_context.echo = true
4
+ irb_context.echo = (irb_context.echo ? false : true)
3
5
  end
4
6
 
5
7
  alias vt verbose_toggle
@@ -1,3 +1,41 @@
1
+ ## 0.1.7 (January 14, 2021)
2
+ - added :range parameter to :provide, hence to :provide_cached, :provide_daily
3
+ - added forgotten module_functions
4
+
5
+ ## 0.1.6 (January 07, 2021)
6
+ - prefering datetime instead date (in helpers and daily)
7
+ - changed keyword :set to :filter in cached, provide and trading_hours
8
+
9
+ ## 0.1.5 (January 02, 2021)
10
+ - applied some still missing cops
11
+
12
+ ## 0.1.4 (January 02, 2021)
13
+ - two minor fixes (cached.rb, daily.rb)
14
+ - adding first (shy) specs ... to be continued
15
+ - cotcube-bardata.rb: added dependency parallel, added new module files and functions
16
+ - provide.rb: writing provide, the central accessor to actual bardata
17
+ - cached.rb: implementing 'provide_cached', which manages reduced and dimished subsets of 'quarters'
18
+ - helpers.rb: added get_id_set
19
+ - daily.rb: applied cops
20
+ - quarters.rb: applied cops, used new get_id_set, slimmed down content in favor of 'provide'
21
+ - eods.rb: renamed get_id_from to get_id_set
22
+ - added explanation to range_matrix.rb
23
+ - added 'holidays' to trade_dates.csv, depending on according CSV
24
+ - applied cops to init.rb
25
+ - changed name from get_range to trading_hours
26
+ - minor change in gemspec
27
+ - fixed typos in README
28
+ - added bounded versions to gemspec
29
+ - applied cops
30
+ - new file trading_hours.rb providing get_range(). Based on CSV data it provides a list of ranges depicting seconds since Sunday 0:00am, which in turn can be used with the helper Array.new.to_time_interval.
31
+ - new file and method 'range_matrix', investigating high-low ranges of entire daily
32
+ - Too bad, found copied README...fixing something quite embarassing.
33
+
34
+ ## 0.1.3 (December 23, 2020)
35
+ - added .provide_most_liquids_by_eod which supports :age, filtering out files that have been updated more recently
36
+ - added 'type' to symbols to filter for e.g. currencies
37
+ - changed .provide_eods not to raise on missing eod-file but just to WARN
38
+
1
39
  ## 0.1.2 (December 22, 2020)
2
40
  - created and added .provide_quarters
3
41
  - added cotcube-helpers as new dependency to gempsec
data/Gemfile CHANGED
@@ -1,5 +1,6 @@
1
- source "https://rubygems.org"
1
+ # frozen_string_literal: true
2
+
3
+ source 'https://rubygems.org'
2
4
 
3
5
  # Specify your gem's dependencies in bitangent.gemspec
4
6
  gemspec
5
-
data/README.md CHANGED
@@ -1,36 +1,19 @@
1
- # Bitangent
1
+ # cotcube-bardata
2
2
 
3
- This gem provides a class (and will maybe later provide a commandline tool) to process
4
- time series data into bitangents.
3
+ This gem is a versatile provider of bardata. It relies on a directory structure most probably saved to `/var/cotcube/bardata/`. The following directories and files contain data others might expect to be delivered by a database:
5
4
 
6
- The underlying algorithm starts with the entire range of data and shears it (starting at
7
- 90 or -90 degrees) along the x axis until a bitangent is found parallel to the x axis
8
- (i.e. __y == 0__ resp. __y == y.last__), resulting in an angle and a group of at least
9
- 2 measurements. Please note here:
10
- - Measurements can be clustered to 1 finding in case there is no significant distance to
11
- the bitangent in regard to the :fuzziness, which is at least 1 'tick'.
12
- - Ocassionally a bitangent becomes an N-tangent, when multiple findings or clusters are
13
- in one line resp. the fuzzied ranged on the sheared graph.
14
- - Shearing is limited by reaching 0 degrees, so everything below the horizont (or above resp.)
15
- is discarded.
16
-
17
- After identifiying the angle of Z degress delivering N findings( actually N - 1, as the
18
- last finding always is the last member of the series), the entire time series then is split
19
- into N subranges, where each subrange is processed again until it reaches minimum size
20
- (which defaults to 3 items).
21
-
22
- Except for the very first range the challenge is to trim away the beginning of each sub
23
- range.
24
-
25
- The result of such a search is a tree, where it might be considerable to walk and change
26
- this tree by adding elements to the time series instead of recalculating it completely.
5
+ 1. `eods`: within *eods/<id or symbol>/<date>.csv*, for each date a list of contracts is located, to be applied with the list of headers `%i[ contract date open high low close volume oi ]`.
6
+ 2. `daily`: within *daily/<id or symbol>/<contract>.csv*, for each contract all eods are provided. The list of headers is expected as `%i[ contract date open high low close volume oi ]`. Please note that it is not obvious whether `close` contains settlement or actual closing price, depending on the exchange and the broker providing the source data.
7
+ 3. `quarters`: within *quarters/<id or symbol>/<contract>.csv*, for each contract a list of quarters (15 minute intervals) is provided, depending on the first occurrence of the contract within the topN volume segment. Note the different headers here: `%i[ contract date_alike day open high low close volume ]`.
8
+ 4. `trading_hours`: within *trading_hours/<symbol or type>_<set>.csv* a list of intervals is provided, with the headers `%i[ interval_start interval_end ]` for each interval described by seconds since Sunday 0:00p.m. (as defaulted by Ruby's *DateTime.new.wday)*.
9
+ 5. `trade_dates.csv`: A growing list of trade\_dates as provided by the CME.
27
10
 
28
11
  ## Installation
29
12
 
30
13
  Add this line to your application's Gemfile:
31
14
 
32
15
  ```ruby
33
- gem 'bitangent'
16
+ gem 'cotcube-bardata'
34
17
  ```
35
18
 
36
19
  And then execute:
@@ -39,11 +22,60 @@ And then execute:
39
22
 
40
23
  Or install it yourself as:
41
24
 
42
- $ gem install bitangent
25
+ $ gem install cotcube-bardata
43
26
 
44
27
  ## Usage
45
28
 
46
- TODO: Write usage instructions here
29
+ ### Configuration
30
+
31
+ The gem expects a configfile 'bardata.yml', located in '/etc/cotcube/' on linux platform and '/usr/local/etc/cotcube/' on FreeBSD. The location of the configfile can be overwritten by passing the according parameter to `init`.
32
+
33
+ ### daily.rb
34
+
35
+ Provides
36
+
37
+ * `provide_daily(symbol: nil, id: nil, contract:, timezone: Time.find_zone('America/Chicago'), config: init)`
38
+ * `continuous(symbol: nil, id: nil, config: init, date: nil)`: Loads all dailies for given *id* and groups by date, hence providing a list of eods.
39
+ * `continuous_ml(symbol: nil, id: nil, base: nil)`: Provides a list of contracts, containing a list of most liquid by volume contracts as `{ date: , ml: }`
40
+ * `continuous_actual_ml(symbol: nil, id: nil)`: Same as above, but providing the succeeding trading day (as the signaled 'ML' is yet one day old before it can be used).
41
+ * `continuous_overview(symbol: nil, id: nil, config: init, selector: :volume, human: false, filter: nil)`: Several purposes, but most noticeable providing the range of first and last occurrence within the top N% by volume within eods.
42
+
43
+ ### eods.rb
44
+
45
+ Provides
46
+
47
+ * `most_liquid_for(symbol: nil, id: nil, date: last_trade_date, config: init, quiet: false)`
48
+ * `provide_most_liquids_by_eod(config: init, date: last_trade_date, filter: :volume_part, age: 1.hour)`
49
+ * `provide_eods(**args)`
50
+ * `provide_quarters(**args)`
51
+
52
+ ### quarters.rb
53
+
54
+ Provides `provide_quarters(**args)`.
55
+
56
+ ### provide.rb
57
+
58
+ Provides `provide(**args)`.
59
+
60
+ ### range\_matrix.rb
61
+
62
+ Provides `range_matrix`, a simple method processing data based on `Bardata.continuous_actual_ml` to return a statistical overview of daily high-low ranges (not True Ranges). It contains sets for
63
+
64
+ * all available data,
65
+ * a data subset containing the recent 12 months
66
+ * data diminished by `:dim` (top and bottom) based on all available data
67
+
68
+ and contains *max*, *avg*, *lower*, *median*, *upper* and *max* (where 'upper' and 'lower' are like the median but at the 25percentile and 75percentile resp.).
69
+
70
+ As a third dimension (sorry!) all of the above is applied to days, weeks as well as months.
71
+
72
+ ### trade\_dates.rb
73
+
74
+ Provides `last_trade_date`, simple fetches the current 5 trade dates from CME and returns the very last.
75
+
76
+ ### trading\_hours.rb
77
+
78
+ Provides `get_range(symbol: nil, set: :full, force_set: false, config: init, debug: false)`, loading a set of intervals. The sets are defaulting to :full when the requested set is not found--unless :force\_set is enabled. Furthermore, if symbol is not found, the type-based version is returned. Eventually, if neither could be returned, the 24x7 interval is returned.
47
79
 
48
80
  ## Development
49
81
 
@@ -53,9 +85,10 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
53
85
 
54
86
  ## Contributing
55
87
 
56
- Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bitangent.
88
+ Bug reports and pull requests are welcome on GitHub at https://github.com/donkeybridge/bitangent.
57
89
 
58
90
 
59
91
  ## License
60
92
 
61
93
  The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
94
+
data/Rakefile CHANGED
@@ -1,6 +1,8 @@
1
- require "bundler/gem_tasks"
2
- require "rspec/core/rake_task"
1
+ # frozen_string_literal: true
2
+
3
+ require 'bundler/gem_tasks'
4
+ require 'rspec/core/rake_task'
3
5
 
4
6
  RSpec::Core::RakeTask.new(:spec)
5
7
 
6
- task :default => :spec
8
+ task default: :spec
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.2
1
+ 0.1.7
@@ -9,13 +9,13 @@ Gem::Specification.new do |spec|
9
9
  spec.summary = 'Functions to provide bardata; and some simple time series aggregations'
10
10
  spec.description = 'Functions to provide bardata; and some simple time series aggregations '
11
11
 
12
- spec.homepage = 'https://github.com/donkeybridge/'+ spec.name
12
+ spec.homepage = "https://github.com/donkeybridge/#{spec.name}"
13
13
  spec.license = 'BSD-4-Clause'
14
14
  spec.required_ruby_version = Gem::Requirement.new('~> 2.7')
15
15
 
16
16
  spec.metadata['homepage_uri'] = spec.homepage
17
17
  spec.metadata['source_code_uri'] = spec.homepage
18
- spec.metadata['changelog_uri'] = spec.homepage + '/CHANGELOG.md'
18
+ spec.metadata['changelog_uri'] = "#{spec.homepage}/CHANGELOG.md"
19
19
 
20
20
  # Specify which files should be added to the gem when it is released.
21
21
  # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
@@ -26,16 +26,15 @@ Gem::Specification.new do |spec|
26
26
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
27
  spec.require_paths = ['lib']
28
28
 
29
- spec.add_dependency 'cotcube-indicators'
30
- spec.add_dependency 'cotcube-helpers'
31
- spec.add_dependency 'yaml'
32
- spec.add_dependency 'activesupport'
33
- spec.add_dependency 'colorize'
34
- spec.add_dependency 'httparty'
35
- spec.add_dependency 'rubyzip'
29
+ spec.add_dependency 'activesupport', '~> 6'
30
+ spec.add_dependency 'colorize', '~> 0.8'
31
+ spec.add_dependency 'cotcube-helpers', '~> 0.1'
32
+ spec.add_dependency 'cotcube-indicators', '~> 0.1'
33
+ spec.add_dependency 'httparty', '~> 0.18'
34
+ spec.add_dependency 'parallel', '~> 1'
35
+ spec.add_dependency 'yaml', '~> 0.1'
36
36
 
37
-
38
- spec.add_development_dependency 'rake'
37
+ spec.add_development_dependency 'rake', '>= 12'
39
38
  spec.add_development_dependency 'rspec', '~>3.6'
40
39
  spec.add_development_dependency 'yard', '~>0.9'
41
40
  end
@@ -1,3 +1,5 @@
1
+ # rubocop:disable Naming/FileName
2
+ # rubocop:enable Naming/FileName
1
3
  # frozen_string_literal: true
2
4
 
3
5
  require 'active_support'
@@ -9,34 +11,62 @@ require 'date' unless defined?(DateTime)
9
11
  require 'csv' unless defined?(CSV)
10
12
  require 'yaml' unless defined?(YAML)
11
13
  require 'cotcube-helpers'
12
-
13
-
14
+ require 'parallel'
14
15
 
15
16
  require_relative 'cotcube-bardata/constants'
17
+ require_relative 'cotcube-bardata/helpers'
16
18
  require_relative 'cotcube-bardata/init'
17
19
  require_relative 'cotcube-bardata/trade_dates'
18
20
  require_relative 'cotcube-bardata/daily'
19
21
  require_relative 'cotcube-bardata/quarters'
20
22
  require_relative 'cotcube-bardata/eods'
23
+ require_relative 'cotcube-bardata/cached'
21
24
  require_relative 'cotcube-bardata/provide'
25
+ require_relative 'cotcube-bardata/range_matrix'
26
+ require_relative 'cotcube-bardata/trading_hours'
22
27
 
23
28
  module Cotcube
24
29
  module Bardata
25
-
26
30
  module_function :config_path, # provides the path of configuration directory
27
- :config_prefix, # provides the prefix of the configuration directory according to OS-specific FSH
28
- :init, # checks whether environment is prepared and returns the config hash
29
- :last_trade_date, # Provides the most recent trade date (today or maybe last friday before weekend)
30
- :provide, #
31
- :most_liquid_for, # the most_liquid contract for a given symbol or id, based on date or last_trade_date
32
- :provide_eods, # provides the list of eods, either with data or just the contracts, filtered for liquidity threshold
33
- :provide_daily, # provides the list of dailies for a given symbol, which include OI. Note that the close is settlement price.
34
- :continuous, # for a given date or range, provide all contracts that exceed a given threshold of volume share
35
- :continuous_overview, # based on continuous, create list of when which contract was most liquid
36
- :provide_quarters, # provide the list of quarters, possibly as hours or days.
37
- :symbols # reads and provides the symbols file
38
-
39
- # please not that module_functions of source provided in private files must be published there
31
+ # provides the prefix of the configuration directory according to OS-specific FSH
32
+ :config_prefix,
33
+ # checks whether environment is prepared and returns the config hash
34
+ :init,
35
+ # Provides the most recent trade date (today or maybe last friday before weekend)
36
+ :last_trade_date,
37
+ :provide,
38
+ # the most_liquid contract for a given symbol or id, based on date or last_trade_date
39
+ :most_liquid_for,
40
+ # provides the list of eods, either with data or just the contracts,
41
+ # filtered for liquidity threshold
42
+ :provide_eods,
43
+ :provide_most_liquids_by_eod,
44
+ # provides the list of dailies for a given symbol, which include OI.
45
+ # Note that the close is most probably settlement price.
46
+ :provide_daily,
47
+ # for a given date or range, provide all contracts that exceed a given threshold of volume share
48
+ :continuous,
49
+ # the list of most liquid contracts (by each days volume share)
50
+ :continuous_ml,
51
+ # same list but riped one day each
52
+ :continuous_actual_ml,
53
+ # based on continuous, create list of when which contract was most liquid
54
+ :continuous_overview,
55
+ # provide the list of quarters, possibly as hours or days.
56
+ :provide_quarters,
57
+ # some statistics to estimate daily volatility of specific contract
58
+ :range_matrix,
59
+ # create an array of ranges based on specified source data
60
+ :trading_hours,
61
+ # receive id / symbol information on an uncertain set of parameters
62
+ :get_id_set,
63
+ :select_specific_date,
64
+ :extended_select_for_range,
65
+ :provide_cached,
66
+ :compare,
67
+ :holidays,
68
+ :symbols # reads and provides the symbols file
69
+
70
+ # please note that module_functions of source provided in private files must be published there
40
71
  end
41
72
  end
42
-
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ # missing top level documentation
5
+ module Bardata
6
+ # send pre-created days based on quarters
7
+ def provide_cached(contract:, # rubocop:disable Metrics/ParameterLists
8
+ symbol: nil, id: nil,
9
+ range: nil,
10
+ config: init,
11
+ timezone: Time.find_zone('America/Chicago'),
12
+ filter: :full, # most probably either :full or :rth
13
+ force_update: false, # force reloading via provide_quarters
14
+ force_recent: false) #
15
+
16
+ unless range.nil? ||
17
+ range.is_a?(Range) &&
18
+ [Date, DateTime, ActiveSupport::TimeWithZone].map do |cl|
19
+ (range.begin.nil? || range.begin.is_a?(cl)) &&
20
+ (range.end.nil? || range.end.is_a?(cl))
21
+ end.reduce(:|)
22
+ raise ArgumentError, 'Range, if given, must be either (Integer..Integer) or (Timelike..Timelike)'
23
+ end
24
+
25
+ unless range.nil?
26
+ range_begin = range.begin.nil? ? nil : timezone.parse(range.begin.to_s)
27
+ range_end = range.end.nil? ? nil : timezone.parse(range.end.to_s)
28
+ range = (range_begin..range_end)
29
+ end
30
+
31
+ headers = %i[contract datetime open high low close volume]
32
+ sym = get_id_set(symbol: symbol, id: id, contract: contract)
33
+ contract = contract[-3..]
34
+ dir = "#{config[:data_path]}/cached/#{sym[:id]}_#{filter.to_s.downcase}"
35
+ symlink = "#{config[:data_path]}/cached/#{sym[:symbol]}_#{filter.to_s.downcase}"
36
+ `mkdir -p #{dir}` unless Dir.exist? dir
37
+ `ln -s #{dir} #{symlink}` unless File.exist? symlink
38
+ file = "#{dir}/#{contract}.csv"
39
+ quarters_file = "#{config[:data_path]}/quarters/#{sym[:id]}/#{contract[-3..]}.csv"
40
+ if File.exist?(file) && (not force_update)
41
+ base = CSV.read(file, headers: headers).map do |x|
42
+ x = x.to_h
43
+ x[:datetime] = timezone.parse(x[:datetime])
44
+ %i[open high low close].each { |z| x[z] = x[z].to_f.round(9) }
45
+ x[:volume] = x[:volume].to_i
46
+ x[:type] = "#{filter.to_s.downcase}_day".to_sym
47
+ x
48
+ end
49
+ if base.last[:high].zero?
50
+ # contract exists but is closed (has the CLOSED marker)
51
+ base.pop
52
+ # rubocop:disable Metrics/BlockNesting
53
+ result = if range.nil?
54
+ base
55
+ else
56
+ base.select do |x|
57
+ (range.begin.nil? ? true : x[:datetime] >= range.begin) and
58
+ (range.end.nil? ? true : x[:datetime] <= range.end)
59
+ end
60
+ end
61
+ return result
62
+ elsif File.mtime(file) < File.mtime(quarters_file)
63
+ result = if range.nil?
64
+ base
65
+ else
66
+ base.select do |x|
67
+ (range.begin.nil? ? true : x[:datetime] >= range.begin) and
68
+ (range.end.nil? ? true : x[:datetime] <= range.end)
69
+ end
70
+ end
71
+ # rubocop:enable Metrics/BlockNesting
72
+ return result
73
+ else
74
+ puts "File #{file} exists, but is neither closed nor current. Running update.".colorize(:light_green)
75
+ end
76
+ end
77
+ begin
78
+ data = provide_quarters(contract: contract, id: sym[:id], keep_marker: true)
79
+ rescue StandardError
80
+ puts "Cannot provide quarters for requested contract #{sym[:symbol]}:#{contract},"\
81
+ "returning '[ ]'".colorize(:light_red)
82
+ return []
83
+ end
84
+
85
+ # removing marker if existing
86
+ contract_is_marked = data.last[:high].zero?
87
+ data.pop if contract_is_marked
88
+ unless (filter == :full) || (data.size < 3)
89
+ requested_set = trading_hours(symbol: sym[:symbol], filter: filter)
90
+ data = data.select_within(ranges: requested_set, attr: :datetime) { |x| x.to_datetime.to_sssm }
91
+ end
92
+
93
+ base = Cotcube::Helpers.reduce(bars: data, to: :days)
94
+
95
+ # remove last day of result unless marked
96
+ base.pop unless contract_is_marked || force_recent
97
+
98
+ base.map do |x|
99
+ x[:datetime] = x[:datetime].to_date
100
+ x[:type] = "#{filter}_day".to_sym
101
+ x.delete(:day)
102
+ end
103
+ CSV.open(file, 'w') do |csv|
104
+ base.each { |b| csv << b.values_at(*headers) }
105
+ if contract_is_marked
106
+ marker = ["#{sym[:symbol]}#{contract}", base.last[:datetime] + 1.day, 0, 0, 0, 0, 0]
107
+ csv << marker
108
+ end
109
+ end
110
+ if range.nil?
111
+ base
112
+ else
113
+ base.select do |x|
114
+ (range.begin.nil? ? true : x[:date] >= range.begin) and
115
+ (range.end.nil? ? true : x[:date] <= range.end)
116
+ end
117
+ end
118
+ end
119
+ end
120
+ end