File Coverage

blib/lib/Finance/Quote/IEXCloud.pm
Criterion Covered Total %
statement 18 62 29.0
branch 0 24 0.0
condition 0 3 0.0
subroutine 8 9 88.8
pod 0 4 0.0
total 26 102 25.4


line stmt bran cond sub pod time code
1             #!/usr/bin/perl -w
2             # This module is based on the Finance::Quote::yahooJSON module
3             #
4             # This program is free software; you can redistribute it and/or modify
5             # it under the terms of the GNU General Public License as published by
6             # the Free Software Foundation; either version 2 of the License, or
7             # (at your option) any later version.
8             #
9             # This program is distributed in the hope that it will be useful,
10             # but WITHOUT ANY WARRANTY; without even the implied warranty of
11             # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12             # GNU General Public License for more details.
13             #
14             # You should have received a copy of the GNU General Public License
15             # along with this program; if not, write to the Free Software
16             # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
17             # 02110-1301, USA
18              
19             package Finance::Quote::IEXCloud;
20              
21             require 5.005;
22              
23 5     5   2803 use strict;
  5         20  
  5         166  
24 5     5   31 use JSON qw( decode_json );
  5         12  
  5         32  
25 5     5   534 use HTTP::Request::Common;
  5         10  
  5         354  
26 5     5   36 use Text::Template;
  5         11  
  5         249  
27 5     5   4246 use DateTime::Format::Strptime qw( strptime strftime );
  5         1036014  
  5         33  
28              
29             our $VERSION = '1.58'; # VERSION
30              
31             my $IEX_URL = Text::Template->new(TYPE => 'STRING', SOURCE => 'https://cloud.iexapis.com/v1/stock/{$symbol}/quote?token={$token}');
32              
33             sub methods {
34 5     5 0 42 return ( iexcloud => \&iexcloud,
35             usa => \&iexcloud,
36             nasdaq => \&iexcloud,
37             nyse => \&iexcloud );
38             }
39              
40             sub parameters {
41 1     1 0 5 return ('API_KEY');
42             }
43              
44             {
45             our @labels = qw/symbol open close high low last volume method isodate currency/;
46              
47             sub labels {
48 5     5 0 18 return ( iexcloud => \@labels, );
49             }
50             }
51              
52             sub iexcloud {
53 0     0 0   my $quoter = shift;
54              
55             my $token = exists $quoter->{module_specific_data}->{iexcloud}->{API_KEY} ?
56             $quoter->{module_specific_data}->{iexcloud}->{API_KEY} :
57 0 0         $ENV{"IEXCLOUD_API_KEY"};
58              
59 0           my @stocks = @_;
60 0           my $quantity = @stocks;
61 0           my ( %info, $reply, $url, $code, $desc, $body );
62 0           my $ua = $quoter->user_agent();
63              
64 0 0         die "IEXCloud API_KEY not defined. See documentation." unless defined $token;
65              
66 0           foreach my $symbol (@stocks) {
67 0           $url = $IEX_URL->fill_in(HASH => { symbol => $symbol, token => $token});
68              
69 0           $reply = $ua->request( GET $url);
70 0           $code = $reply->code;
71 0           $desc = HTTP::Status::status_message($code);
72 0           $body = $reply->content;
73            
74 0 0         if ($code != 200) {
75 0           $info{ $symbol, 'success' } = 0;
76 0           $info{ $symbol, 'errormsg' } = $desc;
77 0           next;
78             }
79              
80 0           my $quote;
81 0           eval {$quote = JSON::decode_json $body};
  0            
82 0 0         if ($@) {
83 0           $info{ $symbol, 'success' } = 0;
84 0           $info{ $symbol, 'errormsg' } = $@;
85 0           next;
86             }
87              
88 0 0 0       if (not exists $quote->{'symbol'} or $quote->{'symbol'} ne $symbol) {
89 0           $info{ $symbol, 'success' } = 0;
90 0           $info{ $symbol, 'errormsg' } = "IEXCloud return and unexpected json result";
91 0           next;
92             }
93              
94 0           $info{ $symbol, 'success' } = 1;
95 0           $info{ $symbol, 'symbol' } = $symbol;
96 0 0         $info{ $symbol, 'open' } = $quote->{'open'} if $quote->{'open'};
97 0 0         $info{ $symbol, 'close' } = $quote->{'close'} if $quote->{'close'};
98 0 0         $info{ $symbol, 'high' } = $quote->{'high'} if $quote->{'high'};
99 0 0         $info{ $symbol, 'low' } = $quote->{'low'} if $quote->{'low'};
100 0 0         $info{ $symbol, 'last' } = $quote->{'latestPrice'} if $quote->{'latestPrice'};
101 0 0         $info{ $symbol, 'volume' } = $quote->{'latestVolume'} if $quote->{'latestVolume'};
102 0           $info{ $symbol, 'method' } = 'iexcloud';
103            
104 0           my $iex_date = $quote->{'latestUpdate'}; # milliseconds since midnight Jan 1, 1970
105 0           my $time = strptime('%s', int($iex_date/1000.0));
106 0           my $isodate = strftime('%F', $time);
107 0           $quoter->store_date( \%info, $symbol, { isodate => $isodate } );
108            
109 0           $info{ $symbol, 'currency' } = 'USD';
110 0           $info{ $symbol, 'currency_set_by_fq' } = 1;
111             }
112              
113 0 0         return wantarray() ? %info : \%info;
114             }
115             1;
116              
117             =head1 NAME
118              
119             Finance::Quote::IEXClound - Obtain quotes from https://iexcloud.io
120              
121             =head1 SYNOPSIS
122              
123             use Finance::Quote;
124            
125             $q = Finance::Quote->new('IEXCloud', iexcloud => {API_KEY => 'your-iexcloud-api-key'});
126              
127             %info = Finance::Quote->fetch("IBM", "AAPL");
128              
129             =head1 DESCRIPTION
130              
131             This module fetches information from https://iexcloud.io.
132              
133             This module is loaded by default on a Finance::Quote object. It's
134             also possible to load it explicitly by placing "IEXCloud" in the argument
135             list to Finance::Quote->new().
136              
137             This module provides the "iexcloud" fetch method.
138              
139             =head1 API_KEY
140              
141             https://iexcloud.io requires users to register and obtain an API key, which
142             is also called a token. The token may contain a prefix string, such as 'pk_'
143             and then a sequence of random digits.
144              
145             The API key may be set by either providing a module specific hash to
146             Finance::Quote->new as in the above example, or by setting the environment
147             variable IEXCLOUD_API_KEY.
148              
149             =head1 LABELS RETURNED
150              
151             The following labels may be returned by Finance::Quote::IEXClound :
152             symbol, open, close, high, low, last, volume, method, isodate, currency.
153              
154             =cut