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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 24dc5a778c39638babaa1bb5640e042a26ffba1c
4
- data.tar.gz: c4f5211b7f4425f872939e7bb08c12a955af4691
3
+ metadata.gz: f793e84f6b1444296a2139214ac181e0a3175db5
4
+ data.tar.gz: 1e07e11fac0532a64bb51a61227b76d33ba20ff6
5
5
  SHA512:
6
- metadata.gz: d12d77624a61d51560f2d214189b826174a8bc291460a2651d8075fe398418925fc4e6fb1bda4155d7f566ce70932edc8858330c477f4c2d8191f420f70e5f85
7
- data.tar.gz: 60f8fdb3179b09437abe62f09dd720d43167ce3bab8ca5ad567c56450aba674c870738f9410f926d63be54bd559e0e042465720b719a080d8cb8bcc3ae1d501e
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
@@ -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 = collapse_and_log(data, frequency)
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
- freq = frequency_from_gap(gap)
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, :permutation, :to_a, :cycle, :drop, :take_while, :map, :rotate, :each_slice, :pack, :select!, :combination, :repeated_combination, :shift, :select, :reverse!, :==, :clear, :rotate!, :inspect, :iter_for_each, :sort_by!, :compact!, :|, :copy_data_simple, :nitems, :zip, :take, :rassoc, :flatten!, :join, :compact, :[]=, :frozen?, :slice!, :drop_while, :reverse_each, :shuffle, :slice, :reverse, :insert, :uniq, :first, :count, :fetch, :hash, :to_ary, :find_index, :replace, :-, :product, :iter_for_reverse_each, :pop, :push, :sort, :fill, :uniq!, :length, :&, :flatten, :repeated_permutation, :[], :shuffle!, :sort!, :sample, :include?, :<<, :dimensions, :collect, :+, :rindex, :<=>, :eql?, :indices, :collect!, :iter_for_each_index, :iter_for_each_with_index, :index, :*, :indexes, :copy_data, :delete, :to_s, :assoc, :delete_at, :unshift, :delete_if, :empty?, :reject!, :last, :size, :concat, :map!, :at, :each_index, :transpose, :values_at, :each, :enum_cons, :group_by, :enum_with_index, :entries, :with_object, :chunk, :each_with_index, :min, :inject, :one?, :partition, :enum_slice, :none?, :max_by, :any?, :flat_map, :reduce, :each_entry, :find, :minmax_by, :collect_concat, :each_cons, :member?, :max, :sort_by, :detect, :all?, :minmax, :grep, :each_with_object, :find_all]
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
@@ -0,0 +1,5 @@
1
+ module Quandl::Operation::Errors
2
+
3
+ class UnknownDateFormat < StandardError; end
4
+
5
+ end
@@ -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
- t1 = Time.now
13
- data = hash(data)
14
- data = csv(data)
15
- data = unknown_date_format_to_julian(data)
16
- # data = sort(data)
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 hash(data)
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 csv(data)
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 unknown_date_format_to_julian(data)
53
+ def to_date(data)
58
54
  return data if data_missing_rows?(data)
59
- date = data[0][0]
60
- # formatted like: "2013-06-18"
61
- return date_to_julian(data) if date.is_a?(String) && date =~ /[0-9]{4}-[0-9]{2}-[0-9]{2}/
62
- # formatted like: "2456463"
63
- return julian_string_to_integer(data)
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 date_to_julian(data)
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
- nrow = row.dup
101
+ row = row.dup
74
102
  # string to date
75
- date = nrow[0]
76
- date = Date.parse(nrow[0]) if nrow[0].is_a?(String)
103
+ date = row[0]
104
+ date = Date.parse(row[0]) if row[0].is_a?(String)
77
105
  # date to julian
78
- nrow[0] = date.jd if date.respond_to?(:jd)
106
+ row[0] = date.jd if date.respond_to?(:jd)
79
107
  # save result
80
- result[index] = nrow
108
+ result[index] = row
81
109
  end
82
110
  # all done
83
111
  result
84
112
  end
85
-
86
- def julian_to_date(data)
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
- # dont alter by reference
89
- result = []
90
- # for each row
133
+ # otherwise cast string jds to int
134
+ output = []
91
135
  data.each_with_index do |row, index|
92
- # copy
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
- # all done
100
- result
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 julian_string_to_integer(data)
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?(Integer) || data[0][0].is_a?(Date)
157
+ return data if data_missing_rows?(data) || data[0][0].is_a?(Date)
106
158
  # otherwise cast string jds to int
107
- data.collect{|r| r[0] = r[0].to_i; r }
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) || !data[0][1].is_a?(String)
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 = transform_and_log( data, type )
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
@@ -1,5 +1,5 @@
1
1
  module Quandl
2
2
  module Operation
3
- VERSION = "0.1.23"
3
+ VERSION = "0.2.0"
4
4
  end
5
5
  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.hash( hash_data ).should eq array_data
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.csv( csv_data ).should eq array_data
20
+ subject.csv_to_array( csv_data ).should eq array_data
20
21
  end
21
22
 
22
23
  describe "#perform" do
23
- it "should handle csv_data" do
24
- subject.perform( csv_data ).should eq julian_data
25
- end
26
- it "should handle julian_data" do
27
- subject.perform( julian_data ).should eq julian_data
28
- end
29
- it "should handle hash_data" do
30
- subject.perform( hash_data ).should eq julian_data
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
- it "should handle array_data" do
33
- subject.perform( array_data ).should eq julian_data
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
- it "handles escaped csv_data" do
36
- subject.perform( escaped_csv ).should eq data_array
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.1.23
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-26 00:00:00.000000000 Z
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