| 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 |