Introduction
Many years, especially during international trips, I have used the Yahoo! Finance portal to get fresh foreign exchange rates for my expense reports. I found this site quite useful, especially because the information is free, even though a little bit delayed, but good enough for such goals. Unfortunately, the Yahoo! site doesn't have a version formatted to fit the small screens of mobile devices. That's why I decided to create .NET components that are reusable in WinForms, ASP.NET, and the Compact Framework to cover all my needs. Parsing HTML code is not a trivial task because it doesn't have a strong formatting as XML does. Again, fortunately, Yahoo! duplicates results as a comma-delimited file which is more easy to parse. So, let's look at the code closely.
Walk through the classes
Class diagram:
There are two classes - CurrencyConverter
and CurrencyList
, and a structure CurrencyData
. All of them are packed into the Zayko.Finance
namespace.
CurrencyData structure
This structure represents a pair of currency codes and data coming from the Web Service:
BaseCode
(string
): get/set three-characters of the base currency code, for example: USD for United States Dollar, EUR for Euro etc.
TargetCode
(string
): get/set the target currency code, by the same rules as BaseCode
.
Rate
(double
): last trade price of Base Currency, specified in the BaseCode
property, calculated in currency units, specified in the TargetCode
property.
Max
and Min
(double
): they look like Ask and Bid, but values are different between the HTML version on the site and the comma-delimited file I mentioned above; unfortunately, there is no detailed explanation, that's why I named them "Min" and "Max" to avoid confusion with the real "Bid" and "Ask" values.
TradeDate
(System.DateTime
): last trade Date/Time.
This structure has one constructor:
public CurrencyData(string baseCode, string targetCode)
to create a new structure and set the currency codes.
CurrencyConverter class
This is the main class which accesses the Yahoo! service and gets the data through several overloads of the GetCurrencyData
method:
public CurrencyData GetCurrencyData(string source, string target)
This is the simplest method: just supply the currency codes and get the result in the returned CurrencyData
structure. For example:
using Zayko.Finance;
...
CurrencyData cd = myCurrencyConverter.GetCurrencyData("USD", "EUR");
This version gets the currency pair in the supplied CurrencyData
and packs the results back into there:
public void GetCurrencyData(ref CurrencyData data)
Gets the currency pair in the CurrencyData
structure and sets the data properties (Rate
, Min/Max
, TradeDate
) by the given results. Example:
using Zayko.Finance;
...
CurrencyData cd = new CurrencyData("EUR", "RUB");
try
{
myCurrencyConverter.GetCurrencyData(ref cd);
}
catch
{
}
This method is useful to get data for more than one currency pair at the same time:
public void GetCurrencyData(ref IList<CurrencyData> listData);
Example:
using Zayko.Finance;
...
IList<CurrencyData> currencyList = new List<CurrencyData>();
currencyList.Add(new CurrencyData("USD", "EUR"));
currencyList.Add(new CurrencyData("EUR", "RUR"));
try
{
myCurrencyConverter.GetCurrencyData(ref currencyList);
foreach(CurrencyData cd in currencyList)
{
}
}
catch
{
}
But before calling these functions, don't forget to set some important properties:
CurrencyList class
This class contains only static methods, so doesn't need to be created manually before using it. Use this class to get all the supported currencies: get the three-characters codes from the static read only property Codes
: public static ReadOnlyCollection Codes
and their names from public static ReadOnlyCollection Descriptions
.
Also, it is possible to get the exact code and/or description by its position:
public static string GetCode(int index)
: return a currency code, for example "USD".
public static string GetDescription(int index)
: return a currency description (name), for example "U.S. Dollar".
and opposite functions:
public static int GetCodeIndex(string code)
public static int GetDescriptionIndex(string description)
Since both codes and descriptions are unique, it's possible to get a currency code by its description and vice versa:
public static string GetCode(string description)
public static string GetDescription(string code)
Using the code
Finally, a couple of words about using the source code.
Probably the best way to show all the supported currencies either in a WinForms app or an ASP.NET app is ListBox
or ComboBox
objects. As I said above, this list could be taken from the static CurrencyList
class. This task could be done in two different ways:
string[] currencyDescriptions = new string[CurrencyList.Count];
CurrencyList.Descriptions.CopyTo(currencyDescriptions, 0);
comboBoxCurrencyList.Items.AddRange(currencyDescriptions);
for(int i = 0; i < CurrencyList.Count; i++)
{
DropDownListCurrency.Items.Add(CurrencyList.Descriptions[i]);
DropDownListCurrency.Items[i].Value = CurrencyList.Codes[i];
}
CurrencyConverter cc = new CurrencyConverter();
CurrencyData cd = cc.GetCurrencyData(DropDownListFrom.SelectedValue,
DropDownListTo.SelectedValue);
Don't forget to set the CurrencyData.AdjustToLocalTime
property to true
if you want to make adjustments automatically. If your network is behind a proxy, don't forget to create and assign a proxy object before you call CurrencyData.GetCurrencyData(...)
:
if(useProxy)
cc.Proxy = new System.Net.WebProxy(proxyAddress, proxyPort);
Because the CurrencyConverter
class has several versions of the GetCurrencyData
method, and GetCurrencyData(ref IList<CurrencyData>)
is one of them, you can pass more than one CurrencyData
structure and get data for several currency pairs at the same time. Although this method has no restrictions on the number of currencies you can pass, please remember that some old network routers have a limitation on URL length and can trim everything to below 256 characters.
Here is the demo app screenshot (source code is included with this article):
Important notes
As a developer, I don't impose any restrictions on using this code, but please remember that Yahoo! services could be under different types of licensing and commercial use could be restricted. So please follow Yahoo! instructions.
Although I said at the beginning that I created these classes to fit to any .NET target, I didn't test this code on the Compact Framework at all, but I promise to return to this article in a couple of weeks and hope will get your opinions during this time to make this code more useful.
Enjoy!
Links
History
- March 7, 2007 - Initial release.