class Quandl::Operation::Transform

Public Class Methods

assert_valid_arguments!(data, type) click to toggle source
# File lib/quandl/operation/transform.rb, line 22
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_transformations}. Received: #{type}" unless valid?(type)
end
perform(data, type) click to toggle source
# File lib/quandl/operation/transform.rb, line 5
def perform(data, type)
  assert_valid_arguments!(data, type)
  # nothing to do with an empty array
  return data unless data.compact.present?
  # original order
  order = Sort.order?(data)
  # operations expect data in ascending order
  data = Sort.asc(data)
  # transform
  data = transform(data, type)
  # return to original order
  data = Sort.desc(data) if order == :desc
  # onwards
  data = Value.precision(data, 14)
  data
end
transform(data, type) click to toggle source
# File lib/quandl/operation/transform.rb, line 39
def transform(data, type)
  return data if data.blank?
  # Transforms table from actual data points
  # to differences between points (:diff)
  # or a ratio between points(:rdiff)
  # or a ratio between the latest point and an earlier point (:rdiff_from)
  # If type is other than these two, nothing is done.

  # ensure that type is in the expected format
  type = type.try(:to_sym)
  # nothing to do unless valid transform
  return data unless valid_transformation?(type)

  temparr = []
  # first make a keylist
  keylist = data.transpose.first
  # now sort the keylist from oldest to newest
  # unless there is only one point
  if keylist.count > 1
    keylist = keylist.reverse if keylist[0] > keylist[1] # better performance if we do this first
    keylist.sort!
  end

  # find number of columns
  numcols = data.first.size - 1
  if type == :normalize
    divisor = Array.new(numcols, nil)
    0.upto(keylist.length - 1) do |i|
      temparr[i] = []
      curr_row = data[i][1..-1]
      0.upto(numcols - 1) do |x|
        if curr_row[x].nil?
          temparr[i][x] = nil
        elsif divisor[x].nil?
          if curr_row[x].to_f != 0
            divisor[x] = curr_row[x].to_f
            temparr[i][x] = 100.0
          else
            temparr[i][x] = 0
          end
        else
          temparr[i][x] = curr_row[x] / divisor[x] * 100.0
        end
      end
    end
    0.upto(keylist.length - 1) do |i|
      data[i] = [keylist[i], temparr[i]].flatten
    end
  elsif [:diff, :rdiff].include? type
    # now build temparr
    1.upto(keylist.length - 1) do |i|
      temparr[i] = []
      curr_row = data[i][1..-1]
      prev_row = data[i - 1][1..-1]
      0.upto(numcols - 1) do |x|
        if type == :diff
          if !curr_row[x].nil? && !prev_row[x].nil?
            temparr[i][x] = Float(curr_row[x]) - Float(prev_row[x])
          else
            temparr[i][x] = nil
          end
        else
          if !curr_row[x].nil? && !prev_row[x].nil? && prev_row[x] != 0
            temparr[i][x] = (Float(curr_row[x]) - Float(prev_row[x])) / Float(prev_row[x])
          else
            temparr[i][x] = nil
          end
        end
      end
    end

    # now put temparr into datapac
    1.upto(keylist.length - 1) do |i|
      data[i] = [keylist[i], temparr[i]].flatten
    end

    # delete the first date in datapac (because there is no diff for that)
    data.delete_at(0)
  elsif type == :rdiff_from
    num_rows = keylist.length - 1
    initial = Array.new(numcols, nil)
    num_rows.downto(0) do |i|
      temparr[i] = []
      curr_row = data[i][1..-1]
      0.upto(numcols - 1) do |x|
        if curr_row[x].nil?
          temparr[i][x] = nil
        elsif initial[x].nil?
          initial[x] = curr_row[x]
          temparr[i][x] = 0.0
        elsif curr_row[x] == 0
          temparr[i][x] = nil
        else
          temparr[i][x] = (Float(initial[x]) - Float(curr_row[x])) / Float(curr_row[x])
        end
      end
    end

    0.upto(keylist.length - 1) do |i|
      data[i] = [keylist[i], temparr[i]].flatten
    end
  else
    cumulsum = Array.new(numcols, 0)
    sumstarted = Array.new(numcols, false)
    # now build temparr
    0.upto(keylist.length - 1) do |i|
      temparr[i] = []
      curr_row = data[i][1..-1]
      0.upto(numcols - 1) do |x|
        unless curr_row[x].nil?
          cumulsum[x] = cumulsum[x] + curr_row[x]
          sumstarted[x] = true
        end
        temparr[i][x] = cumulsum[x] if sumstarted[x]
      end
    end
    0.upto(keylist.length - 1) do |i|
      data[i] = [keylist[i], temparr[i]].flatten
    end
  end
  data
end
valid?(type) click to toggle source
# File lib/quandl/operation/transform.rb, line 31
def valid?(type)
  valid_transformations.include?(type.try(:to_sym))
end
valid_transformation?(type) click to toggle source
# File lib/quandl/operation/transform.rb, line 27
def valid_transformation?(type)
  valid?(type)
end
valid_transformations() click to toggle source
# File lib/quandl/operation/transform.rb, line 35
def valid_transformations
  [:diff, :rdiff, :cumul, :normalize, :rdiff_from]
end