Monday, January 26, 2009

The Poor Man’s Stock Quote Web Service

Ever wanted to programmatically fetch stock quotes? Ever look into it? I did. StrikeIron charges top dollar for their stock quote service, and, frankly, I don’t have that kind of money. But I can always go to finance.yahoo.com, and get the same information for free. Let’s exploit that, let’s create The Poor Man’s Stock Quote Web Service.

See it in action!

Using Windows Communication Foundation (Wcf), we will build a web service that takes a ticker symbol for a stock, grabs the text from the yahoo finance webpage, parses out the relevant stock quote information, and then returns a sweet StockQuote struct full of information. The legality of all this in a commercial application could probably be put to question, but we’ll leave that as an exercise for the reader.

Building a Wcf Service is very straightforward, and the source linked at the bottom is a Wcf sample perfect to introduce you to Wcf. This article isn’t an intro to Wcf, but if you’re quick, which I’m sure you are, you could pick it all up from the sample. See my other blog post to see how to host a Wcf service on a shared hosting plan.

First, we must define the ServiceContract for our Wcf Service:

[ServiceContract]    
public interface IStockQuoteService    
{    
    [OperationContract]    
    StockQuote GetQuote(string ticker);    
    [OperationContract]    
    List<StockQuote> GetQuotes(string[] tickers);    
}

As mentioned earlier, I’m going to use the Yahoo Finance to provide information for my Stock Quotes. Thus, the YahooStockService was born:

/// <summary>    
/// The Stock Quote Web Service that scrapes values from Yahoo's finance stock page.    
/// </summary>

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]    
public class YahooStockService : IStockQuoteService

In our Wcf service, we programmatically grab the text from a website using the HtmlScraper.GetPageContent function:

public static string GetPageContent(string url)    
{    
    WebRequest wreq = HttpWebRequest.Create(url);    
    WebResponse wres = wreq.GetResponse();    
    StreamReader sr = new StreamReader(wres.GetResponseStream());    
    string content = sr.ReadToEnd();    
    sr.Close();

    return content;    
}

Now that we have the page’s text, we can clumsily parse the text for the value that prefixes the content we are looking for. I usually break in my debugger, grab the Html page’s string value from the Watch window, and paste it in notepad. Then I look for the company name, and copy whatever’s in front of it.

Here is a simple example of the YahooStockService parsing for the Company Name:

private string ParseCompanyName(string page)    
{    
    // Regex pattern pasted from Html page.    
    Regex parseFor = new Regex("<div class=\"yfi_quote_summary\"><div class=\"hd\"><h1>");    
    return HtmlScraper.ParseContent(page, parseFor, "</h1>");    
}       


And now here’s the source. Many other parse functions exist in the sample, and we eventually end up with all the stock information we could need. Now go forth, poor one, and gather stock information to your heart’s content. At the time of this writing, it’s probably all going down anyways. GGgggooooo Bailout!

One note about the sample: it uses a Silverlight web app to consume the Wcf Service, you might need to install the Silverlight SDK.

References: Building a Web Service to Provide Real-Time Stock Quotes

No comments: