quandl_operation 0.4.1 → 0.4.2.rc1

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.
@@ -2,4 +2,4 @@ require 'quandl/operation/core_ext/array'
2
2
  require 'quandl/operation/core_ext/date'
3
3
  require 'quandl/operation/core_ext/float'
4
4
  require 'quandl/operation/core_ext/string'
5
- require 'quandl/operation/core_ext/time'
5
+ require 'quandl/operation/core_ext/time'
@@ -1,22 +1,24 @@
1
1
  class Array
2
2
  def self.forwardable_methods
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]
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]
15
15
  end
16
+
16
17
  def average
17
- self.sum / self.count
18
+ sum / count
18
19
  end
20
+
19
21
  def extract_options
20
22
  last.is_a?(::Hash) ? last : {}
21
23
  end
22
- end
24
+ end
@@ -1,55 +1,53 @@
1
1
  class Date
2
-
3
2
  def start_of_frequency(freq)
4
3
  case freq.to_sym
5
4
  when :daily then self
6
- when :weekly then self.beginning_of_week
7
- when :monthly then self.beginning_of_month
8
- when :quarterly then self.beginning_of_quarter
9
- when :annual then self.beginning_of_year
10
- when :annually then self.beginning_of_year
5
+ when :weekly then beginning_of_week
6
+ when :monthly then beginning_of_month
7
+ when :quarterly then beginning_of_quarter
8
+ when :annual then beginning_of_year
9
+ when :annually then beginning_of_year
11
10
  else
12
11
  self
13
12
  end
14
13
  end
15
-
14
+
16
15
  def end_of_frequency(freq)
17
16
  case freq.to_sym
18
17
  when :daily then self
19
- when :weekly then self.end_of_week
20
- when :monthly then self.end_of_month
21
- when :quarterly then self.end_of_quarter
22
- when :annual then self.end_of_year
23
- when :annually then self.end_of_year
18
+ when :weekly then end_of_week
19
+ when :monthly then end_of_month
20
+ when :quarterly then end_of_quarter
21
+ when :annual then end_of_year
22
+ when :annually then end_of_year
24
23
  else
25
24
  self
26
25
  end
27
26
  end
28
-
29
- def ranging_until( date )
27
+
28
+ def ranging_until(date)
30
29
  self..date
31
30
  end
32
-
33
- def occurrences_of_frequency_ahead( occurrences, freq )
34
- occurrences_of_frequency_ago( occurrences.to_i * -1, freq )
31
+
32
+ def occurrences_of_frequency_ahead(occurrences, freq)
33
+ occurrences_of_frequency_ago(occurrences.to_i * -1, freq)
35
34
  end
36
35
 
37
- def occurrences_of_frequency_ago( occurrences, freq )
38
- occurrences_of_frequency( occurrences, freq )
36
+ def occurrences_of_frequency_ago(occurrences, freq)
37
+ occurrences_of_frequency(occurrences, freq)
39
38
  end
40
39
 
41
- def occurrences_of_frequency( occurrences, freq )
40
+ def occurrences_of_frequency(occurrences, freq)
42
41
  # ensure occurrences is an integer
43
42
  occurrences = occurrences.to_i
44
43
  case freq.try(:to_sym)
45
44
  when :weekly then self - occurrences.weeks
46
45
  when :monthly then self - occurrences.months
47
- when :quarterly then self - ( occurrences * 3 ).months
46
+ when :quarterly then self - (occurrences * 3).months
48
47
  when :annual then self - occurrences.years
49
48
  when :annually then self - occurrences.years
50
- else
49
+ else
51
50
  self - occurrences
52
51
  end
53
52
  end
54
-
55
- end
53
+ end
@@ -1,7 +1,5 @@
1
1
  class Float
2
-
3
2
  def microseconds
4
3
  (self * 1000.0).to_i
5
4
  end
6
-
7
- end
5
+ end
@@ -1,8 +1,10 @@
1
1
  class String
2
-
3
2
  def numeric?
4
3
  return true if self =~ /^\d+$/
5
- true if Float(self) rescue false
4
+ begin
5
+ true if Float(self)
6
+ rescue
7
+ false
8
+ end
6
9
  end
7
-
8
- end
10
+ end
@@ -1,8 +1,6 @@
1
1
  class Time
