File Coverage

blib/lib/Finance/Quote.pm
Criterion Covered Total %
statement 230 377 61.0
branch 61 162 37.6
condition 28 64 43.7
subroutine 37 52 71.1
pod 32 32 100.0
total 388 687 56.4


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             #
9             # This program is free software; you can redistribute it and/or modify
10             # it under the terms of the GNU General Public License as published by
11             # the Free Software Foundation; either version 2 of the License, or
12             # (at your option) any later version.
13             #
14             # This program is distributed in the hope that it will be useful,
15             # but WITHOUT ANY WARRANTY; without even the implied warranty of
16             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17             # GNU General Public License for more details.
18             #
19             # You should have received a copy of the GNU General Public License
20             # along with this program; if not, write to the Free Software
21             # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
22             # 02110-1301, USA
23             #
24             #
25             # This code derived from Padzensky's work on package Finance::YahooQuote,
26             # but extends its capabilites to encompas a greater number of data sources.
27             #
28             # This code was developed as part of GnuCash <http://www.gnucash.org/>
29              
30             package Finance::Quote;
31              
32 60     60   6686382 use strict;
  60         815  
  60         2533  
33              
34 60     60   368 use constant DEBUG => $ENV{DEBUG};
  60         136  
  60         6399  
35 60     60   21370 use if DEBUG, 'Smart::Comments', '###';
  60         509  
  60         399  
36              
37 60     60   33445 use Module::Load;
  60         70836  
  60         401  
38 60     60   3115 use Exporter ();
  60         145  
  60         1036  
39 60     60   283 use Carp;
  60         125  
  60         3776  
40 60     60   27589 use Finance::Quote::UserAgent;
  60         225  
  60         2387  
41 60     60   32997 use HTTP::Request::Common;
  60         143867  
  60         4326  
42 60     60   32133 use Encode;
  60         894193  
  60         5057  
43 60     60   40468 use JSON qw( decode_json );
  60         630608  
  60         416  
44              
45 60         14227 use vars qw/@ISA @EXPORT @EXPORT_OK @EXPORT_TAGS
46             $TIMEOUT @MODULES %MODULES %METHODS $AUTOLOAD
47 60     60   9423 @CURRENCY_RATES_MODULES $USE_EXPERIMENTAL_UA/;
  60         161  
