23Jul
2008

Tags: , ,

RubyNation is just a week and a half away and in order to prepare myself I thought I'd brush up on some Ruby and Rails in the days preceding the conference. I don't use Ruby on a regular basis, but I'm a huge fan of dynamic languages so I'm really looking forward to attending the conference and finding out what's new in the Ruby community.

By day I'm a Java developer, but I've also spent a fair amount of time studying Groovy. Learning Groovy has been my "training wheels" approach to understanding dynamic languages. Studying Groovy has helped me grasp new (new to me at least) concepts like Metaprogramming and Domain Specific Languages all from the comfort of my Java environment.

As a simple exercise I thought it would be interesting to rewrite the code from my last blog entry in Ruby to see how it compares to the Groovy code I originally wrote. So without further ado let's check out the code:

Authenticating with Google

In order to use the Google Finance API we need to first authenticate with Google by sending our Google Account username and password to Google's client login URL: https://www.google.com/accounts/ClientLogin.

def create_auth_token(username, password)
  https = Net::HTTP.new('www.google.com', 443)
  https.use_ssl = true
  path = '/accounts/ClientLogin'

  query_string = "Email=#{username}&Passwd=#{password}
                 &service=finance&source=company-groovyfinance-1.0"

  https.verify_mode = OpenSSL::SSL::VERIFY_NONE # don't display warnings

  response = https.post(path, query_string)

  if response.code == '200'
    return response.body[/Auth=(.*)/, 1] # The authorization token
  end

  return "Error"
end

In the code above we create an http object and give it the correct URI and path to Google's login service. We then send in a query string with our username, password, service, and source (application name). If everything succeeds Google returns an Authentication token which we will set in the headers in subsequent calls to Google's service.

This code isn't much different from the Groovy code in my previous entry, but I do like the way Ruby allows POST calls directly on the http object. This obsoletes the processRequest() method found in my Groovy code.

Creating a Portfolio

We can create a new portfolio in our Google Finance account by executing calls to the following method:

def create_portfolio(authorization_token, portfolio_name)
  headers={}
  headers["Authorization"] = "GoogleLogin auth=#{authorization_token}"
  headers["Content-Type"] = "application/atom+xml"

  http = Net::HTTP.new('finance.google.com')
  path = "/finance/feeds/default/portfolios"

  atom_string = "<?xml version='1.0'?>
  <entry xmlns='http://www.w3.org/2005/Atom'
         xmlns:gf='http://schemas.google.com/finance/2007'
         xmlns:gd='http://schemas.google.com/g/2005'>
         <title type='text'>#{portfolio_name}</title>
         <gf:portfolioData currencyCode='USD'/>
  </entry>"

  response = http.post(path, atom_string, headers)

  if response.code == '201'
    doc = REXML::Document.new(response.body)
    return doc.root.elements["id"].text[/portfolios\/(.*)/, 1] #portfolio id
  end

  return "Error"
end

This code is almost identical to the Groovy code I wrote last time but I do really like the way Ruby allows you to place header attributes into a Hash and send them directly with a call to http.post().

Placing an Order

Just like the example above, placing an order (stock trade) means that we need to create an Atom feed with our transaction attributes (transaction type, number of shares, etc.) and send them to a Google resource end point. This end point in our case is the URL of the specific portfolio in which we wish to place our new asset.

def create_stock_transaction(authorization_token, ticker_symbol,
                             number_of_shares, transaction_type, portfolio_id)

  headers={}
  headers["Authorization"] = "GoogleLogin auth=#{authorization_token}"
  headers["Content-Type"] = "application/atom+xml"

  http = Net::HTTP.new('finance.google.com')
  path = "/finance/feeds/default/portfolios/#{portfolio_id}/positions/" +
         "#{CGI::escape(ticker_symbol)}/transactions"

  transaction_time = Time.now.strftime("%Y-%m-%dT%H:%M:%S.000")

  atom_string = "<?xml version='1.0'?>
  <entry xmlns='http://www.w3.org/2005/Atom'
         xmlns:gf='http://schemas.google.com/finance/2007'
         xmlns:gd='http://schemas.google.com/g/2005'>
         <gf:transactionData date='#{transaction_time}'
             shares='#{number_of_shares}' type='#{transaction_type}' />
  </entry>"

  response = http.post(path, atom_string, headers)

  if response.code == '201'
    return response.body
  end

  return "Error"
end

Once again the Ruby code looks nearly identical to the Groovy code. We set the correct headers, generate a well formed Atom feed, and the post our data to Google. If all goes well, the transaction will be made and an Atom representation of the transaction will be returned to the client.

