cotcube-cftcsource 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.irbrc.rb +12 -0
- data/.rspec +3 -0
- data/CHANGELOG.md +3 -0
- data/Gemfile +5 -0
- data/LICENSE.txt +21 -0
- data/README.md +86 -0
- data/Rakefile +6 -0
- data/VERSION +1 -0
- data/bin/console +25 -0
- data/bin/setup +8 -0
- data/bin/signals.rb +7 -0
- data/cotcube-cftcsource.gemspec +40 -0
- data/lib/cotcube-cftcsource.rb +45 -0
- data/lib/cotcube-cftcsource/constants.rb +147 -0
- data/lib/cotcube-cftcsource/dates.rb +31 -0
- data/lib/cotcube-cftcsource/decommission.rb +25 -0
- data/lib/cotcube-cftcsource/distribute.rb +62 -0
- data/lib/cotcube-cftcsource/fetch.rb +37 -0
- data/lib/cotcube-cftcsource/init.rb +80 -0
- data/lib/cotcube-cftcsource/provide.rb +60 -0
- data/lib/cotcube-cftcsource/series.rb +100 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -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
|
data/.irbrc.rb
ADDED
@@ -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
data/CHANGELOG.md
ADDED
data/Gemfile
ADDED
data/LICENSE.txt
ADDED
@@ -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.
|
data/README.md
ADDED
@@ -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).
|
data/Rakefile
ADDED
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/bin/console
ADDED
@@ -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__)
|
data/bin/setup
ADDED
data/bin/signals.rb
ADDED
@@ -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: []
|