2
-
3
2
  class << self
4
-
5
- def log_elapsed(message=nil, &block)
3
+ def log_elapsed(message = nil, &block)
6
4
  timer = Time.now
7
5
  result = block.call
8
6
  message = "#{message} (#{timer.elapsed.microseconds}ms)"
@@ -10,56 +8,56 @@ class Time
10
8
  Quandl::Logger.info(message)
11
9
  result
12
10
  end
13
-
14
- def elapsed(message=nil, &block)
11
+
12
+ def elapsed(message = nil, &block)
15
13
  log_elapsed(message, &block)
16
14
  end
17
-
18
15
  end
19
-
16
+
20
17
  def week_from_beginning_to_end
21
- (self.beginning_of_week .. self.end_of_week)
18
+ (beginning_of_week..end_of_week)
22
19
  end
20
+
23
21
  def this_week?
24
- self.week_from_beginning_to_end.cover?(Time.now)
22
+ week_from_beginning_to_end.cover?(Time.now)
25
23
  end
26
24
 
27
25
  def month_from_beginning_to_end
28
- (self.beginning_of_month .. self.end_of_month)
26
+ (beginning_of_month..end_of_month)
29
27
  end
28
+
30
29
  def this_month?
31
- self.month_from_beginning_to_end.cover?(Time.now)
30
+ month_from_beginning_to_end.cover?(Time.now)
32
31
  end
33
32
 
34
33
  def round(seconds = 60)
35
- Time.at((self.to_f / seconds).round * seconds)
34
+ Time.at((to_f / seconds).round * seconds)
36
35
  end
37
36
 
38
37
  def floor(seconds = 60)
39
- Time.at((self.to_f / seconds).floor * seconds)
38
+ Time.at((to_f / seconds).floor * seconds)
40
39
  end
41
-
40
+
42
41
  def microseconds
43
- (self.to_f * 1000.0).to_i
42
+ (to_f * 1000.0).to_i
44
43
  end
45
-
46
- def self.elapsed(message=nil, &block)
44
+
45
+ def self.elapsed(message = nil, &block)
47
46
  timer = Time.now
48
47
  result = block.call
49
48
  puts "#{message} (#{timer.elapsed.microseconds}ms)"
50
49
  result
51
50
  end
52
-
51
+
53
52
  def elapsed
54
53
  elapsed_since(Time.now)
55
54
  end
56
-
55
+
57
56
  def elapsed_since(time)
58
57
  time - self
59
58
  end
60
-
59
+
61
60
  def elapsed_ms
62
61
  "#{elapsed.microseconds}ms"
63
62
  end
64
-
65
- end
63
+ end
@@ -1,22 +1,18 @@
1
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
2
+ module Operation
3
+ class QDate
4
+ class << self
5
+ def parse(value)
6
+ date = Date.jd(value.to_i) if value.is_a?(String) && value.numeric?
7
+ date = Date.jd(value) if value.is_a?(Integer)
8
+ date = Date.parse(value) if value.is_a?(String) && value =~ /^[0-9]{4}\-[0-9]{2}\-[0-9]{2}$/
9
+ date = value if value.is_a?(Date)
10
+ date = value.to_date if value.respond_to?(:to_date)
11
+ date
12
+ rescue
13
+ nil
14
+ end
15
+ end
16
16
  end
17
17
  end
18
-
19
18
  end
20
-
21
- end
22
- end
@@ -1,33 +1,29 @@
1
1
  module Quandl
2
- module Operation
3
- class Sort
4
-
5
- class << self
6
-
7
- def order?(data)
8
- return :none if data.blank? || data[0].blank? || data[1].blank?
9
- data[0][0] > data[1][0] ? :desc : :asc
10
- end
11
-
12
- def order(data, order = :asc)
13
- # ascending
14
- case order
15
- when :asc then data = sort_asc(data)
16
- when :desc then data = sort_desc(data)
17
- end
18
- data
19
- end
2
+ module Operation
3
+ class Sort
4
+ class << self
5
+ def order?(data)
6
+ return :none if data.blank? || data[0].blank? || data[1].blank?
7
+ data[0][0] > data[1][0] ? :desc : :asc
8
+ end
20
9
 
