Class: Quandl::Operation::Collapse

Inherits:
Object
  • Object
show all
Defined in:
lib/quandl/operation/collapse.rb,
lib/quandl/operation/collapse/guess.rb

Defined Under Namespace

Classes: Guess

Class Method Summary collapse

Class Method Details

.assert_valid_arguments!(data, type) ⇒ Object



24
25
26
27
# File 'lib/quandl/operation/collapse.rb', line 24

def assert_valid_arguments!(data, type)
  fail ArgumentError, "data must be an Array. Received: #{data.class}" unless data.is_a?(Array)
  fail ArgumentError, "frequency must be one of #{valid_collapses}. Received: #{type}" unless valid?(type)
end

.collapse(data, frequency) ⇒ Object



41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
# File 'lib/quandl/operation/collapse.rb', line 41

def collapse(data, frequency)
  return data unless valid_collapse?(frequency)

  # Special scenario where we are only fetching the `date` column
  date_column_only = data.count > 0 && data[0].count == 1

  # store the new collapsed data
  collapsed_data = {}
  range = find_end_of_range(data[0][0], frequency)

  # iterate over the data
  data.each do |row|
    # grab date and values
    date = row[0]
    value = row[1..-1]
    value = value.first if value.count == 1

    # bump to the next range if it exceeds the current one
    range = find_end_of_range(date, frequency) unless inside_range?(date, range)

    # consider the value for the next range
    next unless inside_range?(date, range) && (value.present? || date_column_only)
    value = merge_row_values(value, collapsed_data[range]) unless collapsed_data[range].nil?
    # assign value
    collapsed_data[range] = value
  end

  to_table(collapsed_data)
end

.collapses_greater_than(freq) ⇒ Object



92
93
94
95
96
# File 'lib/quandl/operation/collapse.rb', line 92

def collapses_greater_than(freq)
  return [] unless freq.respond_to?(:to_sym)
  index = valid_collapses.index(freq.to_sym)
  index.present? ? valid_collapses.slice(index + 1, valid_collapses.count) : []
end

.collapses_greater_than_or_equal_to(freq) ⇒ Object



98
99
100
101
# File 'lib/quandl/operation/collapse.rb', line 98

def collapses_greater_than_or_equal_to(freq)
  return [] unless freq.respond_to?(:to_sym)
  valid_collapses.slice(valid_collapses.index(freq.to_sym), valid_collapses.count)
end

.find_each_index(array, find) ⇒ Object



115
116
117
118
119
120
121
122
123
124
125
126
127
# File 'lib/quandl/operation/collapse.rb', line 115

def find_each_index(array, find)
  found = -1
  index = -1
  q = []
  while found
    found = array[index + 1..-1].index(find)
    if found
      index = index + found + 1
      q << index
    end
  end
  q
end

.find_end_of_range(date, frequency) ⇒ Object



111
112
113
# File 'lib/quandl/operation/collapse.rb', line 111

def find_end_of_range(date, frequency)
  date.end_of_frequency(frequency)
end

.frequency?(data) ⇒ Boolean

Returns:

  • (Boolean)


103
104
105
# File 'lib/quandl/operation/collapse.rb', line 103

def frequency?(data)
  Guess.frequency(data)
end

.inside_range?(date, range) ⇒ Boolean

Returns:

  • (Boolean)


107
108
109
# File 'lib/quandl/operation/collapse.rb', line 107

def inside_range?(date, range)
  date <= range
end

.merge_row_values(top_row, bottom_row) ⇒ Object



81
82
83
84
85
86
87
88
89
90
# File 'lib/quandl/operation/collapse.rb', line 81

def merge_row_values(top_row, bottom_row)
  # merge previous values when nils are present
  if top_row.is_a?(Array) && top_row.include?(nil)
    # find nil indexes
    indexes = find_each_index(top_row, nil)
    # merge nils with previous values
    indexes.each { |index| top_row[index] = bottom_row[index] }
  end
  top_row
end

.perform(data, type) ⇒ Object



8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
# File 'lib/quandl/operation/collapse.rb', line 8

def perform(data, type)
  assert_valid_arguments!(data, type)
  # nothing to do with an empty array
  return data unless data.compact.present?
  # source order
  order = Sort.order?(data)
  # operations expect data in ascending order
  data = Sort.asc(data)
  # collapse
  data = collapse(data, type)
  # return to original order
  data = Sort.desc(data) if order == :desc
  # onwards
  data
end

.to_table(data) ⇒ Object



71
72
73
74
75
76
77
78
79
# File 'lib/quandl/operation/collapse.rb', line 71

def to_table(data)
  data.collect do |date, values|
    if values.is_a?(Array)
      values.unshift(date)
    else
      [date, values]
    end
  end
end

.valid?(type) ⇒ Boolean

Returns:

  • (Boolean)


33
34
35
# File 'lib/quandl/operation/collapse.rb', line 33

def valid?(type)
  valid_collapses.include?(type.try(:to_sym))
end

.valid_collapse?(type) ⇒ Boolean

Returns:

  • (Boolean)


29
30
31
# File 'lib/quandl/operation/collapse.rb', line 29

def valid_collapse?(type)
  valid?(type)
end

.valid_collapsesObject



37
38
39
# File 'lib/quandl/operation/collapse.rb', line 37

def valid_collapses
  [:daily, :weekly, :monthly, :quarterly, :annual]
end