Tue Feb 17 17:07:06 GMT 2009

Finance::Quote::currency_lookup in action

Having written Finance::Quote::currency_lookup I was able to get back to the little script that triggered the idea in the first place

The idea: a script which I can call with partial code or currency names and an amount which will then try and tell me what the current converted value is. If there's something other than a single matching currency let me know that nothing or too many things matched.

Here's the script (also attached):

 1  #!/usr/bin/env perl
 2
 3  use strict;
 4  use warnings;
 5
 6  use Finance::Quote;
 7  my $q = Finance::Quote->new();
 8
 9  my %trans = ();
10  @trans{qw(from to)} = @ARGV;
11
12  # Copied this patter from Finance::Quote::currency to be consistent
13  $trans{from} =~ s/^\s*(\d*\.?\d*)\s*//;
14  my $amount = $1 || 1;
15
16  # Search out currencies
17  for my $key (qw( from to )) {
18    # Is it a code or a name?
19    my $currencies;
20    if ( $trans{$key} =~ /^[A-Z]{2,}$/ ) {
21      # Guess code
22      $currencies = $q->currency_lookup( code => qr/$trans{$key}/ );
23    }
24    else {
25      # Guess name
26      $currencies = $q->currency_lookup( name => qr/$trans{$key}/i );
27    }
28    if ( scalar keys %{$currencies} == 1 ) {
29      my $real_key = "real_${key}";
30      ($trans{$real_key}) = keys %{$currencies};
31      printf "%s : %s (%s)\n", $key
32                             , $trans{$real_key}
33                             , $currencies->{$trans{$real_key}}->{name};
34    }
35    elsif ( scalar keys %{$currencies} > 1 ) {
36      print "Multiple currency matches for ${key}:\n";
37      print " * $_ (" . $currencies->{$_}->{name} . ")\n" for keys %{$currencies};
38    }
39    else {
40      print "No currency matches for ${key}: " . $trans{$key} . "!\n";
41    }
42  }
43
44  # If real from and to exist run the conversion
45  if ( exists $trans{real_from} && exists $trans{real_to} ) {
46    print "${amount} $trans{real_from} => "
47        . $q->currency("${amount}$trans{real_from}", $trans{real_to})
48        . " $trans{real_to}\n";
49  }

And here's some examples of this script in action:

# Some Australian dollars to pounds
# (name searches only)
$ ./conv.pl 42aus brit
from : AUD (Australian Dollar)
to : GBP (British Pound)
42 AUD => 18.8454 GBP

# And the some pounds to US dollars
# (a name and a code search, because US is all-caps)
$ ./conv.pl brit US
from : GBP (British Pound)
to : USD (U.S. Dollar)
1 GBP => 1.4225 USD

# Oops - a typo on pounds
$ ./conv.pl GPB euro
No currency matches for from: GPB!
to : EUR (Euro)

# And now, to make the British cry...
$ ./conv.pl GBP euro
from : GBP (British Pound)
to : EUR (Euro)
1 GBP => 1.1317 EUR

# And finally, too many matches:
$ ./conv.pl egypt ven
from : EGP (Egyptian Pound)
Multiple currency matches for to:
 * SIT (Slovenian Tolar)
 * VEB (Venezuelan Bolivar)

Posted by Bradley Dean | Permalink | Categories: Perl, Programming

Tue Feb 17 01:52:12 GMT 2009

Adding Finance::Quote::currency_lookup to Finance::Quote

While using Finance::Quote::currency() to do some conversions I found myself having to go searching around the web for currency codes. At the time I thought it would be much easier if you could just asked the module what currency codes existed - and so I started work on a currency_lookup() function to do just that.

Finance::Quote uses the Yahoo Currency Converter website so the new function needed to report a compatible list of currencies.

Having developed the search method against a statically stored list of currencies (as I hadn't implemented the live extraction yet) I then discussed options with the other developers and decided that a hard coded list was a better approach given that the list wasn't going to change very often.

Here's a basic idea of usage:

1    $currencies_by_name = $q->currency_lookup( name => 'Australian' );
2    $currencies_by_code = $q->currency_lookup( code => qr/^b/i      );
3    $currencies_by_both = $q->currency_lookup( name => qr/pound/i
4                                             , code => 'GB'         );

The return value is a hash of hash-refs - for example for the first query above:

1    $VAR1 = { AUD => { name => "Australian Dollar" } }

I had added a module to contain the currency list (Finance::Quote::Currencies). Once the search code was complete I then added a test to compare the static list with a live list and implemented Finance::Quote::Currencies::fetch_live_currencies(). This function uses HTML::Parser to extract the currency list. If the currency list changes this function can be used to easily updated the stored list.

These changes are currently available on the currency_lookup branch on github. Coming to a CPAN release in your town real soon now.


Posted by Bradley Dean | Permalink | Categories: Perl, Programming