21
- def asc(data)
22
- data.sort_by{|r| r[0] }
23
- end
24
-
25
- def desc(data)
26
- data.sort_by{|r| r[0] }.reverse
10
+ def order(data, order = :asc)
11
+ # ascending
12
+ case order
13
+ when :asc then data = sort_asc(data)
14
+ when :desc then data = sort_desc(data)
15
+ end
16
+ data
17
+ end
18
+
19
+ def asc(data)
20
+ data.sort_by { |r| r[0] }
21
+ end
22
+
23
+ def desc(data)
24
+ data.sort_by { |r| r[0] }.reverse
25
+ end
26
+ end
27
27
  end
28
-
29
28
  end
30
-
31
- end
32
29
  end
33
- end
@@ -1,170 +1,164 @@
1
1
  module Quandl
2
- module Operation
2
+ module Operation
3
+ class Transform
4
+ class << self
5
+ def perform(data, type)
6
+ assert_valid_arguments!(data, type)
7
+ # nothing to do with an empty array
8
+ return data unless data.compact.present?
9
+ # original order
10
+ order = Sort.order?(data)
11
+ # operations expect data in ascending order
12
+ data = Sort.asc(data)
13
+ # transform
14
+ data = transform(data, type)
15
+ # return to original order
16
+ data = Sort.desc(data) if order == :desc
17
+ # onwards
18
+ data = Value.precision(data, 14)
19
+ data
20
+ end
3
21
 
4
- class Transform
5
-
6
- class << self
7
-
8
- def perform( data, type )
9
- assert_valid_arguments!(data, type)
10
- # nothing to do with an empty array
11
- return data unless data.compact.present?
12
- # original order
13
- order = Sort.order?(data)
14
- # operations expect data in ascending order
15
- data = Sort.asc(data)
16
- # transform
17
- data = transform( data, type)
18
- # return to original order
19
- data = Sort.desc(data) if order == :desc
20
- # onwards
21
- data = Value.precision(data, 14)
22
- data
23
- end
24
-
25
- def assert_valid_arguments!(data, type)
26
- raise ArgumentError, "data must be an Array. Received: #{data.class}" unless data.is_a?(Array)
27
- raise ArgumentError, "frequency must be one of #{valid_transformations}. Received: #{type}" unless valid?(type)
28
- end
29
-
30
- def valid_transformation?(type)
31
- valid?(type)
32
- end
33
-
34
- def valid?(type)
35
- valid_transformations.include?( type.try(:to_sym) )
36
- end
37
-
38
- def valid_transformations
39
- [ :diff, :rdiff, :cumul, :normalize, :rdiff_from ]
40
- end
41
-
42
- def transform( data, type)
43
- return data if data.blank?
44
- #Transforms table from actual data points
45
- #to differences between points (:diff)
46
- #or a ratio between points(:rdiff)
47
- #or a ratio between the latest point and an earlier point (:rdiff_from)
48
- #If type is other than these two, nothing is done.
49
-
50
- # ensure that type is in the expected format
51
- type = type.try(:to_sym)
52
- # nothing to do unless valid transform
53
- return data unless valid_transformation?( type )
54
-
55
- temparr = Array.new
56
- #first make a keylist
57
- keylist = data.transpose.first
58
- # now sort the keylist from oldest to newest
59
- # unless there is only one point
60
- if keylist.count > 1
61
- keylist = keylist.reverse if keylist[0] > keylist[1] # better performance if we do this first
62
- keylist.sort!
63
- end
22
+ def assert_valid_arguments!(data, type)
23
+ fail ArgumentError, "data must be an Array. Received: #{data.class}" unless data.is_a?(Array)
24
+ fail ArgumentError, "frequency must be one of #{valid_transformations}. Received: #{type}" unless valid?(type)
25
+ end
64
26
 
65
- #find number of columns
66
- numcols = data.first.size - 1
67
- if type == :normalize
68
- divisor = Array.new(numcols,nil)
69
- 0.upto(keylist.length - 1) do |i|
70
- temparr[i] = []
71
- curr_row = data[i][1..-1]
72
- 0.upto(numcols-1) do |x|
73
- if curr_row[x].nil?
74
- temparr[i][x] = nil
75
- elsif divisor[x].nil?
76
- if curr_row[x].to_f != 0
77
- divisor[x] = curr_row[x].to_f
78
- temparr[i][x] = 100.0
79
- else
80
- temparr[i][x] = 0
81
- end
82
- else
83
- temparr[i][x] = curr_row[x] / divisor[x] * 100.0
84
- end
85
- end
27
+ def valid_transformation?(type)
28
+ valid?(type)
86
29
  end
