C# Code, Tutorials and Full Visual Studio Projects

Yahoo Stock Symbol Lookup

Posted by on Jan 6, 2011 in API, Financial | 7 comments

Yahoo Stock Symbol Lookup

Yahoo has a REST based stock lookup service you can use that returns JSON data.

Using the Yahoo Stock Lookup Service

Here is an example of a URL that queries the service:

http://autoc.finance.yahoo.com/autoc?query=google&callback=YAHOO.Finance.SymbolSuggest.ssCallback

You just need to pass what your searching for, in this case “google”. And you get back a list of results that look something like this:

YAHOO.Finance.SymbolSuggest.ssCallback(
{"ResultSet":
{"Query":"google","Result":[
{"symbol":"GOOG","name": "Google Inc.","exch": "NMS","type": "S","exchDisp":"NASDAQ","typeDisp":"Equity"},
{"symbol":"GGQ1.HM","name": "GOOGLE-A","exch": "HAM","type": "S","exchDisp":"Hamburg","typeDisp":"Equity"},
{"symbol":"GGQ1.SG","name": "GOOGLE-A","exch": "STU","type": "S","exchDisp":"Stuttgart","typeDisp":"Equity"},
{"symbol":"GOOF.EX","name": "GOOGLE-A","exch": "EUX","type": "S","exchDisp":"EUREX Futures and Options Exchange","typeDisp":"Equity"},
{"symbol":"GOOG11BF.SA","name": "GOOGLE      -DRN     MB","exch": "SAO","type": "S","exchDisp":"Sao Paolo","typeDisp":"Equity"},
{"symbol":"GGQ1.F","name": "GOOGLE-A","exch": "FRA","type": "S","exchDisp":"Frankfurt","typeDisp":"Equity"},
{"symbol":"GGQ1.MU","name": "GOOGLE-A","exch": "MUN","type": "S","exchDisp":"Munich","typeDisp":"Equity"},
{"symbol":"GGQ1.HA","name": "GOOGLE-A","exch": "HAN","type": "S","exchDisp":"Hanover","typeDisp":"Equity"},
{"symbol":"GOOG-U.TI","name": "GOOGLE-A","exch": "TLO","type": "S","exchDisp":"TLX Exchange","typeDisp":"Equity"},
{"symbol":"GGQ1.DE","name": "GOOGLE-A","exch": "GER","type": "S","exchDisp":"XETRA","typeDisp":"Equity"}
]}})

Using the Stock Lookup Service in C#

C# has many wonderful functions, but it’s handling of JSON leaves quite a bit to be desired. Normally you would use the C# DataContractDataSerializer to deserialize the JSON, but this approach as a big drawback: You must create each object you wish to deserialize.

With .NET 4 came the dynamic keyword. This lets us defer checks until runtime allowing us to solve this without making lots of small classes just for deserialization.

After getting half-way through writing a dynamic JSON library I found some great code that already did it. With this new dynamic library all you need to do to parse and use the Yahoo Stock Symbol Lookup is this:

using System;
using System.Net;
using System.Text.RegularExpressions;
using System.Web.Script.Serialization;

namespace Jarloo.StockSymbolLookup
{
    class Program
    {
        static void Main(string[] args)
        {
            using(WebClient web = new WebClient())
            {
                string query = "google";
                string url = string.Format("http://autoc.finance.yahoo.com/autoc?query={0}&callback=YAHOO.Finance.SymbolSuggest.ssCallback",query);

                string data = web.DownloadString(url);

                //remove the class/method name from the JSON
                Match match = Regex.Match(data, @"YAHOO.Finance.SymbolSuggest.ssCallback((.*?))");
                data = match.Groups[1].Value;

                var serializer = new JavaScriptSerializer();
                serializer.RegisterConverters(new[] { new DynamicJsonConverter() });
                dynamic obj = serializer.Deserialize(data, typeof(object));

                foreach (dynamic result in obj.ResultSet.Result)
                {
                    Console.WriteLine(string.Format("{0} {1} {2}", result.symbol,result.name,result.exch));
                }

                Console.ReadLine();
            }
        }
    }
}

The library I found is from Shawn Weisfeld’s Blog. There was a few code fixes done on the original by others so I’ll post the version that I used here so you don’t need to jump around looking for the exact version I used.

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Dynamic;
using System.Linq;
using System.Text;
using System.Web.Script.Serialization;

namespace Jarloo.StockSymbolLookup
{
    public class DynamicJsonConverter : JavaScriptConverter
    {
        public override object Deserialize(IDictionary<string, object> dictionary, Type type, JavaScriptSerializer serializer)
        {
            if (dictionary == null) throw new ArgumentNullException("dictionary");

            return type == typeof(object) ? new DynamicJsonObject(dictionary) : null;
        }

