|
|
|
|
|
|
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 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 below to see the live demo:
|
|
http://www.igotmessage.com/Finance.aspx
|
|
License
|
|
This article, along with any associated source code and files, is licensed under the LGPL.
|
|
Background
|
|
It is easy to download stock data from Yahoo. For example, copy and paste URL below into your browser address:
|
|
http://download.finance.yahoo.com/d/quotes.csv?s=YHOO+GOOG+MSFT&f=sl1d1t1c1hgvbap2
|
Depends on you Internet browser setting, you maybe asked to save the results into a filename call "quotes.csv" or the follow page 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=' - Append a bunch of stock symbols separated by "+" after this
& - to join the string
'f=' - Append 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 follow:
|
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 looks 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 to 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 Mosftsoft stock:
|
http://chart.finance.yahoo.com/c/3m/d/msft
|
The URL also starts with a base URL and then adds a stock symbo after that.
|
Small chart:
|
1 day: http://ichart.yahoo.com/t?s=MSFT
5 days: http://ichart.yahoo.com/v?s=MSFT
1 year: http://ichart.finance.yahoo.com/c/bb/m/msft
|
Big chart:
|
1 day: http://ichart.finance.yahoo.com/b?s=MSFT
5 days: http://ichart.finance.yahoo.com/w?s=MSFT
3 months: http://chart.finance.yahoo.com/c/3m/msft
6 months: http://chart.finance.yahoo.com/c/6m/msft
1 year: http://chart.finance.yahoo.com/c/1y/msft
2 years: http://chart.finance.yahoo.com/c/2y/msft
5 years: http://chart.finance.yahoo.com/c/5y/msft
max: http://chart.finance.yahoo.com/c/my/msft
|
|
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.
Second, 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">
/// <summary>
/// This function will be called when user clicks the Get Quotes button.
/// </summary>
/// <returns>Always return false.</returns>
function SendRequest()
{
var txtSymbol = document.getElementById("txtSymbol");
// Refresh the page.
window.location = "default.aspx?s=" + txtSymbol.value;
return false;
}
/// <summary>
/// The functyion will be called when a keyboard key is pressed in the textbox.
/// </summary>
/// <param name="e">Onkeypress event.</param>
/// <returns>Return true if user presses Enter key; otherwise false.</returns>
function CheckEnter(e)
{
if ((e.keyCode && e.keyCode == 13) || (e.which && e.which == 13))
// Enter is pressed in the textbox.
return SendRequest();
return true;
}
/// <summary>
/// The function will be called when user changes the chart type to another type.
/// </summary>
/// <param name="type">Chart type.</param>
/// <param name="num">Stock number.</param>
/// <param name="symbol">Stock symobl.</param>
function changeChart(type, num, symbol)
{
// All the DIVs are inside the main DIV and defined in the code-behind class.
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);
// Set innerHTML property.
div1d.innerHTML = "1d";
div5d.innerHTML="5d";
div3m.innerHTML="3m";
div6m.innerHTML="6m";
div1y.innerHTML="1y";
div2y.innerHTML="2y";
div5y.innerHTML="5y";
divMax.innerHTML="Max";
// Use a random number to defeat cache.
var rand_no = Math.random();
rand_no = rand_no * 100000000;
// Display the stock chart.
switch(type)
{
case 1: // 5 days
div5d.innerHTML="<b>5d</b>";
divChart.src = "http://ichart.finance.yahoo.com/w?s=" + symbol + "&" + rand_no;
break;
case 2: // 3 months
div3m.innerHTML="<b>3m</b>";
divChart.src = "http://chart.finance.yahoo.com/c/3m/" + symbol + "?" + rand_no;
break;
case 3: // 6 months
div6m.innerHTML = "<b>6m</b>";
divChart.src = "http://chart.finance.yahoo.com/c/6m/" + symbol + "?" + rand_no;
break;
case 4: // 1 year
div1y.innerHTML = "<b>1y</b>";
divChart.src = "http://chart.finance.yahoo.com/c/1y/" + symbol + "?" + rand_no;
break;
case 5: // 2 years
div2y.innerHTML = "<b>2y</b>";
divChart.src = "http://chart.finance.yahoo.com/c/2y/" + symbol + "?" + rand_no;
break;
case 6: // 5 years
div5y.innerHTML = "<b>5y</b>";
divChart.src = "http://chart.finance.yahoo.com/c/5y/" + symbol + "?" + rand_no;
break;
case 7: // Max
divMax.innerHTML = "<b>msx</b>";
divChart.src = "http://chart.finance.yahoo.com/c/my/" + symbol + "?" + rand_no;
break;
case 0: // 1 day
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">
<!-- Main DIV: this DIV contains text and DIVs that displays stock quotes and chart. -->
</div>
<%}%>
</td>
</tr>
</table> </div>
</form>
</body>
</html> |
|
Third, open the code-behind page (Default.aspx.cs) and write the 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
{
// Stock symbols seperated by space or comma.
protected string m_symbol = "";
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
// The page is being loaded and accessed for the first time.
// Retrieve user input from the form.
if (Request.QueryString["s"] == null)
// Set the default stock symbol to YHOO.
m_symbol = "YHOO";
else
// Get the user's input.
m_symbol = Request.QueryString["s"].ToString().ToUpper();
// Update the textbox value.
txtSymbol.Value = m_symbol;
// This DIV that contains text and DIVs that displays stock quotes and chart from Yahoo.
// Set the innerHTML property to replaces the existing content of the DIV.
divService.InnerHtml = "<br />";
if (m_symbol.Trim() != "")
{
try
{
// Return the stock quote data in XML format.
String arg = GetQuote(m_symbol.Trim());
if (arg == null)
return;
// Read XML.
// Declare an XmlDocument object to represents an XML document.
XmlDocument xd = new XmlDocument();
// Loads the XML data from a stream.
xd.LoadXml(arg);
// Read XSLT
// Declare an XslCompiledTransform object to transform XML data using an XSLT style sheet.
XslCompiledTransform xslt = new XslCompiledTransform();
// Use the Load method to load the Xsl transform object.
xslt.Load(Server.MapPath("stock.xsl"));
// Transform the XML document into HTML.
StringWriter fs = new StringWriter();
xslt.Transform(xd.CreateNavigator(), null, fs);
string result = fs.ToString();
// Replace the characters "<" and ">" back to "<" and ">".
divService.InnerHtml = "<br />" + result.Replace("<", "<").Replace(">", "<") + "<br />";
// Display stock charts.
String[] symbols = m_symbol.Replace(",", " ").Split(' ');
// Loop through each stock
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, the stock symbol is valid.
if (index == -1)
{
// Use a random number to defeat cache.
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 />";
// 1 days
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> ";
// 5 days
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> ";
// 3 months
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>& ";
// 6 months
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> ";
// 1 yeas
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> ";
// 2 years
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> ";
// 5 years
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> ";
// Max
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
{
// Handle exceptions
}
}
}
}
/// <summary>
/// This function handles and parses multiple stock symbols as input parameters
/// and builds a valid XML return document.
/// </summary>
/// <param name="symbol">A bunch of stock symbols seperated by space or comma</param>
/// <returns>Return stock quote data in XML format</returns>
public string GetQuote(string symbol)
{
// Set the return string to null.
string result = null;
try
{
// Use Yahoo finance service to download stock data from Yahoo
string yahooURL = @"http://download.finance.yahoo.com/d/quotes.csv?s=" + symbol + "&f=sl1d1t1c1hgvbap2";
string[] symbols = symbol.Replace(",", " ").Split(' ');
// Initialize a new WebRequest.
HttpWebRequest webreq = (HttpWebRequest)WebRequest.Create(yahooURL);
// Get the response from the Internet resource.
HttpWebResponse webresp = (HttpWebResponse)webreq.GetResponse();
// Read the body of the response from the server.
StreamReader strm = new StreamReader(webresp.GetResponseStream(), Encoding.ASCII);
// Construct a XML in string format.
string tmp = "";
string content = "";
for (int i = 0; i < symbols.Length; i++)
{
// Loop through each line from the stream, building the return XML Document string
if (symbols[i].Trim() == "")
continue;
content = strm.ReadLine().Replace("\"", "");
string[] contents = content.ToString().Split(',');
// If contents[2] = "N/A". the stock symbol is invalid.
if (contents[2] == "N/A")
{
// Construct XML via strings.
tmp += "<Stock>";
// "<" and ">" are illegal in XML elements. Replace the characters "<" and ">" to ">" and "<".
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
{
//construct XML via strings.
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>";
// "<" and ">" are illegal in XML elements. Replace the characters "<" and ">" to ">" and "<".
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>";
}
// Set the return string
result += tmp;
tmp = "";
}
// Set the return string
result += "</StockQuotes>";
// Close the StreamReader object.
strm.Close();
}
catch
{
// Handle exceptions.
}
// Return the stock quote data in XML format.
return result;
}
}
}
|
Fourth, 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 the Data.
- In the right pane, click the XSLT file.
- Rename the item to styles.css.
- Click Open.
|
<?xml version='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 on how to get stock quote data from Yahoo and display them using C#.NET. I am sure there are 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.
|
Reference
|
http://www.gummy-stuff.org/Yahoo-data.htm
http://www.diytraders.com/content/view/26/39/
http://www.eggheadcafe.com/articles/20010404.asp
|
|