Groovy vs. Ruby Thoughts

There are probably "Rubyer" ways to write the code samples listed above, but I did find it interesting that the code I wrote in Ruby was so similar to the code that I wrote in Groovy. I'm not sure whether or not the similarities are due to the subjective nature of having the same programmer write both samples or if it's due to the fact that the languages are so similar to begin with.

Either way, exploring a new language (albeit a similar language) did give me some additional perspective. I found myself bouncing back and forth between the Groovy and Ruby code comparing how similar tasks were performed in each language. This type of information is always useful when trying to determine which technology is the right tool to use for a specific job.

In addition, studying Ruby helped me write better Groovy code. In the create_auth_token() method in the Ruby sample a regular expression is used to parse the authentication token from the returned string. I was able to take this regular expression code and apply it to the same method (createAuthToken()) in my Groovy code to improve its readability.

References


Download the Code

Google Data API Developers Guide
Google Finance Developers Guide
Google Finance Reference

Using Ruby with the Google Data APIs
REXML Guide

Disclaimer

Again... I am in no way endorsing any of the companies mentioned in this blog entry and all company references are for example purposes only.

Share and Enjoy:
  • Print
  • Digg
  • del.icio.us
  • Facebook
  • DZone
  • FSDaily
  • Reddit
  • Slashdot
  • StumbleUpon
  • Technorati
  • Twitter
  1. 15 Responses to “Putting Google Finance to REST with Ruby”

  2. Hey, this is good stuff. Thank you.

    By Scott Motte on Feb 17, 2009

  3. Thanks Scott!

    By Justin Spradlin on Feb 17, 2009

  4. Fantastic article. The only one I found with perfect examples that worked immediately! :) Thank You!

    By Oscar McSpeed on Apr 19, 2009

  5. Hey, Just wondering how I would get this to work. I am pretty clueless about coding but would like to get this installed on my website. It uses cpanel and the applications Ruby Gems and Ruby on Rails are installed. What do I do?

    Thanks every so much in advance
    regards

    By James D on Jul 30, 2009

  6. Hi James,
    I am in the process of creating a Ruby Gem for the google finance services. Be sure to keep track of my github account over the next month or so: http://github.com/jspradlin

    By Justin Spradlin on Jul 31, 2009

  7. Hi, Thats wonderful… Your stuff helped me a lot. I am stuck at creating portfolio, the method ‘create_portfolio(authorization_token, portfolio_name)’ is returning “error”. can you help.

    thank you,
    aashish

    By aashish on Oct 24, 2009

  8. Hey aashish,
    What error are you getting?

    If you are just trying to read items from your portfolio you can use the GMoney gem I created (http://github.com/jspradlin/gmoney)

    Just gem install gmoney

    I’m working on a version that allows you to create, update, and delete portfolios as we speak, but I don’t have an estimate as to when it will be done.

    By Justin Spradlin on Oct 24, 2009

  9. the ‘create_portfolio(authorization_token, portfolio_name)’ is returning “error”.

    How do I solve it.

    By aashish on Oct 30, 2009

  10. in the ‘create_portfolio(authorization_token, portfolio_name)’ method
    AT THE LINE
    response = http.post(path, atom_string, headers)
    I am not getting response.code=201 so it is returning error

    How do I solve it.

    By aashish on Oct 30, 2009

  11. Hello Aashish,
    Download the code using this link:
    http://www.justinspradlin.com/downloads/rubyfinance.zip

    Go to line 99, put in your Google username and password. If you do not have a google account you will need to create one (https://www.google.com/accounts/NewAccount)

    Open a command line and go to the directory where you extracted the code and run:
    ruby rubyfinance.rb

    I just tried it and it worked perfectly for me.

    If you are still having issues you can read the documentation from google:
    http://code.google.com/apis/finance/developers_guide_protocol.html

    By Justin Spradlin on Oct 31, 2009

  12. Thanks, It worked for me too..

    By aashish on Oct 31, 2009

  13. do you know how to develop installed application using fxruby to build google finance interface.

    By aashish on Oct 31, 2009

  14. Thank, for me its working well …

    By Thiyagarajan Veluchamy on Nov 20, 2009

  15. Thanks Thiyagarajan.

    I’ve also just finished a Beta version of a gem called GMoney. This gem wraps the google finance API and allows you to use simple Ruby code to interact with Google Finance. If you are interested you can check out the documentation at:

    http://github.com/jspradlin/gmoney

    By Justin Spradlin on Nov 20, 2009

  1. 1 Trackback(s)

  2. Jan 14, 2009: Bookmarks about Finance

Post a Comment