48              
49             our $VERSION = '1.57_03'; # TRIAL VERSION
50              
51             @CURRENCY_RATES_MODULES = qw/
52             AlphaVantage
53             ECB
54             Fixer
55             OpenExchange
56             YahooJSON
57             /;
58              
59             @MODULES = qw/
60             AEX
61             ASEGR
62             ASX
63             AlphaVantage
64             BSEIndia
65             Bloomberg
66             Bourso
67             BVB
68             CSE
69             Cdnfundlibrary
70             Comdirect
71             Currencies
72             DWS
73             Deka
74             FTfunds
75             Fidelity
76             Finanzpartner
77             Fondsweb
78             Fool
79             Fundata
80             GoldMoney
81             GoogleWeb
82             HU
83             IEXCloud
84             IndiaMutual
85             MarketWatch
86             MorningstarAU
87             MorningstarCH
88             MorningstarJP
89             MorningstarUK
90             NSEIndia
91             NZX
92             OnVista
93             Oslobors
94             SEB
95             SIX
96             Sinvestor
97             TesouroDireto
98             Tiaacref
99             TMX
100             Tradegate
101             TreasuryDirect
102             Troweprice
103             TSP
104             TwelveData
105             Union
106             XETRA
107             YahooJSON
108             YahooWeb
109             ZA
110             /;
111              
112             @ISA = qw/Exporter/;
113             @EXPORT = ();
114             @EXPORT_OK = qw/fidelity troweprice asx tiaacref
115             currency_lookup/;
116             @EXPORT_TAGS = ( all => [@EXPORT_OK]);
117              
118             $USE_EXPERIMENTAL_UA = 0;
119              
120             ################################################################################
121             #
122             # Private Class Methods
123             #
124             ################################################################################
125             # Autoload method for obsolete methods. This also allows people to
126             # call methods that objects export without having to go through fetch.
127              
128             sub AUTOLOAD {
129 0     0   0 my $method = $AUTOLOAD;
130 0         0 (my $name = $method) =~ s/.*:://;
131              
132             # Force the dummy object (and hence default methods) to be loaded.
133 0         0 _dummy();
134              
135 0 0       0 if (exists($METHODS{$name})) {
136 60     60   464 no strict 'refs'; ## no critic
  60         153  
  60         262692  
137            
138             *$method = sub {
139 0 0   0   0 my $this = ref($_[0]) ? shift : _dummy();
140 0         0 $this->fetch($name, @_);
141 0         0 };
142              
143 0         0 return &$method;
144             }
145              
146 0         0 carp "$AUTOLOAD does not refer to a known method.";
147             }
148              
149             # Dummy destroy function to avoid AUTOLOAD catching it.
150 0     0   0 sub DESTROY { return; }
151              
152             # _convert (private object method)
153             #
154             # This function converts between one currency and another. It expects
155             # to receive a hashref to the information, a reference to a list
156             # of the stocks to be converted, and a reference to a list of fields
157             # that conversion should apply to.
158              
159             {
160             my %conversion; # Conversion lookup table.
161              
162             sub _convert {
163 0     0   0 my $this = shift;
164 0         0 my $info = shift;
165 0         0 my $stocks = shift;
166 0         0 my $convert_fields = shift;
167 0         0 my $new_currency = $this->{"currency"};
168              
169             # Skip all this unless they actually want conversion.
170 0 0       0 return unless $new_currency;
171              
172 0         0 foreach my $stock (@$stocks) {
173 0         0 my $currency;
174              
175             # Skip stocks that don't have a currency.
176 0 0       0 next unless ($currency = $info->{$stock,"currency"});
177              
178             # Skip if it's already in the same currency.
179 0 0       0 next if ($currency eq $new_currency);
180              
181             # Lookup the currency conversion if we haven't
182             # already.
183 0 0       0 unless (exists $conversion{$currency,$new_currency}) {
184 0         0 $conversion{$currency,$new_currency} =
185             $this->currency($currency,$new_currency);
186             }
187              
188             # Make sure we have a reasonable currency conversion.
189             # If we don't, mark the stock as bad.
190 0 0       0 unless ($conversion{$currency,$new_currency}) {
191 0         0 $info->{$stock,"success"} = 0;
192 0         0 $info->{$stock,"errormsg"} =
193             "Currency conversion failed.";
194 0         0 next;
195             }
196              
197             # Okay, we have clean data. Convert it. Ideally
198             # we'd like to just *= entire fields, but
199             # unfortunately some things (like ranges,
200             # capitalisation, etc) don't take well to that.
201             # Hence we pull out any numbers we see, convert
202             # them, and stick them back in. That's pretty
203             # yucky, but it works.
204              
205 0         0 foreach my $field (@$convert_fields) {
206 0 0       0 next unless (defined $info->{$stock,$field});
207              
208 0         0 $info->{$stock,$field} = $this->scale_field($info->{$stock,$field},$conversion{$currency,$new_currency});
209             }
210              
211             # Set the new currency.
212 0         0 $info->{$stock,"currency"} = $new_currency;
213             }
214             }
215             }
216              
217             # =======================================================================
218             # _dummy (private function)
219             #
220             # _dummy returns a Finance::Quote object. I'd really rather not have
221             # this, but to maintain backwards compatibility we hold on to it.
222             {
223             my $dummy_obj;
224             sub _dummy {
225 6   66 6   22 return $dummy_obj ||= Finance::Quote->new;
226             }
227             }
228              
229             # _load_module (private class method)
230             # _load_module loads a module(s) and registers its various methods for
231             # use.
232              
233             sub _load_modules {
234 14     14   25 my $class = shift;
235 14   33     46 my $baseclass = ref $class || $class;
236              
237 14         123 my @modules = @_;
238              
239             # Go to each module and use them. Also record what methods
240             # they support and enter them into the %METHODS hash.
241              
242 14         40 foreach my $module (@modules) {
243 700         1546 my $modpath = "${baseclass}::${module}";
244 700 100       1678 unless (defined($MODULES{$modpath})) {
245              
246 250         429 eval {
247 250         837 load $modpath;
248 250         3419 $MODULES{$modpath} = 1;
249              
250 250         1282 my %methodhash = $modpath->methods;
251 250         818 my %labelhash = $modpath->labels;
252 250   50     3767 my $curr_fields_func = $modpath->can("currency_fields") || \&default_currency_fields;
253 250         675 my @currency_fields = &$curr_fields_func;
254 250         444 my %seen;
255 250         513 @currency_fields = grep {!$seen{$_}++} @currency_fields;
  3750         8999  
256              
257 250         855 foreach my $method (keys %methodhash) {
258 480         3515 push (@{$METHODS{$method}},
259             { name => $module,
260             modpath => $modpath,
261             function => $methodhash{$method},
262 480         681 labels => $labelhash{$method},
263             currency_fields => \@currency_fields});
264             }
265             };
266 250 50       1002 carp $@ if $@;
267             }
268             }
269             }
270              
271             # _smart_compare (private method function)
272             #
273             # This function compares values where the method depends on the
274             # type of the parameters.
275             # val1, val2
276             # scalar,scaler - test for substring match
277             # scalar,regex - test val1 against val2 regex
278             # array,scalar - return true if any element of array substring matches scalar
279             # array,regex - return true if any element of array matches regex
280             sub _smart_compare {
281 674     674   1127 my ($val1, $val2) = @_;
282            
283 674 50       1016 if ( ref $val1 eq 'ARRAY' ) {
284 0 0       0 if ( ref $val2 eq 'Regexp' ) {
285 0         0 my @r = grep {$_ =~ $val2} @$val1;
  0         0  
286 0         0 return @r > 0;
287             }
288             else {
289 0         0 my @r = grep {$_ =~ /$val2/} @$val1;
  0         0  
290 0         0 return @r > 0;
291             }
292             }
293             else {
294 674 100       1031 if ( ref $val2 eq 'Regexp' ) {
295 504         1432 return $val1 =~ $val2;
296             }
297             else {
298 170         363 return index($val1, $val2) > -1
299             }
300             }
301             }
302              
303             # This is a list of fields that will be automatically converted during
304             # currency conversion. If a module provides a currency_fields()
305             # function then that list will be used instead.
306              
307             sub get_default_currency_fields {
308 251     251 1 3525 return qw/last high low net bid ask close open day_range year_range
309             eps div cap nav price/;
310             }
311              
312             sub get_default_timeout {
313 2     2 1 460 return $TIMEOUT;
314             }
315              
316             # get_methods returns a list of sources which can be passed to fetch to
317             # obtain information.
318              
319             sub get_methods {
320             # Create a dummy object to ensure METHODS is populated
321 1     1 1 442 my $t = Finance::Quote->new();
322 1 50       49 return(wantarray ? keys %METHODS : [keys %METHODS]);
323             }
324              
325             # return hash:
326             #
327             # quote_methods => hash of
328             # method_name => array of module names
329             # quote_modules => hash of
330             # module_name => array of parameters
331             # currency_modules => hash of
332             # module_name => array of parameters
333             #
334             # {
335             # 'quote_methods' => {'group' => ['module', 'module'], ...},
336             # 'quote_modules' => {'abc' => ['API_KEY'], ...},
337             # 'currency_modules' => {'xyz' => [], 'lmn' => ['USER_NAME', 'API_KEY']},
338             # }
339              
340             sub get_features {
341             # Create a dummy object to ensure METHODS is populated
342 1     1 1 8 my $t = Finance::Quote->new(currency_rates => {order => \@CURRENCY_RATES_MODULES});
343 1         4 my $baseclass = ref $t;
344              
345             my %feature = (
346 77         98 'quote_methods' => {map {$_, [map {$_->{name}} @{$METHODS{$_}}]} keys %METHODS},
  96         329  
  77         167  
347 50         128 'quote_modules' => {map {$_, []} @MODULES},
348 1         49 'currency_modules' => {map {$_, []} @CURRENCY_RATES_MODULES},
  5         18  
349             );
350              
351 1         18 my %mods = ('quote_modules' => $baseclass,
352             'currency_modules' => "${baseclass}::CurrencyRates");
353              
354 1         10 while (my ($field, $base) = each %mods) {
355 2         3 foreach my $name (keys %{$feature{$field}}) {
  2         12  
356 55         101 my $modpath = "${base}::${name}";
357              
358 55 100       577 if ($modpath->can("parameters")) {
359 9         16 push (@{$feature{$field}->{$name}}, $modpath->parameters());
  9         57  
360             }
361             }
362             }
363              
364 1         17 return %feature;
365             }
366              
367             # =======================================================================
368             # new (public class method)
369             #
370             # Returns a new Finance::Quote object.
371             #
372             # Arguments ::
373             # - zero or more module names from the Finance::Quote::get_sources list
374             # - zero or more named parameters, passes as name => value
375             #
376             # Named Parameters ::
377             # - timeout # timeout in seconds for web requests
378             # - failover # boolean value indicating if failover is acceptable
379             # - fetch_currency # currency code for fetch results
380             # - required_labels # array of required labels in fetch results
381             # - <module-name> # hash specific to various Finance::Quote modules
382             #
383             # new() # default constructor
384             # new('a', 'b') # load only modules a and b
385             # new(timeout => 30) # load all default modules, set timeout
386             # new('a', fetch_currency => 'X') # load only module a, use currency X for results
387             # new('z' => {API_KEY => 'K'}) # load all modules, pass hash to module z constructor
388             # new('z', 'z' => {API_KEY => 'K'}) # load only module z and pass hash to its constructor
389             #
390             # Enivornment Variables ::
391             # - FQ_LOAD_QUOTELET # if no modules named in argument list, use ones in this variable
392             #
393             # Return Value ::
394             # - Finanace::Quote object
395              
396             sub new {
397             # Create and bless object
398 14     14 1 4974 my $self = shift;
399 14   33     81 my $class = ref($self) || $self;
400              
401 14         34 my $this = {};
402 14         33 bless $this, $class;
403              
404             # To add a named parameter:
405             # 0. Document it in the POD for new
406             # 1. Add a default value for $this->{object-name}
407             # 2. Add the 'user-visible-name' => [type, object-name] to %named_parameter
408              
409             # Check for FQ_CURRENCY - preferred currency module
410             # Set to AlphaVantage if not set or not in @CURRENCY_RATES_MODULES
411 14         24 my $CURRENCY_MODULE;
412 14 50       51 if (!$ENV{FQ_CURRENCY}) {
413 14         29 $CURRENCY_MODULE='AlphaVantage';
414             } else {
415 0 0       0 if ( grep( /^$ENV{FQ_CURRENCY}$/, @CURRENCY_RATES_MODULES ) ) {
416             $CURRENCY_MODULE=$ENV{FQ_CURRENCY}
417 0         0 } else {
418 0         0 $CURRENCY_MODULE='AlphaVantage';
419             }
420             }
421              
422             # Default values
423 14         56 $this->{FAILOVER} = 1;
424 14         34 $this->{REQUIRED} = [];
425 14 100       46 $this->{TIMEOUT} = $TIMEOUT if defined($TIMEOUT);
426 14         54 $this->{currency_rates} = {order => [$CURRENCY_MODULE]};
427              
428             # Sort out arguments
429 14         90 my %named_parameter = (timeout => ['', 'TIMEOUT'],
430             failover => ['', 'FAILOVER'],
431             fetch_currency => ['', 'currency'],
432             required_labels => ['ARRAY', 'REQUIRED'],
433             currency_rates => ['HASH', 'currency_rates']);
434              
435 14         33 $this->{module_specific_data} = {};
436 14         31 my @load_modules = ();
437              
438 14         54 for (my $i = 0; $i < @_; $i++) {
439 5 50 0     17 if (exists $named_parameter{$_[$i]}) {
    0          
    0          
440 5 50       18 die "missing value for named parameter $_[$i]" if $i + 1 == @_;
441 5 50       24 die "unexpect type for value of named parameter $_[$i]" if ref $_[$i+1] ne $named_parameter{$_[$i]}[0];
442              
443 5         16 $this->{$named_parameter{$_[$i]}[1]} = $_[$i+1];
444 5         14 $i += 1;
445             }
446             elsif ($i + 1 < @_ and ref $_[$i+1] eq 'HASH') {
447 0         0 $this->{module_specific_data}->{$_[$i]} = $_[$i+1];
448 0         0 $i += 1;
449             }
450             elsif ($_[$i] eq '-defaults') {
451 0         0 push (@load_modules, @MODULES);
452             }
453             else {
454 0         0 push (@load_modules, $_[$i]);
455             }
456             }
457              
458             # Honor FQ_LOAD_QUOTELET if @load_modules is empty
459 14 50 33     68 if ($ENV{FQ_LOAD_QUOTELET} and !@load_modules) {
    50          
460 0         0 @load_modules = split(' ',$ENV{FQ_LOAD_QUOTELET});
461 0 0       0 if ($load_modules[0] eq '-defaults') {
462 0         0 shift @load_modules;
463 0         0 push(@load_modules, @MODULES);
464             }
465             }
466             elsif (@load_modules == 0) {
467 14         151 push(@load_modules, @MODULES);
468             }
469              
470 14         58 $this->_load_modules(@load_modules);
471              
472             # Load the currency rate methods
473 14         41 my %currency_check = map { $_ => 1 } @CURRENCY_RATES_MODULES;
  70         178  
474 14         57 $this->{currency_rate_method} = [];
475 14         27 foreach my $method (@{$this->{currency_rates}->{order}}) {
  14         48  
476 18 50       61 unless (defined($currency_check{$method})) {
477 0         0 carp "Unknown curreny rates method: $method";
478 0         0 return;
479             }
480              
481 18         107 my $method_path = "${class}::CurrencyRates::${method}";
482 18         33 eval {
483 18         76 autoload $method_path;
484 18 50       1100 my $args = exists $this->{currency_rates}->{lc($method)} ? $this->{currency_rates}->{lc($method)} : {};
485 18         73 my $rate = $method_path->new($args);
486 18 100       78 die unless defined $rate;
487            
488 16         38 push(@{$this->{currency_rate_method}}, $rate);
  16         56  
489             };
490              
491 18 100       60 if ($@) {
492 2         7 next;
493             }
494             }
495              
496 14         207 return $this;
497             }
498              
499             sub set_default_timeout {
500 1     1 1 3 $TIMEOUT = shift;
501             }
502              
503             ################################################################################
504             #
505             # Private Object Methods
506             #
507             ################################################################################
508              
509             # _require_test (private object method)
510             #
511             # This function takes an array. It returns true if all required
512             # labels appear in the arrayref. It returns false otherwise.
513             #
514             # This function could probably be made more efficient.
515              
516             sub _require_test {
517 0     0   0 my $this = shift;
518 0         0 my %available;
519 0         0 @available{@_} = (); # Ooooh, hash-slice. :)
520 0         0 my @required = @{$this->{REQUIRED}};
  0         0  
521 0 0       0 return 1 unless @required;
522 0         0 for (my $i = 0; $i < @required; $i++) {
523 0 0       0 return 0 unless exists $available{$required[$i]};
524             }
525 0         0 return 1;
526             }
527              
528             ################################################################################
529             #
530             # Public Object Methods
531             #
532             ################################################################################
533              
534             # If $str ends with a B like "20B" or "1.6B" then expand it as billions like
535             # "20000000000" or "1600000000".
536             #
537             # This is done with string manipulations so floating-point rounding doesn't
538             # produce spurious digits for values like "1.6" which aren't exactly
539             # representable in binary.
540             #
541             # Is "B" for billions the only abbreviation from Yahoo?
542             # Could extend and rename this if there's also millions or thousands.
543             #
544             # For reference, if the value was just for use within perl then simply
545             # substituting to exponential "1.5e9" might work. But expanding to full
546             # digits seems a better idea as the value is likely to be printed directly
547             # as a string.
548             sub B_to_billions {
549 4     4 1 18 my ($self,$str) = @_;
550              
551             # B_to_billions() $str
552 4 50       29 if ($str =~ s/B$//i) {
553 4         15 $str = $self->decimal_shiftup ($str, 9);
554             }
555 4         22 return $str;
556             }
557              
558             # $str is a number like "123" or "123.45"
559             # return it with the decimal point moved $shift places to the right
560             # must have $shift>=1
561             # eg. decimal_shiftup("123",3) -> "123000"
562             # decimal_shiftup("123.45",1) -> "1234.5"
563             # decimal_shiftup("0.25",1) -> "2.5"
564             #
565             sub decimal_shiftup {
566 19     19 1 51 my ($self, $str, $shift) = @_;
567              
568             # delete decimal point and set $after to count of chars after decimal.
569             # Leading "0" as in "0.25" is deleted too giving "25" so as not to end up
570             # with something that might look like leading 0 for octal.
571 19 100       150 my $after = ($str =~ s/(?:^0)?\.(.*)/$1/ ? length($1) : 0);
572              
573 19         37 $shift -= $after;
574             # now $str is an integer and $shift is relative to the end of $str
575              
576 19 100       43 if ($shift >= 0) {
577             # moving right, eg. "1234" becomes "12334000"
578 12         69 return $str . ('0' x $shift); # extra zeros appended
579             } else {
580             # negative means left, eg. "12345" becomes "12.345"
581             # no need to prepend zeros since demanding initial $shift>=1
582 7         20 substr ($str, $shift,0, '.'); # new '.' at shifted spot from end
583 7         38 return $str;
584             }
585             }
586              
587             # =======================================================================
588             # fetch (public object method)
589             #
590             # Fetch is a wonderful generic fetcher. It takes a method and stuff to
591             # fetch. It's a nicer interface for when you have a list of stocks with
592             # different sources which you wish to deal with.
593             sub fetch {
594 0 0   0 1 0 my $this = ref($_[0]) ? shift : _dummy();
595              
596 0         0 my $method = lc(shift);
597 0         0 my @stocks = @_;
598              
599 0 0       0 unless (exists $METHODS{$method}) {
600 0         0 carp "Undefined fetch-method $method passed to ".
601             "Finance::Quote::fetch";
602 0         0 return;
603             }
604              
605             # Temporary Counting - not concerned about return code
606 0         0 my $COUNT_URL =
607             'http://www.panix.com/~hd-fxsts/finance-quote.html?' . $method;
608 0         0 my $count_ua = LWP::UserAgent->new(timeout => 10);
609 0         0 my $count_response = $count_ua->head($COUNT_URL);
610              
611             ### COUNT_URL: $COUNT_URL
612             ### Code: $count_response->code
613              
614             # Failover code. This steps through all available methods while
615             # we still have failed stocks to look-up. This loop only
616             # runs a single time unless FAILOVER is defined.
617 0         0 my %returnhash = ();
618              
619 0         0 foreach my $methodinfo (@{$METHODS{$method}}) {
  0         0  
620 0         0 my $funcref = $methodinfo->{"function"};
621 0 0       0 next unless $this->_require_test(@{$methodinfo->{"labels"}});
  0         0  
622 0         0 my @failed_stocks = ();
623 0         0 %returnhash = (%returnhash,&$funcref($this,@stocks));
624              
625 0         0 foreach my $stock (@stocks) {
626             push(@failed_stocks,$stock)
627 0 0       0 unless ($returnhash{$stock,"success"});
628             }
629              
630             $this->_convert(\%returnhash,\@stocks,
631 0         0 $methodinfo->{"currency_fields"});
632              
633 0 0       0 last unless $this->{FAILOVER};
634 0 0       0 last unless @failed_stocks;
635 0         0 @stocks = @failed_stocks;
636             }
637              
638 0 0       0 return wantarray() ? %returnhash : \%returnhash;
639             }
640              
641             sub get_failover {
642 3     3 1 10 my $self = shift;
643 3         15 return $self->{FAILOVER};
644             }
645              
646             sub get_fetch_currency {
647 3     3 1 14 my $self = shift;
648 3         14 return $self->{currency};
649             }
650              
651             sub get_required_labels {
652 3     3 1 15 my $self = shift;
653 3         18 return $self->{REQUIRED};
654             }
655              
656             sub get_timeout {
657 4     4 1 19 my $self = shift;
658 4         21 return $self->{TIMEOUT};
659             }
660              
661             sub get_user_agent {
662 2     2 1 12 my $this = shift;
663              
664 2 100       15 return $this->{UserAgent} if $this->{UserAgent};
665              
666 1         2 my $ua;
667              
668 1 50       4 if ($USE_EXPERIMENTAL_UA) {
669 0         0 $ua = Finance::Quote::UserAgent->new;
670             } else {
671 1         14 $ua = LWP::UserAgent->new;
672             }
673              
674 1 50       362 $ua->timeout($this->{TIMEOUT}) if defined($this->{TIMEOUT});
675 1         25 $ua->env_proxy;
676              
677 1         387 $this->{UserAgent} = $ua;
678              
679 1         52 return $ua;
680             }
681              
682             sub isoTime {
683 11     11 1 37 my ($self,$timeString) = @_ ;
684 11         27 $timeString =~ tr/ //d ;
685 11         23 $timeString = uc $timeString ;
686 11         17 my $retTime = "00:00"; # return zero time if unparsable input
687 11 50       76 if ($timeString=~m/^(\d+)[\.:UH](\d+) *(AM|am|PM|pm)?/) {
688 11         49 my ($hours,$mins)= ($1-0,$2-0) ;
689 11 50 66     40 $hours-=12 if ($hours==12 && $3 && ($3 =~ /AM/i));
      33        
690 11 100 100     64 $hours+=12 if ($3 && ($3 =~ /PM/i) && ($hours != 12));
      100        
691 11 100 33     65 if ($hours>=0 && $hours<=23 && $mins>=0 && $mins<=59 ) {
      33        
      66        
692 10         42 $retTime = sprintf ("%02d:%02d", $hours, $mins) ;
693             }
694             }
695 11         87 return $retTime;
696             }
697              
698             sub set_failover {
699 1     1 1 3 my $self = shift;
700 1         3 $self->{FAILOVER} = shift;
701             }
702              
703             sub set_fetch_currency {
704 1     1 1 3 my $self = shift;
705 1         3 $self->{currency} = shift;
706             }
707              
708             sub set_required_labels {
709 1     1 1 2 my $self = shift;
710 1         4 $self->{REQUIRED} = shift;
711             }
712              
713             sub set_timeout {
714 1     1 1 3 my $self = shift;
715 1         3 $self->{TIMEOUT} = shift;
716             }
717              
718             # =======================================================================
719             # store_date (public object method)
720             #
721             # Given the various pieces of a date, this functions figure out how to
722             # store them in both the pre-existing US date format (mm/dd/yyyy), and
723             # also in the ISO date format (yyyy-mm-dd). This function expects to
724             # be called with the arguments:
725             #
726             # (inforef, symbol_name, data_hash)
727             #
728             # The components of date hash can be any of:
729             #
730             # usdate - A date in mm/dd/yy or mm/dd/yyyy
731             # eurodate - A date in dd/mm/yy or dd/mm/yyyy
732             # isodate - A date in yy-mm-dd or yyyy-mm-dd, yyyy/mm/dd, yyyy.mm.dd, or yyyymmdd
733             # year - The year in yyyy
734             # month - The month in mm or mmm format (i.e. 07 or Jul)
735             # day - The day
736             # today - A flag to indicate todays date should be used.
737             #
738             # The separator for the *date forms is ignored. It can be any
739             # non-alphanumeric character. Any combination of year, month, and day
740             # values can be provided. Missing fields are filled in based upon
741             # today's date.
742             #
743             sub store_date
744             {
745 13     13 1 5540 my $this = shift;
746 13         21 my $inforef = shift;
747 13         21 my $symbol = shift;
748 13         19 my $piecesref = shift;
749              
750 13         25 my ($year, $month, $day, $this_month, $year_specified);
751 13         72 my %mnames = (jan => 1, feb => 2, mar => 3, apr => 4, may => 5, jun => 6,
752             jul => 7, aug => 8, sep => 9, oct =>10, nov =>11, dec =>12);
753              
754             ### store_date symbol: $symbol
755             ### store_date pieces: $piecesref
756              
757             # Default to today's date.
758 13         274 ($month, $day, $year) = (localtime())[4,3,5];
759 13         40 $month++;
760 13         31 $year += 1900;
761 13         21 $this_month = $month;
762 13         21 $year_specified = 0;
763              
764             # Process the inputs
765 13 50 66     51 if ((defined $piecesref->{isodate}) && ($piecesref->{isodate})) {
766 3 50       19 if ($piecesref->{isodate} =~ /^([0-9]{4})([0-9]{2})([0-9]{2})$/) {
767 0         0 ($year, $month, $day) = ($1, $2, $3);
768             }
769             else {
770 3         19 ($year, $month, $day) = ($piecesref->{isodate} =~ m|([0-9]{4})\W+(\w+)\W+(\w+)|);
771             }
772              
773 3 50       12 $year += 2000 if $year < 100;
774 3         7 $year_specified = 1;
775              
776             ### format: printf "isodate %s -> Day %d, Month %s, Year %d\n", $piecesref->{isodate}, $day, $month, $year
777             }
778              
779 13 50 66     39 if ((defined $piecesref->{usdate}) && ($piecesref->{usdate})) {
780 3         24 ($month, $day, $year) = ($piecesref->{usdate} =~ /(\w+)\W+(\d+)\W+(\d+)/);
781 3 50       13 $year += 2000 if $year < 100;
782 3         5 $year_specified = 1;
783              
784             ### format: printf "usdate %s -> Day %d, Month %s, Year %d\n", $piecesref->{usdate}, $day, $month, $year
785             }
786              
787 13 50 66     40 if ((defined $piecesref->{eurodate}) && ($piecesref->{eurodate})) {
788 3         25 ($day, $month, $year) = ($piecesref->{eurodate} =~ /(\d+)\W+(\w+)\W+(\d+)/);
789 3 50       12 $year += 2000 if $year < 100;
790 3         5 $year_specified = 1;
791              
792             ### format: printf "eurodate %s -> Day %d, Month %s, Year %d\n", $piecesref->{eurodate}, $day, $month, $year
793             }
794              
795 13 100       30 if (defined ($piecesref->{year})) {
796 1         3 $year = $piecesref->{year};
797 1 50       5 $year += 2000 if $year < 100;
798 1         3 $year_specified = 1;
799              
800             ### format: printf "year %s -> Year %d\n", $piecesref->{year}, $year
801             }
802              
803 13 100       24 if (defined ($piecesref->{month})) {
804 3         8 $month = $piecesref->{month};
805              
806             ### format: printf "month %s -> Month %s\n", $piecesref->{month}, $month
807             }
808              
809 13 100       31 if (defined ($piecesref->{day})) {
810 3         5 $day = $piecesref->{day};
811              
812             ### format: printf "day %s -> Day %d\n", $piecesref->{day}, $day
813             }
814              
815 13 100       56 $month = $mnames{lc(substr($month,0,3))} if ($month =~ /\D/);
816 13 100 100     42 $year-- if (($year_specified == 0) && ($this_month < $month));
817              
818             ### format: printf "Final Year-Month-Day -> %04d-%02d-%02d\n", $year, $month, $day
819              
820 13         77 $inforef->{$symbol, "date"} = sprintf "%02d/%02d/%04d", $month, $day, $year;
821 13         92 $inforef->{$symbol, "isodate"} = sprintf "%04d-%02d-%02d", $year, $month, $day;
822             }
823              
824             ################################################################################
825             #
826             # Public Class or Object Methods
827             #
828             ################################################################################
829              
830             # =======================================================================
831             # Helper function that can scale a field. This is useful because it
832             # handles things like ranges "105.4 - 108.3", and not just straight fields.
833             #
834             # The function takes a string or number to scale, and the factor to scale
835             # it by. For example, scale_field("1023","0.01") would return "10.23".
836              
837             sub scale_field {
838 1 50   1 1 940 shift if ref $_[0]; # Shift off the object, if there is one.
839              
840 1         4 my ($field, $scale) = @_;
841 1         7 my @chunks = split(/([^0-9.])/,$field);
842              
843 1         6 for (my $i=0; $i < @chunks; $i++) {
844 1 50       8 next unless $chunks[$i] =~ /\d/;
845 1         7 $chunks[$i] *= $scale;
846             }
847 1         16 return join("",@chunks);
848             }
849              
850             # =======================================================================
851             # currency (public object method)
852             #
853             # currency allows the conversion of one currency to another.
854             #
855             # Usage: $quoter->currency("USD","AUD");
856             # $quoter->currency("15.95 USD","AUD");
857             #
858             # undef is returned upon error.
859              
860             sub currency {
861 0 0   0 1 0 my $this = ref($_[0]) ? shift : _dummy();
862              
863 0         0 my ($from_code, $to_code) = @_;
864 0 0 0     0 return unless ($from_code and $to_code);
865              
866 0         0 $from_code =~ s/^\s*(\d*\.?\d*)\s*//;
867 0   0     0 my $amount = $1 || 1;
868              
869 0         0 $to_code = uc($to_code);
870 0         0 $from_code = uc($from_code);
871              
872 0 0       0 return $amount if ($from_code eq $to_code); # Trivial case.
873              
874 0         0 my $ua = $this->get_user_agent;
875            
876 0         0 foreach my $rate (@{$this->{currency_rate_method}}) {
  0         0  
877             ### rate: ref($rate)
878 0         0 my $final = eval {
879 0         0 my ($from, $to) = $rate->multipliers($ua, $from_code, $to_code);
880              
881 0 0 0     0 die("Failed to find currency rates for $from_code or $to_code") unless defined $from and defined $to;
882              
883             ### to weight : $to
884             ### from weight: $from
885             ### amount : $amount
886              
887             # Is from closest to (amount, to, amount * to)?
888             # (amount * to) / from
889 0         0 my $delta = abs($amount - $from);
890 0         0 my $result = ($amount/$from) * $to;
891             ### amount/from -> delta/result : ($delta, $result)
892 0 0       0 if ($delta > abs($to - $from)) {
893 0         0 $delta = abs($to - $from);
894 0         0 $result = ($to/$from) * $amount;
895             ### to/from -> delta/result : ($delta, $result)
896             }
897 0 0       0 if ($delta > abs($amount*$to - $from)) {
898 0         0 $delta = abs($amount*$to - $from);
899 0         0 $result = ($amount * $to)/$from;
900             ### (amount * to)/from -> delta/result : ($delta, $result)
901             }
902              
903 0         0 return $result;
904             };
905              
906 0 0       0 if ($@) {
907             ### Rate Error: chomp($@), $@
908 0         0 next;
909             }
910              
911 0         0 return $final;
912             }
913              
914 0         0 return;
915             }
916              
917             # =======================================================================
918             # currency_lookup (public object method)
919             #
920             # search for available currency codes
921             #
922             # Usage:
923             # $currency = $quoter->currency_lookup();
924             # $currency = $quoter->currency_lookup( name => "Dollar");
925             # $currency = $quoter->currency_loopup( country => qw/denmark/i );
926             # $currency = $q->currency_lookup(country => qr/united states/i, number => 840);
927             #
928             # If more than one lookup parameter is given all must match for
929             # a currency to match.
930             #
931             # undef is returned upon error.
932              
933             sub currency_lookup {
934 6 50   6 1 6170 my $this = ref $_[0] ? shift : _dummy();
935              
936 6         19 my %params = @_;
937 6         23 my $currencies = Finance::Quote::Currencies::known_currencies();
938              
939 6         62 my %attributes = map {$_ => 1} map {keys %$_} values %$currencies;
  4032         6017  
  1008         1889  
940              
941 6         313 for my $key (keys %params ) {
942 7 100       21 if ( ! exists $attributes{$key}) {
943 1         21 warn "Invalid parameter: $key";
944 1         9 return;
945             }
946             }
947            
948 5         22 while (my ($tag, $check) = each(%params)) {
949 6         83 $currencies = {map {$_ => $currencies->{$_}} grep {_smart_compare($currencies->{$_}->{$tag}, $check)} keys %$currencies};
  12         58  
  674         7704  
950             }
951            
952 5         24 return $currencies;
953             }
954              
955             # =======================================================================
956             # parse_csv (public object method)
957             #
958             # Grabbed from the Perl Cookbook. Parsing csv isn't as simple as you thought!
959             #
960             sub parse_csv
961             {
962 0 0   0 1 0 shift if (ref $_[0]); # Shift off the object if we have one.
963 0         0 my $text = shift; # record containing comma-separated values
964 0         0 my @new = ();
965              
966 0         0 push(@new, $+) while $text =~ m{
967             # the first part groups the phrase inside the quotes.
968             # see explanation of this pattern in MRE
969             "([^\"\\]*(?:\\.[^\"\\]*)*)",?
970             | ([^,]+),?
971             | ,
972             }gx;
973 0 0       0 push(@new, undef) if substr($text, -1,1) eq ',';
974              
975 0         0 return @new; # list of values that were comma-separated
976             }
977              
978             # =======================================================================
979             # parse_csv_semicolon (public object method)
980             #
981             # Grabbed from the Perl Cookbook. Parsing csv isn't as simple as you thought!
982             #
983             sub parse_csv_semicolon
984             {
985 0 0   0 1 0 shift if (ref $_[0]); # Shift off the object if we have one.
986 0         0 my $text = shift; # record containing comma-separated values
987 0         0 my @new = ();
988              
989 0         0 push(@new, $+) while $text =~ m{
990             # the first part groups the phrase inside the quotes.
991             # see explanation of this pattern in MRE
992             "([^\"\\]*(?:\\.[^\"\\]*)*)";?
993             | ([^;]+);?
994             | ;
995             }gx;
996 0 0       0 push(@new, undef) if substr($text, -1,1) eq ';';
997              
998 0         0 return @new; # list of values that were comma-separated
999             }
1000              
1001             ###############################################################################
1002             #
1003             # Legacy Class Methods
1004             #
1005             ###############################################################################
1006              
1007             sub sources {
1008 0     0 1 0 return get_methods();
1009             }
1010              
1011             sub default_currency_fields {
1012 250     250 1 604 return get_default_currency_fields();
1013             }
1014              
1015             ###############################################################################
1016             #
1017             # Legacy Class or Object Methods
1018             #
1019             ###############################################################################
1020              
1021             # =======================================================================
1022             # set_currency (public object method)
1023             #
1024             # set_currency allows information to be requested in the specified
1025             # currency. If called with no arguments then information is returned
1026             # in the default currency.
1027             #
1028             # Requesting stocks in a particular currency increases the time taken,
1029             # and the likelyhood of failure, as additional operations are required
1030             # to fetch the currency conversion information.
1031             #
1032             # This method should only be called from the quote object unless you
1033             # know what you are doing.
1034              
1035             sub set_currency {
1036 0 0 0 0 1   if (@_ == 1 or !ref($_[0])) {
1037             # Direct or class call - there is no class default currency
1038 0           return;
1039             }
1040              
1041 0           my $this = shift;
1042 0 0         if (defined($_[0])) {
1043 0           $this->set_fetch_currency($_[0]);
1044             }
1045              
1046 0           return $this->get_fetch_currency();
1047             }
1048              
1049             # =======================================================================
1050             # Timeout code. If called on a particular object, then it sets
1051             # the timout for that object only. If called as a class method
1052             # (or as Finance::Quote::timeout) then it sets the default timeout
1053             # for all new objects that will be created.
1054              
1055             sub timeout {
1056 0 0 0 0 1   if (@_ == 1 or !ref($_[0])) {
1057             # Direct or class call
1058 0           Finance::Quote::set_default_timeout(shift);
1059 0           return Finance::Quote::get_default_timeout();
1060             }
1061              
1062             # Otherwise we were called through an object. Yay.
1063             # Set the timeout in this object only.
1064 0           my $this = shift;
1065 0           $this->set_timeout(shift);
1066 0           return $this->get_timeout();
1067             }
1068              
1069             ###############################################################################
1070             #
1071             # Legacy Object Methods
1072             #
1073             ###############################################################################
1074              
1075             # =======================================================================
1076             # failover (public object method)
1077             #
1078             # This sets/gets whether or not it's acceptable to use failover techniques.
1079              
1080             sub failover {
1081 0     0 1   my $this = shift;
1082 0           my $value = shift;
1083              
1084 0 0         $this->set_failover($value) if defined $value;
1085 0           return $this->get_failover();
1086             }
1087              
1088             # =======================================================================
1089             # require_labels (public object method)
1090             #
1091             # Require_labels indicates which labels are required for lookups. Only methods
1092             # that have registered all the labels specified in the list passed to
1093             # require_labels() will be called.
1094             #
1095             # require_labels takes a list of required labels. When called with no
1096             # arguments, the require list is cleared.
1097             #
1098             # This method always succeeds.
1099              
1100             sub require_labels {
1101 0     0 1   my $this = shift;
1102 0           my @labels = @_;
1103 0           $this->set_required_labels(\@labels);
1104 0           return;
1105             }
1106              
1107             # =======================================================================
1108             # user_agent (public object method)
1109             #
1110             # Returns a LWP::UserAgent which conforms to the relevant timeouts,
1111             # proxies, and other settings on the particular Finance::Quote object.
1112             #
1113             # This function is mainly intended to be used by the modules that we load,
1114             # but it can be used by the application to directly play with the
1115             # user-agent settings.
1116              
1117             sub user_agent {
1118 0     0 1   my $this = shift;
1119 0           return $this->get_user_agent();
1120             }
1121              
1122             1;
1123              
1124             __END__
1125              
1126             =for comment README.md generated from lib/Finance/Quote.pm
1127              
1128             =head1 NAME
1129              
1130             Finance::Quote - Get stock and mutual fund quotes from various exchanges
1131              
1132             =head1 SYNOPSIS
1133              
1134             use Finance::Quote;
1135              
1136             $q = Finance::Quote->new;
1137             %quotes = $q->fetch("nasdaq", @stocks);
1138              
1139             =head1 DESCRIPTION
1140              
1141             This module gets stock quotes from various internet sources all over the world.
1142             Quotes are obtained by constructing a quoter object and using the fetch method
1143             to gather data, which is returned as a two-dimensional hash (or a reference to
1144             such a hash, if called in a scalar context). For example:
1145              
1146             $q = Finance::Quote->new;
1147             %info = $q->fetch("australia", "CML");
1148             print "The price of CML is ".$info{"CML", "price"};
1149              
1150             The first part of the hash (eg, "CML") is referred to as the stock.
1151             The second part (in this case, "price") is referred to as the label.
1152              
1153             =head2 LABELS
1154              
1155             When information about a stock is returned, the following standard labels may
1156             be used. Some custom-written modules may use labels not mentioned here. If
1157             you wish to be certain that you obtain a certain set of labels for a given
1158             stock, you can specify that using require_labels().
1159              
1160             ask Ask
1161             avg_vol Average Daily Vol
1162             bid Bid
1163             cap Market Capitalization
1164             close Previous Close
1165             currency Currency code for the returned data
1166             date Last Trade Date (MM/DD/YY format)
1167             day_range Day's Range
1168             div Dividend per Share
1169             div_date Dividend Pay Date
1170             div_yield Dividend Yield
1171             eps Earnings per Share
1172             errormsg If success is false, this field may contain the reason why.
1173             ex_div Ex-Dividend Date.
1174             exchange The exchange the information was obtained from.
1175             high Highest trade today
1176             isin International Securities Identification Number
1177             isodate ISO 8601 formatted date
1178             last Last Price
1179             low Lowest trade today
1180             method The module (as could be passed to fetch) which found this information.
1181             name Company or Mutual Fund Name
1182             nav Net Asset Value
1183             net Net Change
1184             open Today's Open
1185             p_change Percent Change from previous day's close
1186             pe P/E Ratio
1187             success Did the stock successfully return information? (true/false)
1188             time Last Trade Time
1189             type The type of equity returned
1190             volume Volume
1191             year_range 52-Week Range
1192             yield Yield (usually 30 day avg)
1193              
1194             If all stock lookups fail (possibly because of a failed connection) then the
1195             empty list may be returned, or undef in a scalar context.
1196              
1197             =head1 INSTALLATION
1198              
1199             Please note that the Github repository is not meant for general users
1200             of Finance::Quote for installation.
1201              
1202             If you downloaded the Finance-Quote-N.NN.tar.gz tarball from CPAN
1203             (N.NN is the version number, ex: Finance-Quote-1.50.tar.gz),
1204             run the following commands:
1205              
1206             tar xzf Finance-Quote-1.50.tar.gz
1207             cd Finance-Quote-1.50.tar.gz
1208             perl Makefile.PL
1209             make
1210             make test
1211             make install
1212              
1213             If you have the CPAN module installed:
1214             Using cpanm (Requires App::cpanminus)
1215              
1216             cpanm Finance::Quote
1217              
1218             or
1219             Using CPAN shell
1220              
1221             perl -MCPAN -e shell
1222             install Finance::Quote
1223              
1224             =head1 SUPPORT AND DOCUMENTATION
1225              
1226             After installing, you can find documentation for this module with the
1227             perldoc command.
1228              
1229             perldoc Finance::Quote
1230              
1231             You can also look for information at:
1232              
1233             =over
1234              
1235             =item Finance::Quote GitHub project
1236              
1237             https://github.com/finance-quote/finance-quote
1238              
1239             =item Search CPAN
1240              
1241             http://search.cpan.org/dist/Finance-Quote
1242              
1243             =item The Finance::Quote home page
1244              
1245             http://finance-quote.sourceforge.net/
1246              
1247             =item The Finance::YahooQuote home page
1248              
1249             http://www.padz.net/~djpadz/YahooQuote/
1250              
1251             =item The GnuCash home page
1252              
1253             http://www.gnucash.org/
1254              
1255             =back
1256              
1257             =head1 PUBLIC CLASS METHODS
1258              
1259             Finance::Quote implements public class methods for constructing a quoter
1260             object, getting or setting default class values, and for listing available
1261             methods.
1262              
1263             =head2 new
1264              
1265             my $q = Finance::Quote->new()
1266             my $q = Finance::Quote->new('-defaults')
1267             my $q = Finance::Quote->new('AEX', 'Fool')
1268             my $q = Finance::Quote->new(timeout => 30)
1269             my $q = Finance::Quote->new('YahooJSON', fetch_currency => 'EUR')
1270             my $q = Finance::Quote->new('alphavantage' => {API_KEY => '...'})
1271             my $q = Finance::Quote->new('IEXCloud', 'iexcloud' => {API_KEY => '...'});
1272             my $q = Finance::Quote->new(currency_rates => {order => ['ECB', 'Fixer'], 'fixer' => {API_KEY => '...'}});
1273              
1274             Finance::Quote modules access a wide range of sources to provide quotes. A
1275             module provides one or more methods to fetch quotes. One method is usually the
1276             name of the module in lower case. Other methods, if provided, are descriptive
1277             names, such as 'canada', 'nasdaq', or 'nyse'.
1278              
1279             A Finance::Quote object uses one or more methods to fetch quotes for
1280             securities.
1281              
1282             C<new> constructs a Finance::Quote object and enables the caller to load only
1283             specific modules, set parameters that control the behavior of the fetch method,
1284             and pass method specific parameters.
1285              
1286             =over
1287              
1288             =item C<timeout => T> sets the web request timeout to C<T> seconds
1289              
1290             =item C<failover => B> where C<B> is a boolean value indicating if failover in
1291             fetch is permitted
1292              
1293             =item C<fetch_currency => C> sets the desired currency code to C<C> for fetch
1294             results
1295              
1296             =item C<currency_rates => H> configures the order currency rate modules are
1297             consulted for exchange rates and currency rate module options
1298              
1299             =item C<required_labels => A> sets the required labels for fetch results to
1300             array C<A>
1301              
1302             =item C<<ModuleName>> as a string is the name of a specific
1303             Finance::Quote::Module to load
1304              
1305             =item C<<methodname> => H> passes hash C<H> to methodname during fetch to
1306             configure the method
1307              
1308             =back
1309              
1310             With no arguments, C<new> creates a Finance::Quote object with the default
1311             methods. If the environment variable FQ_LOAD_QUOTELET is set, then the
1312             contents of FQ_LOAD_QUOTELET (split on whitespace) will be used as the argument
1313             list. This allows users to load their own custom modules without having to
1314             change existing code. If any method names are passed to C<new> or the flag
1315             '-defaults' is included in the argument list, then FQ_LOAD_QUOTELET is ignored.
1316              
1317             When new() is passed one or more class name arguments, an object is created with
1318             only the specified modules loaded. If the first argument is '-defaults', then
1319             the default modules will be loaded first, followed by any other specified
1320             modules. Note that the FQ_LOAD_QUOTELET environment variable must begin with
1321             '-defaults' if you wish the default modules to be loaded.
1322              
1323             Method names correspond to the Perl module in the Finance::Quote module space.
1324             For example, C<Finance::Quote->new('ASX')> will load the module
1325             Finance::Quote::ASX, which provides the method "asx".
1326              
1327             Some methods require API keys or have unique options. Passing 'method => HASH'
1328             to new() enables the caller to provide a configuration HASH to the corresponding
1329             method.
1330              
1331             The key 'currency_rates' configures the Finanace::Quote currency rate
1332             conversion. By default, to maintain backward compatibility,
1333             Finance::Quote::CurrencyRates::AlphaVantage is used for currency conversion.
1334             This end point requires an API key, which can either be set in the environment
1335             or included in the configuration hash. To specify a different primary currency
1336             conversion method or configure fallback methods, include the 'order' key, which
1337             points to an array of Finance::Quote::CurrencyRates module names.
1338             Setting the environment variable FQ_CURRENCY will change the default
1339             endpoint used for currency conversion.
1340             See the documentation for the individual Finance::Quote::CurrencyRates to
1341             learn more.
1342              
1343             =head2 get_default_currency_fields
1344              
1345             my @fields = Finance::Quote::get_default_currency_fields();
1346              
1347             C<get_default_currency_fields> returns the standard list of fields in a quote
1348             that are automatically converted during currency conversion. Individual modules
1349             may override this list.
1350              
1351             =head2 get_default_timeout
1352            
1353             my $value = Finance::Quote::get_default_timeout();
1354              
1355             C<get_default_timeout> returns the current Finance::Quote default timeout in
1356             seconds for web requests. Finance::Quote does not specify a default timeout,
1357             deferring to the underlying user agent for web requests. So this function
1358             will return undef unless C<set_default_timeout> was previously called.
1359              
1360             =head2 set_default_timeout
1361              
1362             Finance::Quote::set_default_timeout(45);
1363              
1364             C<set_default_timeout> sets the Finance::Quote default timeout to a new value.
1365              
1366             =head2 get_methods
1367              
1368             my @methods = Finance::Quote::get_methods();
1369              
1370             C<get_methods> returns the list of methods that can be passed to C<new> when
1371             creating a quoter object and as the first argument to C<fetch>.
1372              
1373             =head2 get_features
1374              
1375             my %features = Finance::Quote::get_features();
1376              
1377             C<get_features> returns a hash with three keys: quote_methods, quote_modules, and currency_modules.
1378              
1379             $features{quote_methods} is a hash with key/value pairs of method_name => [array of module names]
1380             $features{quote_modules} is a hash with key/value pairs of module_name => [array of parameter names]
1381             $features{currency_modules} is a hash with key/value pairs of currency_module_name => [array of paramater names]
1382              
1383             Parameter names are values that the module needs to function, such as API_KEY. Most
1384             modules will have an empty list. Modules with a parameter are configured when creating
1385             the Finance::Quote by passing the argument
1386              
1387             'module_name_in_lower_case' => {paramter => value}
1388              
1389             to Finance::Quote->new().
1390              
1391             The keys of the $features{currency_modules} hash are the names of currency
1392             modules that can be used for currency conversion and the order in which the
1393             modules are used is controlled by the argument
1394              
1395             currency_rates => {order => [subset of $features{currency_modules}]}
1396              
1397             to Finance::Quote->new(). By default, only AlphaVantage in used for
1398             currency conversion, so "order" must be set to use other currency modules.
1399              
1400              
1401             =head1 PUBLIC OBJECT METHODS
1402              
1403             =head2 B_to_billions
1404              
1405             my $value = $q->B_to_billions("20B");
1406              
1407             C<B_to_billions> is a utility function that expands a numeric string with a "B"
1408             suffix to the corresponding multiple of 1000000000.
1409              
1410             =head2 decimal_shiftup
1411              
1412             my $value = $q->decimal_shiftup("123.45", 1); # returns 1234.5
1413             my $value = $q->decimal_shiftup("0.25", 1); # returns 2.5
1414              
1415             C<decimal_shiftup> moves a the decimal point in a numeric string the specified
1416             number of places to the right.
1417              
1418             =head2 fetch
1419              
1420             my %stocks = $q->fetch("alphavantage", "IBM", "MSFT", "LNUX");
1421             my $hashref = $q->fetch("nasdaq", "IBM", "MSFT", "LNUX");
1422              
1423             C<fetch> takes a method as its first argument and the remaining arguments are
1424             treated as securities. If the quoter C<$q> was constructed with a specific
1425             method or methods, then only those methods are available.
1426              
1427             When called in an array context, a hash is returned. In a scalar context, a
1428             reference to a hash will be returned. The keys for the returned hash are
1429             C<{SECURITY,LABEL}>. For the above example call, C<$stocks{"IBM","high"}> is
1430             the high value for IBM.
1431              
1432             $q->get_methods() returns the list of valid methods for quoter object $q. Some
1433             methods specify a specific Finance::Quote module, such as 'alphavantage'. Other
1434             methods are available from multiple Finance::Quote modules, such as 'nasdaq'.
1435             The quoter failover over option determines if multiple modules are consulted
1436             for methods such as 'nasdaq' that more than one implementation.
1437              
1438             =head2 get_failover
1439              
1440             my $failover = $q->get_failover();
1441              
1442             Failover is when the C<fetch> method attempts to retrieve quote information for
1443             a security from alternate sources when the requested method fails.
1444             C<get_failover> returns a boolean value indicating if the quoter object will
1445             use failover or not.
1446              
1447             =head2 set_failover
1448              
1449             $q->set_failover(False);
1450              
1451             C<set_failover> sets the failover flag on the quoter object.
1452              
1453             =head2 get_fetch_currency
1454              
1455             my $currency = $q->get_fetch_currency();
1456              
1457             C<get_fetch_currency> returns either the desired currency code for the quoter
1458             object or undef if no target currency was set during construction or with the
1459             C<set_fetch_currency> function.
1460              
1461             =head2 set_fetch_currency
1462              
1463             $q->set_fetch_currency("FRF"); # Get results in French Francs.
1464              
1465             C<set_fetch_currency> method is used to request that all information be
1466             returned in the specified currency. Note that this increases the chance
1467             stock-lookup failure, as remote requests must be made to fetch both the stock
1468             information and the currency rates. In order to improve reliability and speed
1469             performance, currency conversion rates are cached and are assumed not to change
1470             for the duration of the Finance::Quote object.
1471              
1472             See the introduction to this page for information on how to configure the
1473             source of currency conversion rates.
1474              
1475             =head2 get_required_labels
1476              
1477             my @labels = $q->get_required_labels();
1478              
1479             C<get_required_labels> returns the list of labels that must be populated for a
1480             security quote to be considered valid and returned by C<fetch>.
1481              
1482             =head2 set_required_labels
1483              
1484             my $labels = ['close', 'isodate', 'last'];
1485             $q->set_required_labels($labels);
1486              
1487             C<set_required_labels> updates the list of required labels for the quoter object.
1488              
1489             =head2 get_timeout
1490              
1491             my $timeout = $q->get_timeout();
1492              
1493             C<get_timeout> returns the timeout in seconds the quoter object is using for
1494             web requests.
1495              
1496             =head2 set_timeout
1497              
1498             $q->set_timeout(45);
1499              
1500             C<set_timeout> updated the timeout in seconds for the quoter object.
1501              
1502             =head2 store_date
1503              
1504             $quoter->store_date(\%info, $stocks, {eurodate => '06/11/2020'});
1505              
1506             C<store_date> is used by modules to consistent store date information about
1507             securities. Given the various pieces of a date, this function figures out how to
1508             construct a ISO date (yyyy-mm-dd) and US date (mm/dd/yyyy) and stores those
1509             values in C<%info> for security C<$stock>.
1510              
1511             =head2 get_user_agent
1512              
1513             my $ua = $q->get_user_agent();
1514              
1515             C<get_user_agent> returns the LWP::UserAgent the quoter object is using for web
1516             requests.
1517              
1518             =head2 isoTime
1519              
1520             $q->isoTime("11:39PM"); # returns "23:39"
1521             $q->isoTime("9:10 AM"); # returns "09:10"
1522              
1523             C<isoTime> returns an ISO formatted time.
1524              
1525             =head1 PUBLIC CLASS OR OBJECT METHODS
1526              
1527             The following methods are available as class methods, but can also be called
1528             from Finance::Quote objects.
1529              
1530             =head2 scale_field
1531              
1532             my $value = Finance::Quote->scale_field('1023', '0.01')
1533              
1534             C<scale_field> is a utility function that scales the first argument by the
1535             second argument. In the above example, C<value> is C<'10.23'>.
1536              
1537             =head2 currency
1538              
1539             my $value = $q->currency('15.95 USD', 'AUD');
1540             my $value = Finance::Quote->currency('23.45 EUR', 'RUB');
1541              
1542             C<currency> converts a value with a currency code suffix to another currency
1543             using the current exchange rate as determined by the
1544             Finance::Quote::CurrencyRates method or methods configured for the quoter $q.
1545             When called as a class method, only Finance::Quote::AlphaVantage is used, which
1546             requires an API key. See the introduction for information on configuring
1547             currency rate conversions and see Finance::Quote::CurrencyRates::AlphaVantage
1548             for information about the API key.
1549              
1550             =head2 currency_lookup
1551              
1552             my $currency = $quoter->currency_lookup();
1553             my $currency = $quoter->currency_lookup( name => "Caribbean");
1554             my $currency = $quoter->currency_loopup( country => qw/denmark/i );
1555             my $currency = $q->currency_lookup(country => qr/united states/i, number => 840);
1556              
1557             C<currency_lookup> takes zero or more constraints and filters the list of
1558             currencies known to Finance::Quote. It returns a hash reference where the keys
1559             are ISO currency codes and the values are hash references containing metadata
1560             about the currency.
1561              
1562             A constraint is a key name and either a scalar or regular expression. A
1563             currency satisfies the constraint if its metadata hash contains the constraint
1564             key and the value of that metadata field matches the regular expression or
1565             contains the constraint value as a substring. If the metadata field is an
1566             array, then it satisfies the constraint if any value in the array satisfies the
1567             constraint.
1568              
1569             =head2 parse_csv
1570              
1571             my @list = Finance::Quote::parse_csv($string);
1572              
1573             C<parse_csv> is a utility function for splitting a comma separated value string
1574             into a list of terms, treating double-quoted strings that contain commas as a
1575             single value.
1576              
1577             =head2 parse_csv_semicolon
1578              
1579             my @list = Finance::Quote::parse_csv_semicolon($string);
1580              
1581             C<parse_csv> is a utility function for splitting a semicolon separated value string
1582             into a list of terms, treating double-quoted strings that contain semicolons as a
1583             single value.
1584              
1585             =head1 LEGACY METHODS
1586              
1587             =head2 default_currency_fields
1588              
1589             Replaced with get_default_currency_fields().
1590              
1591             =head2 sources
1592              
1593             Replaced with get_methods().
1594              
1595             =head2 failover
1596              
1597             Replaced with get_failover() and set_failover().
1598              
1599             =head2 require_labels
1600              
1601             Replaced with get_required_labels() and set_required_labels().
1602              
1603             =head2 user_agent
1604              
1605             Replaced with get_user_agent().
1606              
1607             =head2 set_currency
1608              
1609             Replaced with get_fetch_currency() and set_fetch_currency().
1610              
1611             =head1 ENVIRONMENT
1612              
1613             Finance::Quote respects all environment that your installed version of
1614             LWP::UserAgent respects. Most importantly, it respects the http_proxy
1615             environment variable.
1616              
1617             =head1 BUGS
1618              
1619             The caller cannot control the fetch failover order.
1620              
1621             The two-dimensional hash is a somewhat unwieldly method of passing around
1622             information when compared to references
1623              
1624             =head1 COPYRIGHT & LICENSE
1625              
1626             Copyright 1998, Dj Padzensky
1627             Copyright 1998, 1999 Linas Vepstas
1628             Copyright 2000, Yannick LE NY (update for Yahoo Europe and YahooQuote)
1629             Copyright 2000-2001, Paul Fenwick (updates for ASX, maintenance and release)
1630             Copyright 2000-2001, Brent Neal (update for TIAA-CREF)
1631             Copyright 2000 Volker Stuerzl (DWS)
1632             Copyright 2001 Rob Sessink (AEX support)
1633             Copyright 2001 Leigh Wedding (ASX updates)
1634             Copyright 2001 Tobias Vancura (Fool support)
1635             Copyright 2001 James Treacy (TD Waterhouse support)
1636             Copyright 2008 Erik Colson (isoTime)
1637              
1638             This program is free software; you can redistribute it and/or modify it under
1639             the terms of the GNU General Public License as published by the Free Software
1640             Foundation; either version 2 of the License, or (at your option) any later
1641             version.
1642              
1643             Currency information fetched through this module is bound by the terms and
1644             conditons of the data source.
1645              
1646             Other copyrights and conditions may apply to data fetched through this module.
1647             Please refer to the sub-modules for further information.
1648              
1649             =head1 AUTHORS
1650              
1651             Dj Padzensky <djpadz@padz.net>, PadzNet, Inc.
1652             Linas Vepstas <linas@linas.org>
1653             Yannick LE NY <y-le-ny@ifrance.com>
1654             Paul Fenwick <pjf@cpan.org>
1655             Brent Neal <brentn@users.sourceforge.net>
1656             Volker Stuerzl <volker.stuerzl@gmx.de>
1657             Keith Refson <Keith.Refson#earth.ox.ac.uk>
1658             Rob Sessink <rob_ses@users.sourceforge.net>
1659             Leigh Wedding <leigh.wedding@telstra.com>
1660             Tobias Vancura <tvancura@altavista.net>
1661             James Treacy <treacy@debian.org>
1662             Bradley Dean <bjdean@bjdean.id.au>
1663             Erik Colson <eco@ecocode.net>
1664              
1665             The Finance::Quote home page can be found at
1666             http://finance-quote.sourceforge.net/
1667              
1668             The Finance::YahooQuote home page can be found at
1669             http://www.padz.net/~djpadz/YahooQuote/
1670              
1671             The GnuCash home page can be found at
1672             http://www.gnucash.org/
1673              
1674             =head1 SEE ALSO
1675              
1676             Finance::Quote::CurrencyRates::AlphaVantage,
1677             Finance::Quote::CurrencyRates::ECB,
1678             Finance::Quote::CurrencyRates::Fixer,
1679             Finance::Quote::CurrencyRates::OpenExchange,
1680             Finance::Quote::CurrencyRates::YahooJSON,
1681             Finance::Quote::AEX,
1682             Finance::Quote::ASEGR,
1683             Finance::Quote::ASX,
1684             Finance::Quote::Bloomberg,
1685             Finance::Quote::BSEIndia,
1686             Finance::Quote::Bourso,
1687             Finance::Quote::BVB,
1688             Finance::Quote::CSE,
1689             Finance::Quote::Cdnfundlibrary,
1690             Finance::Quote::Comdirect,
1691             Finance::Quote::Currencies,
1692             Finance::Quote::DWS,
1693             Finance::Quote::Deka,
1694             Finance::Quote::FTfunds,
1695             Finance::Quote::Fidelity,
1696             Finance::Quote::Finanzpartner,
1697             Finance::Quote::Fondsweb,
1698             Finance::Quote::Fool,
1699             Finance::Quote::Fundata
1700             Finance::Quote::GoldMoney,
1701             Finance::Quote::GoogleWeb,
1702             Finance::Quote::HU,
1703             Finance::Quote::IEXCloud,
1704             Finance::Quote::IndiaMutual,
1705             Finance::Quote::MorningstarAU,
1706             Finance::Quote::MorningstarCH,
1707             Finance::Quote::MorningstarJP,
1708             Finance::Quote::MorningstarUK,
1709             Finance::Quote::NSEIndia,
1710             Finance::Quote::NZX,
1711             Finance::Quote::OnVista,
1712             Finance::Quote::Oslobors,
1713             Finance::Quote::SEB,
1714             Finance::Quote::SIX,
1715             Finance::Quote::TSP,
1716             Finance::Quote::TMX,
1717             Finance::Quote::Tiaacref,
1718             Finance::Quote::TesouroDireto,
1719             Finance::Quote::TreasuryDirect,
1720             Finance::Quote::Troweprice,
1721             Finance::Quote::TwelveData,
1722             Finance::Quote::Union,
1723             Finance::Quote::YahooJSON,
1724             Finance::Quote::YahooWeb,
1725             Finance::Quote::ZA
1726              
1727             You should have received the Finance::Quote hacker's guide with this package.
1728             Please read it if you are interested in adding extra methods to this package.
1729             The latest hacker's guide can also be found on GitHub at
1730             https://github.com/finance-quote/finance-quote/blob/master/Documentation/Hackers-Guide
1731              
1732             =cut