cotcube-bardata 0.1.1

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: c4c50df76637c9cb761c86db2b64afe372f2dd6be052a11615b9b9e961c6c890
4
+ data.tar.gz: 53eb198be134abc15d92e27eb34fa5b9482b964998e7016aedc9378a3199968c
5
+ SHA512:
6
+ metadata.gz: a15393072fd65a449cdeed625409bb175c3db7c10821d4727fa2aa62577897cf7350b97520f35c70e3485bcf74eab2b8f56ae814803ff77f0276de29957e1181
7
+ data.tar.gz: 7c8b44f3a15abed527ff6be6c461fa786bfa2b73ca51b7aeeb718a28be38524a37788b5fab8e8513a4ede8318c134dafeda76a0171957244f75cd69668e20275
@@ -0,0 +1,12 @@
1
+ def verbose_toggle
2
+ irb_context.echo ? irb_context.echo = false : irb_context.echo = true
3
+ end
4
+
5
+ alias vt verbose_toggle
6
+
7
+ $debug = true
8
+ IRB.conf[:USE_MULTILINE] = false
9
+ # require 'bundler'
10
+ # Bundler.require
11
+
12
+ require_relative 'lib/cotcube-bardata'
@@ -0,0 +1,3 @@
1
+ ## 0.1.1 (December 16, 2020)
2
+
3
+
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in bitangent.gemspec
4
+ gemspec
5
+
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2020 Benjamin L. Tischendorf
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
@@ -0,0 +1,61 @@
1
+ # Bitangent
2
+
3
+ This gem provides a class (and will maybe later provide a commandline tool) to process
4
+ time series data into bitangents.
5
+
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.
27
+
28
+ ## Installation
29
+
30
+ Add this line to your application's Gemfile:
31
+
32
+ ```ruby
33
+ gem 'bitangent'
34
+ ```
35
+
36
+ And then execute:
37
+
38
+ $ bundle install
39
+
40
+ Or install it yourself as:
41
+
42
+ $ gem install bitangent
43
+
44
+ ## Usage
45
+
46
+ TODO: Write usage instructions here
47
+
48
+ ## Development
49
+
50
+ After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
51
+
52
+ To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
53
+
54
+ ## Contributing
55
+
56
+ Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/bitangent.
57
+
58
+
59
+ ## License
60
+
61
+ The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task :default => :spec
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.1
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'cotcube-bardata'
5
+ spec.version = File.read("#{__dir__}/VERSION")
6
+ spec.authors = ['Benjamin L. Tischendorf']
7
+ spec.email = ['donkeybridge@jtown.eu']
8
+
9
+ spec.summary = 'Functions to provide bardata; and some simple time series aggregations'
10
+ spec.description = 'Functions to provide bardata; and some simple time series aggregations '
11
+
12
+ spec.homepage = 'https://github.com/donkeybridge/'+ spec.name
13
+ spec.license = 'BSD-4-Clause'
14
+ spec.required_ruby_version = Gem::Requirement.new('~> 2.7')
15
+
16
+ spec.metadata['homepage_uri'] = spec.homepage
17
+ spec.metadata['source_code_uri'] = spec.homepage
18
+ spec.metadata['changelog_uri'] = spec.homepage + '/CHANGELOG.md'
19
+
20
+ # Specify which files should be added to the gem when it is released.
21
+ # The `git ls-files -z` loads the files in the RubyGem that have been added into git.
22
+ spec.files = Dir.chdir(File.expand_path(__dir__)) do
23
+ `git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
24
+ end
25
+ spec.bindir = 'bin'
26
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
27
+ spec.require_paths = ['lib']
28
+
29
+ spec.add_dependency 'cotcube-indicators'
30
+ spec.add_dependency 'yaml'
31
+ spec.add_dependency 'activesupport'
32
+ spec.add_dependency 'colorize'
33
+ spec.add_dependency 'httparty'
34
+ spec.add_dependency 'rubyzip'
35
+
36
+
37
+ spec.add_development_dependency 'rake'
38
+ spec.add_development_dependency 'rspec', '~>3.6'
39
+ spec.add_development_dependency 'yard', '~>0.9'
40
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'active_support'
4
+ require 'colorize'
5
+ require 'date' unless defined?(DateTime)
6
+ require 'csv' unless defined?(CSV)
7
+ require 'yaml' unless defined?(YAML)
8
+ require 'httparty'
9
+ require 'zip'
10
+
11
+
12
+ require_relative 'cotcube-bardata/constants'
13
+ require_relative 'cotcube-bardata/init'
14
+ require_relative 'cotcube-bardata/provide'
15
+
16
+ private_files = Dir[__dir__ + '/cotcube-bardata/private/*.rb']
17
+ private_files.each do |file|
18
+ # puts 'Loading private module extension ' + file.chomp
19
+ require file.chomp
20
+ end
21
+
22
+ module Cotcube
23
+ module Bardata
24
+
25
+ module_function :config_path, # provides the path of configuration directory
26
+ :config_prefix, # provides the prefix of the configuration directory according to OS-specific FSH
27
+ :init, # checks whether environment is prepared and returns the config hash
28
+ :provide,
29
+ :continuous,
30
+ :continuous_overview,
31
+
32
+ :symbols # reads and provides the symbols file
33
+
34
+ # please not that module_functions of source provided in private files must be published there
35
+ end
36
+ end
37
+
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module Bardata
5
+
6
+ SYMBOL_EXAMPLES = [
7
+ { id: "13874U", symbol: "ET", ticksize: 0.25, power: 1.25, months: "HMUZ", bcf: 1.0, reports: "LF", name: "S&P 500 MICRO" },
8
+ { id: "209747", symbol: "NM", ticksize: 0.25, power: 0.5, monhts: "HMUZ", bcf: 1.0, reports: "LF", name: "NASDAQ 100 MICRO" }
9
+ ].freeze
10
+
11
+ MONTH_COLOURS = { 'F' => :cyan, 'G' => :green, 'H' => :light_green,
12
+ 'J' => :blue, 'K' => :yellow, 'M' => :light_yellow,
13
+ 'N' => :cyan, 'Q' => :magenta, 'U' => :light_magenta,
14
+ 'V' => :blue, 'X' => :red, 'Z' => :light_red }.freeze
15
+
16
+ end
17
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module Bardata
5
+
6
+
7
+ def symbols(config: init)
8
+ if config[:symbols_file].nil?
9
+ SYMBOL_EXAMPLES
10
+ else
11
+ CSV
12
+ .read(config[:symbols_file], headers: %i{ id symbol ticksize power months type bcf reports name})
13
+ .map{|row| row.to_h }
14
+ .map{|row| [ :ticksize, :power, :bcf ].each {|z| row[z] = row[z].to_f}; row }
15
+ .reject{|row| row[:id].nil? }
16
+ end
17
+ end
18
+
19
+ def config_prefix
20
+ os = Gem::Platform.local.os
21
+ case os
22
+ when 'linux'
23
+ ''
24
+ when 'freebsd'
25
+ '/usr/local'
26
+ else
27
+ raise RuntimeError, 'unknown architecture'
28
+ end
29
+ end
30
+
31
+ def config_path
32
+ config_prefix + '/etc/cotcube'
33
+ end
34
+
35
+ def init(config_file_name: 'bardata.yml', debug: false)
36
+ name = 'bardata'
37
+ config_file = config_path + "/#{config_file_name}"
38
+
39
+ if File.exist?(config_file)
40
+ config = YAML.load(File.read config_file).transform_keys(&:to_sym)
41
+ else
42
+ config = {}
43
+ end
44
+
45
+ defaults = {
46
+ data_path: config_prefix + '/var/cotcube/' + name,
47
+ }
48
+
49
+
50
+ config = defaults.merge(config)
51
+
52
+
53
+ # part 2 of init process: Prepare directories
54
+
55
+ save_create_directory = lambda do |directory_name|
56
+ unless Dir.exist?(directory_name)
57
+ begin
58
+ `mkdir -p #{directory_name}`
59
+ unless $?.exitstatus.zero?
60
+ puts "Missing permissions to create or access '#{directory_name}', please clarify manually"
61
+ exit 1 unless defined?(IRB)
62
+ end
63
+ rescue
64
+ puts "Missing permissions to create or access '#{directory_name}', please clarify manually"
65
+ exit 1 unless defined?(IRB)
66
+ end
67
+ end
68
+ end
69
+ ['',:daily,:quarters].each do |path|
70
+ dir = "#{config[:data_path]}#{path == '' ? '' : '/'}#{path.to_s}"
71
+ save_create_directory.call(dir)
72
+ end
73
+
74
+ # eventually return config
75
+ config
76
+ end
77
+
78
+ end
79
+ end
80
+
@@ -0,0 +1,87 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module Bardata
5
+
6
+ def provide(symbol: nil, id: nil, contract:, config: init)
7
+ raise ArgumentError, "Contract '#{contract}' is bogus, should be like 'M21' or 'ESM21'" unless contract.is_a? String and [3,5].include? contract.size
8
+ if contract.to_s.size == 5
9
+ symbol = contract[0..1]
10
+ contract = contract[2..4]
11
+ end
12
+ unless symbol.nil?
13
+ symbol_id = symbols.select{|s| s[:symbol] == symbol.to_s.upcase}.first[:id]
14
+ raise ArgumentError, "Could not find match in #{config[:symbols_file]} for given symbol #{symbol}" if symbol_id.nil?
15
+ raise ArgumentError, "Mismatching symbol #{symbol} and given id #{id}" if not id.nil? and symbol_id != id
16
+ id = symbol_id
17
+ end
18
+ raise ArgumentError, "Could not guess :id or :symbol from 'contract: #{contract}', please clarify." if id.nil?
19
+ id_path = "#{config[:data_path]}/daily/#{id}"
20
+ data_file = "#{id_path}/#{contract}.csv"
21
+ raise RuntimeError, "No data found for requested :id (#{id_path} does not exist)" unless Dir.exist?(id_path)
22
+ raise RuntimeError, "No data found for requested contract #{symbol}:#{contract} in #{id_path}." unless File.exist?(data_file)
23
+ data = CSV.read(data_file, headers: %i[contract date open high low close volume oi] ).map do |row|
24
+ row = row.to_h
25
+ row.each do |k, _|
26
+ row[k] = row[k].to_f if [:open, :high, :low, :close].include? k
27
+ row[k] = row[k].to_i if [:volume, :oi].include? k
28
+ end
29
+ row
30
+ end
31
+ data
32
+ end
33
+
34
+ def continuous(symbol: nil, id: nil, config: init)
35
+ unless symbol.nil?
36
+ symbol_id = symbols.select{|s| s[:symbol] == symbol.to_s.upcase}.first[:id]
37
+ raise ArgumentError, "Could not find match in #{config[:symbols_file]} for given symbol #{symbol}" if symbol_id.nil?
38
+ raise ArgumentError, "Mismatching symbol #{symbol} and given id #{id}" if not id.nil? and symbol_id != id
39
+ id = symbol_id
40
+ end
41
+ raise ArgumentError, "Could not guess :id or :symbol, please clarify." if id.nil?
42
+ id_path = "#{config[:data_path]}/daily/#{id}"
43
+ available_contracts = Dir[id_path + '/*.csv'].map{|x| x.split('/').last.split('.').first}.sort_by{|x| x[-7]}.sort_by{|x| x[-6..-5]}
44
+ data = []
45
+ available_contracts.each do |c|
46
+ provide(id: id, config: config, contract: c).each do |x|
47
+ data << x
48
+ end
49
+ end
50
+ result = []
51
+ data.sort_by{|x| x[:date]}.group_by{|x| x[:date]}.map{|k,v|
52
+ v.map{|x| x.delete(:date)}
53
+ result << {
54
+ date: k,
55
+ volume: v.map{|x| x[:volume]}.reduce(:+),
56
+ oi: v.map{|x| x[:oi ]}.reduce(:+)
57
+ }
58
+ result.last[:contracts] = v
59
+ }
60
+ result
61
+ end
62
+
63
+ def continuous_overview(symbol: nil, id: nil, config: init, selector: :volume, human: false, filter: nil)
64
+ raise ArgumentError, "Selector must be either :volume or :oi" unless selector.is_a? Symbol and [:volume, :oi].include? selector
65
+
66
+ unless symbol.nil?
67
+ symbol_id = symbols.select{|s| s[:symbol] == symbol.to_s.upcase}.first[:id]
68
+ raise ArgumentError, "Could not find match in #{config[:symbols_file]} for given symbol #{symbol}" if symbol_id.nil?
69
+ raise ArgumentError, "Mismatching symbol #{symbol} and given id #{id}" if not id.nil? and symbol_id != id
70
+ id = symbol_id
71
+ end
72
+ raise ArgumentError, "Could not guess :id or :symbol, please clarify." if id.nil?
73
+ data = continuous(id: id, config: config).map{|x|
74
+ {
75
+ date: x[:date],
76
+ volume: x[:contracts].sort_by{|x| - x[:volume]}[0..4].compact.select{|x| not x[:volume].zero?},
77
+ oi: x[:contracts].sort_by{|x| - x[:oi]}[0..4].compact.select{|x| not x[:oi].zero?}
78
+ }
79
+ }.select{|x| not x[selector].empty? }
80
+ result = data.group_by{|x| x[selector].first[:contract]}
81
+ if human
82
+ result.each {|k,v| puts "#{k}\t#{v.first[:date]}\t#{v.last[:date]}" if filter.nil? or v.first[selector].first[:contract][2..4]=~ /#{filter}/ }
83
+ end
84
+ result
85
+ end
86
+ end
87
+ end
metadata ADDED
@@ -0,0 +1,184 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cotcube-bardata
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.1
5
+ platform: ruby
6
+ authors:
7
+ - Benjamin L. Tischendorf
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2020-12-16 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: cotcube-indicators
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: yaml
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: colorize
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :runtime
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :runtime
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - ">="
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: rubyzip
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - "~>"
116
+ - !ruby/object:Gem::Version
117
+ version: '3.6'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - "~>"
123
+ - !ruby/object:Gem::Version
124
+ version: '3.6'
125
+ - !ruby/object:Gem::Dependency
126
+ name: yard
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - "~>"
130
+ - !ruby/object:Gem::Version
131
+ version: '0.9'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - "~>"
137
+ - !ruby/object:Gem::Version
138
+ version: '0.9'
139
+ description: 'Functions to provide bardata; and some simple time series aggregations '
140
+ email:
141
+ - donkeybridge@jtown.eu
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".irbrc.rb"
147
+ - CHANGELOG.md
148
+ - Gemfile
149
+ - LICENSE.txt
150
+ - README.md
151
+ - Rakefile
152
+ - VERSION
153
+ - cotcube-bardata.gemspec
154
+ - lib/cotcube-bardata.rb
155
+ - lib/cotcube-bardata/constants.rb
156
+ - lib/cotcube-bardata/init.rb
157
+ - lib/cotcube-bardata/provide.rb
158
+ homepage: https://github.com/donkeybridge/cotcube-bardata
159
+ licenses:
160
+ - BSD-4-Clause
161
+ metadata:
162
+ homepage_uri: https://github.com/donkeybridge/cotcube-bardata
163
+ source_code_uri: https://github.com/donkeybridge/cotcube-bardata
164
+ changelog_uri: https://github.com/donkeybridge/cotcube-bardata/CHANGELOG.md
165
+ post_install_message:
166
+ rdoc_options: []
167
+ require_paths:
168
+ - lib
169
+ required_ruby_version: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - "~>"
172
+ - !ruby/object:Gem::Version
173
+ version: '2.7'
174
+ required_rubygems_version: !ruby/object:Gem::Requirement
175
+ requirements:
176
+ - - ">="
177
+ - !ruby/object:Gem::Version
178
+ version: '0'
179
+ requirements: []
180
+ rubygems_version: 3.1.2
181
+ signing_key:
182
+ specification_version: 4
183
+ summary: Functions to provide bardata; and some simple time series aggregations
184
+ test_files: []