Sunday, February 26, 2012

Fetching Stock Data From Yahoo For iOS Applications

Yahoo! provides a great service called Yahoo! Query Language (YQL) which provides a SQL-like interface to a whole bunch of Web services. YQL queries can also be performed via REST. A wide range of services can be accessed through YQL including Yahoo! Finance.


A convenient way to play with YQL and explore the available Web services, is to use the YQL Console. The bottom right of the console lists all the data tables, grouped by provider. (Be sure to click "Show Community Tables" to view all the available tables.) The yahoo provider includes the data table yahoo.finance.quote. This table provides access to stock quotes from Yahoo! Finance. As an example, here's the YQL console showing a query for stock data for AAPL. The console helpfully shows the REST URL for the query at the bottom.


Armed with the REST URL, it is trivial to write code in Objective-C/iOS to fetch quote data. Here's some code that takes in an NSArray of ticker symbols (NSStrings) and returns a NSDictionary with tickers as keys and quotes (realtime bid) as values.


#define QUOTE_QUERY_PREFIX @"http://query.yahooapis.com/v1/public/yql?q=select%20symbol%2C%20BidRealtime%20from%20yahoo.finance.quotes%20where%20symbol%20in%20("
#define QUOTE_QUERY_SUFFIX @")&format=json&env=store%3A%2F%2Fdatatables.org%2Falltableswithkeys&callback="

+ (NSDictionary *)fetchQuotesFor:(NSArray *)tickers
{
NSMutableDictionary *quotes;
if (tickers && [tickers count] > 0) {
NSMutableString *query = [[NSMutableString alloc] init];
[query appendString:QUOTE_QUERY_PREFIX];
for (int i = 0; i < [tickers count]; i++) {
            NSString *ticker = [tickers objectAtIndex:i];
            [query appendFormat:@"%%22%@%%22", ticker];
            if (i != [tickers count] - 1) [query appendString:@"%2C"];
        }
        [query appendString:QUOTE_QUERY_SUFFIX];
        // NSLog(@"Query: %@", query);
        NSData *jsonData = [[NSString stringWithContentsOfURL:[NSURL URLWithString:query] encoding:NSUTF8StringEncoding error:nil] dataUsingEncoding:NSUTF8StringEncoding];
        NSError *error = nil;
        NSDictionary *results = jsonData ? [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error] : nil;
        if (error) NSLog(@"[%@ %@] JSON error: %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), error.localizedDescription);
        // NSLog(@"[%@ %@] received %@", NSStringFromClass([self class]), NSStringFromSelector(_cmd), results);
        NSArray *quoteEntries = [results valueForKeyPath:@"query.results.quote"];
        quotes = [[NSMutableDictionary alloc] initWithCapacity:[quoteEntries count]];
        for (NSDictionary *quoteEntry in quoteEntries) {
            [quotes setValue:[quoteEntry valueForKey:@"BidRealtime"] forKey:[quoteEntry valueForKey:@"symbol"]];
        }
    }
    return quotes;
}

No comments: