Search code examples
asp.netapistocks

Anyone know how to get historical stock data for free in ASP.NET?


I'm looking for an API that can be accessed via C# implementation where I can get access to free stock market historical information (index and individual companies).


Solution

  • I have a couple of C# examples on my blog for getting historical data from Yahoo. It's really simple...

    Update

    Regarding my example... I'm not saving the data to anything, I'm just printing in the console. You'd have to save the data in whatever format or data structure is most reasonable for you.

    // A dictionary with tags where the key is the tag
    // and the value is the description of the tag
    private Dictionary<string, string> _tags = new Dictionary<string, string>();
    
    private void DownloadData(String symbol)
    {
        string url = String.Format(
            "http://finance.yahoo.com/d/quotes.csv?s={0}&f=", symbol);
    
        //Get page showing the table with the chosen indices
        HttpWebRequest request = null;
        DFDataSet ds = new DFDataSet();
        Random rand = new Random(DateTime.Now.Millisecond);
        try
        {
            while (_running)
            {
                foreach (String key in _tags.Keys)
                {
                    lock (_sync)
                    {
                        request = (HttpWebRequest)WebRequest.CreateDefault(
                            new Uri(url + key));
                        request.Timeout = 30000;
    
                        using (var response = (HttpWebResponse)request.GetResponse())
                        using (StreamReader input = new StreamReader(
                            response.GetResponseStream()))
                        {
                            Console.WriteLine(String.Format("{0} {1} = {2}",
                                symbol, _tags[key], input.ReadLine());
                        }
                    }
                }
                Console.WriteLine(Thread.CurrentThread.Name + " running.");
                Thread.Sleep(60*1000); // 60 seconds
            }
        }
        catch (Exception exc)
        {
            Console.WriteLine(exc.Message);
        }
    }
    

    Note that you can request multiple tags in the same csv file, instead of one tag at a time... to do that, just string all the tags of interest together and add them to the URL just like you add a single tag. The values for the tags will be comma separated.

    Update 2.0

    Here is how you can get end of day (EOD) historical data from yahoo:

    void DownloadDataFromWeb(string symbol)
    {
        DateTime startDate = DateTime.Parse("1900-01-01");
    
        string baseURL = "http://ichart.finance.yahoo.com/table.csv?";
        string queryText = BuildHistoricalDataRequest(symbol, startDate, DateTime.Today);
        string url = string.Format("{0}{1}", baseURL, queryText);
    
        //Get page showing the table with the chosen indices
        HttpWebRequest request = null;
        HttpWebResponse response = null;
        StreamReader stReader = null;
    
        //csv content
        string docText = string.Empty;
        string csvLine = null;
        try
        {
            request = (HttpWebRequest)WebRequest.CreateDefault(new Uri(url));
            request.Timeout = 300000;
    
            response = (HttpWebResponse)request.GetResponse();
    
            stReader = new StreamReader(response.GetResponseStream(), true);
    
            stReader.ReadLine();//skip the first (header row)
            while ((csvLine = stReader.ReadLine()) != null)
            {
                string[] sa = csvLine.Split(new char[] { ',' });
    
                DateTime date = DateTime.Parse(sa[0].Trim('"'));
                Double open =  double.Parse(sa[1]);
                Double high = double.Parse(sa[2]);
                Double low = double.Parse(sa[3]);
                Double close = double.Parse(sa[4]);
                Double volume = double.Parse(sa[5]);
                Double adjClose = double.Parse(sa[6]);
                // Process the data (e.g. insert into DB)
            }
        }
        catch (Exception e)
        {
            throw e;
        }
    }
    
    string BuildHistoricalDataRequest(string symbol, DateTime startDate, DateTime endDate)
    {
        // We're subtracting 1 from the month because yahoo
        // counts the months from 0 to 11 not from 1 to 12.
        StringBuilder request = new StringBuilder();
        request.AppendFormat("s={0}", symbol);
        request.AppendFormat("&a={0}", startDate.Month-1);
        request.AppendFormat("&b={0}", startDate.Day);
        request.AppendFormat("&c={0}", startDate.Year);
        request.AppendFormat("&d={0}", endDate.Month-1);
        request.AppendFormat("&e={0}", endDate.Day);
        request.AppendFormat("&f={0}", endDate.Year);
        request.AppendFormat("&g={0}", "d"); //daily
    
        return request.ToString();
    }
    

    The code above will go through each data instance in the CSV file, so you just need to save the data instances to arrays. Calculating the return should be straight forward from then on.

    // Create your data lists
    List<DateTime> date = new List<DateTime>();
    List<Double> open = new List<Double>();
    List<Double> high = new List<Double>();
    List<Double> low = new List<Double>();
    List<Double> close = new List<Double>();
    List<Double> volume = new List<Double>();
    List<Double> adjClose = new List<Double>();
    
    //
    // ...
    //
    
    // inside the DownloadDataFromWeb function:
    
    // Add the data points as you're going through the loop
    date.Add(DateTime.Parse(sa[0].Trim('"')));
    open.Add(double.Parse(sa[1]));
    high.Add(double.Parse(sa[2]));
    low.Add(double.Parse(sa[3]));
    close.Add(double.Parse(sa[4]));
    volume.Add(double.Parse(sa[5]));
    adjClose.Add(double.Parse(sa[6]));
    
    //
    // ...
    //
    
    // Calculate the return after you've downloaded all the data...
    

    I hope that's helpful :).