cotcube-bardata 0.1.1 → 0.1.6
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 +4 -4
- data/.irbrc.rb +3 -1
- data/CHANGELOG.md +43 -0
- data/Gemfile +3 -2
- data/README.md +61 -28
- data/Rakefile +5 -3
- data/VERSION +1 -1
- data/cotcube-bardata.gemspec +10 -10
- data/lib/cotcube-bardata.rb +52 -19
- data/lib/cotcube-bardata/cached.rb +79 -0
- data/lib/cotcube-bardata/constants.rb +8 -8
- data/lib/cotcube-bardata/daily.rb +133 -0
- data/lib/cotcube-bardata/eods.rb +122 -0
- data/lib/cotcube-bardata/helpers.rb +107 -0
- data/lib/cotcube-bardata/init.rb +23 -26
- data/lib/cotcube-bardata/provide.rb +39 -75
- data/lib/cotcube-bardata/quarters.rb +43 -0
- data/lib/cotcube-bardata/range_matrix.rb +117 -0
- data/lib/cotcube-bardata/trade_dates.rb +28 -0
- data/lib/cotcube-bardata/trading_hours.rb +47 -0
- metadata +55 -33
@@ -1,87 +1,51 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Cotcube
|
4
|
+
# Missing top level documentation comment
|
4
5
|
module Bardata
|
6
|
+
def provide(contract:, # rubocop:disable Metrics/ParameterLists
|
7
|
+
# Can be like ("2020-12-01 12:00"..."2020-12-14 11:00")
|
8
|
+
range: nil,
|
9
|
+
symbol: nil, id: nil,
|
10
|
+
config: init,
|
11
|
+
# supported types are :quarters, :hours, :days, :rth, :dailies, :weeks, :months
|
12
|
+
interval: :days,
|
13
|
+
# supported filters are :raw, :_24x7_, :full and :rth (and custom named, if provided as file)
|
14
|
+
filter: :full,
|
15
|
+
# TODO: for future compatibility and suggestion: planning to include a function to update
|
16
|
+
# with live data from broker
|
17
|
+
force_recent: false)
|
5
18
|
|
6
|
-
|
7
|
-
raise ArgumentError, "Contract '#{contract}' is bogus, should be like 'M21' or 'ESM21'" unless contract.is_a? String and [3,5].include? contract.size
|
8
|
-
if contract.to_s.size == 5
|
9
|
-
symbol = contract[0..1]
|
10
|
-
contract = contract[2..4]
|
11
|
-
end
|
12
|
-
unless symbol.nil?
|
13
|
-
symbol_id = symbols.select{|s| s[:symbol] == symbol.to_s.upcase}.first[:id]
|
14
|
-
raise ArgumentError, "Could not find match in #{config[:symbols_file]} for given symbol #{symbol}" if symbol_id.nil?
|
15
|
-
raise ArgumentError, "Mismatching symbol #{symbol} and given id #{id}" if not id.nil? and symbol_id != id
|
16
|
-
id = symbol_id
|
17
|
-
end
|
18
|
-
raise ArgumentError, "Could not guess :id or :symbol from 'contract: #{contract}', please clarify." if id.nil?
|
19
|
-
id_path = "#{config[:data_path]}/daily/#{id}"
|
20
|
-
data_file = "#{id_path}/#{contract}.csv"
|
21
|
-
raise RuntimeError, "No data found for requested :id (#{id_path} does not exist)" unless Dir.exist?(id_path)
|
22
|
-
raise RuntimeError, "No data found for requested contract #{symbol}:#{contract} in #{id_path}." unless File.exist?(data_file)
|
23
|
-
data = CSV.read(data_file, headers: %i[contract date open high low close volume oi] ).map do |row|
|
24
|
-
row = row.to_h
|
25
|
-
row.each do |k, _|
|
26
|
-
row[k] = row[k].to_f if [:open, :high, :low, :close].include? k
|
27
|
-
row[k] = row[k].to_i if [:volume, :oi].include? k
|
28
|
-
end
|
29
|
-
row
|
30
|
-
end
|
31
|
-
data
|
32
|
-
end
|
19
|
+
sym = get_id_set(symbol: symbol, id: id, contract: contract, config: config)
|
33
20
|
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
available_contracts.each do |c|
|
46
|
-
provide(id: id, config: config, contract: c).each do |x|
|
47
|
-
data << x
|
21
|
+
case interval
|
22
|
+
when :quarters, :hours, :quarter, :hour
|
23
|
+
base = provide_quarters(contract: contract, symbol: symbol, id: id, config: config)
|
24
|
+
base = extended_select_for_range(range: range, base: base) if range
|
25
|
+
requested_set = trading_hours(symbol: sym[:symbol], filter: filter)
|
26
|
+
|
27
|
+
base = base.select_within(ranges: requested_set, attr: :datetime) { |x| x.to_datetime.to_sssm }
|
28
|
+
return base if %i[quarters quarter].include? interval
|
29
|
+
|
30
|
+
Cotcube::Helpers.reduce(bars: base, to: :hours) do |c, b|
|
31
|
+
c[:day] == b[:day] and c[:datetime].hour == b[:datetime].hour
|
48
32
|
end
|
49
|
-
end
|
50
|
-
result = []
|
51
|
-
data.sort_by{|x| x[:date]}.group_by{|x| x[:date]}.map{|k,v|
|
52
|
-
v.map{|x| x.delete(:date)}
|
53
|
-
result << {
|
54
|
-
date: k,
|
55
|
-
volume: v.map{|x| x[:volume]}.reduce(:+),
|
56
|
-
oi: v.map{|x| x[:oi ]}.reduce(:+)
|
57
|
-
}
|
58
|
-
result.last[:contracts] = v
|
59
|
-
}
|
60
|
-
result
|
61
|
-
end
|
62
33
|
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
oi: x[:contracts].sort_by{|x| - x[:oi]}[0..4].compact.select{|x| not x[:oi].zero?}
|
78
|
-
}
|
79
|
-
}.select{|x| not x[selector].empty? }
|
80
|
-
result = data.group_by{|x| x[selector].first[:contract]}
|
81
|
-
if human
|
82
|
-
result.each {|k,v| puts "#{k}\t#{v.first[:date]}\t#{v.last[:date]}" if filter.nil? or v.first[selector].first[:contract][2..4]=~ /#{filter}/ }
|
34
|
+
when :days, :weeks, :months
|
35
|
+
base = provide_cached contract: contract, symbol: symbol, id: id, config: config, filter: filter,
|
36
|
+
force_recent: force_recent
|
37
|
+
base = extended_select_for_range(range: range, base: base) if range
|
38
|
+
return base if %i[day days].include? interval
|
39
|
+
|
40
|
+
# TODO: Missing implementation to reduce cached days to weeks or months
|
41
|
+
raise 'Missing implementation to reduce cached days to weeks or months'
|
42
|
+
when :dailies, :daily
|
43
|
+
base = provide_daily contract: contract, symbol: symbol, id: id, config: config
|
44
|
+
base = extended_select_for_range(range: range, base: base) if range
|
45
|
+
base
|
46
|
+
else
|
47
|
+
raise ArgumentError, "Unsupported or unknown interval '#{interval}' in Bardata.provide"
|
83
48
|
end
|
84
|
-
result
|
85
49
|
end
|
86
50
|
end
|
87
51
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cotcube
|
4
|
+
# Missing top level documentation
|
5
|
+
module Bardata
|
6
|
+
# the following method loads the quarterly bars (15-min bars) from the directory tree
|
7
|
+
# also note that a former version of this method allowed to provide range or date parameters. this has been moved
|
8
|
+
# to #provide itself.
|
9
|
+
def provide_quarters(contract:, # rubocop:disable Metrics/ParameterLists
|
10
|
+
symbol: nil, id: nil,
|
11
|
+
timezone: Time.find_zone('America/Chicago'),
|
12
|
+
config: init,
|
13
|
+
keep_marker: false)
|
14
|
+
|
15
|
+
unless contract.is_a?(String) && [3, 5].include?(contract.size)
|
16
|
+
raise ArgumentError, "Contract '#{contract}' is bogus, should be like 'M21' or 'ESM21'"
|
17
|
+
end
|
18
|
+
|
19
|
+
sym = get_id_set(symbol: symbol, id: id, contract: contract)
|
20
|
+
|
21
|
+
contract = contract[2..4] if contract.to_s.size == 5
|
22
|
+
id = sym[:id]
|
23
|
+
symbol = sym[:symbol]
|
24
|
+
|
25
|
+
id_path = "#{config[:data_path]}/quarters/#{id}"
|
26
|
+
data_file = "#{id_path}/#{contract}.csv"
|
27
|
+
raise "No data found for requested :id (#{id_path} does not exist)" unless Dir.exist?(id_path)
|
28
|
+
|
29
|
+
raise "No data found for requested contract #{symbol}:#{contract} in #{id_path}." unless File.exist?(data_file)
|
30
|
+
|
31
|
+
data = CSV.read(data_file, headers: %i[contract datetime day open high low close volume]).map do |row|
|
32
|
+
row = row.to_h
|
33
|
+
%i[open high low close].map { |x| row[x] = row[x].to_f }
|
34
|
+
%i[volume day].map { |x| row[x] = row[x].to_i }
|
35
|
+
row[:datetime] = timezone.parse(row[:datetime])
|
36
|
+
row[:type] = :quarter
|
37
|
+
row
|
38
|
+
end
|
39
|
+
data.pop if data.last[:high].zero? && (not keep_marker)
|
40
|
+
data
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,117 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cotcube
|
4
|
+
# Missing top level documentation
|
5
|
+
module Bardata
|
6
|
+
# this is an analysis tool to investigate actual ranges of an underlying symbol
|
7
|
+
# it is in particular no true range or average true range, as a 'true range' can only be applied to
|
8
|
+
# a steady series, what changing contracts definitely aren't
|
9
|
+
#
|
10
|
+
# The result printed / returned is a table, containing a matrix of rows:
|
11
|
+
# 1. size: the amount of values evaluated
|
12
|
+
# 2. avg:
|
13
|
+
# 3. lower: like median, but not at 1/2 but 1/4
|
14
|
+
# 4. median:
|
15
|
+
# 5. upper: like median, bot not at 1/2 but 3/4
|
16
|
+
# 6. max:
|
17
|
+
# and columns:
|
18
|
+
# 1.a) all days os the series
|
19
|
+
# 1.b) all days of the series, diminished by 2* :dim*100% extreme values (i.e. at both ends)
|
20
|
+
# 1.c) the last 200 days
|
21
|
+
# 2.a-c) same with days reduced to weeks (c: 52 weeks)
|
22
|
+
# 3.a-c) same with days reduced to months (c: 12 months)
|
23
|
+
def range_matrix(symbol: nil, id: nil, print: false, dim: 0.05)
|
24
|
+
# rubocop:disable Style/MultilineBlockChain
|
25
|
+
sym = get_id_set(symbol: symbol, id: id)
|
26
|
+
source = {}
|
27
|
+
target = {}
|
28
|
+
source[:days] = Cotcube::Bardata.continuous_actual_ml symbol: symbol
|
29
|
+
source[:weeks] = Cotcube::Helpers.reduce bars: source[:days], to: :weeks
|
30
|
+
source[:months] = Cotcube::Helpers.reduce bars: source[:days], to: :months
|
31
|
+
|
32
|
+
%i[days weeks months].each do |period|
|
33
|
+
source[period].map! do |x|
|
34
|
+
x[:range] = ((x[:high] - x[:low]) / sym[:ticksize]).round
|
35
|
+
x
|
36
|
+
end
|
37
|
+
target[period] = {}
|
38
|
+
target[period][:all_size] = source[period].size
|
39
|
+
target[period][:all_avg] = (source[period].map { |x| x[:range] }.reduce(:+) / source[period].size).round
|
40
|
+
target[period][:all_lower] = source[period].sort_by do |x|
|
41
|
+
x[:range]
|
42
|
+
end.map { |x| x[:range] }[ (source[period].size * 1 / 4).round ]
|
43
|
+
target[period][:all_median] = source[period].sort_by do |x|
|
44
|
+
x[:range]
|
45
|
+
end.map { |x| x[:range] }[ (source[period].size * 2 / 4).round ]
|
46
|
+
target[period][:all_upper] = source[period].sort_by do |x|
|
47
|
+
x[:range]
|
48
|
+
end.map { |x| x[:range] }[ (source[period].size * 3 / 4).round ]
|
49
|
+
target[period][:all_max] = source[period].map { |x| x[:range] }.max
|
50
|
+
target[period][:all_records] = source[period].sort_by do |x|
|
51
|
+
-x[:range]
|
52
|
+
end.map { |x| { contract: x[:contract], range: x[:range] } }.take(5)
|
53
|
+
|
54
|
+
tenth = (source[period].size * dim).round
|
55
|
+
custom = source[period].sort_by { |x| x[:range] }[tenth..source[period].size - tenth]
|
56
|
+
target[period][:dim_size] = custom.size
|
57
|
+
target[period][:dim_avg] = (custom.map { |x| x[:range] }.reduce(:+) / custom.size).round
|
58
|
+
target[period][:dim_lower] = custom.sort_by do |x|
|
59
|
+
x[:range]
|
60
|
+
end.map { |x| x[:range] }[ (custom.size * 1 / 4).round ]
|
61
|
+
target[period][:dim_median] = custom.sort_by do |x|
|
62
|
+
x[:range]
|
63
|
+
end.map { |x| x[:range] }[ (custom.size * 2 / 4).round ]
|
64
|
+
target[period][:dim_upper] = custom.sort_by do |x|
|
65
|
+
x[:range]
|
66
|
+
end.map { |x| x[:range] }[ (custom.size * 3 / 4).round ]
|
67
|
+
target[period][:dim_max] = custom.map { |x| x[:range] }.max
|
68
|
+
target[period][:dim_records] = custom.sort_by do |x|
|
69
|
+
-x[:range]
|
70
|
+
end.map { |x| { contract: x[:contract], range: x[:range] } }.take(5)
|
71
|
+
|
72
|
+
range = case period
|
73
|
+
when :months
|
74
|
+
-13..-2
|
75
|
+
when :weeks
|
76
|
+
-53..-2
|
77
|
+
when :days
|
78
|
+
-200..-1
|
79
|
+
else
|
80
|
+
raise ArgumentError, "Unsupported period: '#{period}'"
|
81
|
+
end
|
82
|
+
custom = source[period][range]
|
83
|
+
target[period][:rec_size] = custom.size
|
84
|
+
target[period][:rec_avg] = (custom.map { |x| x[:range] }.reduce(:+) / custom.size).round
|
85
|
+
target[period][:rec_lower] = custom.sort_by do |x|
|
86
|
+
x[:range]
|
87
|
+
end.map { |x| x[:range] }[ (custom.size * 1 / 4).round ]
|
88
|
+
target[period][:rec_median] = custom.sort_by do |x|
|
89
|
+
x[:range]
|
90
|
+
end.map { |x| x[:range] }[ (custom.size * 2 / 4).round ]
|
91
|
+
target[period][:rec_upper] = custom.sort_by do |x|
|
92
|
+
x[:range]
|
93
|
+
end.map { |x| x[:range] }[ (custom.size * 3 / 4).round ]
|
94
|
+
target[period][:rec_max] = custom.map { |x| x[:range] }.max
|
95
|
+
target[period][:rec_records] = custom.sort_by do |x|
|
96
|
+
-x[:range]
|
97
|
+
end.map { |x| { contract: x[:contract], range: x[:range] } }.take(5)
|
98
|
+
end
|
99
|
+
|
100
|
+
if print
|
101
|
+
%w[size avg lower median upper max].each do |a|
|
102
|
+
print "#{'%10s' % a} | " # rubocop:disable Style/FormatString
|
103
|
+
%i[days weeks months].each do |b|
|
104
|
+
%w[all dim rec].each do |c|
|
105
|
+
print ('%8d' % target[b]["#{c}_#{a}".to_sym]).to_s # rubocop:disable Style/FormatString
|
106
|
+
end
|
107
|
+
print ' | '
|
108
|
+
end
|
109
|
+
puts ''
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
target
|
114
|
+
# rubocop:enable Style/MultilineBlockChain
|
115
|
+
end
|
116
|
+
end
|
117
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cotcube
|
4
|
+
# missing top level documentation
|
5
|
+
module Bardata
|
6
|
+
# fetching official trade dates from CME
|
7
|
+
# it returns the current trade date or, if today isn't a trading day, the last trade date.
|
8
|
+
def last_trade_date
|
9
|
+
uri = 'https://www.cmegroup.com/CmeWS/mvc/Volume/TradeDates?exchange=CME'
|
10
|
+
begin
|
11
|
+
HTTParty.get(uri)
|
12
|
+
.parsed_response
|
13
|
+
.map do |x|
|
14
|
+
a = x['tradeDate'].chars.each_slice(2).map(&:join)
|
15
|
+
"#{a[0]}#{a[1]}-#{a[2]}-#{a[3]}"
|
16
|
+
end
|
17
|
+
.first
|
18
|
+
rescue StandardError
|
19
|
+
nil
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def holidays(config: init)
|
24
|
+
CSV.read("#{config[:data_path]}/holidays.csv").map{|x| DateTime.parse(x[0])}
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Cotcube
|
4
|
+
# Missing top level comment
|
5
|
+
module Bardata
|
6
|
+
# returns an Array of ranges containing a week of trading hours, specified by seconds since monday morning
|
7
|
+
# (as sunday is wday:0)
|
8
|
+
# according files are located in config[:data_path]/trading_hours and picked either
|
9
|
+
# by the symbol itself or by the assigned type
|
10
|
+
# commonly there are two filter for each symbol: :full and :rth, exceptions are e.g. meats
|
11
|
+
def trading_hours(symbol: nil, id: nil, # rubocop:disable Metrics/ParameterLists
|
12
|
+
filter: ,
|
13
|
+
force_filter: false, # with force_filter one would avoid falling back
|
14
|
+
# to the contract_type based range set
|
15
|
+
config: init, debug: false)
|
16
|
+
return (0...24 * 7 * 3600) if filter.to_s =~ /24x7/
|
17
|
+
|
18
|
+
prepare = lambda do |f|
|
19
|
+
CSV.read(f, converters: :numeric)
|
20
|
+
.map(&:to_a)
|
21
|
+
.tap { |x| x.shift unless x.first.first.is_a?(Numeric) }
|
22
|
+
.map { |x| (x.first...x.last) }
|
23
|
+
end
|
24
|
+
|
25
|
+
sym = get_id_set(symbol: symbol, id: id)
|
26
|
+
|
27
|
+
file = "#{config[:data_path]}/trading_hours/#{sym[:symbol]}_#{filter}.csv"
|
28
|
+
puts "Trying to use #{file} for #{symbol} + #{filter}" if debug
|
29
|
+
return prepare.call(file) if File.exist? file
|
30
|
+
|
31
|
+
file = "#{config[:data_path]}/trading_hours/#{sym[:symbol]}_full.csv"
|
32
|
+
puts "Failed. Trying to use #{file} now" if debug
|
33
|
+
return prepare.call(file) if File.exist?(file) && (not force_filter)
|
34
|
+
|
35
|
+
file = "#{config[:data_path]}/trading_hours/#{sym[:type]}_#{filter}.csv"
|
36
|
+
puts "Failed. Trying to use #{file} now." if debug
|
37
|
+
return prepare.call(file) if File.exist? file
|
38
|
+
|
39
|
+
file = "#{config[:data_path]}/trading_hours/#{sym[:type]}_full.csv"
|
40
|
+
puts "Failed. Trying to use #{file} now." if debug
|
41
|
+
return prepare.call(file) if File.exist?(file) && (not force_filter)
|
42
|
+
|
43
|
+
puts "Finally failed to find range filter for #{symbol} + #{filter}, returning 24x7".colorize(:light_yellow)
|
44
|
+
(0...24 * 7 * 3600)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
metadata
CHANGED
@@ -1,113 +1,127 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cotcube-bardata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Benjamin L. Tischendorf
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-01-07 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
|
-
name:
|
14
|
+
name: activesupport
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- - "
|
17
|
+
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '
|
19
|
+
version: '6'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- - "
|
24
|
+
- - "~>"
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: '
|
26
|
+
version: '6'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
|
-
name:
|
28
|
+
name: colorize
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - "
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version: '0'
|
33
|
+
version: '0.8'
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - "
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version: '0'
|
40
|
+
version: '0.8'
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
|
-
name:
|
42
|
+
name: cotcube-helpers
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
44
44
|
requirements:
|
45
|
-
- - "
|
45
|
+
- - "~>"
|
46
46
|
- !ruby/object:Gem::Version
|
47
|
-
version: '0'
|
47
|
+
version: '0.1'
|
48
48
|
type: :runtime
|
49
49
|
prerelease: false
|
50
50
|
version_requirements: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
|
-
- - "
|
52
|
+
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
|
-
version: '0'
|
54
|
+
version: '0.1'
|
55
55
|
- !ruby/object:Gem::Dependency
|
56
|
-
name:
|
56
|
+
name: cotcube-indicators
|
57
57
|
requirement: !ruby/object:Gem::Requirement
|
58
58
|
requirements:
|
59
|
-
- - "
|
59
|
+
- - "~>"
|
60
60
|
- !ruby/object:Gem::Version
|
61
|
-
version: '0'
|
61
|
+
version: '0.1'
|
62
62
|
type: :runtime
|
63
63
|
prerelease: false
|
64
64
|
version_requirements: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
|
-
- - "
|
66
|
+
- - "~>"
|
67
67
|
- !ruby/object:Gem::Version
|
68
|
-
version: '0'
|
68
|
+
version: '0.1'
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: httparty
|
71
71
|
requirement: !ruby/object:Gem::Requirement
|
72
72
|
requirements:
|
73
|
-
- - "
|
73
|
+
- - "~>"
|
74
74
|
- !ruby/object:Gem::Version
|
75
|
-
version: '0'
|
75
|
+
version: '0.18'
|
76
76
|
type: :runtime
|
77
77
|
prerelease: false
|
78
78
|
version_requirements: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
|
-
- - "
|
80
|
+
- - "~>"
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: '0'
|
82
|
+
version: '0.18'
|
83
83
|
- !ruby/object:Gem::Dependency
|
84
|
-
name:
|
84
|
+
name: parallel
|
85
85
|
requirement: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
|
-
- - "
|
87
|
+
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '
|
89
|
+
version: '1'
|
90
90
|
type: :runtime
|
91
91
|
prerelease: false
|
92
92
|
version_requirements: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
|
-
- - "
|
94
|
+
- - "~>"
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '1'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: yaml
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - "~>"
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0.1'
|
104
|
+
type: :runtime
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - "~>"
|
95
109
|
- !ruby/object:Gem::Version
|
96
|
-
version: '0'
|
110
|
+
version: '0.1'
|
97
111
|
- !ruby/object:Gem::Dependency
|
98
112
|
name: rake
|
99
113
|
requirement: !ruby/object:Gem::Requirement
|
100
114
|
requirements:
|
101
115
|
- - ">="
|
102
116
|
- !ruby/object:Gem::Version
|
103
|
-
version: '
|
117
|
+
version: '12'
|
104
118
|
type: :development
|
105
119
|
prerelease: false
|
106
120
|
version_requirements: !ruby/object:Gem::Requirement
|
107
121
|
requirements:
|
108
122
|
- - ">="
|
109
123
|
- !ruby/object:Gem::Version
|
110
|
-
version: '
|
124
|
+
version: '12'
|
111
125
|
- !ruby/object:Gem::Dependency
|
112
126
|
name: rspec
|
113
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -152,9 +166,17 @@ files:
|
|
152
166
|
- VERSION
|
153
167
|
- cotcube-bardata.gemspec
|
154
168
|
- lib/cotcube-bardata.rb
|
169
|
+
- lib/cotcube-bardata/cached.rb
|
155
170
|
- lib/cotcube-bardata/constants.rb
|
171
|
+
- lib/cotcube-bardata/daily.rb
|
172
|
+
- lib/cotcube-bardata/eods.rb
|
173
|
+
- lib/cotcube-bardata/helpers.rb
|
156
174
|
- lib/cotcube-bardata/init.rb
|
157
175
|
- lib/cotcube-bardata/provide.rb
|
176
|
+
- lib/cotcube-bardata/quarters.rb
|
177
|
+
- lib/cotcube-bardata/range_matrix.rb
|
178
|
+
- lib/cotcube-bardata/trade_dates.rb
|
179
|
+
- lib/cotcube-bardata/trading_hours.rb
|
158
180
|
homepage: https://github.com/donkeybridge/cotcube-bardata
|
159
181
|
licenses:
|
160
182
|
- BSD-4-Clause
|