class GoogleFinance::HistoricalPrices

Constants

NUM_COLS
NUM_ROWS
STOCK_CLOSE
STOCK_HIGH
STOCK_LOW
STOCK_OPEN

xpath positions on which Google Finance returns the prices

STOCK_VOLUME

Attributes

stock_perf[R]

Public Class Methods

fix_date(input_date) click to toggle source

Input date should be in dd-mm-yyyy format

# File lib/GoogleFinance/HistoricalPrices.rb, line 109
def self.fix_date(input_date)

  months = %w{Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec}
  d = Date.strptime(input_date.to_s, "%Y-%m-%d") unless input_date.class == "Date"

  # add '+' between all paramters, and for some reason, the ',' is equal to %2C but won't
  #   escape to it using addresable, whatever, it works this way
  "#{months[d.mon - 1]}+#{d.day}%2C+#{d.year}"

end
google_date_to_ruby(input_date) click to toggle source

Take the Gooel date format, bring it in to YYYY-mm-dd

# File lib/GoogleFinance/HistoricalPrices.rb, line 122
def self.google_date_to_ruby(input_date)

  dump, mon, day, year = input_date.split(/(...) ([0-9]*), (....)/) 

  # change month to numerical stuff
  months = { "Jan" => 1, "Feb" => 2, "Mar" => 3, "Apr" => 4,
             "May" => 5, "Jun" => 6, "Jul" => 7, "Aug" => 8,
             "Sep" => 9, "Oct" => 10,"Nov" => 11, "Dec" => 12}
  mon = months[mon]
  mon = "0" + mon.to_s unless mon >= 10
  day = "0" + day.to_s unless day.to_i >= 10

  return  "#{year}-#{mon}-#{day}" 

end
new(ticker, date_start, date_end) click to toggle source
# File lib/GoogleFinance/HistoricalPrices.rb, line 20
def initialize(ticker, date_start, date_end)

  @ticker     = ticker
  @date_start = Date.strptime(date_start, "%Y-%m-%d")
  @date_end   = Date.strptime(date_end,   "%Y-%m-%d")
  @stock_perf = {}

  load_share_prices()

end

Public Instance Methods

extract_prices_from_page(page) click to toggle source
# File lib/GoogleFinance/HistoricalPrices.rb, line 59
def extract_prices_from_page(page)

  quote_dates  = []
  quote_close  = []
  quote_open   = []
  quote_high   = []
  quote_low    = []
  quote_volume = []

  # extract the dates
  dates = page.xpath("//td[@class='lm']")
  dates.each do |date|
    quote_dates.push(HistoricalPrices.google_date_to_ruby(date.content.gsub("\n","")))
  end

   # get the stock prices
   counter = 0
   figures = page.xpath("//td[@class='rgt']")
   figures.each do |figure|
    val = figure.content.gsub("\n", "")
    if    counter.modulo(GoogleFinance::HistoricalPrices::NUM_COLS)  == GoogleFinance::HistoricalPrices::STOCK_OPEN  then
      quote_open.push(val)
    elsif counter.modulo(GoogleFinance::HistoricalPrices::NUM_COLS) == GoogleFinance::HistoricalPrices::STOCK_HIGH  then
      quote_high.push(val)
    elsif counter.modulo(GoogleFinance::HistoricalPrices::NUM_COLS) == GoogleFinance::HistoricalPrices::STOCK_LOW   then
      quote_low.push(val)
    elsif counter.modulo(GoogleFinance::HistoricalPrices::NUM_COLS) == GoogleFinance::HistoricalPrices::STOCK_CLOSE then
      quote_close.push(val)
    end
    counter = counter + 1
  end

  # get the volumnes
  volumes = page.xpath("//td[@class='rgt rm']")
  volumes.each do |volume|
    quote_volume.push(volume.content.gsub("\n",""))
  end

  # we've extracted everything - build the share price hash
  for i in 0..(quote_dates.length - 1)
    @stock_perf[quote_dates[i]] = [quote_open[i], quote_high[i], quote_low[i], quote_close[i], quote_volume[i]]
  end

  @stock_perf

end
load_share_prices() click to toggle source

Load the historical prices in the internal hash

# File lib/GoogleFinance/HistoricalPrices.rb, line 33
def load_share_prices()
  #
  # build URL in the right format, in pages of 100 day quotes
  historical_url = @@URL_HIS + @ticker + "&startdate=" + HistoricalPrices.fix_date(@date_start) + 
                   "&enddate=" + HistoricalPrices.fix_date(@date_end) + "&num=#{NUM_ROWS}&start=0"
  page = Nokogiri::HTML(open(historical_url))

  # pagination element is in javascript, 9th script element in the page
  element   = page.search("script")[9]
  @rows     = element.text.scan(/applyPagination\(\n[0-9]+,\n[0-9]*,\n([0-9]+)/)[0].first.to_i
  num_calls = @rows / NUM_ROWS # we are going to make this many page calls to get all the data

  # first page is already acquired, don't make another call
  extract_prices_from_page(page)
  for i in 1..num_calls

    historical_url = @@URL_HIS + @ticker + "&startdate=" + HistoricalPrices.fix_date(@date_start) + 
                     "&enddate=" + HistoricalPrices.fix_date(@date_end) + "&num=#{NUM_ROWS}&start=#{i * NUM_ROWS}"
    page = Nokogiri::HTML(open(historical_url))
    extract_prices_from_page(page)
  end

end