Introduction
The U.S. stock market went down today and I lost a lot of money, but hopefully everyone here has made money from the stock market. Anyway, in this article, I will introduce you to how to access stock quotes with a 20 minute delay from the Yahoo! Finance service. You can download the source code and modify it according to your needs. Click here to see the live demo: http://www.igotmessage.com/Finance.aspx.
Background
It is easy to download stock data from Yahoo!. For example, copy and paste this URL into your browser address: http://download.finance.yahoo.com/d/quotes.csv?s=YHOO+GOOG+MSFT&f=sl1d1t1c1hgvbap2.
Depending on your Internet browser setting, you may be asked to save the results into a filename called "quotes.csv" or the following will appear in your browser:
"YHOO",14.8188,"6/22/2009","1:20pm",-0.9812,15.61,14.80,13944065,14.81,14.82,"-6.21%"
"GOOG",402.25,"6/22/2009","1:20pm",-17.84,417.49,402.11,2399141,402.14,402.27,"-4.25%"
"MSFT",23.359,"6/22/2009","1:20pm",-0.711,23.95,23.32,36595084,23.35,23.36,"-2.95%"
The URL starts with a base URL and then adds parameters and values after a question mark (?).
- http://quote.yahoo.com/d/quotes.csv? - The default URL to get the information
- 's=' - Appends a bunch of stock symbols separated by "+" after this
- & - to join the string
- 'f=' - Appends a bunch of special tags after this with no spaces in between
The following are special tags provided by Yahoo! Finance:
a |
Ask |
a2 |
Average Daily Volume |
a5 |
Ask Size |
b |
Bid |
b2 |
Ask (Real-time) |
b3 |
Bid (Real-time) |
b4 |
Book Value |
b6 |
Bid Size |
c |
Change & Percent Change |
c1 |
Change |
c3 |
Commission |
c6 |
Change (Real-time) |
c8 |
After Hours Change (Real-time) |
d |
Dividend/Share |
d1 |
Last Trade Date |
d2 |
Trade Date |
e |
Earnings/Share |
e1 |
Error Indication (returned for symbol changed / invalid) |
e7 |
EPS Estimate Current Year |
e8 |
EPS Estimate Next Year |
e9 |
EPS Estimate Next Quarter |
f6 |
Float Shares |
g |
Day’s Low |
h |
Day’s High |
j |
52-week Low |
k |
52-week High |
g1 |
Holdings Gain Percent |
g3 |
Annualized Gain |
g4 |
Holdings Gain |
g5 |
Holdings Gain Percent (Real-time) |
g6 |
Holdings Gain (Real-time) |
i |
More Info |
i5 |
Order Book (Real-time) |
j1 |
Market Capitalization |
j3 |
Market Cap (Real-time) |
j4 |
EBITDA |
j5 |
Change From 52-week Low |
j6 |
Percent Change From 52-week Low |
k1 |
Last Trade (Real-time) With Time |
k2 |
Change Percent (Real-time) |
k3 |
Last Trade Size |
k4 |
Change From 52-week High |
k5 |
Percebt Change From 52-week High |
l |
Last Trade (With Time) |
l1 |
Last Trade (Price Only) |
l2 |
High Limit |
l3 |
Low Limit |
m |
Day’s Range |
m2 |
Day’s Range (Real-time) |
m3 |
50-day Moving Average |
m4 |
200-day Moving Average |
m5 |
Change From 200-day Moving Average |
m6 |
Percent Change From 200-day Moving Average |
m7 |
Change From 50-day Moving Average |
m8 |
Percent Change From 50-day Moving Average |
n |
Name |
n4 |
Notes |
o |
Open |
p |
Previous Close |
p1 |
Price Paid |
p2 |
Change in Percent |
p5 |
Price/Sales |
p6 |
Price/Book |
q |
Ex-Dividend Date |
r |
P/E Ratio |
r1 |
Dividend Pay Date |
r2 |
P/E Ratio (Real-time) |
r5 |
PEG Ratio |
r6 |
Price/EPS Estimate Current Year |
r7 |
Price/EPS Estimate Next Year |
s |
Symbol |
s1 |
Shares Owned |
s7 |
Short Ratio |
t1 |
Last Trade Time |
t6 |
Trade Links |
t7 |
Ticker Trend |
t8 |
1 yr Target Price |
v |
Volume/td> |
v1 |
Holdings Value |
v7 |
Holdings Value (Real-time)/td> |
w |
52-week Range |
w1 |
Day’s Value Change |
w4 |
Day’s Value Change (Real-time) |
x |
Stock Exchange |
y |
Dividend Yield |
|
|
|
|
Let's say that you want to have the following quotes: YHOO, GOOG, GE, MSFT. You want to get the Name, Last Price, Last Traded Volume, 52-Week High. From the table above, you can find out that the special tags needed are as follows:
- Name - n
- Last Price- l1
- Last Traded Volume - v
- 52-Week High - k
- 52-Week Low - j
All you need to do is to construct the URL with the given special tags above. The URL will look like this: http://quote.yahoo.com/d/quotes.csv?s=YHOO+GOOG+GE+MSFT&f=nl1vkj.
Chart
It's also easy to get stock charts from Yahoo! Finance. All you need to do is make a request for the image with the identical URL that is in the Yahoo! Finance page. For example, this is the last three months of Microsoft stock: http://chart.finance.yahoo.com/c/3m/d/msft.
The URL also starts with a base URL and then adds a stock symbol after that.
Small chart:
Big chart:
Implementation
First, create a new ASP.NET Web Application by using Microsoft Visual C# .NET.
- Open Visual Studio .NET.
- On the File menu, point to New, and then click Project.
- In the New Project dialog box, under Project Types, click Visual C# Projects. Under Templates, click ASP.NET Web Application.
- In the Name text box, type sample.
- Click OK.
Now, open the Default.aspx page and add the following code:
<%@ Page Language="C#" AutoEventWireup="true"
CodeBehind="Default.aspx.cs" Inherits="sample._Default" %>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" >
<head runat="server">
<title>Stock quote and chart from Yahoo in C#</title>
<script type="text/javascript" language="JavaScript">
function SendRequest()
{
var txtSymbol = document.getElementById("txtSymbol");
window.location = "default.aspx?s=" + txtSymbol.value;
return false;
}
function CheckEnter(e)
{
if ((e.keyCode && e.keyCode == 13) || (e.which && e.which == 13))
return SendRequest();
return true;
}
function changeChart(type, num, symbol)
{
var div1d=document.getElementById("div1d_"+num);
var div5d = document.getElementById("div5d_" + num);
var div3m = document.getElementById("div3m_" + num);
var div6m = document.getElementById("div6m_" + num);
var div1y = document.getElementById("div1y_" + num);
var div2y = document.getElementById("div2y_" + num);
var div5y = document.getElementById("div5y_" + num);
var divMax = document.getElementById("divMax_" + num);
var divChart = document.getElementById("imgChart_" + num);
div1d.innerHTML = "1d";
div5d.innerHTML="5d";
div3m.innerHTML="3m";
div6m.innerHTML="6m";
div1y.innerHTML="1y";
div2y.innerHTML="2y";
div5y.innerHTML="5y";
divMax.innerHTML="Max";
var rand_no = Math.random();
rand_no = rand_no * 100000000;
switch(type)
{
case 1: div5d.innerHTML="<b>5d</b>";
divChart.src = "http://ichart.finance.yahoo.com/w?s=" +
symbol + "&" + rand_no;
break;
case 2: div3m.innerHTML="<b>3m</b>";
divChart.src = "http://chart.finance.yahoo.com/c/3m/" +
symbol + "?" + rand_no;
break;
case 3: div6m.innerHTML = "<b>6m</b>";
divChart.src = "http://chart.finance.yahoo.com/c/6m/" +
symbol + "?" + rand_no;
break;
case 4: div1y.innerHTML = "<b>1y</b>";
divChart.src = "http://chart.finance.yahoo.com/c/1y/" +
symbol + "?" + rand_no;
break;
case 5: div2y.innerHTML = "<b>2y</b>";
divChart.src = "http://chart.finance.yahoo.com/c/2y/" +
symbol + "?" + rand_no;
break;
case 6: div5y.innerHTML = "<b>5y</b>";
divChart.src = "http://chart.finance.yahoo.com/c/5y/" +
symbol + "?" + rand_no;
break;
case 7: divMax.innerHTML = "<b>msx</b>";
divChart.src = "http://chart.finance.yahoo.com/c/my/" +
symbol + "?" + rand_no;
break;
case 0: default:
div1d.innerHTML = "<b>1d</b>";
divChart.src = "http://ichart.finance.yahoo.com/b?s=" +
symbol + "&" + rand_no;
break;
}
}
</script>
</head>
<body>
<form id="form1" runat="server">
<div>
<table width="100%" border="0"
cellspacing="0" cellpadding="0">
<tr valign="top">
<td style="font-family: Arial, Helvetica, sans-serif;
font-size: 14px; color: #000; text-decoration: none;">
<input type="text" value="" id="txtSymbol"
runat="server" onkeypress="return CheckEnter(event);" />
<input type="button" value="Get Quotes"
onclick="return SendRequest();" />
<br />
<span style="font-family: Arial, Helvetica, sans-serif;
font-size: 11px; color: #666;">
e.g. "YHOO or YHOO GOOG"
</span>
<%if (m_symbol != "") {%>
<div id="divService" runat="server">
-->
</div>
<%}%>
</td>
</tr>
</table>
</div>
</form>
</body>
</html>
Next, open the code-behind page (Default.aspx.cs) and write this code:
using System;
using System.IO;
using System.Xml;
using System.Xml.Xsl;
using System.Xml.XPath;
using System.Net;
using System.Text;
namespace sample
{
public partial class _Default : System.Web.UI.Page
{
protected string m_symbol = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
if (Request.QueryString["s"] == null)
m_symbol = "YHOO";
else
m_symbol = Request.QueryString["s"].ToString().ToUpper();
txtSymbol.Value = m_symbol;
divService.InnerHtml = "<br />";
if (m_symbol.Trim() != "")
{
try
{
String arg = GetQuote(m_symbol.Trim());
if (arg == null)
return;
XmlDocument xd = new XmlDocument();
xd.LoadXml(arg);
XslCompiledTransform xslt = new XslCompiledTransform();
xslt.Load(Server.MapPath("stock.xsl"));
StringWriter fs = new StringWriter();
xslt.Transform(xd.CreateNavigator(), null, fs);
string result = fs.ToString();
divService.InnerHtml = "<br />" +
result.Replace("<", "<").Replace(
">", "<") + "<br />";
String[] symbols = m_symbol.Replace(",", " ").Split(' ');
for (int i = 0; i < symbols.Length; ++i)
{
if (symbols[i].Trim() == "")
continue;
int index =
divService.InnerHtml.ToLower().IndexOf(
symbols[i].Trim().ToLower() +
" is invalid.");
if (index == -1)
{
Random random = new Random();
divService.InnerHtml += "<img id='imgChart_" +
i.ToString() +
"' src='http://ichart.finance.yahoo.com/b?s=" +
symbols[i].Trim().ToUpper() + "& " +
random.Next() + "' border=0><br />";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(0," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div1d_" + i.ToString() +
"'><b>1d</b></span></a> ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(1," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div5d_" + i.ToString() +
"'>5d</span></a> ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(2," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div3m_" + i.ToString() +
"'>3m</span></a>& ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(3," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div6m_" + i.ToString() +
"'>6m</span></a> ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(4," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div1y_" + i.ToString() +
"'>1y</span></a> ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(5," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div2y_" + i.ToString() +
"'>2y</span></a> ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(6," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='div5y_" + i.ToString() +
"'>5y</span></a> ";
divService.InnerHtml +=
"<a style='font-family: Arial, Helvetica, sans-serif; " +
"font-size: 14px; color: Blue;' " +
"href='javascript:changeChart(7," +
i.ToString() + ", \"" + symbols[i].ToLower() +
"\");'><span id='divMax_" + i.ToString() +
"'>Max</span></a>" +
"<br><br /><br /> ";
}
}
}
catch
{
}
}
}
}
public string GetQuote(string symbol)
{
string result = null;
try
{
string yahooURL = @"http://download.finance.yahoo.com/d/quotes.csv?s=" +
symbol + "&f=sl1d1t1c1hgvbap2";
string[] symbols = symbol.Replace(",", " ").Split(' ');
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(yahooURL);
HttpWebResponse webresp = (HttpWebResponse)webreq.GetResponse();
StreamReader strm =
new StreamReader(webresp.GetResponseStream(), Encoding.ASCII);
string tmp = "<stockquotes />";
string content = "";
for (int i = 0; i < symbols.Length; i++)
{
if (symbols[i].Trim() == "")
continue;
content = strm.ReadLine().Replace("\"", "");
string[] contents = content.ToString().Split(',');
if (contents[2] == "N/A")
{
tmp += "<Stock>";
tmp += "<Symbol><span style='color:red'>" +
symbols[i].ToUpper() +
" is invalid.</span></Symbol>";
tmp += "<Last></Last>";
tmp += "<Date></Date>";
tmp += "<Time></Time>";
tmp += "<Change></Change>";
tmp += "<High></High>";
tmp += "<Low></Low>";
tmp += "<Volume></Volume>";
tmp += "<Bid></Bid>";
tmp += "<Ask></Ask>";
tmp += "<Ask></Ask>";
tmp += "</Stock>";
}
else
{
tmp += "<Stock>";
tmp += "<Symbol>" + contents[0] + "</Symbol>";
try
{
tmp += "<Last>" +
String.Format("{0:c}", Convert.ToDouble(contents[1])) +
"</Last>";
}
catch
{
tmp += "<Last>" + contents[1] + "</Last>";
}
tmp += "<Date>" + contents[2] + "</Date>";
tmp += "<Time>" + contents[3] + "</Time>";
if (contents[4].Trim().Substring(0, 1) == "-")
tmp += "<Change><span style='color:red'>" +
contents[4] + "(" + contents[10] + ")" +
"<span></Change>";
else if (contents[4].Trim().Substring(0, 1) == "+")
tmp += "<Change><span style='color:green'>" +
contents[4] + "(" + contents[10] + ")" +
"<span></Change>";
else
tmp += "<Change>" + contents[4] + "(" +
contents[10] + ")" + "</Change>";
tmp += "<High>" + contents[5] + "</High>";
tmp += "<Low>" + contents[6] + "</Low>";
try
{
tmp += "<Volume>" + String.Format("{0:0,0}",
Convert.ToInt64(contents[7])) + "</Volume>";
}
catch
{
tmp += "<Volume>" + contents[7] + "</Volume>";
}
tmp += "<Bid>" + contents[8] + "</Bid>";
tmp += "<Ask>" + contents[9] + "</Ask>";
tmp += "</Stock>";
}
result += tmp;
tmp = "";
}
result += "</StockQuotes>";
strm.Close();
}
catch
{
}
return result;
}
}
}
Next, add a new XSLT file named stock.xsl to the project. With this XSLT, we can transform the stock quotes XML document into HTML.
- In Solution Explorer, select the project.
- On the Project menu, click Add New Item. The Add New Item dialog box appears.
- Click Data.
- In the right pane, click the XSLT file.
- Rename the item to styles.css.
- Click Open.
='1.0'
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
<xsl:output method="html"/>
<xsl:template match="/">
<html>
<TABLE width="770" STYLE="border:1px solid black">
<TR STYLE="font-size:14px; font-family:Arial,
Helvetica, sans-serif; font-weight:bold">
<TD>Symbol</TD>
<TD>Date</TD>
<TD>Time</TD>
<TD>Trade</TD>
<TD>% Chg</TD>
<TD>Bid</TD>
<TD>Ask</TD>
<TD>Volume</TD>
<TD>High</TD>
<TD>Low</TD>
</TR>
<xsl:for-each select="StockQuotes/Stock">
<TR STYLE="font-family:Arial, Helvetica, sans-serif;
font-size:14px; padding:0px 2px">
<TD>
<xsl:value-of select="Symbol" />
</TD>
<TD>
<xsl:value-of select="Date" />
</TD>
<TD>
<xsl:value-of select="Time" />
</TD>
<TD>
<xsl:value-of select="Last" />
</TD>
<TD>
<xsl:value-of select="Change" />
</TD>
<TD>
<xsl:value-of select="Bid" />
</TD>
<TD>
<xsl:value-of select="Ask" />
</TD>
<TD>
<xsl:value-of select="Volume" />
</TD>
<TD>
<xsl:value-of select="High" />
</TD>
<TD>
<xsl:value-of select="Low" />
</TD>
</TR>
</xsl:for-each>
</TABLE>
</html>
</xsl:template>
</xsl:stylesheet>
Finally, press Control+F5 to run the project.
Conclusion
This article walked you through a step-by-step guide of how to get stock quote data from Yahoo! and display it using C# .NET. I am sure there are a lot of things that can be improved. For example, you can use AJAX technology to update stock quotes automatically without refreshing the whole page. I hope this article gives you some ideas of where to start. For more information, please go to: http://www.igotmessage.com/StockQuote.aspx.
Reference