        public override IDictionary<string, object> Serialize(object obj, JavaScriptSerializer serializer)
        {
            throw new NotImplementedException();
        }

        public override IEnumerable<Type> SupportedTypes
        {
            get { return new ReadOnlyCollection<Type>(new List<Type>(new[] { typeof(object) })); }
        }

        private sealed class DynamicJsonObject : DynamicObject
        {
            private readonly IDictionary<string, object> _dictionary;

            public DynamicJsonObject(IDictionary<string, object> dictionary)
            {
                if (dictionary == null) throw new ArgumentNullException("dictionary");
                _dictionary = dictionary;
            }

            public override string ToString()
            {
                var sb = new StringBuilder("{");
                ToString(sb);
                return sb.ToString();
            }

            private void ToString(StringBuilder sb)
            {
                bool firstInDictionary = true;

                foreach (var pair in _dictionary)
                {
                    if (!firstInDictionary) sb.Append(",");
                    firstInDictionary = false;
                    var value = pair.Value;
                    var name = pair.Key;

                    if (value is string)
                    {
                        sb.AppendFormat("{0}:"{1}"", name, value);
                    }
                    else if (value is IDictionary<string, object>)
                    {
                        new DynamicJsonObject((IDictionary<string, object>)value).ToString(sb);
                    }
                    else if (value is ArrayList)
                    {
                        sb.Append(name + ":[");
                        var firstInArray = true;

                        foreach (var arrayValue in (ArrayList)value)
                        {
                            if (!firstInArray)
                                sb.Append(",");
                            firstInArray = false;
                            if (arrayValue is IDictionary<string, object>)
                                new DynamicJsonObject((IDictionary<string, object>)arrayValue).ToString(sb);
                            else if (arrayValue is string)
                                sb.AppendFormat(""{0}"", arrayValue);
                            else
                                sb.AppendFormat("{0}", arrayValue);
                        }
                        sb.Append("]");
                    }
                    else
                    {
                        sb.AppendFormat("{0}:{1}", name, value);
                    }
                }

                sb.Append("}");
            }

            public override bool TryGetMember(GetMemberBinder binder, out object result)
            {
                if (!_dictionary.TryGetValue(binder.Name, out result))
                {
                    // return null to avoid exception.  caller can check for null this way...
                    result = null;
                    return true;
                }

                var dictionary = result as IDictionary<string, object>;
                if (dictionary != null)
                {
                    result = new DynamicJsonObject(dictionary);
                    return true;
                }

                var arrayList = result as ArrayList;
                if (arrayList != null && arrayList.Count > 0)
                {
                    if (arrayList[0] is IDictionary<string, object>)
                        result = new List<object>(arrayList.Cast<IDictionary<string, object>>().Select(x => new DynamicJsonObject(x)));
                    else
                        result = new List<object>(arrayList.Cast<object>());
                }

                return true;
            }
        }
    }
}

I’m happy I ran across Shawn’s blog as this code was exactly what I was hoping to build. If you haven’t already go checkout his blog and the explanation of the code.


7 Comments

Join the conversation and post a comment.

  1. passow

    found one bug in you code use this line instead.
    dynamic obj = serializer.Deserialize(data);

  2. Sandeep

    This returns a maximum of 10 results !!! How can we bypass the limitation of returning only 10 results ?? I need to see all results like it is being displayed at the yahoo site url ( http://finance.yahoo.com/lookup?s=bank ) It lists 1789 results in total !!! but the same query returns only 10 results at YQL

  3. admin

    I don’t believe there is a setting to return more then 10 equities. (I could be wrong, I’ve never had the need to look.)

    You could always make multiple concurrent calls, but if your looking to get a real-time snapshot of the entire market this would not be the service I would use. Instead look up the BATS Exchange. It’s free and you can connect to them to get your real-time data. http://www.FreeStockCharts.com is an example of a service that uses the BATS Exchange to get stock quote info.

  4. Uttam Debnath

    I need to get DJI price, but Yahoo Finance API returns DJX not DJI. Google Finance returns but it limit per day is very low.

    I need DJI price in every 30 seconds. Can you please help to inform about API (Free or Paid) and implementation code (preferred in C#/ASP.Net) to get DJI price without any interrupt.

  5. Kelly Elias

    Yahoo does not offer that service. I suggest you look at the BATS exchange, they have a good API system that should work for you.

  6. Sylvain

    Can you send me a link to see the BATS services API ?
    thanks

  7. Kelly Elias

    Not sure if it’s still free or not, but here is the BATS document I believe your looking for: http://cdn.batstrading.com/resources/membership/BATS_Connectivity_Manual.pdf

Leave a Comment

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>