quandl_operation 0.1.23 → 0.2.0
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/UPGRADE.md +13 -0
- data/lib/quandl/operation.rb +4 -0
- data/lib/quandl/operation/collapse.rb +3 -8
- data/lib/quandl/operation/collapse/guess.rb +1 -4
- data/lib/quandl/operation/core_ext/array.rb +12 -1
- data/lib/quandl/operation/errors.rb +5 -0
- data/lib/quandl/operation/parse.rb +144 -41
- data/lib/quandl/operation/qdate.rb +22 -0
- data/lib/quandl/operation/transform.rb +5 -10
- data/lib/quandl/operation/version.rb +1 -1
- data/spec/lib/quandl/operation/parse_spec.rb +46 -19
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f793e84f6b1444296a2139214ac181e0a3175db5
|
4
|
+
data.tar.gz: 1e07e11fac0532a64bb51a61227b76d33ba20ff6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 72f3392d5646b4fac36ac7d83b11c0d53481b1bb4ed12c237b40c7acdb554f35450e9376ff6000fa3cb80fe3dd3c52116011301090bdf4dc7c2273ba0e5ab341
|
7
|
+
data.tar.gz: 8bd50d06f6f8b57789694840594b9ff34e3326052cb05d4bc2f881e302c8432819d587e78217c85ade3866f34d417e14e6786a8c3bf2f98744e659bb342399f3
|
data/UPGRADE.md
CHANGED
@@ -1,7 +1,20 @@
|
|
1
|
+
## 0.2.0
|
2
|
+
|
3
|
+
* rename Parse methods to be more informative
|
4
|
+
* add qdate
|
5
|
+
* reject dates that preceed time
|
6
|
+
* add Quandl::Operation::Errors
|
7
|
+
* add Quandl::Operation::Errors::UnknownDateFormat
|
8
|
+
* Quandl::Operation::Parse.perform(data)
|
9
|
+
* outputs dates as Date instead of Integer
|
10
|
+
* invalid dates raise date_format_error with informative message
|
11
|
+
|
12
|
+
|
1
13
|
## 0.1.22
|
2
14
|
|
3
15
|
* refactor QDFormat to support full yaml. metadata and data are seperated by a
|
4
16
|
|
17
|
+
|
5
18
|
## 0.1.21
|
6
19
|
|
7
20
|
* QDFormat should handle new lines in attributes
|
data/lib/quandl/operation.rb
CHANGED
@@ -2,6 +2,8 @@ require 'quandl/logger'
|
|
2
2
|
|
3
3
|
require "quandl/operation/version"
|
4
4
|
|
5
|
+
require 'csv'
|
6
|
+
|
5
7
|
require "active_support"
|
6
8
|
require "active_support/inflector"
|
7
9
|
require "active_support/core_ext/hash"
|
@@ -11,6 +13,8 @@ require 'quandl/operation/core_ext'
|
|
11
13
|
require 'quandl/operation/collapse'
|
12
14
|
require 'quandl/operation/transform'
|
13
15
|
require 'quandl/operation/parse'
|
16
|
+
require 'quandl/operation/errors'
|
17
|
+
require 'quandl/operation/qdate'
|
14
18
|
|
15
19
|
module Quandl
|
16
20
|
module Operation
|
@@ -12,23 +12,18 @@ class Collapse
|
|
12
12
|
return data unless data.is_a?(Array) && data.compact.present?
|
13
13
|
# source order
|
14
14
|
order = Parse.sort_order?(data)
|
15
|
+
# ensure data is in expected format
|
16
|
+
data = Parse.to_jd(data)
|
15
17
|
# operations expect data in ascending order
|
16
18
|
data = Parse.sort( data, :asc )
|
17
19
|
# collapse
|
18
|
-
data =
|
20
|
+
data = collapse(data, frequency)
|
19
21
|
# return to original order
|
20
22
|
data = Parse.sort( data, :desc ) if order == :desc
|
21
23
|
# onwards
|
22
24
|
data
|
23
25
|
end
|
24
26
|
|
25
|
-
def collapse_and_log(data, frequency)
|
26
|
-
t1 = Time.now
|
27
|
-
r = collapse(data, frequency)
|
28
|
-
Quandl::Logger.debug "#{self.name}.perform(#{data.try(:count)} rows, #{frequency}) (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
|
29
|
-
r
|
30
|
-
end
|
31
|
-
|
32
27
|
def valid_collapse?(type)
|
33
28
|
valid?(type)
|
34
29
|
end
|
@@ -7,15 +7,12 @@ class Guess
|
|
7
7
|
|
8
8
|
def frequency(data)
|
9
9
|
return :annual unless data && data[0] && data[0][0]
|
10
|
-
t1 = Time.now
|
11
10
|
# find the smallest point of difference between dates
|
12
11
|
gap = find_average_gap(data)
|
13
12
|
# ensure gap is not negative
|
14
13
|
gap = ensure_positive_gap(gap)
|
15
14
|
# determine the freq from the size of the smallest gap
|
16
|
-
|
17
|
-
Quandl::Logger.debug "#{self.name}.perform (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
|
18
|
-
freq
|
15
|
+
frequency_from_gap(gap)
|
19
16
|
end
|
20
17
|
|
21
18
|
def find_smallest_gap(data)
|
@@ -1,6 +1,17 @@
|
|
1
1
|
class Array
|
2
2
|
def self.forwardable_methods
|
3
|
-
[:reject, :keep_if, :
|
3
|
+
[:reject, :keep_if, :to_a, :cycle, :drop, :map, :rotate, :each_slice, :pack, :select!,
|
4
|
+
:combination, :repeated_combination, :shift, :select, :reverse!, :==, :clear, :rotate!, :inspect, :iter_for_each,
|
5
|
+
:sort_by!, :compact!, :|, :copy_data_simple, :nitems, :zip, :take, :rassoc, :flatten!, :join, :compact, :[]=,
|
6
|
+
:frozen?, :slice!, :drop_while, :reverse_each, :shuffle, :slice, :reverse, :insert, :uniq, :first, :count, :fetch,
|
7
|
+
:hash, :to_ary, :find_index, :replace, :-, :product, :iter_for_reverse_each, :pop, :push, :sort, :fill, :uniq!,
|
8
|
+
:length, :&, :flatten, :repeated_permutation, :[], :shuffle!, :sort!, :sample, :include?, :<<, :dimensions,
|
9
|
+
:collect, :+, :rindex, :<=>, :eql?, :indices, :collect!, :iter_for_each_index, :iter_for_each_with_index, :index,
|
10
|
+
:*, :indexes, :copy_data, :delete, :to_s, :assoc, :delete_at, :unshift, :delete_if, :empty?, :reject!, :last,
|
11
|
+
:size, :concat, :map!, :at, :each_index, :transpose, :values_at, :each, :enum_cons, :group_by, :enum_with_index,
|
12
|
+
:entries, :with_object, :chunk, :each_with_index, :min, :inject, :one?, :partition, :enum_slice, :none?, :max_by,
|
13
|
+
:any?, :flat_map, :reduce, :each_entry, :find, :minmax_by, :collect_concat, :each_cons, :member?, :max, :sort_by,
|
14
|
+
:detect, :all?, :minmax, :grep, :each_with_object, :find_all]
|
4
15
|
end
|
5
16
|
def average
|
6
17
|
self.sum / self.count
|
@@ -1,29 +1,25 @@
|
|
1
|
-
require 'csv'
|
2
|
-
|
3
1
|
module Quandl
|
4
2
|
module Operation
|
5
|
-
|
3
|
+
|
6
4
|
class Parse
|
7
5
|
|
8
6
|
class << self
|
9
7
|
|
10
8
|
def perform(data)
|
11
9
|
return [] if data.blank?
|
12
|
-
|
13
|
-
data =
|
14
|
-
data =
|
15
|
-
data =
|
16
|
-
|
17
|
-
Quandl::Logger.debug "#{self.name}.perform (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
|
18
|
-
data
|
10
|
+
data = hash_to_array(data)
|
11
|
+
data = csv_to_array(data)
|
12
|
+
# data = to_jd(data)
|
13
|
+
data = to_date(data)
|
14
|
+
data.dup
|
19
15
|
end
|
20
16
|
|
21
|
-
def
|
17
|
+
def hash_to_array(data)
|
22
18
|
data = data.collect{|k,v| [k] + v } if data.kind_of?(Hash)
|
23
19
|
data
|
24
20
|
end
|
25
21
|
|
26
|
-
def
|
22
|
+
def csv_to_array(data)
|
27
23
|
if data.is_a?(String)
|
28
24
|
data = data.gsub('\n', "\n")
|
29
25
|
data = CSV.parse( data )
|
@@ -54,62 +50,127 @@ class Parse
|
|
54
50
|
data.sort_by{|r| r[0] }.reverse
|
55
51
|
end
|
56
52
|
|
57
|
-
def
|
53
|
+
def to_date(data)
|
58
54
|
return data if data_missing_rows?(data)
|
59
|
-
date
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
return
|
55
|
+
# guess the current date format
|
56
|
+
format = date_format?(data)
|
57
|
+
# convert dates to Date
|
58
|
+
case format
|
59
|
+
when :date then return data
|
60
|
+
when :date_string then return date_strings_to_date( data )
|
61
|
+
when :jd, :jd_string then return jds_to_date( data )
|
62
|
+
when :unknown then raise_date_format_error!( data[0] )
|
63
|
+
end
|
64
|
+
# return data
|
65
|
+
data
|
64
66
|
end
|
65
67
|
|
66
|
-
def
|
68
|
+
def to_jd(data)
|
69
|
+
return data if data_missing_rows?(data)
|
70
|
+
# guess the current date format
|
71
|
+
format = date_format?(data)
|
72
|
+
# convert dates to Date
|
73
|
+
case format
|
74
|
+
when :jd then return data
|
75
|
+
when :jd_string then return jd_strings_to_jd( data )
|
76
|
+
when :date then return dates_to_jd( data )
|
77
|
+
when :date_string then return date_strings_to_jd( data )
|
78
|
+
when :unknown then raise_date_format_error!( data[0] )
|
79
|
+
end
|
80
|
+
# return data
|
81
|
+
data
|
82
|
+
end
|
83
|
+
|
84
|
+
def date_format?(data)
|
85
|
+
value = data[0][0]
|
86
|
+
# julian date?
|
87
|
+
return :date if value.is_a?(Date)
|
88
|
+
return :jd if value.is_a?(Integer)
|
89
|
+
return :date_string if value.is_a?(String) && value =~ /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/
|
90
|
+
return :jd_string if value.kind_of?(String) && value.numeric?
|
91
|
+
return :unknown
|
92
|
+
end
|
93
|
+
|
94
|
+
def dates_to_jd(data)
|
67
95
|
return data if data_missing_rows?(data) || data[0][0].is_a?(Integer)
|
68
96
|
# dont alter by reference
|
69
97
|
result = []
|
70
98
|
# for each row
|
71
99
|
data.each_with_index do |row, index|
|
72
100
|
# copy
|
73
|
-
|
101
|
+
row = row.dup
|
74
102
|
# string to date
|
75
|
-
date =
|
76
|
-
date = Date.parse(
|
103
|
+
date = row[0]
|
104
|
+
date = Date.parse(row[0]) if row[0].is_a?(String)
|
77
105
|
# date to julian
|
78
|
-
|
106
|
+
row[0] = date.jd if date.respond_to?(:jd)
|
79
107
|
# save result
|
80
|
-
result[index] =
|
108
|
+
result[index] = row
|
81
109
|
end
|
82
110
|
# all done
|
83
111
|
result
|
84
112
|
end
|
85
|
-
|
86
|
-
|
113
|
+
|
114
|
+
|
115
|
+
###################
|
116
|
+
# DATES TO JULIAN #
|
117
|
+
###################
|
118
|
+
|
119
|
+
def jd_strings_to_jd(data)
|
120
|
+
# skip when already formatted correctly
|
121
|
+
return data if data_missing_rows?(data) || data[0][0].is_a?(Integer)
|
122
|
+
# otherwise cast string jds to int
|
123
|
+
output = []
|
124
|
+
data.each_with_index do |row, index|
|
125
|
+
output << parse_jd_string(row) rescue raise_date_format_error!( row, index, :jd_strings_to_jd )
|
126
|
+
end
|
127
|
+
output
|
128
|
+
end
|
129
|
+
|
130
|
+
def date_strings_to_jd(data)
|
131
|
+
# skip when already formatted correctly
|
87
132
|
return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
|
88
|
-
#
|
89
|
-
|
90
|
-
# for each row
|
133
|
+
# otherwise cast string jds to int
|
134
|
+
output = []
|
91
135
|
data.each_with_index do |row, index|
|
92
|
-
|
93
|
-
nrow = row.dup
|
94
|
-
# parse date
|
95
|
-
nrow[0] = Date.jd( nrow[0].to_i ) unless nrow[0].is_a?(Date)
|
96
|
-
# save result
|
97
|
-
result[index] = nrow
|
136
|
+
output << parse_date_string(row).jd rescue raise_date_format_error!( row, index, :date_strings_to_jd )
|
98
137
|
end
|
99
|
-
|
100
|
-
|
138
|
+
output
|
139
|
+
end
|
140
|
+
|
141
|
+
|
142
|
+
#################
|
143
|
+
# DATES TO DATE #
|
144
|
+
#################
|
145
|
+
|
146
|
+
def jds_to_date(data)
|
147
|
+
return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
|
148
|
+
output = []
|
149
|
+
data.each_with_index do |row, index|
|
150
|
+
output << parse_jd(row) rescue raise_date_format_error!( row, index, :jds_to_date )
|
151
|
+
end
|
152
|
+
output
|
101
153
|
end
|
102
154
|
|
103
|
-
def
|
155
|
+
def date_strings_to_date(data)
|
104
156
|
# skip when already formatted correctly
|
105
|
-
return data if data_missing_rows?(data) || data[0][0].is_a?(
|
157
|
+
return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
|
106
158
|
# otherwise cast string jds to int
|
107
|
-
|
159
|
+
output = []
|
160
|
+
data.each_with_index do |row, index|
|
161
|
+
output << parse_date_string(row) rescue raise_date_format_error!( row, index, :date_strings_to_date )
|
162
|
+
end
|
163
|
+
output
|
108
164
|
end
|
109
165
|
|
166
|
+
|
167
|
+
###################
|
168
|
+
# VALUES TO FLOAT #
|
169
|
+
###################
|
170
|
+
|
110
171
|
def values_to_float(data)
|
111
172
|
# skip unless value is a string
|
112
|
-
return data if data_missing_rows?(data) ||
|
173
|
+
return data if data_missing_rows?(data) || data[0][1].is_a?(Float)
|
113
174
|
# cast values to float
|
114
175
|
data.collect do |row|
|
115
176
|
new_row = [row[0]]
|
@@ -121,6 +182,7 @@ class Parse
|
|
121
182
|
end
|
122
183
|
end
|
123
184
|
|
185
|
+
|
124
186
|
def data_missing_rows?(data)
|
125
187
|
!data_has_rows?(data)
|
126
188
|
end
|
@@ -129,6 +191,47 @@ class Parse
|
|
129
191
|
data.is_a?(Array) && data[0].is_a?(Array) && data[0][0].present?
|
130
192
|
end
|
131
193
|
|
194
|
+
|
195
|
+
protected
|
196
|
+
|
197
|
+
def parse_jd(row)
|
198
|
+
# parse jd_string
|
199
|
+
row = parse_jd_string(row)
|
200
|
+
# jd to date
|
201
|
+
row[0] = Date.jd( row[0] )
|
202
|
+
# onwards
|
203
|
+
row
|
204
|
+
end
|
205
|
+
|
206
|
+
def parse_jd_string(row)
|
207
|
+
row = row.dup
|
208
|
+
row[0] = row[0].to_i
|
209
|
+
# dont allow dates that are before 0000
|
210
|
+
raise Errors::UnknownDateFormat if row[0] <= 1721058
|
211
|
+
row
|
212
|
+
end
|
213
|
+
|
214
|
+
def parse_date_string(row)
|
215
|
+
row = row.dup
|
216
|
+
# extract date
|
217
|
+
date = row[0]
|
218
|
+
# split date into parts
|
219
|
+
date_values = date.split('-').collect(&:to_i)
|
220
|
+
# ensure date is valid
|
221
|
+
raise Errors::UnknownDateFormat unless date_values.count == 3
|
222
|
+
# add to row
|
223
|
+
row[0] = Date.new( *date_values )
|
224
|
+
row
|
225
|
+
end
|
226
|
+
|
227
|
+
|
228
|
+
private
|
229
|
+
|
230
|
+
def raise_date_format_error!(row, index = 0, type = :none)
|
231
|
+
message = "UnknownDateFormat: '#{row[0]}', index: data[#{index}][0], strategy: '#{type}', row: #{row}"
|
232
|
+
raise Errors::UnknownDateFormat, message
|
233
|
+
end
|
234
|
+
|
132
235
|
end
|
133
236
|
|
134
237
|
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Quandl
|
2
|
+
module Operation
|
3
|
+
|
4
|
+
class QDate
|
5
|
+
|
6
|
+
class << self
|
7
|
+
def parse(value)
|
8
|
+
date = Date.jd(value.to_i) if value.kind_of?(String) && value.numeric?
|
9
|
+
date = Date.jd(value) if value.is_a?(Integer)
|
10
|
+
date = Date.parse(value) if value.is_a?(String) && value =~ /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/
|
11
|
+
date = value if value.is_a?(Date)
|
12
|
+
date = value.to_date if value.respond_to?(:to_date)
|
13
|
+
date
|
14
|
+
rescue
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -1,9 +1,10 @@
|
|
1
1
|
module Quandl
|
2
2
|
module Operation
|
3
|
-
|
3
|
+
|
4
4
|
class Transform
|
5
|
+
|
5
6
|
class << self
|
6
|
-
|
7
|
+
|
7
8
|
def perform( data, type )
|
8
9
|
return data unless data.is_a?(Array) && data.compact.present?
|
9
10
|
# original order
|
@@ -13,20 +14,13 @@ class Transform
|
|
13
14
|
# operations expect float values
|
14
15
|
data = Parse.values_to_float(data)
|
15
16
|
# transform
|
16
|
-
data =
|
17
|
+
data = transform( data, type)
|
17
18
|
# return to original order
|
18
19
|
data = Parse.sort( data, :desc ) if order == :desc
|
19
20
|
# onwards
|
20
21
|
data
|
21
22
|
end
|
22
23
|
|
23
|
-
def transform_and_log( data, type)
|
24
|
-
t1 = Time.now
|
25
|
-
r = transform( data, type)
|
26
|
-
Quandl::Logger.debug "#{self.name}.perform(#{data.try(:count)} rows, #{type}) (#{t1.elapsed.microseconds}ms)" if t1.elapsed.microseconds > 1
|
27
|
-
r
|
28
|
-
end
|
29
|
-
|
30
24
|
def valid_transformation?(type)
|
31
25
|
valid?(type)
|
32
26
|
end
|
@@ -164,6 +158,7 @@ class Transform
|
|
164
158
|
end
|
165
159
|
|
166
160
|
end
|
161
|
+
|
167
162
|
end
|
168
163
|
end
|
169
164
|
end
|
@@ -4,39 +4,66 @@ require 'spec_helper'
|
|
4
4
|
describe Quandl::Operation::Parse do
|
5
5
|
subject{ Quandl::Operation::Parse }
|
6
6
|
let(:escaped_csv){ '2444628,0.00385,0.001,0.123,0.00631,0.534\n2444627,0.00384,0.00159507,0.0056,0.00628948,0.009896' }
|
7
|
-
let(:data_array){ [[ 2444628,0.00385,0.001,0.123,0.00631,0.534], [ 2444627,0.00384,0.00159507,0.0056,0.00628948,0.009896 ]] }
|
8
|
-
|
7
|
+
let(:data_array){ [[ Date.jd(2444628),0.00385,0.001,0.123,0.00631,0.534], [ Date.jd(2444627),0.00384,0.00159507,0.0056,0.00628948,0.009896 ]] }
|
8
|
+
|
9
9
|
let(:csv_data){ "#{Date.today}, 1.0, 2.0" }
|
10
10
|
let(:hash_data){ { Date.today.to_s => [ 1.0, 2.0 ] } }
|
11
11
|
let(:array_data){ [[ Date.today.to_s, 1.0, 2.0 ]] }
|
12
12
|
let(:julian_data){ [[ Date.today.jd, 1.0, 2.0 ]] }
|
13
|
+
let(:date_data){ [[ Date.today, 1.0, 2.0 ]] }
|
13
14
|
|
14
15
|
it "#hash outputs array" do
|
15
|
-
subject.
|
16
|
+
subject.hash_to_array( hash_data ).should eq array_data
|
16
17
|
end
|
17
18
|
|
18
19
|
it "#csv outputs array" do
|
19
|
-
subject.
|
20
|
+
subject.csv_to_array( csv_data ).should eq array_data
|
20
21
|
end
|
21
22
|
|
22
23
|
describe "#perform" do
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
|
25
|
+
[:csv, :hash, :array, :julian, :date].each do |type|
|
26
|
+
context "#{type} data" do
|
27
|
+
it "should eq date_data" do
|
28
|
+
subject.perform( self.send("#{type}_data") ).should eq date_data
|
29
|
+
end
|
30
|
+
it "values should be_a Float" do
|
31
|
+
subject.perform( self.send("#{type}_data") ).each{|r| r[1..-1].each{|v| v.should be_a Float } }
|
32
|
+
end
|
33
|
+
end
|
31
34
|
end
|
32
|
-
|
33
|
-
|
35
|
+
|
36
|
+
|
37
|
+
let(:csv1){ "2012-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,18.0,33.99,0.0,25.0,0.0,10.0,22.0,34.0,10.0,20.0,26.0,0.0,18.5,25.0,33.0,30.0,20.0,27.5,10.0,19.0,25.0,29.0,23.0,25.0,21.0,30.0,28.0,24.5,33.33,0.0,29.48,10.0,20.0,31.0,0.0,35.0,16.5,19.0,20.0,32.45,25.0,12.5,0.0,25.0,31.4,33.33,38.01,0.0,14.0,20.0,30.0,24.2,15.0,15.0,20.0,12.5,15.0,28.8,12.0,10.0,30.0,25.0,35.0,15.0,30.0,9.0,32.0,34.0,25.0,28.0,30.0,28.0,12.0,35.0,25.0,30.0,10.0,30.0,30.0,19.0,25.0,10.0,16.0,20.0,0.0,27.0,20.0,10.0,17.0,19.0,18.0,34.55,30.0,28.0,0.0,34.5,35.0,26.3,21.17,28.0,17.0,30.0,23.0,25.0,30.0,20.0,30.0,21.0,55.0,24.0,40.0,25.0,0.0,34.0,25.0,20.0,35.0,25.75,29.02,33.0,22.89,20.5,28.3,28.6,22.6,25.25,24.43\n2011-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,24.0,33.99,0.0,0.0,0.0,10.0,22.0,34.0,10.0,20.0,28.0,0.0,20.0,25.0,33.0,30.0,20.0,34.5,10.0,19.0,25.0,29.0,24.0,20.0,21.0,0.0,28.0,26.0,33.33,0.0,29.37,10.0,20.0,31.0,0.0,35.0,16.5,19.0,20.0,32.44,25.0,12.5,0.0,24.0,31.4,33.33,40.69,0.0,14.0,20.0,0.0,22.0,15.0,15.0,20.0,12.5,15.0,28.8,12.0,10.0,0.0,25.0,35.0,15.0,30.0,9.0,32.0,34.0,25.0,28.0,30.0,28.0,12.0,35.0,25.0,30.0,10.0,30.0,30.0,19.0,25.0,10.0,16.0,20.0,0.0,27.0,20.0,10.0,17.0,19.0,20.0,34.55,30.0,28.0,0.0,34.5,35.0,26.3,21.17,28.0,17.0,30.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,26.0,40.0,25.0,0.0,34.0,25.0,20.0,35.0,25.75,28.55,34.0,23.1,20.88,29.02,28.6,22.8,25.5,24.52\n2010-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,24.0,33.99,0.0,25.0,0.0,10.0,25.0,34.0,10.0,20.0,31.0,0.0,17.0,25.0,33.0,30.0,20.0,0.0,10.0,19.0,25.0,25.0,25.0,20.0,21.0,0.0,28.0,26.0,33.33,0.0,29.41,22.0,24.0,31.0,0.0,25.0,16.5,19.0,18.0,33.99,25.0,12.5,0.0,25.0,31.4,33.33,40.69,0.0,14.0,20.0,0.0,24.2,15.0,15.0,40.0,0.0,15.0,28.59,12.0,10.0,0.0,25.0,35.0,15.0,30.0,9.0,32.0,0.0,25.5,30.0,30.0,28.0,12.0,35.0,27.5,30.0,10.0,30.0,30.0,19.0,25.0,10.0,16.0,20.0,0.0,27.0,20.0,10.0,17.0,19.0,20.0,34.55,30.0,35.0,0.0,0.0,15.0,26.3,21.17,28.0,17.0,30.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,28.0,40.0,25.0,0.0,34.0,25.0,35.0,35.0,25.75,28.38,35.5,23.96,21.52,27.52,29.0,23.04,25.79,24.71\n2009-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,27.5,25.0,24.0,33.99,0.0,0.0,0.0,10.0,25.0,34.0,10.0,0.0,33.0,0.0,17.0,25.0,33.0,30.0,20.0,0.0,10.0,20.0,25.0,25.0,25.0,20.0,21.0,0.0,29.0,26.0,33.33,0.0,29.44,27.0,25.0,31.0,0.0,30.0,16.5,16.0,15.0,33.99,28.0,12.5,0.0,26.0,31.4,33.33,40.69,0.0,25.0,20.0,0.0,24.2,15.0,15.0,40.0,0.0,20.0,28.59,12.0,10.0,0.0,25.0,35.0,15.0,28.0,9.0,32.0,0.0,25.5,30.0,30.0,28.0,12.0,35.0,30.0,30.0,10.0,30.0,30.0,19.0,25.0,35.0,16.0,20.0,0.0,27.0,20.0,10.0,18.0,19.0,21.0,34.55,30.0,35.0,0.0,0.0,15.0,26.3,21.17,28.0,25.0,30.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,28.0,40.0,25.0,0.0,34.0,25.0,35.0,35.0,30.9,28.75,36.5,25.73,21.7,27.96,29.2,23.22,25.73,25.4\n2008-12-31,20.0,10.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,30.0,25.0,24.0,33.99,0.0,0.0,0.0,10.0,25.0,34.0,10.0,0.0,33.5,0.0,17.0,25.0,33.0,30.0,20.0,0.0,10.0,21.0,25.0,25.0,25.0,20.0,21.0,0.0,31.0,26.0,33.33,0.0,29.51,33.0,25.0,31.0,0.0,30.0,16.5,16.0,15.0,33.99,30.0,12.5,0.0,27.0,31.4,33.33,40.69,0.0,25.0,30.0,0.0,27.5,55.0,15.0,40.0,0.0,15.0,29.63,12.0,10.0,0.0,26.0,35.0,15.0,28.0,9.0,32.0,0.0,25.5,30.0,30.0,28.0,12.0,35.0,30.0,30.0,10.0,30.0,35.0,19.0,25.0,35.0,16.0,24.0,0.0,27.0,20.0,10.0,18.0,19.0,22.0,34.55,30.0,35.0,0.0,0.0,15.0,28.0,21.17,28.0,25.0,0.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,30.0,40.0,25.0,0.0,34.0,28.0,35.0,35.0,30.9,28.65,36.75,27.99,22.0,27.96,29.6,23.29,26.08,26.12\n2007-12-31,20.0,20.0,35.0,35.0,20.0,28.0,30.0,25.0,0.0,0.0,30.0,25.0,24.0,33.99,0.0,0.0,0.0,10.0,25.0,34.0,10.0,0.0,36.1,0.0,17.0,33.0,34.0,30.0,20.0,0.0,10.0,24.0,25.0,25.0,25.0,20.0,22.0,0.0,31.0,26.0,33.33,0.0,38.36,35.0,25.0,31.0,0.0,30.0,17.5,16.0,18.0,33.99,30.0,12.5,0.0,29.0,37.25,33.33,40.69,0.0,25.0,30.0,0.0,27.5,55.0,15.0,40.0,0.0,15.0,29.63,12.0,12.0,0.0,27.0,35.0,22.5,28.0,9.0,32.0,0.0,25.5,33.0,30.0,28.0,12.0,35.0,30.0,30.0,10.0,30.0,35.0,19.0,25.0,35.0,16.0,24.0,0.0,27.0,20.0,10.0,20.0,19.0,23.0,36.89,32.5,35.0,0.0,0.0,30.0,28.0,21.32,28.0,25.0,0.0,30.0,0.0,30.0,20.0,30.0,25.0,55.0,30.0,40.0,30.0,0.0,34.0,28.0,35.0,35.0,30.9,30.56,38.05,28.46,23.01,28.3,30.2,24.11,27.08,26.96\n"}
|
38
|
+
let(:csv2){ "2012-03-07,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-06,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-05,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-04,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-29,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-28,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n" }
|
39
|
+
|
40
|
+
[:csv1, :csv2].each do |type|
|
41
|
+
context "#{type} data" do
|
42
|
+
it "dates should be_a Date" do
|
43
|
+
subject.perform( self.send(type) ).each{|r| r[0].should be_a Date }
|
44
|
+
end
|
45
|
+
|
46
|
+
it "values should be_a Float" do
|
47
|
+
subject.perform( self.send(type) ).each do |row|
|
48
|
+
row[1..-1].each do |value|
|
49
|
+
next if value.nil?
|
50
|
+
value.should be_a Float
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
34
56
|
end
|
35
|
-
|
36
|
-
|
57
|
+
|
58
|
+
let(:invalid1){ "Date, Column 1, Column 2, C3, C4, C5, C6, C7\n 2012-03-07,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-06,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-05,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-04,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-29,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-28,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n" }
|
59
|
+
let(:invalid2){ "2012-03-07,,69.75,69.75,69.75,0.0,0.0,0.0\nDate, Column 1, Column 2, C3, C4, C5, C6, C7\n2012-03-06,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-05,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-03-04,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-29,,69.75,69.75,69.75,0.0,0.0,0.0\n2012-02-28,69.75,69.75,69.75,69.75,0.0,0.0,0.0\n" }
|
60
|
+
|
61
|
+
[:invalid1, :invalid2].each do |type|
|
62
|
+
it "#{type} should raise Quandl::Operation::Errors::UnknownDateFormat" do
|
63
|
+
expect { Quandl::Operation::Parse.perform( self.send(type) ) }.to raise_error Quandl::Operation::Errors::UnknownDateFormat
|
64
|
+
end
|
37
65
|
end
|
66
|
+
|
38
67
|
end
|
39
68
|
|
40
|
-
end
|
41
|
-
|
42
|
-
|
69
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quandl_operation
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Blake Hilscher
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-11-
|
11
|
+
date: 2013-11-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -147,7 +147,9 @@ files:
|
|
147
147
|
- lib/quandl/operation/core_ext/float.rb
|
148
148
|
- lib/quandl/operation/core_ext/string.rb
|
149
149
|
- lib/quandl/operation/core_ext/time.rb
|
150
|
+
- lib/quandl/operation/errors.rb
|
150
151
|
- lib/quandl/operation/parse.rb
|
152
|
+
- lib/quandl/operation/qdate.rb
|
151
153
|
- lib/quandl/operation/transform.rb
|
152
154
|
- lib/quandl/operation/version.rb
|
153
155
|
- quandl_operation.gemspec
|