87
- 0.upto(keylist.length-1) do |i|
88
- data[i] = [keylist[i], temparr[i]].flatten
30
+
31
+ def valid?(type)
32
+ valid_transformations.include?(type.try(:to_sym))
33
+ end
34
+
35
+ def valid_transformations
36
+ [:diff, :rdiff, :cumul, :normalize, :rdiff_from]
89
37
  end
90
- elsif [:diff, :rdiff].include? type
91
- #now build temparr
92
- 1.upto(keylist.length - 1) do |i|
93
- temparr[i] = []
94
- curr_row = data[i][1..-1]
95
- prev_row = data[i-1][1..-1]
96
- 0.upto(numcols-1) do |x|
97
- if type == :diff
98
- if !curr_row[x].nil? and !prev_row[x].nil?
99
- temparr[i][x] = Float(curr_row[x]) - Float(prev_row[x])
100
- else
101
- temparr[i][x] = nil
38
+
39
+ def transform(data, type)
40
+ return data if data.blank?
41
+ # Transforms table from actual data points
42
+ # to differences between points (:diff)
43
+ # or a ratio between points(:rdiff)
44
+ # or a ratio between the latest point and an earlier point (:rdiff_from)
45
+ # If type is other than these two, nothing is done.
46
+
47
+ # ensure that type is in the expected format
48
+ type = type.try(:to_sym)
49
+ # nothing to do unless valid transform
50
+ return data unless valid_transformation?(type)
51
+
52
+ temparr = []
53
+ # first make a keylist
54
+ keylist = data.transpose.first
55
+ # now sort the keylist from oldest to newest
56
+ # unless there is only one point
57
+ if keylist.count > 1
58
+ keylist = keylist.reverse if keylist[0] > keylist[1] # better performance if we do this first
59
+ keylist.sort!
60
+ end
61
+
62
+ # find number of columns
63
+ numcols = data.first.size - 1
64
+ if type == :normalize
65
+ divisor = Array.new(numcols, nil)
66
+ 0.upto(keylist.length - 1) do |i|
67
+ temparr[i] = []
68
+ curr_row = data[i][1..-1]
69
+ 0.upto(numcols - 1) do |x|
70
+ if curr_row[x].nil?
71
+ temparr[i][x] = nil
72
+ elsif divisor[x].nil?
73
+ if curr_row[x].to_f != 0
74
+ divisor[x] = curr_row[x].to_f
75
+ temparr[i][x] = 100.0
76
+ else
77
+ temparr[i][x] = 0
78
+ end
79
+ else
80
+ temparr[i][x] = curr_row[x] / divisor[x] * 100.0
81
+ end
102
82
  end
103
- else
104
- if !curr_row[x].nil? and !prev_row[x].nil? and prev_row[x] != 0
105
- temparr[i][x] = ( Float(curr_row[x]) - Float(prev_row[x]) ) / Float( prev_row[x] )
106
- else
107
- temparr[i][x] = nil
83
+ end
84
+ 0.upto(keylist.length - 1) do |i|
85
+ data[i] = [keylist[i], temparr[i]].flatten
86
+ end
87
+ elsif [:diff, :rdiff].include? type
88
+ # now build temparr
89
+ 1.upto(keylist.length - 1) do |i|
90
+ temparr[i] = []
91
+ curr_row = data[i][1..-1]
92
+ prev_row = data[i - 1][1..-1]
93
+ 0.upto(numcols - 1) do |x|
94
+ if type == :diff
95
+ if !curr_row[x].nil? && !prev_row[x].nil?
96
+ temparr[i][x] = Float(curr_row[x]) - Float(prev_row[x])
97
+ else
98
+ temparr[i][x] = nil
99
+ end
100
+ else
101
+ if !curr_row[x].nil? && !prev_row[x].nil? && prev_row[x] != 0
102
+ temparr[i][x] = (Float(curr_row[x]) - Float(prev_row[x])) / Float(prev_row[x])
103
+ else
104
+ temparr[i][x] = nil
105
+ end
106
+ end
108
107
  end
