Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

Stock quote and chart from Yahoo! in C#

0.00/5 (No votes)
23 Jun 2009 1  
This article introduces you to how to access stock quotes from the Yahoo! Finance service.

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.

  1. Open Visual Studio .NET.
  2. On the File menu, point to New, and then click Project.
  3. In the New Project dialog box, under Project Types, click Visual C# Projects. Under Templates, click ASP.NET Web Application.
  4. In the Name text box, type sample.
  5. 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">
    /// <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>

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
    {
        // 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 "&lt;" and "&gt;"
                        // back to "<" and ">".
                        divService.InnerHtml = "<br />" + 
                          result.Replace("&lt;", "<").Replace(
                          "&gt;", "<") + "<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 = "<stockquotes />";
                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 "&gt;" and "&lt;".
                        tmp += "<Symbol>&lt;span style='color:red'&gt;" + 
                               symbols[i].ToUpper() + 
                               " is invalid.&lt;/span&gt;</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 "&gt;" and "&lt;".
                        if (contents[4].Trim().Substring(0, 1) == "-")
                            tmp += "<Change>&lt;span style='color:red'&gt;" + 
                                   contents[4] + "(" + contents[10] + ")" + 
                                   "&lt;span&gt;</Change>";
                        else if (contents[4].Trim().Substring(0, 1) == "+")
                            tmp += "<Change>&lt;span style='color:green'&gt;" + 
                                   contents[4] + "(" + contents[10] + ")" + 
                                   "&lt;span&gt;</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;
        }        
    }
}

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.

  1. In Solution Explorer, select the project.
  2. On the Project menu, click Add New Item. The Add New Item dialog box appears.
  3. Click Data.
  4. In the right pane, click the XSLT file.
  5. Rename the item to styles.css.
  6. 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 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

License

This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

A list of licenses authors might use can be found here