01Feb
2010

Tags: , , ,

Update March 03, 2010:

Due to changes in the Google Finance API only GMoney gem versions >= 0.4.3 are working. If you run gem update gmoney to get the latest version or install the gem from scratch you will be fine.

Let’s pretend the year is 2007 and I have a close “friend” who is really excited about the upcoming 2010 World Cup. My friend is not too naive and realizes that airfare to Africa, lodging, tickets to the games, and Safaris are all very expensive. My friend has a little extra cash to save each month and with a three year time horizon he figures he can stow away a little money in a moderately aggressive mutual fund in order to take advantage of some growth opportunities.

Unfortunately for my friend the next two years would be some of the worst the world economy has ever seen. Like many people, my friend took a bath on his investments and his hopes and dreams of going to the World Cup went down the drain along with his money.

It’s too bad my friend didn’t keep better track of his investments. Perhaps if he had he could have pulled his money out of the stock market and salvaged his vacation. Since my friend is an avid Ruby lover I figured I’d help make sure he doesn’t end up in this situation ever again. That’s why I wrote GMoney, a RubyGem for interacting with the Google Finance API.

Background

The Google Finance API allows users to interact with Google Finance and can help developers programmatically “request a list of a user’s portfolios, retrieve performance and return statistics on an existing portfolio, query the positions and transactions in a portfolio, and create new portfolios and transactions.”

GMoney is a wrapper for this API and allows developers to take advantage of the API’s functionality using the Ruby programming language. To minimize the learning curve I tried to give GMoney an interface similar to that of ActiveRecord so that developers would have a familiar starting point.

Google Finance Model

The Google Finance model is pretty simple. It is made up of the following three entities:

Portfolios

A portfolio is a collection of positions that the user holds in various securities, plus metadata. Each portfolio entry contains the portfolio’s title along with data such as currency and total market value. Each portfolio entry also contains a link to the portfolio’s position feed (i.e. a Portfolio “has_many” Positions).

Positions

A position is a collection of information about a security that the user holds. Each position entry contains the ticker exchange and symbol for a stock, mutual fund, or other security, along with the number of units of that security that the user holds. Each position entry also contains a link to the position’s transaction feed (i.e. a Position “has_many” Transactions).

You can’t directly create or update position entries; positions are derived from transactions.

Transactions

A transaction is a collection of information about an instance of buying or selling a particular security. Each transaction entry contains a transaction type (such as buy or sell), a number of units, the price, and so on.

Installation

To install GMoney simply run the following command:

gem install gmoney

Login

You will need a Google account in order to use the Google Finance API. Once you have obtained an account you can login via GMoney using the following code:

require 'rubygems'
require 'gmoney'

GMoney::GFSession.login('<YOUR GOOGLE USER ID>','<YOUR GOOGLE PASSWORD>')

Create a portfolio

If you were to login to Google Finance for the first time using a browser you would see the following screen showing the default Google Finance Portfolio called “My Portfolio”:

Create Portfolio

To create your own Portfolio using GMoney use the following code:

portfolio = GMoney::Portfolio.new
portfolio.title = "My New Ruby Portfolio"
portfolio.save

After executing the code and refreshing the browser you should see that the “My New Ruby Portfolio” has been created.

Create Portfolio

Create a transaction(s)

As mentioned above transactions are used to buy and sell stocks within a given portfolio. The positions within your portfolio will be based on the transaction information. Running the following code will buy shares of Apple, Red Hat, Google, and Microsoft and place them into your portfolio:

stocks = {"NASDAQ:GOOG" => 529.00, 
          "NASDAQ:AAPL" => 192.00, 
          "NYSE:RHT" => 27.00, 
          "NASDAQ:MSFT" => 28.00}
 
stocks.each do |symbol, price| 
  transaction = GMoney::Transaction.new
  #pid is the human readable id of the portfolio created above
  transaction.portfolio = portfolio.pid
  transaction.type = GMoney::BUY
  transaction.shares = 50
  transaction.ticker = symbol
  transaction.price = price  
  transaction.save
end

The result of running the code is as follows:

Create Portfolio

Update Transaction

If you actually meant to buy 100 shares of Goolge instead of 50 you can update the transaction using the following code:

#I know the transaction id is '4'
transaction = GMoney::Transaction.find "#{portfolio.pid}/NASDAQ:GOOG/4"
transaction.shares = 100
transaction.save

The result:

Create Portfolio

Delete Transaction

We can delete a transaction like so:

GMoney::Position.find("#{portfolio.pid}/NASDAQ:MSFT").delete

Now we have no more MSFT stock:

Create Portfolio

Reading all the Positions in a Porfolio

If we’d like to see all of the positions within our portfolio we can execute this code:

portfolio.positions.each do |position| 
  puts position.title
end

Output:

Red Hat, Inc.
Apple Inc.
Google Inc.

Gotcha

There is a bit of a “gotcha” right now with the Google Finance API. For whatever reason, stock returns information is not being sent by Google. I figured it was something I was doing wrong in my code, but then I used Google’s official API client and was still unable to retrieve the returns data. I’ll be sure to file a bug report with Google over the next few days.

Conclusion

GMoney offers a lot more features than what has been written about here. Be sure to check out the documentation and the source code on Github. The full script of the code used for this blog entry can also be found on Github.

Overall building GMoney was an incredible learning experience. It was my first significant Ruby project and also my first Open Source project. As of today GMoney has been downloaded almost 200 times. I’ve tested GMoney on Windows and Linux using Ruby versions 1.8.6, 1.8.7, and 1.9.1 (via RVM). Feedback and bug reports are more than welcome.

