cotcube-cftcsource 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: 75a8631a91ea90a9fdf4505c9265508cfac8b06d385ab1b41f2e5683876e8617
4
+ data.tar.gz: db8caed963d6dcd7dc13d29faac945965bf1b55dfbeb36ce51a89ace235c149a
5
+ SHA512:
6
+ metadata.gz: 38aa716749ec46151657f0e503019ba05de75b3f26e461a7df850ba3b3580f7ece53b00ed9bc9fde3f667200dd74972060fdf7f71f8a1d13403b6238943fa060
7
+ data.tar.gz: d53d40b0b11e515b8cc405e915aca658e1fbafeb5a8b9cd6dc495bfb338bcd76daff3934a9c1e4674e3b147c28e74652cc733dd11914984a8534862e4a361d75
@@ -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-cftcsource'
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
@@ -0,0 +1,3 @@
1
+ ## 0.1.1 (December 12, 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,86 @@
1
+ # cotcube-cftcsource
2
+
3
+ This gem provides a module containing a set of methods to download, maintain, provide and
4
+ analyze the COT data issued by the CFTC. It is part of the Cotcube suite.
5
+
6
+ ## Installation
7
+
8
+ Add this line to your application's Gemfile:
9
+
10
+ ```ruby
11
+ gem 'cotcube-cftcsource'
12
+ ```
13
+
14
+ And then execute:
15
+
16
+ $ bundle install
17
+
18
+ Or install it yourself as:
19
+
20
+ $ gem install cotcube-cftcsource
21
+
22
+ ## Usage
23
+
24
+ ### Configuration
25
+
26
+ The gem expects a configfile 'cftcsource.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`.
27
+
28
+ Following parameters are currently supported (please let me know if something is missing):
29
+
30
+ ```yaml
31
+ data_path: 'path where the raw downloaded data is saved and other data is cached'
32
+ symbols_file: 'A file containing a CSV with supported symbols--if ommited, an example set from constants.rb is used'
33
+ headers_path: 'Where the CSV headers for cot data and signal sets are cached.'
34
+ default_lookback: 'the amount of weeks to be used for indicators in signal processing'
35
+ default_set: 'the name of the indicator set to be used (as saved in etc/cotcube/indicators-<default_set>.rb)
36
+ ```
37
+
38
+ ### constants.rb
39
+
40
+ Basically sets up 3 constants:
41
+
42
+ 1. CFTC\_LINKS contains all URLs to download all zipped COT reports from cftc.gov
43
+ 2. CFTC\_HEADERS provides lists of symbols serving as headers for the CSV-saved COT data.
44
+ 3. CFTC\_SYMBOL\_EXAMPLES contains 2 sets of configuration data. Each set has the following structure:
45
+ * id: The CFTC id of the future.
46
+ * symbol: Some verbal, unambiguous short identifier for this future.
47
+ * ticksize:
48
+ * power: The leverage per tick.
49
+ * months: The set of trading months.
50
+ * bcf: A legacy constant, it is '1.0' in almost most cases.
51
+ * reports: uppercase letters, signaling which reports are available for the futures (Legacy, Financial, Disaggregated and Cit)
52
+ * name:
53
+
54
+ ### init.rb
55
+ ### fetch and distribute
56
+
57
+ `CftcSource.fetch` downloads and unzips all COT-packages from CFTC.gov matching the :year parameter, defaulting to the current year.
58
+ Please see https://cftc.gov/MarketReports/CommitmentsofTraders/HistoricalCompressed/index.htm for which year parameters are available.
59
+
60
+ `CftcSource.distribute` breaks down the packages into the separated ID based directory tree.
61
+
62
+ NOTE: When building from scratch you should fetch and distribute all packages in proper annual order, as each run just updates data after the last available record.
63
+
64
+ ### provide.rb
65
+
66
+ Returns the requested series of raw COT data for given either :symbol or :id. The parameter :subset currently filters for 'std\_count', a further implementation is pending. If :subset is set to false, the complete series is returned.
67
+
68
+ ### series.rb
69
+
70
+ Based on the data returned by CftcSource.provide and the given indicator set, a series is created, cached and returned.
71
+
72
+ The default indicator simply calculates the net positions for pairs of `_long` and `_short`. Other indicator sets can be created. A simple example is in `etc/cotcube/indicators-example.rb`.
73
+ ## Development
74
+
75
+ 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.
76
+
77
+ 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).
78
+
79
+ ## Contributing
80
+
81
+ Bug reports and pull requests are welcome on GitHub at https://github.com/donkeybridge/bitangent.
82
+
83
+
84
+ ## License
85
+
86
+ 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,25 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require __dir__ + '/../lib/cotcube-cftcsource.rb'
5
+
6
+ require 'irb'
7
+ require 'irb/completion'
8
+ require 'irb/ext/save-history'
9
+
10
+
11
+ # You can add fixtures and/or initialization code here to make experimenting
12
+ # with your gem easier. You can also use a different console, if you like.
13
+
14
+ # (If you use this, don't forget to add pry to your Gemfile!)
15
+ # require "pry"
16
+ # Pry.start
17
+
18
+ $debug = true
19
+
20
+ IRB.conf[:SAVE_HISTORY] = 1500
21
+ IRB.conf[:HISTORY_FILE] = '~/.irb-history'
22
+ IRB.conf[:ECHO] = false
23
+
24
+
25
+ IRB.start(__FILE__)
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ bundle install
7
+
8
+ # Do any other automated setup that you need to do here
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require_relative '../lib/cotcube-cftcsource.rb'
4
+
5
+ s = Cotcube::CftcSource.signals symbol: ARGV[0], report: ARGV[1].downcase.to_sym, human: false, count: 800, quiet: true
6
+ s.each {|x| puts x}
7
+
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ Gem::Specification.new do |spec|
4
+ spec.name = 'cotcube-cftcsource'
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 download and process COT data, aggregated into a module'
10
+ spec.description = 'Functions to download and process COT data, aggregated into a module'
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,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ # require 'bundler/setup'
4
+ # require 'rubygems/package'
5
+ require 'active_support'
6
+ require '../ci-dev/lib/cotcube-indicators'
7
+ require 'colorize'
8
+ require 'date' unless defined?(DateTime)
9
+ require 'csv' unless defined?(CSV)
10
+ require 'yaml' unless defined?(YAML)
11
+ require 'httparty'
12
+ require 'zip'
13
+
14
+
15
+ require_relative 'cotcube-cftcsource/init'
16
+ require_relative 'cotcube-cftcsource/constants'
17
+ require_relative 'cotcube-cftcsource/dates'
18
+ require_relative 'cotcube-cftcsource/fetch'
19
+ require_relative 'cotcube-cftcsource/distribute'
20
+ require_relative 'cotcube-cftcsource/provide'
21
+ require_relative 'cotcube-cftcsource/series'
22
+
23
+ private_files = Dir[__dir__ + '/cotcube-cftcsource/private/*.rb']
24
+ private_files.each do |file|
25
+ # puts 'Loading private module extension ' + file.chomp
26
+ require file.chomp
27
+ end
28
+
29
+ module Cotcube
30
+ module CftcSource
31
+ module_function :config_path, # provides the path of configuration directory
32
+ :config_prefix, # provides the prefix of the configuration directory according to OS-specific FSH
33
+ :init, # checks whether environment is prepared and returns the config hash
34
+ :symbols, # reads and provides the symbols file
35
+ :date_of_last_report, # returns the date of the currently last locally available report
36
+ :current_cot_date_on_website, # returns the date of the current report officially available on cftc.gov
37
+ :fetch, # downloads all (annual) reports, based on given year
38
+ :distribute, # distributes currently downloaded ('fetch'ed) reports to id_based directories
39
+ :available_cftc_ids, # returns a list of locally available cftc ids
40
+ :provide, # returns a series based on id (or symbol) and report / combined
41
+ :series # returns a series based on provide, after application of indicator set
42
+
43
+ # please not that module_functions of source provided in private files must be published there
44
+ end
45
+ end
@@ -0,0 +1,147 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+
6
+ CFTC_LINKS = {
7
+ disagg: {
8
+ fut: {
9
+ current: 'https://www.cftc.gov/dea/newcot/f_disagg.txt',
10
+ hist: 'https://www.cftc.gov/files/dea/history/fut_disagg_txt_'
11
+ },
12
+ com: {
13
+ current: 'https://www.cftc.gov/dea/newcot/c_disagg.txt',
14
+ hist: 'https://www.cftc.gov/files/dea/history/com_disagg_txt_'
15
+ }
16
+ },
17
+ legacy: {
18
+ fut: {
19
+ current: 'https://www.cftc.gov/dea/newcot/deafut.txt',
20
+ hist: 'https://www.cftc.gov/files/dea/history/deacot'
21
+ },
22
+ com: {
23
+ current: 'https://www.cftc.gov/dea/newcot/deacom.txt',
24
+ hist: 'https://www.cftc.gov/files/dea/history/deahistfo'
25
+ }
26
+ },
27
+ financial: {
28
+ fut: {
29
+ current: 'https://www.cftc.gov/dea/newcot/FinFutWk.txt',
30
+ hist: 'https://www.cftc.gov/files/dea/history/fut_fin_txt_'
31
+ },
32
+ com: {
33
+ current: 'https://www.cftc.gov/dea/newcot/FinComWk.txt',
34
+ hist: 'https://www.cftc.gov/files/dea/history/com_fin_txt_'
35
+ }
36
+ },
37
+ cit: {
38
+ com: {
39
+ current: 'https://www.cftc.gov/dea/newcot/deacit.txt',
40
+ hist: 'https://www.cftc.gov/files/dea/history/dea_cit_txt_'
41
+ }
42
+ }
43
+ }.freeze
44
+
45
+ CFTC_HEADERS = {
46
+ legacy: %i[ name date date2 cftcid cftcid2 cftcid3 cftcid3] +
47
+ %i[ std_count_oi_all std_count_ncom_long std_count_ncom_short std_count_ncom_spread std_count_com_long std_count_com_short] +
48
+ %i[ std_count_rept_long std_count_rept_short std_count_nrept_long std_count_nrept_short] +
49
+ %i[ old_count_oi_all old_count_ncom_long old_count_ncom_short old_count_ncom_spread old_count_com_long old_count_com_short] +
50
+ %i[ old_count_rept_long old_count_rept_short old_count_nrept_long old_count_nrept_short] +
51
+ %i[ other_count_oi_all other_count_ncom_long other_count_ncom_short other_count_ncom_spread other_count_com_long other_count_com_short] +
52
+ %i[ other_count_rept_long other_count_rept_short other_count_nrept_long other_count_nrept_short] +
53
+ %i[ std_change_oi_all std_change_ncom_long std_change_ncom_short std_change_ncom_spread std_change_com_long std_change_com_short] +
54
+ %i[ std_change_rept_long std_change_rept_short std_change_nrept_long std_change_nrept_short] +
55
+ %i[ std_pct_oi_all std_pct_ncom_long std_pct_ncom_short std_pct_ncom_spread std_pct_com_long std_pct_com_short] +
56
+ %i[ std_pct_rept_long std_pct_rept_short std_pct_nrept_long std_pct_nrept_short] +
57
+ %i[ old_pct_oi_all old_pct_ncom_long old_pct_ncom_short old_pct_ncom_spread old_pct_com_long old_pct_com_short] +
58
+ %i[ old_pct_rept_long old_pct_rept_short old_pct_nrept_long old_pct_nrept_short] +
59
+ %i[ other_pct_oi_all other_pct_ncom_long other_pct_ncom_short other_pct_ncom_spread other_pct_com_long other_pct_com_short] +
60
+ %i[ other_pct_rept_long other_pct_rept_short other_pct_nrept_long other_pct_nrept_short] +
61
+ %i[ std_traders_oi_all std_traders_ncom_long std_traders_ncom_short std_traders_ncom_spread std_traders_com_long std_traders_com_short] +
62
+ %i[ std_traders_rept_long std_traders_rept_short] +
63
+ %i[ old_traders_oi_all old_traders_ncom_long old_traders_ncom_short old_traders_ncom_spread old_traders_com_long old_traders_com_short] +
64
+ %i[ old_traders_rept_long old_traders_rept_short] +
65
+ %i[ other_traders_oi_all other_traders_ncom_long other_traders_ncom_short other_traders_ncom_spread other_traders_com_long] +
66
+ %i[ other_traders_com_short other_traders_rept_long other_traders_rept_short] +
67
+ %i[ std_conc_gross4_long std_conc_gross4_short std_conc_gross8_long std_conc_gross8_short std_conc_net4_long std_conc_net4_short] +
68
+ %i[ std_conc_net8_long std_conc_net8_short old_conc_gross4_long old_conc_gross4_short old_conc_gross8_long old_conc_gross8_short] +
69
+ %i[ old_conc_net4_long old_conc_net4_short old_conc_net8_long old_conc_net8_short other_conc_gross4_long other_conc_gross4_short] +
70
+ %i[ other_conc_gross8_long other_conc_gross8_short other_conc_net4_long other_conc_net4_short other_conc_net8_long other_conc_net8_short] +
71
+ %i[ units CFTCContractMarketCode(Quotes) CFTCMarketCodeinInitials(Quotes) CFTCCommodityCode(Quotes) supplement],
72
+
73
+ disagg: %i[name date date2 cftcid cftcid2 cftcid3 cftcid3] +
74
+ %i[ std_count_oi_all std_count_prod_long std_count_prod_short std_count_swap_long std_count_swap_short std_count_swap_spread] +
75
+ %i[ std_count_money_long std_count_money_short std_count_money_spread std_count_other_long std_count_other_short std_count_other_spread] +
76
+ %i[ std_count_rept_long std_count_rept_short std_count_nrept_long std_count_nrept_short] +
77
+ %i[ old_count_oi_all old_count_prod_long old_count_prod_short old_count_swap_long old_count_swap_short old_count_swap_spread] +
78
+ %i[ old_count_money_long old_count_money_short old_count_money_spread old_count_other_long old_count_other_short old_count_other_spread] +
79
+ %i[ old_count_rept_long old_count_rept_short old_count_nrept_long old_count_nrept_short] +
80
+ %i[ other_count_oi_all other_count_prod_long other_count_prod_short other_count_swap_long other_count_swap_short other_count_swap_spread] +
81
+ %i[ other_count_money_long other_count_money_short other_count_money_spread other_count_other_long other_count_other_short other_count_other_spread] +
82
+ %i[ other_count_rept_long other_count_rept_short other_count_nrept_long other_count_nrept_short] +
83
+ %i[ std_change_oi_all std_change_prod_long std_change_prod_short std_change_swap_long std_change_swap_short std_change_swap_spread] +
84
+ %i[ std_change_money_long std_change_money_short std_change_money_spread std_change_other_long std_change_other_short std_change_other_spread] +
85
+ %i[ std_change_rept_long std_change_rept_short std_change_nrept_long std_change_nrept_short] +
86
+ %i[ std_pct_oi_all std_pct_prod_long std_pct_prod_short std_pct_swap_long std_pct_swap_short std_pct_swap_spread] +
87
+ %i[ std_pct_money_long std_pct_money_short std_pct_money_spread std_pct_other_long std_pct_other_short std_pct_other_spread] +
88
+ %i[ std_pct_rept_long std_pct_rept_short std_pct_nrept_long std_pct_nrept_short] +
89
+ %i[ old_pct_oi_all old_pct_prod_long old_pct_prod_short old_pct_swap_long old_pct_swap_short old_pct_swap_spread old_pct_money_long] +
90
+ %i[ old_pct_money_short old_pct_money_spread old_pct_other_long old_pct_other_short old_pct_other_spread] +
91
+ %i[ old_pct_rept_long old_pct_rept_short old_pct_nrept_long old_pct_nrept_short] +
92
+ %i[ other_pct_oi_all other_pct_prod_long other_pct_prod_short other_pct_swap_long other_pct_swap_short other_pct_swap_spread] +
93
+ %i[ other_pct_money_long other_pct_money_short other_pct_money_spread other_pct_other_long other_pct_other_short other_pct_other_spread] +
94
+ %i[ other_pct_rept_long other_pct_rept_short other_pct_nrept_long other_pct_nrept_short] +
95
+ %i[ std_traders_oi_all std_traders_prod_long std_traders_prod_short std_traders_swap_long std_traders_swap_short std_traders_swap_spread] +
96
+ %i[ std_traders_money_long std_traders_money_short std_traders_money_spread std_traders_other_long std_traders_other_short std_traders_other_spread] +
97
+ %i[ std_traders_rept_long std_traders_rept_short] +
98
+ %i[ old_traders_oi_all old_traders_prod_long old_traders_prod_short old_traders_swap_long old_traders_swap_short old_traders_swap_spread] +
99
+ %i[ old_traders_money_long old_traders_money_short old_traders_money_spread old_traders_other_long old_traders_other_short old_traders_other_spread] +
100
+ %i[ old_traders_rept_long old_traders_rept_short] +
101
+ %i[ other_traders_oi_all other_traders_prod_long other_traders_prod_short other_traders_swap_long other_traders_swap_short] +
102
+ %i[ other_traders_swap_spread other_traders_money_long other_traders_money_short other_traders_money_spread other_traders_other_long] +
103
+ %i[ other_traders_other_short other_traders_other_spread other_traders_rept_long other_traders_rept_short] +
104
+ %i[ std_conc_gross4_long std_conc_gross4_short std_conc_gross8_long std_conc_gross8_short std_conc_net4_long std_conc_net4_short std_conc_net8_long] +
105
+ %i[ std_conc_net8_short old_conc_gross4_long old_conc_gross4_short old_conc_gross8_long old_conc_gross8_short old_conc_net4_long old_conc_net4_short] +
106
+ %i[ old_conc_net8_long old_conc_net8_short other_conc_gross4_long other_conc_gross4_short other_conc_gross8_long other_conc_gross8_short] +
107
+ %i[ other_conc_net4_long other_conc_net4_short other_conc_net8_long other_conc_net8_short] +
108
+ %i[ units CFTC_Contract_Market_Code_Quotes CFTC_Market_Code_Quotes CFTC_Commodity_Code_Quotes CFTC_SubGroup_Code Fut_Combined supplement],
109
+
110
+ financial: %i[ name date date2 cftcid cftcid2 cftcid3 cftcid3] +
111
+ %i[ std_count_oi_all std_count_dealers_long std_count_dealers_short std_count_dealers_spread std_count_asset_long std_count_asset_short] +
112
+ %i[ std_count_asset_spread std_count_lev_long std_count_lev_short std_count_lev_spread std_count_other_long std_count_other_short] +
113
+ %i[ std_count_other_spread std_count_rept_long std_count_rept_short std_count_nrept_long std_count_nrept_short] +
114
+ %i[ std_change_oi_all std_change_dealers_long std_change_dealers_short std_change_dealers_spread std_change_asset_long std_change_asset_short] +
115
+ %i[ std_change_asset_spread std_change_lev_long std_change_lev_short std_change_lev_spread std_change_other_long std_change_other_short] +
116
+ %i[ std_change_other_spread std_change_rept_long std_change_rept_short std_change_nrept_long std_change_nrept_short] +
117
+ %i[ std_pct_oi_all std_pct_dealers_long std_pct_dealers_short std_pct_dealers_spread std_pct_asset_long std_pct_asset_short] +
118
+ %i[ std_pct_asset_spread std_pct_lev_long std_pct_lev_short std_pct_lev_spread std_pct_other_long std_pct_other_short] +
119
+ %i[ std_pct_other_spread std_pct_rept_long std_pct_rept_short std_pct_nrept_long std_pct_nrept_short] +
120
+ %i[ std_traders_oi_all std_traders_dealers_long std_traders_dealers_short std_traders_dealers_spread std_traders_asset_long std_traders_asset_short] +
121
+ %i[ std_traders_asset_spread std_traders_lev_long std_traders_lev_short std_traders_lev_spread std_traders_other_long std_traders_other_short std] +
122
+ %i[_traders_other_spread std_traders_rept_long std_traders_rept_short] +
123
+ %i[ std_conc_gross4_long std_conc_gross4_short std_conc_gross8_long std_conc_gross8_short std_conc_net4_long std_conc_net4_short] +
124
+ %i[ std_conc_net8_long std_conc_net8_short] +
125
+ %i[ units CFTC_Contract_Market_Code_Quotes CFTC_Market_Code_Quotes CFTC_Commodity_Code_Quotes CFTC_SubGroup_Code type supplement],
126
+
127
+
128
+ cit: %i[name date date2 cftcid cftcid2 cftcid3 cftcid3] +
129
+ %i[std_count_oi_all std_count_ncom_long std_count_ncom_short std_count_ncom_spread std_count_com_long std_count_com_short] +
130
+ %i[std_count_rept_long std_count_rept_short std_count_nrept_long std_count_nrept_short std_count_cit_long std_count_cit_short] +
131
+ %i[std_change_oi_all std_change_ncom_long std_change_ncom_short std_change_ncom_spread std_change_com_long std_change_com_short] +
132
+ %i[std_change_rept_long std_change_rept_short std_change_nrept_long std_change_nrept_short std_change_cit_long std_change_cit_short] +
133
+ %i[std_pct_oi_all std_pct_ncom_long std_pct_ncom_short std_pct_ncom_spread std_pct_com_long std_pct_com_short] +
134
+ %i[std_pct_rept_long std_pct_rept_short std_pct_nrept_long std_pct_nrept_short std_pct_cit_long std_pct_cit_short] +
135
+ %i[std_traders_oi_all std_traders_ncom_long std_traders_ncom_short std_traders_ncom_spread std_traders_com_long std_traders_com_short] +
136
+ %i[std_traders_rept_long std_traders_rept_short std_traders_cit_long std_traders_cit_short] +
137
+ %i[units supplement]
138
+ }.freeze
139
+
140
+ CFTC_SYMBOL_EXAMPLES = [
141
+ { id: "13874U", symbol: "ET", ticksize: 0.25, power: 1.25, months: "HMUZ", bcf: 1.0, reports: "LF", name: "S&P 500 MICRO" },
142
+ { id: "209747", symbol: "NM", ticksize: 0.25, power: 0.5, monhts: "HMUZ", bcf: 1.0, reports: "LF", name: "NASDAQ 100 MICRO" }
143
+ ].freeze
144
+
145
+
146
+ end
147
+ end
@@ -0,0 +1,31 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+
6
+ # method to parse current years raw CFTC cot_files and return the latest available date
7
+ #
8
+ # @return [DateTime] DateTime object containing the date found
9
+ def date_of_last_report(config: init_config)
10
+ files = Dir["#{config[:data_path]}/raw/*#{Time.now.strftime('%Y')}.csv"]
11
+ DateTime.strptime(CSV.read(files[0]).tap { |x| x.shift if x[0][0] =~ /Market/ }.map { |x| x[2] }.max, '%Y-%m-%d') rescue nil
12
+ end
13
+
14
+ # method to extract the currently available most recent COT report from the according CFTC website
15
+ #
16
+ # @return [DateTime] a DateTime object containing the extracted date
17
+ def current_cot_date_on_website
18
+ uri = 'https://www.cftc.gov/MarketReports/CommitmentsofTraders/index.htm'
19
+ raw = HTTParty.get(uri).to_s
20
+ encoding_options = {
21
+ :invalid => :replace, # Replace invalid byte sequences
22
+ :undef => :replace, # Replace anything not defined in ASCII
23
+ :replace => '', # Use a blank for those replacements
24
+ :universal_newline => true # Always break lines with \n
25
+ }
26
+ line = raw.each_line.select{|x| x if x =~ /Reports Dated/ }[0].encode(Encoding.find('ASCII'), encoding_options)
27
+ date_string = line.split('Dated ').last.split('- Current').first
28
+ DateTime.strptime(date_string, '%B %d,%Y')
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,25 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+ # move expired
6
+
7
+ def move_expired_reports
8
+ Dir['/var/cotcube/cftc/cot/*'].each do |dir|
9
+ target = "/var/cotcube/cftc/expired/#{dir.split('/').last}/"
10
+ Dir["#{dir}/*.csv"].each do |file|
11
+ next unless CSV.read(file, converters: :all).last[2] < Date.today - 30
12
+
13
+ xdebug "Moving #{file} to #{target}"
14
+ `mkdir -p #{target}` unless File.exist? target
15
+ `mv #{file} #{target}`
16
+ end
17
+ if Dir["#{dir}/*"].empty?
18
+ xdebug "Removing #{dir}"
19
+ `rm -rf #{dir}`
20
+ end
21
+ end
22
+ end
23
+
24
+ end
25
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+
6
+ # Goes through CFTCLINKS to iterate over all types of reports
7
+ #
8
+ # @param [Hash] opts
9
+ # @option [Integer, String] Year to be processed, defaults to current year
10
+
11
+ def distribute(year: Time.now.year, debug: false, config: init)
12
+ raw_path = "#{config[:data_path]}/raw"
13
+ cot_path = "#{config[:data_path]}/cot"
14
+ CFTC_LINKS.each do |report, a|
15
+ a.each do |combined, _b|
16
+ puts ("Processing #{report}\t#{combined}\t#{year}") if debug
17
+
18
+ infile = "#{raw_path}/#{report}_#{combined}_#{year}.csv"
19
+ outfile = ->(symbol) { "#{cot_path}/#{symbol}/#{report}_#{combined}.csv" }
20
+
21
+ last_report = lambda do |symbol|
22
+ CSV.read("#{cot_path}/#{symbol}/#{report}_#{combined}.csv").last[1]
23
+ rescue StandardError
24
+ '1900-01-01'
25
+ end
26
+
27
+ cache = {}
28
+ csv_data = CSV.read(infile).tap { |lines| lines.shift if lines[0][0] =~ /Market/ }
29
+ csv_data.sort_by { |x| x[2] }.each do |line|
30
+ next if line[3].length != 6
31
+
32
+ sym = line[3]
33
+ cache[sym] ||= last_report.call(sym)
34
+ next if cache[sym] >= line[2]
35
+
36
+ line << "#{report} #{combined}"
37
+ line.map! { |x| x&.strip }
38
+ begin
39
+ CSV.open(outfile.call(sym), 'a+') { |f| f << line }
40
+ rescue StandardError
41
+ puts ("Found new id: #{sym}").colorize(:light_green)
42
+ `mkdir #{cot_path}/#{sym}`
43
+ CSV.open(outfile.call(sym), 'a+') { |f| f << line }
44
+ end
45
+ end
46
+ end
47
+ end
48
+ end
49
+
50
+ # print list
51
+
52
+ def available_cftc_ids(config: init, print: true, sort: :exchange)
53
+ result = CSV.parse(`find #{init[:data_path]}/cot/* | grep legacy | xargs head -n1 | grep , | awk -v FS=, -v OFS=, '{print $5,$4,$1}' | sed 's/"//g' | sort | uniq`.chomp, headers: %i{ exchange id name }).map{|x| x.to_h}
54
+ result = result.uniq{|row| row[:id] }
55
+ if print
56
+ result.sort_by{|x| x[sort]}.each {|row| puts "#{row[:exchange]}\t#{row[:id]}\t#{row[:name]}" }
57
+ end
58
+ result
59
+ end
60
+
61
+ end
62
+ end
@@ -0,0 +1,37 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+
6
+
7
+ # method to download all available historical cot report files
8
+ #
9
+ # @param [Integer, String] year
10
+ # @param [Boolean] debug
11
+ # @param [Hash] config
12
+ def fetch(year: Time.now.year, debug: false, silent: false, config: init)
13
+
14
+ CFTC_LINKS.each do |report, a|
15
+ a.each do |combined, _b|
16
+ puts ("====> working on #{report}\t#{combined}") if debug
17
+ raw_dir = "#{config[:data_path]}/raw"
18
+
19
+ uri = "#{CFTC_LINKS[report][combined][:hist]}#{year}.zip"
20
+ file_data = nil
21
+ input = HTTParty.get(uri).body
22
+ Zip::InputStream.open(StringIO.new(input)) do |io|
23
+ while entry = io.get_next_entry
24
+ file_data = io.read
25
+ end
26
+ end
27
+ file = "#{raw_dir}/#{report}_#{combined}_#{year}.csv"
28
+ File.write(file, file_data)
29
+
30
+ puts "Contents have been written to '#{file}'." if debug
31
+ print "Check whether current date for #{report}_#{combined}_#{year} makes sense: " unless silent
32
+ puts `head -n2 #{file} | tail -n1 | cut -d, -f1,3`.chomp.light_white unless silent
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,80 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+
6
+
7
+ def symbols(config: init)
8
+ if config[:symbols_file].nil?
9
+ CFTC_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: 'cftcsource.yml', debug: false)
36
+ name = 'cftcsource'
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
+ ['','raw','cot','series'].each do |path|
70
+ dir = "#{config[:data_path]}#{path == '' ? '' : '/'}#{path}"
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,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+ def provide(symbol: nil, # The barchart symbol of the contract
6
+ id: nil, # The CFTC ID of the contract
7
+ report: :legacy, # report type (legacy, disagg, financial, cit)
8
+ combined: :com, # combined of fut_only
9
+ after: '1900-01-01', # start at given date
10
+ subset: true, # set to false to return full data
11
+ measure: false,
12
+ config: init, #
13
+ debug: false) #
14
+
15
+ after = DateTime.strptime(after, '%Y-%m-%d') if after.is_a? String
16
+
17
+ unless symbol.nil?
18
+ symbol_id = symbols.select{|s| s[:symbol] == symbol.to_s.upcase}.first[:id]
19
+ raise ArgumentError, "Could not find match in #{config[:symbols_file]} for given symbol #{symbol}" if symbol_id.nil?
20
+ raise ArgumentError, "Mismatching symbol #{symbol} and given id #{id}" if not id.nil? and symbol_id != id
21
+ id = symbol_id
22
+ end
23
+ raise ArgumentError, "Need either :symbol or :id as parameter" if id.nil?
24
+
25
+ id_path = "#{config[:data_path]}/cot/#{id}"
26
+ data_file = "#{id_path}/#{report}_#{combined}.csv"
27
+
28
+ raise RuntimeError, "No data found for requested :id (#{id_path} does not exist)" unless Dir.exist?(id_path)
29
+ raise RuntimeError, "No data found for requested :report (#{report} #{combined} in #{id_path}" unless File.exist?(data_file)
30
+
31
+ puts "#{Time.now - measure}: PROVIDE: before CSV parse" if measure
32
+ raw = `cat #{data_file} | sed -e 's/\r//'`
33
+ data = CSV.parse(raw, row_sep: :auto, converters: :all, headers: CFTC_HEADERS[report]).map do |row|
34
+ d = row.to_h
35
+ d[:date] = d[:date2].strftime('%Y-%m-%d')
36
+ d
37
+ end
38
+ puts "#{Time.now - measure}: PROVIDE: after CSV parse" if measure
39
+ data.select! { |x| x[:date2] > after } if after
40
+ data.sort! { |x| x[:date2] }.uniq!{ |x| x[:date2] }
41
+ data.reverse!
42
+
43
+ if subset
44
+ data.map do |dataset|
45
+ dataset.map do |key,value|
46
+ dataset.delete(key) if key.to_s =~ (/_traders_/) ||
47
+ key.to_s =~ (/_pct_/) || key.to_s =~ (/_conc_/) ||
48
+ key.to_s =~ (/^other_/) || key.to_s =~ (/^old_/) || key.to_s =~ (/_change_/) ||
49
+ [ :units, :"CFTCContractMarketCode(Quotes)", :"CFTCMarketCodeinInitials(Quotes)",
50
+ :"CFTCCommodityCode(Quotes)", :name, :cftcid3, :date2 ].include?(key)
51
+ end
52
+ end
53
+ end
54
+ puts "#{Time.now - measure}: PROVIDE: after subset application, returning " if measure
55
+
56
+ data
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,100 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Cotcube
4
+ module CftcSource
5
+
6
+ # - there will be configfile, containing the indicators
7
+ # a call hence
8
+ # 1. will try to load from the series directory
9
+ # 2. will try to update the series already loaded (or starting from empty)
10
+ # 3. provides the series (containing only the lookback period requested)\q
11
+ #
12
+ def series(symbol: nil,
13
+ report: :legacy,
14
+ combined: :com,
15
+ config: init,
16
+ after: '1900-01-01',
17
+ lookback: nil,
18
+ set: nil,
19
+ force: false,
20
+ measure: false,
21
+ debug: false
22
+ )
23
+ raise ArgumentError, "Can only build series with given symbol" if symbol.nil?
24
+ symbol_config = symbols.select{|s| s[:symbol] == symbol.to_s.upcase }.first
25
+ raise ArgumentError, "Can only build series with known symbol, '#{symbol}' is unknown." if symbol_config.nil?
26
+ puts "Using symbol_config '#{symbol_config}'" if debug
27
+
28
+ lookback = config[:default_lookback] if lookback.nil?
29
+ raise ArgumentError, "Lookback may not be nil, either provide option or set :default_lookback in configfile" if lookback.nil?
30
+
31
+ set = config[:default_set] if set.nil?
32
+ set = 'default' if set.nil?
33
+
34
+ series_dir = "#{config[:data_path]}/series/#{symbol}"
35
+ series_file = "#{series_dir}/#{report}_#{combined}_#{set}_#{lookback}.csv"
36
+ puts "Guessing series_file '#{series_file}'" if debug
37
+
38
+ `mkdir -p #{series_dir}` unless Dir.exist?(series_dir)
39
+
40
+ header_keys = CFTC_HEADERS[report]
41
+ .select { |key| key.to_s =~ /std_count/ }
42
+ .group_by { |key| key.to_s.split('_')[2] }
43
+ .keys
44
+ .tap { |k| k.delete('oi') }
45
+
46
+ puts "Using header_keys '#{header_keys}'" if debug
47
+
48
+
49
+ if set == 'default' or set.nil?
50
+ # load default indicatorset
51
+ indicators = {}
52
+ prefix = "std_count"
53
+ header_keys.map do |key|
54
+ indicators["#{prefix}_#{key}_net"] = Cotcube::Indicators.calc(a: "#{prefix}_#{key}_long", b: "#{prefix}_#{key}_short"){|a,b| a - b }
55
+ end
56
+ else
57
+ # load custom indicatorset
58
+ indicators_file = "#{config_path}/indicators-#{set}.rb"
59
+ raise ArgumentError, "Indicatorsfile #{indicators_file} does not exist" unless File.exist? indicators_file
60
+ load indicators_file
61
+ indicators = Cotcube::Indicators.build(lookback: lookback, keys: header_keys)
62
+ end
63
+
64
+ if File.exist?(series_file) and (Time.now - File.stat(series_file).mtime).to_i / 86400.0 < 5.0 and not force and not config[:always_force]
65
+ headers_file = "#{config[:headers_path]}/#{report}_#{combined}.json"
66
+ if File.exist? headers_file
67
+ provide_headers = JSON.parse(File.read(headers_file)).map{|x| x.to_sym}
68
+ else
69
+ provide_headers = (Cotcube::CftcSource.provide symbol: symbol, report: report, combined: combined, after: (Time.now - 20 * 86000).strftime("%Y-%m-%d")).first.keys
70
+ File.open(headers_file, 'w'){|f| f << provide_headers.to_json }
71
+ end
72
+ headers = provide_headers + indicators.keys
73
+ puts 'Returning saved data' if debug
74
+ puts "#{Time.now - measure}: SERIES: returning series from file" if measure
75
+
76
+ return CSV.read(series_file, headers: headers, converters: :all).map(&:to_h)
77
+ end
78
+
79
+ puts "#{Time.now - measure}: SERIES: before source" if measure
80
+
81
+ source = provide(symbol: symbol, report: report, combined: combined, config: config, after: after, measure: measure)
82
+
83
+ puts "#{Time.now - measure}: SERIES: after source" if measure
84
+
85
+ puts "First source: #{source.first}" if debug
86
+ puts "#{config}" if debug
87
+
88
+ source.each do |dataset|
89
+ indicators.each do |key, lambada|
90
+ dataset[key] = lambada.call(dataset)
91
+ end
92
+ end
93
+ CSV.open(series_file, 'w') { |csv| source.map{|x| csv << x.values } }
94
+
95
+ puts "#{Time.now - measure}: SERIES: returning series from source" if measure
96
+ source
97
+
98
+ end
99
+ end
100
+ end
metadata ADDED
@@ -0,0 +1,193 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: cotcube-cftcsource
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-12 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 download and process COT data, aggregated into a module
140
+ email:
141
+ - donkeybridge@jtown.eu
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".irbrc.rb"
147
+ - ".rspec"
148
+ - CHANGELOG.md
149
+ - Gemfile
150
+ - LICENSE.txt
151
+ - README.md
152
+ - Rakefile
153
+ - VERSION
154
+ - bin/console
155
+ - bin/setup
156
+ - bin/signals.rb
157
+ - cotcube-cftcsource.gemspec
158
+ - lib/cotcube-cftcsource.rb
159
+ - lib/cotcube-cftcsource/constants.rb
160
+ - lib/cotcube-cftcsource/dates.rb
161
+ - lib/cotcube-cftcsource/decommission.rb
162
+ - lib/cotcube-cftcsource/distribute.rb
163
+ - lib/cotcube-cftcsource/fetch.rb
164
+ - lib/cotcube-cftcsource/init.rb
165
+ - lib/cotcube-cftcsource/provide.rb
166
+ - lib/cotcube-cftcsource/series.rb
167
+ homepage: https://github.com/donkeybridge/cotcube-cftcsource
168
+ licenses:
169
+ - BSD-4-Clause
170
+ metadata:
171
+ homepage_uri: https://github.com/donkeybridge/cotcube-cftcsource
172
+ source_code_uri: https://github.com/donkeybridge/cotcube-cftcsource
173
+ changelog_uri: https://github.com/donkeybridge/cotcube-cftcsource/CHANGELOG.md
174
+ post_install_message:
175
+ rdoc_options: []
176
+ require_paths:
177
+ - lib
178
+ required_ruby_version: !ruby/object:Gem::Requirement
179
+ requirements:
180
+ - - "~>"
181
+ - !ruby/object:Gem::Version
182
+ version: '2.7'
183
+ required_rubygems_version: !ruby/object:Gem::Requirement
184
+ requirements:
185
+ - - ">="
186
+ - !ruby/object:Gem::Version
187
+ version: '0'
188
+ requirements: []
189
+ rubygems_version: 3.1.2
190
+ signing_key:
191
+ specification_version: 4
192
+ summary: Functions to download and process COT data, aggregated into a module
193
+ test_files: []