quandl_operation 0.1.23 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|