109
108
  end
110
- end
111
- end
112
109
 
113
- #now put temparr into datapac
114
- 1.upto(keylist.length-1) do |i|
115
- data[i] = [keylist[i], temparr[i]].flatten
116
- end
117
-
118
- #delete the first date in datapac (because there is no diff for that)
119
- data.delete_at(0)
120
- elsif type == :rdiff_from
121
- num_rows = keylist.length - 1
122
- initial = Array.new(numcols,nil)
123
- num_rows.downto(0) do |i|
124
- temparr[i] = []
125
- curr_row = data[i][1..-1]
126
- 0.upto(numcols-1) do |x|
127
- if curr_row[x].nil?
128
- temparr[i][x] = nil
129
- elsif initial[x].nil?
130
- initial[x] = curr_row[x]
131
- temparr[i][x] = 0.0
132
- elsif curr_row[x] == 0
133
- temparr[i][x] = nil
134
- else
135
- temparr[i][x] = ( Float(initial[x]) - Float(curr_row[x]) ) / Float(curr_row[x])
110
+ # now put temparr into datapac
111
+ 1.upto(keylist.length - 1) do |i|
112
+ data[i] = [keylist[i], temparr[i]].flatten
136
113
  end
137
- end
138
- end
139
114
 
115
+ # delete the first date in datapac (because there is no diff for that)
116
+ data.delete_at(0)
117
+ elsif type == :rdiff_from
118
+ num_rows = keylist.length - 1
119
+ initial = Array.new(numcols, nil)
120
+ num_rows.downto(0) do |i|
121
+ temparr[i] = []
122
+ curr_row = data[i][1..-1]
123
+ 0.upto(numcols - 1) do |x|
124
+ if curr_row[x].nil?
125
+ temparr[i][x] = nil
126
+ elsif initial[x].nil?
127
+ initial[x] = curr_row[x]
128
+ temparr[i][x] = 0.0
129
+ elsif curr_row[x] == 0
130
+ temparr[i][x] = nil
131
+ else
132
+ temparr[i][x] = (Float(initial[x]) - Float(curr_row[x])) / Float(curr_row[x])
133
+ end
134
+ end
135
+ end
140
136
 
141
- 0.upto(keylist.length-1) do |i|
142
- data[i] = [keylist[i], temparr[i]].flatten
143
- end
144
- else
145
- cumulsum = Array.new(numcols,0)
146
- sumstarted = Array.new(numcols,false)
147
- #now build temparr
148
- 0.upto(keylist.length - 1) do |i|
149
- temparr[i] = []
150
- curr_row = data[i][1..-1]
151
- 0.upto(numcols-1) do |x|
152
- if !curr_row[x].nil?
153
- cumulsum[x] = cumulsum[x] + curr_row[x]
154
- sumstarted[x] = true
137
+ 0.upto(keylist.length - 1) do |i|
138
+ data[i] = [keylist[i], temparr[i]].flatten
139
+ end
140
+ else
141
+ cumulsum = Array.new(numcols, 0)
142
+ sumstarted = Array.new(numcols, false)
143
+ # now build temparr
144
+ 0.upto(keylist.length - 1) do |i|
145
+ temparr[i] = []
146
+ curr_row = data[i][1..-1]
147
+ 0.upto(numcols - 1) do |x|
148
+ unless curr_row[x].nil?
149
+ cumulsum[x] = cumulsum[x] + curr_row[x]
150
+ sumstarted[x] = true
151
+ end
152
+ temparr[i][x] = cumulsum[x] if sumstarted[x]
153
+ end
154
+ end
155
+ 0.upto(keylist.length - 1) do |i|
156
+ data[i] = [keylist[i], temparr[i]].flatten
155
157
  end
156
- temparr[i][x] = cumulsum[x] if sumstarted[x]
157
158
  end
158
- end
159
- 0.upto(keylist.length-1) do |i|
160
- data[i] = [keylist[i],temparr[i]].flatten
159
+ data
161
160
  end
162
161
  end
163
- data
164
162
  end
165
-
166
163
  end
167
-
168
- end
169
164
  end
170
- end