Innocence

I am building a finance app for iOS. For production we plan to pay big bucks to a commercial data service for stock and option information but, until then, I need to build a ui, work out all the asynchronous data acquisition, and do some research to bulk up my finance domain knowledge. So, before the big bucks start to flow to that data service I need to get information using something else, a free something else, and I chose to use the Google Finance API. I made that choice knowing it was to be shut down last year, yes last year:

We were using the Yahoo Finance API to get stock price information. That was pretty straightforward, but I needed option chain information and I found the Yahoo methods to be very (very, very) slow. The Google API was very (very, very) fast, so I opted for Google, thinking it would better represent the access speed I would get with the big bucks service. I might be able to find a better way to use Yahoo but this Google api only needs to hang in there for another month or so until our beta is ready.

Writing the fetch code using the Google API was not difficult:

Parsing the results was another story. Normally you would do something like this to access the data:

Disappointment

If you didn’t have the presence of mind to test the optionChainString with isValidJSONObject you would be unpleasantly surprised. It seems that the dictionary keys returned in the json are not double quoted and thus, are not read as NSString – a requirement for NSJSONSerialization. What to do… why, StackOverflow of course! With apologies to the Correct Answer Man since I can’t seem to re-find this posting, the solution is to use a regular expression to add the quotes to the keys before processing with JSONObjectWithData:

Success

Now, if you had the presence of mind to add that isValidJSONObject check this time, you would be surprised to see that it is still invalid! But I don’t care – it parses just fine – so I move on.

This is the data we now have using the symbol, BGG, which I think is Briggs & Stratton, they make gas engines for things like lawn mowers:

What we have is a dictionary with six keys; puts, calls, expirations, expiry, underlying\_id, and underlying\_price. I removed much of the puts and calls arrays to shorten the text. Here’s a rundown on the meaning of the put and call keys:

Now I have what I need and can parse this data into my own data structures. With the data source squared away, I spent a lot of time implementing the flow and layout provided by our excellent designer, Josh. Life was good, too good.

Near Death Experience

It wasn’t until weeks later, when I was way down the road of testing the user interface that I realized that the option information available was only for the most recent expiry date. I had made a bad assumption; Yahoo requests returned all option data for all expiry dates so I assumed that Google did as well. Remember one of those six top-level keys called, “expiry”? Turns out that this key tells us that the put and call data is for this expiry date only. You cannot request all put and call data at once. If you look at the option codes for all the puts and calls above, (including the ones I removed for brevity) you will see, BGG140719, or, expiry=Jul 19, 2014. In my test app there were a dozen or so expiry dates that had no option data at all! It was absolutely critical that I have the rest of that data or the app would be useless, unable to provide even a demo for an option trader. I was feeling the cold fist of failure reaching inside my body to tear out my heart.

Perseverence

I held my dog and cried a little, but then I straightened up, wiped my face with my dog and leapt into action. There has to be something on the internet somewhere that describes how to use the Google api to get date-based option information.

Nada.

I had to get creative. StackOverflow had failed me, so now I’m going to have to think for myself. Ouch.

How do you format the query string to request a particular month? The query string I used had no date information. It is simply default behavior that the server returns the put/call data for the earliest expiry date. What about that web page that always comes up when I do a Google search for “Google finance options”?

Can I use Charles to nab the request url that page uses to get its data? If you don’t use Charles and you are interested in this topic, you should be using Charles:

If you do have Charles you can see for yourself that changing the expiry date on that google.com page/finance page issues this request:

I think that’s what we are looking for, expd, expm, and expy. But what are cid and that ugly hashy looking thing, ei? Do I need those? Well, I recognize cid, that’s in the put/call information, so I’ll try that. Ugly hashy thing, I’ll just take it out to see if it still works – it does. So I can hack the url to see if it returns option info for a different expiry date using the BGG cid, a new date from the expirations list, and no ei param:

It doesn’t work. Sh*t! But that cid looks pretty funny. It’s, what, 28 trillion and something? The AAPL cid was only 5 digits, 22144. I have the AAPL data downloaded from the test request. It’s in TextMate. Easy to do a cmd-F to search the page for 22144. There it is. Remember underlying\_id? underlying\_id:22144. For BGG, that’s underlying\_id:4755 (do cmd-F on this page and you will find it just like I did). Substitute 4755 as the cid:

Vindication

And, bingo! The put/call results for January 1, 2015 (abridged):

Iterate across the expirations array to get it all, or just get it for one date when you need it. And, by the way, you can substitute q=BGG instead of cid=4755. Same result.

There you have it. Now you know as much as I do about the Google Finance API. It is still ticking, but for how long?