/usr/share/perl5/Finance/Quote/Yahoo/Base.pm is in libfinance-quote-perl 1.17+git20110918-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 | #!/usr/bin/perl -w
#
# Copyright (C) 1998, Dj Padzensky <djpadz@padz.net>
# Copyright (C) 1998, 1999 Linas Vepstas <linas@linas.org>
# Copyright (C) 2000, Yannick LE NY <y-le-ny@ifrance.com>
# Copyright (C) 2000, Paul Fenwick <pjf@cpan.org>
# Copyright (C) 2000, Brent Neal <brentn@users.sourceforge.net>
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
# 02111-1307, USA
#
# This code derived from Padzensky's work on package Finance::YahooQuote,
# but extends its capabilites to encompas a greater number of data sources.
#
# This package provides a base class for the various Yahoo services,
# and is based upon code by Xose Manoel Ramos <xmanoel@bigfoot.com>.
# Improvements based upon patches supplied by Peter Thatcher have
# also been integrated.
package Finance::Quote::Yahoo::Base;
require 5.005;
use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
use Exporter;
use vars qw/$VERSION @FIELDS @FIELD_ENCODING $MAX_REQUEST_SIZE @ISA
@EXPORT @EXPORT_OK/;
@ISA = qw/Exporter/;
@EXPORT = qw//;
@EXPORT_OK = qw/yahoo_request base_yahoo_labels/;
$VERSION = '1.17';
# This is the maximum number of stocks we'll batch into one operation.
# If this gets too big (>50 or thereabouts) things will break because
# some proxies and/or webservers cannot handle very large URLS.
$MAX_REQUEST_SIZE = 40;
# Yahoo uses encodes the desired fields as 1-2 character strings
# in the URL. These are recorded below, along with their corresponding
# field names.
@FIELDS = qw/symbol name last date time net p_change volume bid ask
close open day_range year_range eps pe div_date div div_yield
cap ex_div avg_vol currency/;
@FIELD_ENCODING = qw/s n l1 d1 t1 c1 p2 v b a p o m w e r r1 d y j1 q a2 c4/;
# This returns a list of labels that are provided, so that code
# that make use of this module can know what it's dealing with.
# It also means that if we extend the code in the future to provide
# more information, we simply need to change this in one spot.
sub base_yahoo_labels {
return (@FIELDS,"price","high","low");
}
# Yahoo uses a suffix on the stock symbol to denote the exchange on
# which the stock is traded. Use this suffix to map from the stock
# symbol to the currency in which its prices are reported.
my %currency_tags = (
# Country City/Exchange Name
US => "USD", # USA AMEX, Nasdaq, NYSE
A => "USD", # USA American Stock Exchange (ASE)
B => "USD", # USA Boston Stock Exchange (BOS)
N => "USD", # USA Nasdaq Stock Exchange (NAS)
O => "USD", # USA NYSE Stock Exchange (NYS)
OB => "USD", # USA OTC Bulletin Board
PK => "USD", # USA Pink Sheets
X => "USD", # USA US Options
BA => "ARS", # Argentina Buenos Aires
VI => "EUR", # Austria Vienna
AX => "AUD", # Australia
SA => "BRL", # Brazil Sao Paolo
BR => "EUR", # Belgium Brussels
TO => "CAD", # Canada Toronto
V => "CAD", # Toronto Venture
SN => "CLP", # Chile Santiago
SS => "CNY", # China Shanghai
SZ => "CNY", # Shenzhen
CO => "DKK", # Denmark Copenhagen
PA => "EUR", # France Paris
BE => "EUR", # Germany Berlin
BM => "EUR", # Bremen
D => "EUR", # Dusseldorf
F => "EUR", # Frankfurt
H => "EUR", # Hamburg
HA => "EUR", # Hanover
MU => "EUR", # Munich
SG => "EUR", # Stuttgart
DE => "EUR", # XETRA
HK => "HKD", # Hong Kong
BO => "INR", # India Bombay
CL => "INR", # Calcutta
NS => "INR", # National Stock Exchange
JK => "IDR", # Indonesia Jakarta
I => "EUR", # Ireland Dublin
TA => "ILS", # Israel Tel Aviv
MI => "EUR", # Italy Milan
KS => "KRW", # Korea Stock Exchange
KQ => "KRW", # KOSDAQ
KL => "MYR", # Malaysia Kuala Lampur
MX => "MXP", # Mexico
NZ => "NZD", # New Zealand
AS => "EUR", # Netherlands Amsterdam
OL => "NOK", # Norway Oslo
LM => "PEN", # Peru Lima
IN => "EUR", # Portugal Lisbon
SI => "SGD", # Singapore
BC => "EUR", # Spain Barcelona
BI => "EUR", # Bilbao
MF => "EUR", # Madrid Fixed Income
MC => "EUR", # Madrid SE CATS
MA => "EUR", # Madrid
VA => "EUR", # Valence
ST => "SEK", # Sweden Stockholm
S => "CHF", # Switzerland Zurich
TW => "TWD", # Taiwan Taiwan Stock Exchange
TWO => "TWD", # OTC
BK => "THB", # Thialand Thailand Stock Exchange
TH => "THB", # ??? From Asia.pm, (in Thai Baht)
L => "GBP", # United Kingdom London
);
# yahoo_request (restricted function)
#
# This function expects a Finance::Quote object, a base URL to use,
# a refernece to a list of symbols to lookup. If a fourth argument is
# used then it will act as a suffix that needs to be appended to the stocks
# in order to obtain the correct information. This function relies upon
# the fact that the various Yahoo's all work the same way.
sub yahoo_request {
my $quoter = shift;
my $base_url = shift;
# Extract our original symbols.
my @orig_symbols = @{shift()};
# The suffix is used to specify particular markets.
my $suffix = shift || "";
my $uses_semicolon = shift || 0;
my %info;
my $ua = $quoter->user_agent;
# Generate a suitable URL, now all it needs is the
# ticker symbols.
$base_url .= "?f=".join("",@FIELD_ENCODING)."&e=.csv&s=";
while (my @symbols = splice(@orig_symbols,0,$MAX_REQUEST_SIZE)) {
# By pushing an extra symbol on to our array, we can
# be sure that everythng ends up with the correct suffix
# in the join() below.
push(@symbols,"");
my $url = $base_url . join("$suffix+",@symbols);
chop $url; # Chop off the final +
my $response = $ua->request(GET $url);
return unless $response->is_success;
# Okay, we have the data. Just stuff it in
# the hash now.
foreach (split('\015?\012',$response->content)) {
my @q;
if ($uses_semicolon) {
@q = $quoter->parse_csv_semicolon($_);
} else {
@q = $quoter->parse_csv($_);
}
my $symbol = $q[0];
my ($exchange) = $symbol =~ m/\.([A-Z]+)/;
# Strip out suffixes. Mmmm, functions as lvalues.
substr($symbol,-length($suffix),length($suffix)) = "";
# If we weren't using a two dimesonal
# hash, we could do the following with
# a hash-slice. Alas, we can't. This just
# loads all the returned fields into our hash.
for (my $i=0; $i < @FIELDS; $i++) {
# Every now and then on a failed
# retrieval, Yahoo will drop in an
# undefined field
next unless (defined $q[$i] && length $q[$i]);
# remove trailing spaces added for
# yahoo::europe quotes, since currency
# is returned with a trailing white
# space
$q[$i] =~ s/\s*$// ;
$info{$symbol,$FIELDS[$i]} = $q[$i];
}
# Yahoo returns a line filled with N/A's if we
# look up a non-existant symbol. AFAIK, the
# date flag will /never/ be defined properly
# unless we've looked up a real stock. Hence
# we can use this to check if we've
# successfully obtained the stock or not.
if ($info{$symbol,"date"} eq "N/A") {
$info{$symbol,"success"} = 0;
$info{$symbol,"errormsg"} = "Stock lookup failed";
next;
} else {
$info{$symbol,"success"} = 1;
}
# Whack the dates. This will add an isodate,
# and regularize the us date.
$quoter->store_date(\%info, $symbol, {usdate => $info{$symbol,"date"}});
$info{$symbol,"price"} = $info{$symbol,"last"};
# Remove spurious percentage signs in p_change.
$info{$symbol,"p_change"} =~ s/%//;
# Extract the high and low values from the
# day-range, if available
if ($info{$symbol,"day_range"} =~ m{^"?\s*(\S+)\s*-\s*(\S+)"?$}) {
$info{$symbol, "low"} = $1;
$info{$symbol, "high"} = $2;
}
if (defined($info{$symbol,"time"})) {
# uniform time output
$info{$symbol,"time"} = $quoter->isoTime($info{$symbol,"time"});
}
# "cap" from Yahoo::USA sometimes has "B" for
# billions suffix, eg. from "F" Ford -- expand that
# to a plain number for ease of use
if (defined($info{$symbol,"cap"})) {
$info{$symbol,"cap"}
= $quoter->B_to_billions ($info{$symbol,"cap"});
}
# Convert prices (when needed). E.G. Some London sources
# return in pence. Yahoo denotes this with GBP vs GBp
# We'd like them to return in pounds (divide by 100).
if (defined($exchange)) {
if ((($exchange eq "L") &&
(($info{$symbol,"currency"} eq "GBp") ||
#Assume GBX also quoted in pence; if not remove next line
($info{$symbol,"currency"} eq "GBX"))) ||
($exchange eq "TA")) {
foreach my $field ($quoter->default_currency_fields) {
next unless ($info{$symbol,$field});
$info{$symbol,$field} =
$quoter->scale_field($info{$symbol,$field},0.01);
}
} ;
if (($exchange eq "L") && defined($info{$symbol,"year_range"})) { # if a year range is returned for exchange=L
if ($info{$symbol,"year_range"}=~ m/([\d\.]+)\s*-\s*([\d\.]+)/) { # take year low and high
my ($year_low,$year_high) = ($1,$2) ;
if ($info{$symbol,"close"} <= $year_low) { # sometimes year_range was expressed in .01 GBp
$info{$symbol,"year_range"} = ($year_low/100)." - ".($year_high/100) ;
}
}
}
# Other exchanges here as needed.
}
if (defined($info{$symbol,"currency"})) {
# Having converted London prices to GBP above we
# make upper-case and turn GBX to GBP.
$info{$symbol,"currency"} =~ tr/a-z/A-Z/;
# yahoo started to return GBX instead of GBP
# somewhere arround 9 oct 2008.
$info{$symbol,"currency"} =~ s/GBX/GBP/;
# printf "Currency %s specified by Yahoo\n", $info{$symbol,"currency"};
} else {
# Determine the currency from the exchange name.
# Symbols without an exchange are in USD. Symbols
# starting with a hat are always indexes, so they
# don't have a currency.
if (defined($exchange)) {
$info{$symbol,"currency"} = $currency_tags{$exchange};
# print "Set currency based on exchange $exchange\n";
} elsif (substr($symbol,0,1) ne "^") {
# print "No exchange, not an index, set currency to USD\n";
$info{$symbol,"currency"} = "USD";
}
$info{$symbol,"currency_set_by_fq"} = 1;
}
} # End of processing each stock line.
} # End of lookup loop.
# Return undef's rather than N/As. This makes things more suitable
# for insertion into databases, etc. Also remove silly HTML that
# Yahoo inserts to put in little Euro symbols and stuff. It's
# pretty stupid to have HTML tags in a CSV file in the first
# place, don't you think?
foreach my $key (keys %info) {
#if (!defined $info{$key}) {
# printf STDERR "\n";
# printf STDERR "$key points to undefined value\n";
# printf STDERR "\n";
#}
if (defined $info{$key}) {
$info{$key} =~ s/<[^>]*>//g;
$info{$key} =~ s/ .*$//;
undef $info{$key} if ($info{$key} eq "N/A");
}
}
return %info if wantarray;
return \%info;
}
1;
=head1 NAME
Finance::Quote::Yahoo::Base - Common functions for fetching Yahoo info.
=head1 SYNOPSIS
Base functions for use by the Finance::Quote::Yahoo::* modules.
=head1 DESCRIPTION
This module is not called directly, rather it provides a set of
base functions which other Yahoo-related modules can use. If you're
thinking of writing a module to fetch specific information from
Yahoo, then you might wish to look through the source code for
this module.
=head1 LABELS RETURNED
Most Yahoo functions will return a standard set of labels. These
include (where available): symbol, name, last, date, time, net,
p_change, volume, bid, ask close, open, day_range, year_range, eps,
pe, div_date, div, div_yield, cap, ex_div, avg_vol.
=head1 SEE ALSO
Finance::Quote::Yahoo::Australia, Finance::Quote::Yahoo::USA,
Finance::Quote::Yahoo::Europe.
=cut
|