With GMoney in place my friend will be sure to keep much better track of his investments and is looking forward to the 2014 World Cup in Brazil.

Disclaimer: 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. 18 Responses to “Introducing GMoney – A RubyGem for Interacting with the Google Finance API”

  2. A good start, and a great idea. I don’t see how to download current market information from the portfolio, however — the attribute market_value, returns ‘nil’. Perhaps there’s a method that needs to be called?

    By NG540 on Feb 1, 2010

  3. @NG540

    Thanks for the comment.

    You can get the current market_value information by setting the “returns” option to true. i.e.:

    #Where 22 is your portfolio id
    port = GMoney::Portfolio.find(22, :returns => true)

    #returns a value assuming there are positions in your portfolio
    port.market_value

    By Justin Spradlin on Feb 1, 2010

  4. Oh, I see from the GitHub README. If I call ‘find’ on a particular position, such as position = GMoney::Position.find(“9/NASDAQ:GOOG”), the market value is available as an attribute of the returned position object.
    Question: If I obtain an array of the positions in a particular portfolio through positions = portfolio.positions (or positions = GMoney::Position.find(9)), can I iterate through the positions to obtain the market_value for each, or do I have to call ‘find’ on each position feed?
    Thanks so much — I’m almost where I need to be. Sorry for all the questions…

    By NG540 on Feb 2, 2010

  5. @NG540

    You just need to specify the :returns parameter in your calls. For example:

    positions = GMoney::Position.find(22, :returns => true)
    positions.each { |p| puts “#{p.title} #{p.market_value}” }

    #Output
    Google Inc. 26468.5
    Freddie Mac 119.0

    or

    port = GMoney::Portfolio.find 22
    positions = port.positions(:returns => true)
    positions.each { |p| puts “#{p.title} #{p.market_value}” }

    #Output
    Google Inc. 26497.5
    Freddie Mac 120.0

    By Justin Spradlin on Feb 2, 2010

  6. That works! Thanks!
    Now, if only there were a simple way to suppress the printing of the object.inspect strings returned with the various method calls – this string is typically long and not all that informative. A user could always overwrite the ‘.to_s’ method in the GMoney class, but that seems like an awkward hack.
    Once again, great project! One nice application would be to run a GMoney program automatically every day, storing the results in a series of timestamped data files, for later review and statistical analysis at the user’s leisure.

    By NG540 on Feb 2, 2010

  7. excellent, I’ve been looking for a way to pull data and do what I want with it for awhile

    By Source on Feb 2, 2010

  8. @NG540
    I can provide a to_s method in the next release for the Portfolio, Position, and Transaction classes.

    Thanks for all of the feedback. Let me know if you come up with any cool projects using GMoney. Enjoy!

    By Justin Spradlin on Feb 2, 2010

  9. Looks like a great gem. One question, is it possible to create the transaction without prefacing NYSE or NASDAQ in front (is it smart enough to recognize which exchange the stock is in)? Or is there a method to look this up with your Gmoney api?

    By Scotty Motte on Jun 24, 2010

  10. @Scott

    I tried creating a transaction by using the ticker symbol of a company without the market it trades on. For example I used:

    transaction.ticker = ‘GOOG’

    instead of:

    transaction.ticker = ‘NASDAQ:GOOG’

    It did throw a transaction save error when I saved it, but it looks like it did create the transaction in my google portfolio.

    Looks like a bug/feature that I should look to improve with gmoney.

    Thanks for the feedback.

    By Justin Spradlin on Jun 24, 2010

  11. That’s a great gem for ruby. Can I program an app that uses this plug in to get information about financial information from a specific stock such as net income, current asset, etc?

    By Chim Kan on Aug 3, 2010

  12. Hi Chim,
    The GMoney gem can basically be used to manage a mock stock portfolio using Google Finance as a back end. It can be used to “buy” and “sell” assets and track their performance. The exact data made available through this gem (and the Google Finance API) can be found here: http://code.google.com/apis/finance/docs/2.0/reference.html

    By Justin Spradlin on Aug 4, 2010

  13. I’ve got 2 existing portfolios under an Google Apps account. The pid in the URL for one of the portfolios is 2, but I GMoney::Portfolio.all returns nothing (and Portfolio.all.size returns 0). I assume the Gem works with existing portfolios. Am I doing something wrong?

    By Luke Hartman on Sep 23, 2010

  14. Hey Luke,
    Are you sure that you are logging in correctly? I just ran the following script and everything worked fine. Also, have you updated to the latest version of the gem (0.4.4)?

    require ‘rubygems’
    require ‘gmoney’

    GMoney::GFSession.login(‘‘,’‘)

    GMoney::Portfolio.all

    By Justin Spradlin on Sep 25, 2010

  15. Justin,

    Yes, I just installed the gem before my comment and it’s 0.4.4. When I login, I get a long string returned (what I assume is a token) but no portfolios (just []).

    I’ll keep playing with it to see what’s going on, but I double-checked the login in a browser, and it shows two portfolios.

    By Luke Hartman on Sep 27, 2010

  16. Luke,
    You mentioned that you are using “Google Apps” in your first comment. Have you tried using this gem with the regular Google finance page (http://www.google.com/finance)?

    By Justin Spradlin on Sep 27, 2010

  17. 1) Can GMoney be used to download historic stock price data for an array of Tickers?
    2) Is there a good way to get in touch with you about help on contractual basis to build out GMoney in certain ways?

    By NG540 on Oct 19, 2010

  1. 2 Trackback(s)

  2. Feb 4, 2010: Caffeine Driven Development » Blog Archive » L33t Links #76
  3. Feb 14, 2010: Ennuyer.net » Blog Archive » Rails Reading February 14 2010

Post a Comment