cotcube-bardata 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []