Friday, August 28, 2009

GnuCash can't get currency quotes

I have just installed GnuCash and like it immensely. However when I tried to get a currency quote all I got was:
unable to retrieve quotes CURRENCY:USD
Not too useful! It has taken me a while to track down the problem even with Google, so I thought I would give a simple quick fix here. This quick fix is followed by a fuller description of the problem.

Locate the file on your computer. On my Mac it is in /Library/Perl/5.8.8/Finance. You must replace it with this version of

GnuCash will now be able to get currencies properly. You can test it with:
bin $ ./gnc-fq-dump currency USD EUR
1 USD = 0.6963 EUR
bin $ ./gnc-fq-dump currency EUR USD
1 EUR = 1.4362 USD
Note: It is not a good idea to trust code files from the web so you should really do a diff on your file and the new one before installing it. That way you can see that there is no malicious code there. If you do a diff command you should see something like the following. If you see extra code or are worried about what you see do not install it.

bash-3.2# diff -w -u
--- 2009-04-13 16:15:29.000000000 +0200
+++ 2009-08-28 15:42:25.000000000 +0200
@@ -1,5 +1,11 @@
#!/usr/bin/perl -w
+# Warning: This file has been edited to fix currencies not working because
+# the Yahoo page has changed. You should keep an eye out for an official
+# fix and use that when it comes out. This file may cause future problems
+# keep the old one available.
# Copyright (C) 1998, Dj Padzensky
# Copyright (C) 1998, 1999 Linas Vepstas
# Copyright (C) 2000, Yannick LE NY
@@ -36,15 +42,17 @@
use Finance::Quote::UserAgent;
use HTTP::Request::Common;
use HTML::TableExtract;
+use Finance::Quote::Yahoo::Base qw/yahoo_request/;
use Encode;
# If the above URL ever fails, try rewriting this module to use the URL below.
@ISA = qw/Exporter/;
@EXPORT = ();
@@ -239,18 +247,13 @@
return $amount if ($from eq $to); # Trivial case.
- my $ua = $this->user_agent;
- my $data = $ua->request(GET "${YAHOO_CURRENCY_URL}from=$from&to=$to")->content;
- my $te = HTML::TableExtract->new( headers => ['Symbol', 'Bid', 'Ask'] );
- $te->parse(decode_utf8($data)); # The web page returns utf8 content which gives
- # a warning when parsing $data in HTML::Parser
+ my $symbol = "$from$to=X";
+ my @symbols = ($symbol);
+ my %info = yahoo_request($this,$YAHOO_CURRENCY_URL,\@symbols);
+ return undef unless $info{$symbol,"success"};
- # Make sure there's a table to parse.
- return undef unless ($te->tables);
+ my $exchange_rate = $info{$symbol,"last"};
- my $row = ($te->rows())[0];
- my ($exchange_rate) = $$row[1];
$exchange_rate =~ s/,// ; # solve a bug when conversion rate
# involves thousands. yahoo inserts
# a comma when thousands occur

It turns out to be a problem in the Perl Finance::Quote module because Yahoo have changed the way they have done their currency web page; that's the problem with page scraping. Anyway, I finally found a patch for the problem here but it did not work out of the box because I have the latest version of Finance::Quote and it was incompatible. So, after hand editing it I thought that I would make a patched of Finance::Quote version 1.16 available above.

Keep an eye on the official version and switch to that when it is released.

Happy Accounting!