| line | stmt | bran | cond | sub | pod | time | code | 
| 1 |  |  |  |  |  |  | #!/usr/bin/perl -w | 
| 2 |  |  |  |  |  |  | # | 
| 3 |  |  |  |  |  |  | #    Copyright (C) 1998, Dj Padzensky <djpadz@padz.net> | 
| 4 |  |  |  |  |  |  | #    Copyright (C) 1998, 1999 Linas Vepstas <linas@linas.org> | 
| 5 |  |  |  |  |  |  | #    Copyright (C) 2000, Yannick LE NY <y-le-ny@ifrance.com> | 
| 6 |  |  |  |  |  |  | #    Copyright (C) 2000, Paul Fenwick <pjf@cpan.org> | 
| 7 |  |  |  |  |  |  | #    Copyright (C) 2000, Brent Neal <brentn@users.sourceforge.net> | 
| 8 |  |  |  |  |  |  | #    Copyright (C) 2000, Volker Stuerzl <volker.stuerzl@gmx.de> | 
| 9 |  |  |  |  |  |  | #    Copyright (C) 2002, Rainer Dorsch <rainer.dorsch@informatik.uni-stuttgart.de> | 
| 10 |  |  |  |  |  |  | #    Copyright (C) 2022, Andre Joost <andrejoost@gmx.de> | 
| 11 |  |  |  |  |  |  | # | 
| 12 |  |  |  |  |  |  | #    This program is free software; you can redistribute it and/or modify | 
| 13 |  |  |  |  |  |  | #    it under the terms of the GNU General Public License as published by | 
| 14 |  |  |  |  |  |  | #    the Free Software Foundation; either version 2 of the License, or | 
| 15 |  |  |  |  |  |  | #    (at your option) any later version. | 
| 16 |  |  |  |  |  |  | # | 
| 17 |  |  |  |  |  |  | #    This program is distributed in the hope that it will be useful, | 
| 18 |  |  |  |  |  |  | #    but WITHOUT ANY WARRANTY; without even the implied warranty of | 
| 19 |  |  |  |  |  |  | #    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the | 
| 20 |  |  |  |  |  |  | #    GNU General Public License for more details. | 
| 21 |  |  |  |  |  |  | # | 
| 22 |  |  |  |  |  |  | #    You should have received a copy of the GNU General Public License | 
| 23 |  |  |  |  |  |  | #    along with this program; if not, write to the Free Software | 
| 24 |  |  |  |  |  |  | #    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA | 
| 25 |  |  |  |  |  |  | #    02110-1301, USA | 
| 26 |  |  |  |  |  |  | # | 
| 27 |  |  |  |  |  |  | # | 
| 28 |  |  |  |  |  |  | # This code derived from Padzensky's work on package Finance::YahooQuote, | 
| 29 |  |  |  |  |  |  | # but extends its capabilites to encompas a greater number of data sources. | 
| 30 |  |  |  |  |  |  | # | 
| 31 |  |  |  |  |  |  | # This code was developed as part of GnuCash <http://www.gnucash.org/> | 
| 32 |  |  |  |  |  |  | # | 
| 33 |  |  |  |  |  |  | # $Id: Union.pm,v 1.3 2005/03/20 01:44:13 hampton Exp $ | 
| 34 |  |  |  |  |  |  |  | 
| 35 |  |  |  |  |  |  | package Finance::Quote::Union; | 
| 36 |  |  |  |  |  |  | require 5.005; | 
| 37 |  |  |  |  |  |  |  | 
| 38 | 5 |  |  | 5 |  | 2606 | use strict; | 
|  | 5 |  |  |  |  | 12 |  | 
|  | 5 |  |  |  |  | 157 |  | 
| 39 | 5 |  |  | 5 |  | 29 | use LWP::UserAgent; | 
|  | 5 |  |  |  |  | 12 |  | 
|  | 5 |  |  |  |  | 38 |  | 
| 40 | 5 |  |  | 5 |  | 106 | use HTTP::Request::Common; | 
|  | 5 |  |  |  |  | 11 |  | 
|  | 5 |  |  |  |  | 356 |  | 
| 41 | 5 |  |  | 5 |  | 31 | use POSIX qw(strftime); | 
|  | 5 |  |  |  |  | 11 |  | 
|  | 5 |  |  |  |  | 33 |  | 
| 42 |  |  |  |  |  |  |  | 
| 43 |  |  |  |  |  |  | our $VERSION = '1.58'; # VERSION | 
| 44 |  |  |  |  |  |  |  | 
| 45 |  |  |  |  |  |  | our $UNION_URL1 = "https://legacy-apps.union-investment.de/handle?generate=true&action=doDownloadSearch&start_time="; | 
| 46 |  |  |  |  |  |  | # Date format 27.07.2022&end_time=01.08.2022 | 
| 47 |  |  |  |  |  |  | our $UNION_URL2 ="&csvformat=us&choose_indi_fondsnames="; | 
| 48 |  |  |  |  |  |  |  | 
| 49 | 5 |  |  | 5 | 0 | 22 | sub methods { return (unionfunds => \&unionfunds); } | 
| 50 | 5 |  |  | 5 | 0 | 19 | sub labels { return (unionfunds => [qw/exchange name date isodate price method/]); } | 
| 51 |  |  |  |  |  |  |  | 
| 52 |  |  |  |  |  |  | # ======================================================================= | 
| 53 |  |  |  |  |  |  | # The unionfunds routine gets quotes of UNION funds (Union Invest) | 
| 54 |  |  |  |  |  |  | # On their website UNION provides a csv file in the format | 
| 55 |  |  |  |  |  |  | #    label1,label2,... | 
| 56 |  |  |  |  |  |  | #    name1,symbol1,buy1,bid1,... | 
| 57 |  |  |  |  |  |  | #    name2,symbol2,buy2,bid2,... | 
| 58 |  |  |  |  |  |  | #    ... | 
| 59 |  |  |  |  |  |  | # | 
| 60 |  |  |  |  |  |  | # This subroutine was written by Volker Stuerzl <volker.stuerzl@gmx.de> | 
| 61 |  |  |  |  |  |  |  | 
| 62 |  |  |  |  |  |  | sub unionfunds | 
| 63 |  |  |  |  |  |  | { | 
| 64 | 0 |  |  | 0 | 0 |  | my $quoter = shift; | 
| 65 | 0 |  |  |  |  |  | my @funds = @_; | 
| 66 | 0 | 0 |  |  |  |  | return unless @funds; | 
| 67 | 0 |  |  |  |  |  | my $ua = $quoter->user_agent; | 
| 68 | 0 |  |  |  |  |  | my (%fundhash, @q, %info, $tempdate); | 
| 69 |  |  |  |  |  |  |  | 
| 70 |  |  |  |  |  |  | # create hash of all funds requested | 
| 71 | 0 |  |  |  |  |  | foreach my $fund (@funds) | 
| 72 |  |  |  |  |  |  | { | 
| 73 | 0 |  |  |  |  |  | $fundhash{$fund} = 0; | 
| 74 | 0 |  |  |  |  |  | my $endtime = POSIX::strftime ("%d.%m.%Y" , localtime()); | 
| 75 | 0 |  |  |  |  |  | my $epoc = time(); | 
| 76 | 0 |  |  |  |  |  | $epoc = $epoc - 7 * 24 * 60 * 60;   # one week before of current date. | 
| 77 | 0 |  |  |  |  |  | my $starttime = POSIX::strftime ("%d.%m.%Y" , localtime($epoc)); | 
| 78 | 0 |  |  |  |  |  | my $url = $UNION_URL1 . $starttime."&end_time=" . $endtime . $UNION_URL2 . $fund; | 
| 79 |  |  |  |  |  |  |  | 
| 80 |  |  |  |  |  |  |  | 
| 81 |  |  |  |  |  |  | # get csv data | 
| 82 | 0 |  |  |  |  |  | my $response = $ua->request(GET $url); | 
| 83 | 0 | 0 |  |  |  |  | if ($response->is_success) | 
| 84 |  |  |  |  |  |  | { | 
| 85 |  |  |  |  |  |  | # process csv data | 
| 86 | 0 |  |  |  |  |  | foreach (split('\015?\012',$response->content)) | 
| 87 |  |  |  |  |  |  | { | 
| 88 |  |  |  |  |  |  |  | 
| 89 | 0 | 0 |  |  |  |  | @q = split(/,/) or next; | 
| 90 | 0 | 0 |  |  |  |  | next unless (defined $q[1]); | 
| 91 | 0 | 0 |  |  |  |  | if (exists $fundhash{$q[1]}) | 
| 92 |  |  |  |  |  |  | { | 
| 93 | 0 |  |  |  |  |  | $fundhash{$q[1]} = 1; | 
| 94 |  |  |  |  |  |  |  | 
| 95 |  |  |  |  |  |  |  | 
| 96 | 0 |  |  |  |  |  | $info{$q[1], "exchange"} = "UNION"; | 
| 97 | 0 |  |  |  |  |  | $info{$q[1], "name"}     = $q[0]; | 
| 98 | 0 |  |  |  |  |  | $info{$q[1], "symbol"}   = $q[1]; | 
| 99 | 0 |  |  |  |  |  | $info{$q[1], "price"}    = $q[4]; | 
| 100 | 0 |  |  |  |  |  | $info{$q[1], "last"}     = $q[4]; | 
| 101 | 0 |  |  |  |  |  | $quoter->store_date(\%info, $q[1], {eurodate => $q[6]}); | 
| 102 | 0 |  |  |  |  |  | $info{$q[1], "method"}   = "unionfunds"; | 
| 103 | 0 |  |  |  |  |  | $info{$q[1], "currency"} = $q[2]; | 
| 104 | 0 |  |  |  |  |  | $info{$q[1], "success"}  = 1; | 
| 105 |  |  |  |  |  |  | } | 
| 106 |  |  |  |  |  |  | } | 
| 107 |  |  |  |  |  |  | } | 
| 108 |  |  |  |  |  |  | } | 
| 109 |  |  |  |  |  |  | # check to make sure a value was returned for every fund requested | 
| 110 | 0 |  |  |  |  |  | foreach my $fund (keys %fundhash) | 
| 111 |  |  |  |  |  |  | { | 
| 112 | 0 | 0 |  |  |  |  | if ($fundhash{$fund} == 0) | 
| 113 |  |  |  |  |  |  | { | 
| 114 | 0 |  |  |  |  |  | $info{$fund, "success"}  = 0; | 
| 115 | 0 |  |  |  |  |  | $info{$fund, "errormsg"} = "No data returned"; | 
| 116 |  |  |  |  |  |  | } | 
| 117 |  |  |  |  |  |  | } | 
| 118 |  |  |  |  |  |  |  | 
| 119 | 0 | 0 |  |  |  |  | return wantarray() ? %info : \%info; | 
| 120 |  |  |  |  |  |  |  | 
| 121 |  |  |  |  |  |  | } | 
| 122 |  |  |  |  |  |  |  | 
| 123 |  |  |  |  |  |  | 1; | 
| 124 |  |  |  |  |  |  |  | 
| 125 |  |  |  |  |  |  | # UNION provides a csv file named historische-preise.csv on | 
| 126 |  |  |  |  |  |  | # <https://www.union-investment.de/fonds_depot/fonds-finden/preise-berechnen#HistorischeTagespreise> | 
| 127 |  |  |  |  |  |  | # containing the prices of a selction of all their funds for a selected period. | 
| 128 |  |  |  |  |  |  |  | 
| 129 |  |  |  |  |  |  |  | 
| 130 |  |  |  |  |  |  | __END__ | 
| 131 |  |  |  |  |  |  |  | 
| 132 |  |  |  |  |  |  | =head1 NAME | 
| 133 |  |  |  |  |  |  |  | 
| 134 |  |  |  |  |  |  | Finance::Quote::Union	- Obtain quotes from UNION (Union Investment). | 
| 135 |  |  |  |  |  |  |  | 
| 136 |  |  |  |  |  |  | =head1 SYNOPSIS | 
| 137 |  |  |  |  |  |  |  | 
| 138 |  |  |  |  |  |  | use Finance::Quote; | 
| 139 |  |  |  |  |  |  |  | 
| 140 |  |  |  |  |  |  | $q = Finance::Quote->new; | 
| 141 |  |  |  |  |  |  |  | 
| 142 |  |  |  |  |  |  | %stockinfo = $q->fetch("unionfunds","DE0008491002"); | 
| 143 |  |  |  |  |  |  |  | 
| 144 |  |  |  |  |  |  | =head1 DESCRIPTION | 
| 145 |  |  |  |  |  |  |  | 
| 146 |  |  |  |  |  |  | This module obtains information about UNION managed funds. | 
| 147 |  |  |  |  |  |  |  | 
| 148 |  |  |  |  |  |  | Information returned by this module is governed by UNION's terms | 
| 149 |  |  |  |  |  |  | and conditions. | 
| 150 |  |  |  |  |  |  |  | 
| 151 |  |  |  |  |  |  | Note that previous versions of the module required the WKN, | 
| 152 |  |  |  |  |  |  | now the ISIN is needed as symbol value. | 
| 153 |  |  |  |  |  |  |  | 
| 154 |  |  |  |  |  |  | =head1 LABELS RETURNED | 
| 155 |  |  |  |  |  |  |  | 
| 156 |  |  |  |  |  |  | The following labels may be returned by Finance::Quote::UNION: | 
| 157 |  |  |  |  |  |  | exchange, name, date, price, last. | 
| 158 |  |  |  |  |  |  |  | 
| 159 |  |  |  |  |  |  | =head1 SEE ALSO | 
| 160 |  |  |  |  |  |  |  | 
| 161 |  |  |  |  |  |  | UNION (Union Investment), https://www.union-investment.de/ | 
| 162 |  |  |  |  |  |  |  | 
| 163 |  |  |  |  |  |  | =cut |