Jarloo

Menu

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.

 

Categories:   Finance

Comments

Sorry, comments are closed for this item.