# Finance::Quote Perl module to retrieve prices of funds from DKB # Copyright (C) 2016 Matthias Merz # # This program is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA package Finance::Quote::DKB; use strict; use HTML::TreeBuilder::XPath; use POSIX qw(strftime); my $agent_string = 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'; my %urlmap_wkn = ( '532656' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=4071891&id_notation=3688058&id=0107980', '974515' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=102918&id_notation=3228063&id=0107980', 'a0dpw0' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=11659733&id_notation=11014630&id=0107980', 'a0m430' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=18085585&id_notation=20644387&id=0107980', 'a0m8hd' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=19179789&id_notation=21240603&id=0107980', 'a0m9a2' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=19035880&id_notation=23679474&id=0107980', 'a0ndda' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=25204090&id_notation=31156472&id=0107980', 'a0x754' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=22407622&id_notation=26567264&id=0107980', 'a0x758' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=22533730&id_notation=26567263&id=0107980', 'a0ya5q' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=26097198&id_notation=32652184&id=0107980', 'dws0pr' => 'https://kurse.dkb.de/MIS/?pid=dkb_fnd_details&id_instrument=18286450&id_notation=22946309&id=0107980', 'ewg0ld' => 'https://kurse.dkb.de/MIS/?pid=dkb_cer_details&id_instrument=55061564&id_notation=70580062&id=0107980' ); my %wknmap = ( 'de0005326565' => '532656', 'de000a0m8hd2' => 'a0m8hd', 'de000a0x7541' => 'a0x754', 'de000a0x7582' => 'a0x758', 'de000ewg0ld1' => 'ewg0ld', 'fr0010135103' => 'a0dpw0', 'lu0087412390' => '974515', 'lu0323578657' => 'a0m430', 'lu0327386487' => 'dws0pr', 'lu0336084032' => 'a0m9a2', 'lu0438336264' => 'a0ndda', 'lu0454071019' => 'a0ya5q' ); sub methods {return ('dkb' => \&dkb, 'europe' => \&dkb);} { my @labels = ('name', 'date', 'price', 'last', 'currency'); sub labels { return (dkb => \@labels, europe => \@labels); } } sub get_stock_url { my $stock_wkn = shift; my $url = $urlmap_wkn{lc($stock_wkn)}; if (!defined($url) || length($url) == 0) { my $wkn = $wknmap{lc($stock_wkn)}; $url = $urlmap_wkn{$wkn}; } return $url; } sub dkb { my $quoter = shift; # The Finance::Quote object. my @stocks = @_; my $ua = $quoter->user_agent(); $ua->agent($agent_string); my %info; foreach my $stock (@stocks) { my $get_url = get_stock_url($stock); if (!defined($get_url) || length($get_url) == 0) { $info{$stock,"errormsg"} = "undefined DKB-UR"; next; } my $response = $ua->get($get_url . "&search_value=" . $stock); #print $response->content, "\n"; $info{$stock,"success"} = 0; if (!$response -> is_success()) { $info{$stock,"errormsg"} = "HTTP failure"; } else { $info{$stock,"success"} = 1; $info{$stock,'symbol'} = $stock; my $parser = HTML::TreeBuilder::XPath->new_from_content($response->decoded_content); my @names = $parser->findnodes( '//span[@class="h2"]'); if (@names) { $info{$stock,'name'} = $names[0]->as_text; }; my @prices = $parser->findnodes( '//span[@class="quote"]'); if (@prices) { my $pricestr = $prices[0]->as_text; my @splitvals = ( $pricestr =~ /((\d|,|\.)*)\s*/g); if (@splitvals) { my $converted_price = $splitvals[0]; $converted_price =~ s/\.//g; $converted_price =~ s/,/./g; $info{$stock,'price'} = $converted_price; $info{$stock,'last'} = $converted_price; } }; my @units = $parser->findnodes( '//span[@class="unit"]'); if (@units) { $info{$stock,'currency'} = $units[0]->as_text; }; my @dates = $parser->findnodes( '//div[@class="exchangeLine"]/span'); if (@dates) { my $tradedate = $dates[0]->as_text; $tradedate =~ s/.*\|\s*(\d\d.*) $/$1/g; if (length($tradedate) < 10) { $tradedate = POSIX::strftime( '%d.%m.%Y', localtime()); } $info{$stock,'date'} = $tradedate; $quoter->store_date(\%info, $stock, {eurodate => $tradedate}); }; $info{$stock,'timezone'} = 'Europe/Berlin'; #$info{$stock,'currency'} = 'EUR'; } } return wantarray ? %info : \%info; } 1; =head1 NAME Finance::Quote::DKB - Obtain fonds quotes from DKB. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new("DKB"); %info = Finance::Quote->fetch("dkb","A0M9A2"); =head1 DESCRIPTION This module obtains fund prices from DKB, http://www.dkb.de/. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::DKB: name, date, price, last, method. =head1 SEE ALSO DKB, http://www.dkb.de/ Finance::Quote; =cut