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
|
|
|
|
|
|
|
# 2019-12-01: Added additional labels for net and p_change. Set |
20
|
|
|
|
|
|
|
# close to previous close as returned in the JSON. |
21
|
|
|
|
|
|
|
# Bruce Schuck (bschuck at asgard hyphen systems dot com) |
22
|
|
|
|
|
|
|
|
23
|
|
|
|
|
|
|
package Finance::Quote::AlphaVantage; |
24
|
|
|
|
|
|
|
|
25
|
5
|
|
|
5
|
|
3207
|
use strict; |
|
5
|
|
|
|
|
20
|
|
|
5
|
|
|
|
|
178
|
|
26
|
5
|
|
|
5
|
|
28
|
use JSON qw( decode_json ); |
|
5
|
|
|
|
|
9
|
|
|
5
|
|
|
|
|
35
|
|
27
|
5
|
|
|
5
|
|
506
|
use HTTP::Request::Common; |
|
5
|
|
|
|
|
11
|
|
|
5
|
|
|
|
|
7433
|
|
28
|
|
|
|
|
|
|
|
29
|
|
|
|
|
|
|
our $VERSION = '1.57_03'; # TRIAL VERSION |
30
|
|
|
|
|
|
|
|
31
|
|
|
|
|
|
|
# Alpha Vantage recommends that API call frequency does not extend far |
32
|
|
|
|
|
|
|
# beyond ~1 call per second so that they can continue to deliver |
33
|
|
|
|
|
|
|
# optimal server-side performance: |
34
|
|
|
|
|
|
|
# https://www.alphavantage.co/support/#api-key |
35
|
|
|
|
|
|
|
our @alphaqueries=(); |
36
|
|
|
|
|
|
|
my $maxQueries = { quantity =>5 , seconds => 60}; # no more than x |
37
|
|
|
|
|
|
|
# queries per y |
38
|
|
|
|
|
|
|
# seconds, based on |
39
|
|
|
|
|
|
|
# https://www.alphavantage.co/support/#support |
40
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
my $ALPHAVANTAGE_URL = |
42
|
|
|
|
|
|
|
'https://www.alphavantage.co/query?function=GLOBAL_QUOTE&datatype=json'; |
43
|
|
|
|
|
|
|
|
44
|
|
|
|
|
|
|
my %currencies_by_suffix = ( |
45
|
|
|
|
|
|
|
|
46
|
|
|
|
|
|
|
# Country City/Exchange Name |
47
|
|
|
|
|
|
|
'.US' => "USD", # USA AMEX, Nasdaq, NYSE |
48
|
|
|
|
|
|
|
'.A' => "USD", # USA American Stock Exchange (ASE) |
49
|
|
|
|
|
|
|
'.B' => "USD", # USA Boston Stock Exchange (BOS) |
50
|
|
|
|
|
|
|
'.N' => "USD", # USA Nasdaq Stock Exchange (NAS) |
51
|
|
|
|
|
|
|
'.O' => "USD", # USA NYSE Stock Exchange (NYS) |
52
|
|
|
|
|
|
|
'.OB' => "USD", # USA OTC Bulletin Board |
53
|
|
|
|
|
|
|
'.PK' => "USD", # USA Pink Sheets |
54
|
|
|
|
|
|
|
'.X' => "USD", # USA US Options |
55
|
|
|
|
|
|
|
'.BA' => "ARS", # Argentina Buenos Aires |
56
|
|
|
|
|
|
|
'.VI' => "EUR", # Austria Vienna |
57
|
|
|
|
|
|
|
'.AX' => "AUD", # Australia |
58
|
|
|
|
|
|
|
'.SA' => "BRL", # Brazil Sao Paolo |
59
|
|
|
|
|
|
|
'.BR' => "EUR", # Belgium Brussels |
60
|
|
|
|
|
|
|
'.TO' => "CAD", # Canada Toronto |
61
|
|
|
|
|
|
|
'.TRV' => "CAD", # Canada Toronto Venture |
62
|
|
|
|
|
|
|
'.V' => "CAD", # Canada Toronto Venture |
63
|
|
|
|
|
|
|
'.TRT' => "CAD", # Canada Toronto |
64
|
|
|
|
|
|
|
'.SN' => "CLP", # Chile Santiago |
65
|
|
|
|
|
|
|
'.SS' => "CNY", # China Shanghai |
66
|
|
|
|
|
|
|
'.SZ' => "CNY", # Shenzhen |
67
|
|
|
|
|
|
|
'.CO' => "DKK", # Denmark Copenhagen |
68
|
|
|
|
|
|
|
'.PA' => "EUR", # France Paris |
69
|
|
|
|
|
|
|
'.BE' => "EUR", # Germany Berlin |
70
|
|
|
|
|
|
|
'.BM' => "EUR", # Bremen |
71
|
|
|
|
|
|
|
'.D' => "EUR", # Dusseldorf |
72
|
|
|
|
|
|
|
'.F' => "EUR", # Frankfurt |
73
|
|
|
|
|
|
|
'.FRK' => "EUR", # Frankfurt |
74
|
|
|
|
|
|
|
'.H' => "EUR", # Hamburg |
75
|
|
|
|
|
|
|
'.HA' => "EUR", # Hanover |
76
|
|
|
|
|
|
|
'.MU' => "EUR", # Munich |
77
|
|
|
|
|
|
|
'.DEX' => "EUR", # Xetra |
78
|
|
|
|
|
|
|
'.ME' => "RUB", # Russia Moscow |
79
|
|
|
|
|
|
|
'.SG' => "EUR", # Stuttgart |
80
|
|
|
|
|
|
|
'.DE' => "EUR", # XETRA |
81
|
|
|
|
|
|
|
'.HK' => "HKD", # Hong Kong |
82
|
|
|
|
|
|
|
'.BO' => "INR", # India Bombay |
83
|
|
|
|
|
|
|
'.CL' => "INR", # Calcutta |
84
|
|
|
|
|
|
|
'.NS' => "INR", # National Stock Exchange |
85
|
|
|
|
|
|
|
'.JK' => "IDR", # Indonesia Jakarta |
86
|
|
|
|
|
|
|
'.I' => "EUR", # Ireland Dublin |
87
|
|
|
|
|
|
|
'.TA' => "ILS", # Israel Tel Aviv |
88
|
|
|
|
|
|
|
'.MI' => "EUR", # Italy Milan |
89
|
|
|
|
|
|
|
'.KS' => "KRW", # Korea Stock Exchange |
90
|
|
|
|
|
|
|
'.KQ' => "KRW", # KOSDAQ |
91
|
|
|
|
|
|
|
'.KL' => "MYR", # Malaysia Kuala Lampur |
92
|
|
|
|
|
|
|
'.MX' => "MXP", # Mexico |
93
|
|
|
|
|
|
|
'.NZ' => "NZD", # New Zealand |
94
|
|
|
|
|
|
|
'.AS' => "EUR", # Netherlands Amsterdam |
95
|
|
|
|
|
|
|
'.AMS' => "EUR", # Netherlands Amsterdam |
96
|
|
|
|
|
|
|
'.OL' => "NOK", # Norway Oslo |
97
|
|
|
|
|
|
|
'.LM' => "PEN", # Peru Lima |
98
|
|
|
|
|
|
|
'.IN' => "EUR", # Portugal Lisbon |
99
|
|
|
|
|
|
|
'.SI' => "SGD", # Singapore |
100
|
|
|
|
|
|
|
'.BC' => "EUR", # Spain Barcelona |
101
|
|
|
|
|
|
|
'.BI' => "EUR", # Bilbao |
102
|
|
|
|
|
|
|
'.MF' => "EUR", # Madrid Fixed Income |
103
|
|
|
|
|
|
|
'.MC' => "EUR", # Madrid SE CATS |
104
|
|
|
|
|
|
|
'.MA' => "EUR", # Madrid |
105
|
|
|
|
|
|
|
'.VA' => "EUR", # Valence |
106
|
|
|
|
|
|
|
'.ST' => "SEK", # Sweden Stockholm |
107
|
|
|
|
|
|
|
'.STO' => "SEK", # Sweden Stockholm |
108
|
|
|
|
|
|
|
'.HE' => "EUR", # Finland Helsinki |
109
|
|
|
|
|
|
|
'.S' => "CHF", # Switzerland Zurich |
110
|
|
|
|
|
|
|
'.TW' => "TWD", # Taiwan Taiwan Stock Exchange |
111
|
|
|
|
|
|
|
'.TWO' => "TWD", # OTC |
112
|
|
|
|
|
|
|
'.BK' => "THB", # Thialand Thailand Stock Exchange |
113
|
|
|
|
|
|
|
'.TH' => "THB", # ??? From Asia.pm, (in Thai Baht) |
114
|
|
|
|
|
|
|
'.L' => "GBP", # United Kingdom London |
115
|
|
|
|
|
|
|
'.IL' => "USD", # United Kingdom London USD*100 |
116
|
|
|
|
|
|
|
'.VX' => "CHF", # Switzerland |
117
|
|
|
|
|
|
|
'.SW' => "CHF", # Switzerland |
118
|
|
|
|
|
|
|
); |
119
|
|
|
|
|
|
|
|
120
|
|
|
|
|
|
|
|
121
|
|
|
|
|
|
|
sub methods { |
122
|
5
|
|
|
5
|
0
|
37
|
return ( alphavantage => \&alphavantage, |
123
|
|
|
|
|
|
|
canada => \&alphavantage, |
124
|
|
|
|
|
|
|
usa => \&alphavantage, |
125
|
|
|
|
|
|
|
nyse => \&alphavantage, |
126
|
|
|
|
|
|
|
nasdaq => \&alphavantage, |
127
|
|
|
|
|
|
|
); |
128
|
|
|
|
|
|
|
} |
129
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
sub parameters { |
131
|
1
|
|
|
1
|
0
|
5
|
return ('API_KEY'); |
132
|
|
|
|
|
|
|
} |
133
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
{ |
135
|
|
|
|
|
|
|
my @labels = qw/date isodate open high low close volume last net p_change/; |
136
|
|
|
|
|
|
|
|
137
|
|
|
|
|
|
|
sub labels { |
138
|
5
|
|
|
5
|
0
|
19
|
return ( alphavantage => \@labels, ); |
139
|
|
|
|
|
|
|
} |
140
|
|
|
|
|
|
|
} |
141
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
sub sleep_before_query { |
143
|
|
|
|
|
|
|
# wait till we can query again |
144
|
0
|
|
|
0
|
0
|
|
my $q = $maxQueries->{quantity}-1; |
145
|
0
|
0
|
|
|
|
|
if ( $#alphaqueries >= $q ) { |
146
|
0
|
|
|
|
|
|
my $time_since_x_queries = time()-$alphaqueries[$q]; |
147
|
|
|
|
|
|
|
# print STDERR "LAST QUERY $time_since_x_queries\n"; |
148
|
0
|
0
|
|
|
|
|
if ($time_since_x_queries < $maxQueries->{seconds}) { |
149
|
0
|
|
|
|
|
|
my $sleeptime = ($maxQueries->{seconds} - $time_since_x_queries) ; |
150
|
|
|
|
|
|
|
# print STDERR "SLEEP $sleeptime\n"; |
151
|
0
|
|
|
|
|
|
sleep( $sleeptime ); |
152
|
|
|
|
|
|
|
# print STDERR "CONTINUE\n"; |
153
|
|
|
|
|
|
|
} |
154
|
|
|
|
|
|
|
} |
155
|
0
|
|
|
|
|
|
unshift @alphaqueries, time(); |
156
|
0
|
|
|
|
|
|
pop @alphaqueries while $#alphaqueries>$q; # remove unnecessary data |
157
|
|
|
|
|
|
|
# print STDERR join(",",@alphaqueries)."\n"; |
158
|
|
|
|
|
|
|
} |
159
|
|
|
|
|
|
|
|
160
|
|
|
|
|
|
|
sub alphavantage { |
161
|
0
|
|
|
0
|
0
|
|
my $quoter = shift; |
162
|
|
|
|
|
|
|
|
163
|
0
|
|
|
|
|
|
my @stocks = @_; |
164
|
0
|
|
|
|
|
|
my $quantity = @stocks; |
165
|
0
|
|
|
|
|
|
my ( %info, $reply, $url, $code, $desc, $body ); |
166
|
0
|
|
|
|
|
|
my $ua = $quoter->user_agent(); |
167
|
0
|
|
|
|
|
|
my $launch_time = time(); |
168
|
|
|
|
|
|
|
|
169
|
|
|
|
|
|
|
my $token = exists $quoter->{module_specific_data}->{alphavantage}->{API_KEY} ? |
170
|
|
|
|
|
|
|
$quoter->{module_specific_data}->{alphavantage}->{API_KEY} : |
171
|
0
|
0
|
|
|
|
|
$ENV{"ALPHAVANTAGE_API_KEY"}; |
172
|
|
|
|
|
|
|
|
173
|
0
|
|
|
|
|
|
foreach my $stock (@stocks) { |
174
|
|
|
|
|
|
|
|
175
|
0
|
0
|
|
|
|
|
if ( !defined $token ) { |
176
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
177
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = |
178
|
|
|
|
|
|
|
'An AlphaVantage API is required. Get an API key at https://www.alphavantage.co'; |
179
|
0
|
|
|
|
|
|
next; |
180
|
|
|
|
|
|
|
} |
181
|
|
|
|
|
|
|
|
182
|
|
|
|
|
|
|
$url = |
183
|
0
|
|
|
|
|
|
$ALPHAVANTAGE_URL |
184
|
|
|
|
|
|
|
. '&apikey=' |
185
|
|
|
|
|
|
|
. $token |
186
|
|
|
|
|
|
|
. '&symbol=' |
187
|
|
|
|
|
|
|
. $stock; |
188
|
|
|
|
|
|
|
|
189
|
|
|
|
|
|
|
my $get_content = sub { |
190
|
0
|
|
|
0
|
|
|
sleep_before_query(); |
191
|
0
|
|
|
|
|
|
my $time=int(time()-$launch_time); |
192
|
|
|
|
|
|
|
# print STDERR "Query at:".$time."\n"; |
193
|
0
|
|
|
|
|
|
$reply = $ua->request( GET $url); |
194
|
|
|
|
|
|
|
|
195
|
0
|
|
|
|
|
|
$code = $reply->code; |
196
|
0
|
|
|
|
|
|
$desc = HTTP::Status::status_message($code); |
197
|
0
|
|
|
|
|
|
$body = $reply->content; |
198
|
|
|
|
|
|
|
# print STDERR "AlphaVantage returned: $body\n"; |
199
|
0
|
|
|
|
|
|
}; |
200
|
|
|
|
|
|
|
|
201
|
0
|
|
|
|
|
|
&$get_content(); |
202
|
|
|
|
|
|
|
|
203
|
0
|
0
|
|
|
|
|
if ($code != 200) { |
204
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
205
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = $desc; |
206
|
0
|
|
|
|
|
|
next; |
207
|
|
|
|
|
|
|
} |
208
|
|
|
|
|
|
|
|
209
|
0
|
|
|
|
|
|
my $json_data; |
210
|
0
|
|
|
|
|
|
eval {$json_data = JSON::decode_json $body}; |
|
0
|
|
|
|
|
|
|
211
|
0
|
0
|
|
|
|
|
if ($@) { |
212
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
213
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = $@; |
214
|
|
|
|
|
|
|
} |
215
|
|
|
|
|
|
|
|
216
|
0
|
|
|
|
|
|
my $try_cnt = 0; |
217
|
0
|
|
0
|
|
|
|
while (($try_cnt < 5) && ($json_data->{'Note'})) { |
218
|
|
|
|
|
|
|
# print STDERR "NOTE:".$json_data->{'Note'}."\n"; |
219
|
|
|
|
|
|
|
# print STDERR "ADDITIONAL SLEEPING HERE !"; |
220
|
0
|
|
|
|
|
|
sleep (20); |
221
|
0
|
|
|
|
|
|
&$get_content(); |
222
|
0
|
|
|
|
|
|
eval {$json_data = JSON::decode_json $body}; |
|
0
|
|
|
|
|
|
|
223
|
0
|
|
|
|
|
|
$try_cnt += 1; |
224
|
|
|
|
|
|
|
} |
225
|
|
|
|
|
|
|
|
226
|
0
|
0
|
|
|
|
|
if ( !$json_data ) { |
|
|
0
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
227
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
228
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = 'Query returned no JSON'; |
229
|
0
|
|
|
|
|
|
next; |
230
|
|
|
|
|
|
|
} elsif ( $json_data->{'Error Message'} ) { |
231
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
232
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = $json_data->{'Error Message'}; |
233
|
0
|
|
|
|
|
|
next; |
234
|
|
|
|
|
|
|
} elsif ( $json_data->{'Information'} ) { |
235
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
236
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = $json_data->{'Information'}; |
237
|
0
|
|
|
|
|
|
next; |
238
|
|
|
|
|
|
|
} |
239
|
|
|
|
|
|
|
|
240
|
0
|
|
|
|
|
|
my $quote = $json_data->{'Global Quote'}; |
241
|
0
|
0
|
|
|
|
|
if ( ! %{$quote} ) { |
|
0
|
|
|
|
|
|
|
242
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 0; |
243
|
0
|
|
|
|
|
|
$info{ $stock, 'errormsg' } = "json_data doesn't contain Global Quote"; |
244
|
0
|
|
|
|
|
|
next; |
245
|
|
|
|
|
|
|
} |
246
|
|
|
|
|
|
|
|
247
|
|
|
|
|
|
|
# %ts holds data as |
248
|
|
|
|
|
|
|
# { |
249
|
|
|
|
|
|
|
# "Global Quote": { |
250
|
|
|
|
|
|
|
# "01. symbol": "SOLB.BR", |
251
|
|
|
|
|
|
|
# "02. open": "104.2000", |
252
|
|
|
|
|
|
|
# "03. high": "104.9500", |
253
|
|
|
|
|
|
|
# "04. low": "103.4000", |
254
|
|
|
|
|
|
|
# "05. price": "104.0000", |
255
|
|
|
|
|
|
|
# "06. volume": "203059", |
256
|
|
|
|
|
|
|
# "07. latest trading day": "2019-11-29", |
257
|
|
|
|
|
|
|
# "08. previous close": "105.1500", |
258
|
|
|
|
|
|
|
# "09. change": "-1.1500", |
259
|
|
|
|
|
|
|
# "10. change percent": "-1.0937%" |
260
|
|
|
|
|
|
|
# } |
261
|
|
|
|
|
|
|
# } |
262
|
|
|
|
|
|
|
|
263
|
|
|
|
|
|
|
# remove trailing percent sign, if present |
264
|
0
|
|
|
|
|
|
$quote->{'10. change percent'} =~ s/\%$//; |
265
|
|
|
|
|
|
|
|
266
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 1; |
267
|
0
|
|
|
|
|
|
$info{ $stock, 'success' } = 1; |
268
|
0
|
|
|
|
|
|
$info{ $stock, 'symbol' } = $quote->{'01. symbol'}; |
269
|
0
|
|
|
|
|
|
$info{ $stock, 'open' } = $quote->{'02. open'}; |
270
|
0
|
|
|
|
|
|
$info{ $stock, 'high' } = $quote->{'03. high'}; |
271
|
0
|
|
|
|
|
|
$info{ $stock, 'low' } = $quote->{'04. low'}; |
272
|
0
|
|
|
|
|
|
$info{ $stock, 'last' } = $quote->{'05. price'}; |
273
|
0
|
|
|
|
|
|
$info{ $stock, 'volume' } = $quote->{'06. volume'}; |
274
|
0
|
|
|
|
|
|
$info{ $stock, 'close' } = $quote->{'08. previous close'}; |
275
|
0
|
|
|
|
|
|
$info{ $stock, 'net' } = $quote->{'09. change'}; |
276
|
0
|
|
|
|
|
|
$info{ $stock, 'p_change' } = $quote->{'10. change percent'}; |
277
|
0
|
|
|
|
|
|
$info{ $stock, 'method' } = 'alphavantage'; |
278
|
0
|
|
|
|
|
|
$quoter->store_date( \%info, $stock, { isodate => $quote->{'07. latest trading day'} } ); |
279
|
|
|
|
|
|
|
|
280
|
|
|
|
|
|
|
# deduce currency |
281
|
0
|
0
|
|
|
|
|
if ( $stock =~ /(\..*)/ ) { |
282
|
0
|
|
|
|
|
|
my $suffix = uc $1; |
283
|
0
|
0
|
|
|
|
|
if ( $currencies_by_suffix{$suffix} ) { |
284
|
0
|
|
|
|
|
|
$info{ $stock, 'currency' } = $currencies_by_suffix{$suffix}; |
285
|
|
|
|
|
|
|
|
286
|
|
|
|
|
|
|
# divide GBP quotes by 100 |
287
|
0
|
0
|
0
|
|
|
|
if ( ($info{ $stock, 'currency' } eq 'GBP') || ($info{$stock,'currency'} eq 'GBX') ) { |
288
|
0
|
|
|
|
|
|
foreach my $field ( $quoter->default_currency_fields ) { |
289
|
0
|
0
|
|
|
|
|
next unless ( $info{ $stock, $field } ); |
290
|
|
|
|
|
|
|
$info{ $stock, $field } = |
291
|
0
|
|
|
|
|
|
$quoter->scale_field( $info{ $stock, $field }, |
292
|
|
|
|
|
|
|
0.01 ); |
293
|
|
|
|
|
|
|
} |
294
|
|
|
|
|
|
|
} |
295
|
|
|
|
|
|
|
# divide USD quotes by 100 if suffix is '.IL' |
296
|
0
|
0
|
0
|
|
|
|
if ( ($suffix eq '.IL') && ($info{$stock,'currency'} eq 'USD') ) { |
297
|
0
|
|
|
|
|
|
foreach my $field ( $quoter->default_currency_fields ) { |
298
|
0
|
0
|
|
|
|
|
next unless ( $info{ $stock, $field } ); |
299
|
|
|
|
|
|
|
$info{ $stock, $field } = |
300
|
0
|
|
|
|
|
|
$quoter->scale_field( $info{ $stock, $field }, |
301
|
|
|
|
|
|
|
0.01 ); |
302
|
|
|
|
|
|
|
} |
303
|
|
|
|
|
|
|
} |
304
|
|
|
|
|
|
|
} |
305
|
|
|
|
|
|
|
} |
306
|
|
|
|
|
|
|
else { |
307
|
0
|
|
|
|
|
|
$info{ $stock, 'currency' } = 'USD'; |
308
|
|
|
|
|
|
|
} |
309
|
|
|
|
|
|
|
|
310
|
0
|
|
|
|
|
|
$info{ $stock, "currency_set_by_fq" } = 1; |
311
|
|
|
|
|
|
|
|
312
|
|
|
|
|
|
|
} |
313
|
|
|
|
|
|
|
|
314
|
0
|
0
|
|
|
|
|
return wantarray() ? %info : \%info; |
315
|
|
|
|
|
|
|
} |
316
|
|
|
|
|
|
|
1; |
317
|
|
|
|
|
|
|
|
318
|
|
|
|
|
|
|
=head1 NAME |
319
|
|
|
|
|
|
|
|
320
|
|
|
|
|
|
|
Finance::Quote::AlphaVantage - Obtain quotes from https://iexcloud.io |
321
|
|
|
|
|
|
|
|
322
|
|
|
|
|
|
|
=head1 SYNOPSIS |
323
|
|
|
|
|
|
|
|
324
|
|
|
|
|
|
|
use Finance::Quote; |
325
|
|
|
|
|
|
|
|
326
|
|
|
|
|
|
|
$q = Finance::Quote->new('AlphaVantage', alphavantage => {API_KEY => 'your-alphavantage-api-key'}); |
327
|
|
|
|
|
|
|
|
328
|
|
|
|
|
|
|
%info = $q->fetch('alphavantage', 'IBM', 'AAPL'); |
329
|
|
|
|
|
|
|
|
330
|
|
|
|
|
|
|
=head1 DESCRIPTION |
331
|
|
|
|
|
|
|
|
332
|
|
|
|
|
|
|
This module fetches information from https://www.alphavantage.co. |
333
|
|
|
|
|
|
|
|
334
|
|
|
|
|
|
|
This module is loaded by default on a Finance::Quote object. It's also possible |
335
|
|
|
|
|
|
|
to load it explicitly by placing "AlphaVantage" in the argument list to |
336
|
|
|
|
|
|
|
Finance::Quote->new(). |
337
|
|
|
|
|
|
|
|
338
|
|
|
|
|
|
|
This module provides the "alphavantage" fetch method. |
339
|
|
|
|
|
|
|
|
340
|
|
|
|
|
|
|
=head1 API_KEY |
341
|
|
|
|
|
|
|
|
342
|
|
|
|
|
|
|
https://www.alphavantage.co requires users to register and obtain an API key, which |
343
|
|
|
|
|
|
|
is also called a token. The token is a sequence of random characters. |
344
|
|
|
|
|
|
|
|
345
|
|
|
|
|
|
|
The API key may be set by either providing a module specific hash to |
346
|
|
|
|
|
|
|
Finance::Quote->new as in the above example, or by setting the environment |
347
|
|
|
|
|
|
|
variable ALPHAVANTAGE_API_KEY. |
348
|
|
|
|
|
|
|
|
349
|
|
|
|
|
|
|
=head1 LABELS RETURNED |
350
|
|
|
|
|
|
|
|
351
|
|
|
|
|
|
|
The following labels may be returned by Finance::Quote::AlphaVantage : |
352
|
|
|
|
|
|
|
symbol, open, close, high, low, last, volume, method, isodate, currency. |
353
|
|
|
|
|
|
|
|
354
|
|
|
|
|
|
|
=cut |