cotcube-cftcsource 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- 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: []
|