Introduction
YMD is a Web User Control that encaspulates the ability to view (delayed) market data from Yahoo utilising market symbols and Yahoo's tags. Note that all prices are delayed and this link lists all of the delays. It is possible to retrieve real time quotes but that is a premium service and beyond the scope of this article.
Background
Given the current financial climate I found that I was forever looking at Yahoo, the BBC and a variety of other sites to see what is going on. I realise that other people have also trodden this path and have done so very well; however, I felt there was room for another take on the subject and, so, here it is.
Usage
This is the basic process:
- populate the config file so that YMD knows which symbols to query.
- read the config file
- create a Uri that Yahoo will use to generate data
- retrieve the returned data from Yahoo
- parse the data into a grid view and display
The config file is a simple Xml file which contains 2 sections, 'Settings' and 'Tickers'.
'Settings' contains items required to connect to Yahoo, set which data column items are returned and to denote whether or not to display the Exchanges column. I have chosen to gather all of this data (and that from the following section) using a DataSet object for simplicity. It has the benefit of automatically breaking out sections into constituent DataTable objects: quite easy to manipulate and from which the data can be gathered very simply and with a minimum of code.
'Tickers' contains a list of all the symbols you wish to pass to Yahoo to gather data. Note that these symbols may return garbage or unexpetced results unless you verify that they are the ones used by Yahoo. To check this go to your national Yahoo finance section and view the data for the symbol you have an interest in. Yahoo will always display the symbol it would expect to see; usually as part of the header line for a quote, as below:
Generally you require the text after the exchange; in this case 'LSE' is the exchange (London Stock Exchange) and 'HBOS.L' is the symbol you will need to pass to Yahoo. Markets are usually prefixed with ^ (example) and FX usually looks like CURR1CURR2=X (example). Note it is up to you to check and verify that you are passing the correct symbol.
A typical Ticker (symbol) entry might look like
<Ticker symbol="GBPUSD=X" caption="GBP to USD" />
The 'caption' element contains the string to display in the GridView in place of the symbol. You can put anything here that you want but remember that certain characters (like '&') require special treatment ('&' should be '&'). To add a header prefix both symbol and caption with a '~'.
At its simplest:
DataSet ds = new DataSet();
ds.ReadXml(XMLPath);
gvYahoo.DataSource = GetData();
gvYahoo.DataBind();
ds.Dispose();
A Uri needs to be constructed by taking the BaseUrl and Tags data and combining those with the Tickers from the config file as:
private static Uri Connector
{
get
{
string uri =
string.Format(
CultureInfo.InvariantCulture,
@"{0}{1}{2}",
GetSetting("BaseUrl"),
Tickers(),
GetSetting("Tags"));
return new Uri(uri);
}
}
In this case GetSetting() returns data for a specific element and Tickers() compiles a list of symbols to pass to Yahoo.
The symbols are gathered through:
StringBuilder sb = new StringBuilder();
DataTable table = ds.Tables["Ticker"];
foreach (DataRow row in table.Rows)
{
sb.Append(row[0]);
}
return sb.ToString();
As can be seen the Tickers section is treated as a DataTable extracted from the DataSet and then each row is parsed to extract the symbol and appended to a StringBuilder object. This is what is used in the Connector property above to create the Uri as per the following sample:
http:
You can copy and paste the above into a browser to see what Yahoo returns and also to see that I have used the fact that Yahoo will return a valid if zero row for '~FX' which I can then use to create a header for each section (as ~ means nothing to Yahoo). You can also play around with the tags to see what else can be returned.
At this point I can now 'send' my Uri to Yahoo using a WebResponse object and applying a StreamReader to the response to read the incoming data stream.
WebResponse webResponse = GetWebResponse(Connector);
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream()))
{
while (reader.Peek() >= 0)
{
string data =
reader.ReadLine()
...
The data is passed into a DataTable which then becomes the source of the GridView. I won't belabour that process as it is fairly simple and well documented elsewhere. It would also be worth looking at the RowDataBound event of the GridView where the headers (amongst other items) are created and displayed by using the Header data passed back from Yahoo.
"~NASDAQ","N/A",0.00,N/A,"N/A"
Since I know that anything that starts with ~ is a header I strip that off and replace the cell text with the name of the header and exapnd the cell to cover all of the other cells so as to appear as a single merged cell.
if (sep.Contains("~"))
{
string data = sep.Substring(sep.LastIndexOf('~') + 1);
cellTicker.Text = data;
cellTicker.Font.Bold = true;
cellTicker.BackColor = Color.LightGray;
cellExchange.Visible =
cellPrice.Visible =
cellPosition.Visible =
cellPercentage.Visible =
false;
}
This is a sample taken at about 1530 on the 16th October, 2008:
Conclusion
There are, of course, many other features that could be added and the format string could be enlarged to return a far richer set of data than I present here. I have to thank the good people at http://www.gummy-stuff.org/Yahoo-data.htm for providing information without which this would not work: in particular they have what appears to be a fairly comprehensive list of tags that can be used. Note that you will have to make code changes if you add more columns.
I have created this to compile under Net 2 and have not used any Ajax objects or other thrid-party controls/assemblies so as to keep it really simple. There is a live, working version at LIVE DEMO that is exactly what I have shown here: the control dropped onto a page and the config file placed in the root of the application with no other embellishments of any kind; those I leave to you to add as required, although, for instance, it would certainly benefit from the addition of an Update Panel.
Note that the markets and stocks I have added to Yahoo.xml are for demonstration purposes only and were mostly picked at random. Mostly.
I'm certain that there are a myriad other ways in which this could have been done: I chose this way for no other reason than that's what I felt like at the time. And it works. Well, at least, it did the last time I looked at it! I have been using a variant of this on my own web site (prior to replacement with the demonstration version) for quite some time without any problems.
History
Version 1.0 - 17th October, 2008
Copyright © 2008, Mark Merrens.