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