t000755001750001750 013202072256 12427 5ustar00ecec000000000000Finance-Quote-1.47za.t100755001750001750 243413202072256 13374 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 17; # Test za functions. my $q = Finance::Quote->new("ZA"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->za("AGL","AMS","BOGUS"); ok(%quotes); # Check that the last and date values are defined. ok($quotes{"AGL","success"}); ok($quotes{"AGL","last"} > 0); ok($quotes{"AGL","high"} > 0); ok($quotes{"AGL","low"} > 0); ok(length($quotes{"AGL","date"}) > 0); ok(substr($quotes{"AGL","isodate"},0,4) == $year || substr($quotes{"AGL","isodate"},0,4) == $lastyear); ok(substr($quotes{"AGL","date"},6,4) == $year || substr($quotes{"AGL","date"},6,4) == $lastyear); ok($quotes{"AGL","currency"} eq "ZAR"); ok($quotes{"AMS","success"}); ok($quotes{"AMS","last"} > 0); ok(length($quotes{"AMS","date"}) > 0); ok(substr($quotes{"AMS","isodate"},0,4) == $year || substr($quotes{"AMS","isodate"},0,4) == $lastyear); ok(substr($quotes{"AMS","date"},6,4) == $year || substr($quotes{"AMS","date"},6,4) == $lastyear); ok($quotes{"AMS","currency"} eq "ZAR"); # Check that a bogus fund returns no-success. ok($quotes{"BOGUS","success"} == 0); ok($quotes{"BOGUS","errormsg"} eq "Parse error"); hu.t100644001750001750 472213202072256 13375 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w # # HU.pm # # Version 0.1 - test of Hungarian (HU) F::Q # This version based on za.t module # # Zoltan Levardy # 2009 use strict; use Test::More; use Finance::Quote; if ( not $ENV{ONLINE_TEST} ) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 21; # Test za functions. my $q = Finance::Quote->new("HU"); my $year = ( localtime() )[5] + 1900; my $lastyear = $year - 1; #getting quotes for shares by ticker (OTP,ANY,RABA), # shares by ISIN (ticker: MTELEKOM: HU0000073507, MOL: HU0000068952) # and for funds by ISIN (HU0000702709,HU0000706437) # and finally an incorrect ticker/isin is ZOL, must fail. my %quotes = $q->hu( "OTP", "HU0000068952", "HU0000702709", "ZOL" ) ; #,"ANY","RABA","HU0000073507","HU0000068952","HU0000702709","HU0000706437","ZOL"); ok(%quotes); # Check that the last and date values are defined. ok( $quotes{ "OTP", "success" } ); ok( $quotes{ "OTP", "last" } > 0 ); ok( length( $quotes{ "OTP", "date" } ) > 0 ); ok( substr( $quotes{ "OTP", "isodate" }, 0, 4 ) == $year || substr( $quotes{ "OTP", "isodate" }, 0, 4 ) == $lastyear ); ok( substr( $quotes{ "OTP", "date" }, 6, 4 ) == $year || substr( $quotes{ "OTP", "date" }, 6, 4 ) == $lastyear ); ok( $quotes{ "OTP", "currency" } eq "HUF" ); # MTELEKOM: HU0000073507 ok( $quotes{ "HU0000068952", "success" } ); ok( $quotes{ "HU0000068952", "last" } > 0 ); ok( length( $quotes{ "HU0000068952", "date" } ) > 0 ); ok( substr( $quotes{ "HU0000068952", "isodate" }, 0, 4 ) == $year || substr( $quotes{ "HU0000068952", "isodate" }, 0, 4 ) == $lastyear ); ok( substr( $quotes{ "HU0000068952", "date" }, 6, 4 ) == $year || substr( $quotes{ "HU0000068952", "date" }, 6, 4 ) == $lastyear ); ok( $quotes{ "HU0000068952", "currency" } eq "HUF" ); # Fund: Budapest II, isin: HU0000702709 ok( $quotes{ "HU0000702709", "success" } ); ok( $quotes{ "HU0000702709", "last" } > 0 ); ok( length( $quotes{ "HU0000702709", "date" } ) > 0 ); ok( substr( $quotes{ "HU0000702709", "isodate" }, 0, 4 ) == $year || substr( $quotes{ "HU0000702709", "isodate" }, 0, 4 ) == $lastyear ); ok( substr( $quotes{ "HU0000702709", "date" }, 6, 4 ) == $year || substr( $quotes{ "HU0000702709", "date" }, 6, 4 ) == $lastyear ); ok( $quotes{ "HU0000702709", "currency" } eq "HUF" ); # Check that a ZOL fund returns no-success. ok( !$quotes{ "ZOL", "success" } ); ok( $quotes{ "ZOL", "errormsg" } eq "Fetch from bse or bamosz failed" ); Finance-Quote-1.47000755001750001750 013202072256 12243 5ustar00ecec000000000000README100644001750001750 56113202072256 13166 0ustar00ecec000000000000Finance-Quote-1.47 This archive contains the distribution Finance-Quote, version 1.47: Get stock and mutual fund quotes from various exchanges This software is Copyright (c) 2013 by Erik Colson . This is free software, licensed under: The GNU General Public License, Version 2, June 1991 This README file was generated by Dist::Zilla::Plugin::Readme v6.010. Changes100644001750001750 5752613202072256 13656 0ustar00ecec000000000000Finance-Quote-1.471.47 2017-11-12 17:19:42+01:00 Europe/Brussels * Use AlphaVantage for currency quotes instead of Yahoo (Mike Alexander) 1.46 2017-11-12 17:13:15+01:00 Europe/Brussels * Drop long-obsolete debian directory (Florian Schlichting) * AlphaVantage: - added support for .IL => USD currency and division (Adriano Baldi) - graceful error catchup (Mike Alexander) * Yahoojson: - module adapted to new URL and returned json (Rafael Casali) 1.45 2017-11-08 21:35:51+01:00 Europe/Brussels * alphavantage * more suffix - currency pairs added * GBP and GBX divided by 100 1.44 2017-11-07 21:57:57+01:00 Europe/Brussels * Added currencies for .SA (Brazil) and .TO (Canada/Toronto) markets * Setup a pause of .7s between queries in AlphaVantage.pm to limit queries 1.43 2017-11-06 23:41:47+01:00 Europe/Brussels * Added currency for .DE market * BUGFIX in currency determination regex 1.42 2017-11-06 19:04:25+01:00 Europe/Brussels * more tests in alphavantage.t * BUG resolved: removed time from $last_refresh when markets are open 1.41 2017-11-06 16:06:41+01:00 Europe/Brussels * return symbol for AlphaVantage data 1.39 * added AlphaVantage module (Matthew Patterson) * some other module changes: yahoojson, Morningstar, Bourso, TSX (not working) 1.38 2015-08-22 13:22:56+02:00 Europe/Brussels * module updates: tiaacref, yahooJSON, FTfunds, MStaruk, USFedBonds, GoldMoney * new modules: fidelityfixed (Peter Ratzlaff), yahooYQL * removed modules: MTGox * more tests: yahoo_speed.t, tiaacref.t 1.37 2015-02-01 20:24:32+01:00 Europe/Brussels * modified 00-use.t to show more info * Remove Crypt::SSLeay dependency in favor of LWP::Protocol::https (Geert Janssens) * Updated HU.pm and test file to current website (Kristof Marussy) 1.36 2015-01-31 * MorningstarJP : changed dependency from Date::Calc to DateTime 1.35 2014-06-17 08:06:14+02:00 Europe/Brussels * BUGFIX: VWD - currency returned. 1.34 2014-06-15 21:30:03+02:00 Europe/Brussels * VWD adapted to recent website change. 1.33 2014-06-01 11:24:24+02:00 Europe/Brussels * BUGFIX: yahoo_json never returns currency. so don't set a default. yahoo_json returned current timestamp instead of quote date. 1.32 2014-05-18 21:55:12+02:00 Europe/Brussels * return "symbol" for yahoo_json module * allow to retrieve ISIN codes with VWD module 1.31 2014-05-04 22:56:45+02:00 Europe/Brussels * Case mismatch in ZA_UnitTrusts pod 1.30 2014-05-04 21:56:34+02:00 Europe/Brussels * Bourso.pm works on current website changes. Thanks to Guillaume * New module CSE.pm by Hiranya Samarasekera. Covers Colombo Stock Exchange (CSE) in Sri Lanka. 1.29 2014-04-08 08:28:25+02:00 Europe/Brussels * New module za_unittrusts. kudos to Rolf Endres. * Indiamutual patched to current website. kudos to Vinay S Shastry. 1.28 2014-03-16 12:05:19+01:00 Europe/Brussels * Removed some unnecessary dependencies 1.27 2014-03-05 15:04:22+01:00 Europe/Brussels * New module YahooJSON added (Abhijit Kshirsagar) * mtgox.t should not create errors when ONLINE_TEST is not defined 1.26 2014-03-03 22:24:58+01:00 Europe/Brussels * VWD adapted to current website (skaringa) * Boursorama module mostly fixed (Arnaud Gardelein) 1.25 2014-03-02 23:18:23+01:00 Europe/Brussels * AEX.pm : Some checking added. Not working yet * Quote.pm : readded sub parse_csv_semicolon. 1.24 2014-03-02 21:39:00+01:00 Europe/Brussels * Added module Citywire.pm written by Martin Sadler * Added module FTfunds.pm written by Martin Sadler * Added module MStaruk.pm written by Martin Sadler * Added module TNetuk.pm written by Martin Sadler * Data::Dumper is no more required to build 1.23_02 2014-03-02 14:46:41+01:00 Europe/Brussels (TRIAL RELEASE) TEST RELEASE 1.22 2014-03-02 10:38:18+01:00 Europe/Brussels (TRIAL RELEASE) TEST RELEASE 1.21 2014-03-02 09:56:38+01:00 Europe/Brussels (TRIAL RELEASE) * ASX.pm now supports querying more than 10 symbols (goodvibes2) * Travis config added for automated test build * BUILD: Updated to use Dist::Zilla 2014-02-17 Erik Colson * INSTALLATION FIX: Install Date::Calc as dependency 2014-02-16 Erik Colson * MtGox support added by Sam Morris * MorningstarJP support added by Christopher Hill * Yahoo modules changed due to site change 2010-02-16 Erik Colson * TSP.pm updated. Patch from Kevin Ryde. * YAHOO/Base.pm added conversion from 'B' billions to numbers. Patch from Kevin Ryde. * Billions support moved to Quote.pm 2009-10-05 Erik Colson * Lots of tests added 2009-10-04 Erik Colson * IndiaMutual.t tests added * Yahoo_europe: Bug 44245 solved. Wrong fields returned. * Documentation: Bug 48818 corrected. 2009-10-03 Erik Colson * yahoo_europe.t tests corrected 2009-09-30 Erik Colson * Bourso.t tests corrected 2009-09-29 Erik Colson * AEX.pm removed code for options and futures. (didn't work) 2009-07-19 Erik Colson * Bug in Yahoo::Base corrected. Sometimes year range is wrongly returned. 2009-07-19 Giles Robertson * Bug in Yahoo::Base corrected. GBp wrongly interpreted. 2009-07-19 Stephan Ebelt * Goldmoney.pm patched. support for platinum added. 2009-07-18 Zoltan Levardy * New module HU.pm (Hungarian stocks) 2009-06-14 Divakar Ramachandran * Bug RT 46155 solved by modifying link in IndiaMutual.pm 2009-06-14 Stephan Ebelt * Cominvest URL modified 2009-06-14 Erik Colson * currencies adapted to yahoo denomination 2009-06-13 Sattvik * currency retrieval updated (yahoo website changed) 2009-04-27 Bradley Dean * ASX.pm updated due to website change 2009-04-13 Erik Colson * Release 1.16 2009-04-12 Erik Colson * BUGFIX: Bourso.pm allmost completely rewritten due to website change. * BUGFIX: Morningstar.pm patched by Fredrik Persson. * BUGFIX: AEX.pm patched by Herman van Rink. 2009-03-19 Erik Colson * BUGFIX: 12:XXpm formatted time handling. 2009-03-04 Erik Colson * RENAMED ITE is now RZR 2009-03-02 Erik Colson * BUGFIX: ZA.pm patched. 2009-03-01 Erik Colson * BUGFIX: Stephen Ebelt patch applied for goldmoney.pm * BUGFIX: Encoding problem solved by Ashwin 2009-02-16 Bradley Dean * NEW: Function fetch_live_currencies. 2009-02-15 Bradley Dean * NEW: Module Finance::Quote::Currencies created for use in currency_lookup. 2008-12-05 Erik Colson * Finanzpartner module adapted to site updated. By Jan Wilamowius. * Morningstar patched by Fredrik Persson. 2008-11-09 Erik Colson * Bourso.pm updated due to website update. By Bernard Fuentes 2008-10-26 Erik Colson * BUG correction : IndiaMutual.pm: symbol not set it module. * Release 1.15 2008-10-21 Erik Colson * BUG correction : function isoTime - make sure $hours and $mins are treated as numbers * use sprintf in isoTime 2008-10-15 Erik Colson * Release 1.14 2008-10-13 Erik Colson * Finanzpartner.pm added by Jan Willamowius 2008-10-12 Erik Colson * isoTime function added * added quote.t * yahoo time is now format using isoTime 2008-10-11 Erik Colson * added prerequisite for HTML::TreeBuilder * union.t from todo 2008-10-10 Paul Fenwick * TEST: Ensure Data::Dumper is not accidently left in F::Q code. 2008-10-07 Erik Colson * Root README added * BUGFIX: asx.t 2008-10-05 Erik Colson * Added Cominvest module from Stephan Ebelt 2008-10-04 Erik Colson * Failing tests moved to todo-state for trustnet, usfedbonds, bourso, deka, union * BUGFIX: currency.t * BUGFIX: lerevenu.t - index ID corrected 2008-10-02 Erik Colson * Failing tests moved to todo-state for ftportfolios, aiahk, nzx, maninvestments. 2008-09-30 Paul Fenwick * BUGFIX: Applied patch from Bill Carlson to fix Tiaacref.pm. Thanks Bill, you rock! 2008-09-28 Erik Colson * StockHouseCanada.pm updated to new site layout * DWS.pm updated 2008-09-27 Erik Colson * VWD.pm updated to new site layout * TSX.pm added 2008-09-27 Paul Fenwick * DOCUMENTATION: Fixed malformed formatting in authors email addresses in Fiannce/Quote.pm. 2008-09-26 Erik Colson * AEX.pm updated to new site layout (comma used in numbers) 2008-09-22 Paul Fenwick * BUILD: Module::Install 0.77 is now used for building and installation. (PJF) * TESTING: Finance::Quote's test system has been restructured. Tests are now run during installation, but online and author tests are skipped by default. (PJF) 2008-09-21 Erik Colson * lib/Finance/Quote/Yahoo/Brasil.pm: Enable semicolon. 2007-05-13 David Hampton * lib/Finance/Quote/SEB.pm: Patch from Henrik Riomar to fix a problem finding quotes for funds with the Swedish chars åäö in the name. * lib/Finance/Quote/IndiaMutual.pm: Patch from Devendra Gera to remove white space when splitting the results in the AMFI data file. 2007-01-07 David Hampton * CVSTAG: finance_quote_1_13 * lib/Finance/Quote.pm: Update version to 1.13. * lib/Finance/Quote.pm: Update the store_date() function for the case when the year isn't explicitly stated. If the specified month would put the quote in the future, then consider this a quite from last year. manly intended to handle the rollover from December to January on web sites that don't specify the year. Suggestion from Christian Lupien. * lib/Finance/Quote/BMONesbittBurns.pm: Enhance module to support mutual fund quotes (which have less data than stock quotes). Correct date format parsing. Fix from Christian Lupien . * lib/Finance/Quote/StockHouseCanada.pm: The fund name seems to be a moving target. Search all tables of depth one looking for it. 2007-01-01 David Hampton * lib/Finance/Quote/FTPortfolios.pm: Rewrite this module for the new web site design. * lib/Finance/Quote/TSP.pm: Strip spaces around the dollar values. * lib/Finance/Quote/FinanceCanada.pm: Rewrite this module for the new web site design. * test/*.t: Some restructuring of tests. Add a couple more tests on dates. Replace a couple of test stocks that are no longer valid. * test/*.t: Accept last year as a valid date. Comes in hand when testing modules at the start of the new year. * lib/Finance/Quote/ZA.pm: Update for changes in the display of the web site. 2006-12-31 David Hampton * lib/Finance/Quote/StockHouseCanada.pm: * test/stockhousecanada.t: New module for getting Canadian Mutual fund quotes from Chris Carton . * lib/Finance/Quote/Deka.pm: Update for changes in the display of the web site. Now uses an https url. * lib/Finance/Quote/LeRevenu.pm: Updates from Dominique Corbex for changes in the display of the web site. * lib/Finance/Quote/Trustnet.pm: Update for changes in the display of the web site. 2006-09-11 David Hampton * Move AIA.pm to AIAHK.pm since AIA has sites in multiple countries. 2006-09-10 David Hampton * lib/Finance/Quote/AIA.pm: * test/aia.pm: New module to access American International Assurance fund information. Based on perl script from Wouter van Marle . * lib/Finance/Quote/Bourso.pm: Update the URL to track changes on the web site. 2006-07-10 David Hampton * lib/Finance/Quote.pm: Update version to 1.12. * CVSTAG: finance_quote_1_12 2006-06-27 David Hampton * Makefile.PL: State the dependency on Crypt::SSLeay that several modules now have. * lib/Finance/Quote/Yahoo/Base.pm: Don't set fields that are defined but are empty.. * test/yahoo_brasil.t: Update the test module to have more cases and use better stocks. * lib/Finance/Quote/Yahoo/Brasil.pm: Update for the change of the data separator from a semicolon to a comma. * test/financecanada.t: * test/hex.t: Add new test cases to cover the last untested modules. All modules are now tested. * lib/Finance/Quote/FinanceCanada.pm: Don't set the success flag if the lookup failed. * lib/Finance/Quote/Platinum.pm: Use the new url of the pricing information. * lib/Finance/Quote/ManInvestments.pm: Update for the new table format on the web site. * test/indiamutual.t: * test/aex.t: Update the test cases to use currently listed funds. * lib/Finance/Quote/ManInvestments.pm: The url for updating quotes has changed, as has the table header. * lib/Finance/Quote/Bourso.pm: * lib/Finance/Quote/LeRevenu.pm: * test/bourso.t: * test/lerevenu.t: Updated modules from Dominique Corbex . The name field now returns the real name and not ticker symbols, and other small fixes. 2006-04-08 David Hampton * lib/Finance/Quote/Trustnet.pm: Work around the fact that gnucash escapes the ampersand character when passing stock names to F::Q. * lib/Finance/Quote/DWS.pm: Updated module from Klaus Dahlke to retrieve quotes from the new DWS web page. * lib/Finance/Quote/Tiaacref.pm: Explicitly state in the code that this module requires ssl support (it uses an https:// url). This prevents perl from trying to run the code when ssl support isn't present. * lib/Finance/Quote.pm: * lib/Finance/Quote/HEX.pm: * test/hex.t: New module from Mika Laari to fetch quote information from the Helsinki stock exchange. * Documentation/Hackers-Guide: Add a section on the q->store_date() function. All modules should use this function to set the 'date' and 'isodate' fields based on the retrieved textual date (or lack thereof). * test/lerevenu.t: Test the right module. 2006-04-07 David Hampton * lib/Finance/Quote.pm: * lib/Finance/Quote/LeRevenu.pm: * test/lefrevenu.t: New module from Dominique Corbex to fetch information from the LeRevenu.com site in France. * t/yahoo_europe.t: New test cases for non-GBP London exchange stocks. Use new stock for test of the XETRA exchange. (Can't find a non-Euro stock there, so remove those tests.) * lib/Finance/Quote/Yahoo/Base.pm: Patch from p1n0@sourceforge.net to only divide London exchange values by 100 if they are denominated in pence. 2006-04-06 David Hampton * lib/Finance/Quote.pm: * lib/Finance/Quote/Bourso.pm: * test/bourso.t: New module from Dominique Corbex to fetch information from the "Paris Stock Exchange", http://www.boursorama.com. * lib/Finance/Quote/VWD.pm: Updated module from Jörg Sommer that is more tolerant of the advertising added to the web page. 2006-01-11 David Hampton * CVSTAG: finance_quote_1_11 * lib/Finance/Quote.pm: Updated $VERSION to 1.01 2006-01-10 David Hampton * test/dws.t: * test/maninvestments.t: * test/yahoo_brasil.t: Accept dates in both the previous and current year as valid responses. * test/aex.t: Change test currency to one still on the exchange. * lib/Finance/Quote/VWD.pm: Jörg Sommer's patch to work better with invalid WKNs and to extract the exchange information from its new location. 2005-11-18 David Hampton * lib/Finance/Quote/AEX.pm: Use the store_date function. * lib/Finance/Quote/ASX.pm: * lib/Finance/Quote/Cdnfundlibrary.pm: * lib/Finance/Quote/Platinum.pm: * lib/Finance/Quote/Trustnet.pm: * lib/Finance/Quote/Yahoo/Base.pm: Add code to protect against empty tables, data fields, etc. * test/aex.t: Correct the number of test cases. Changed test stock to one that is still on the exchange. Site no longer provides time (date only) so remove tests for time of quote. Futures quotes don't always have bid/ask values so comment out those tests. * test/indiamutual.t: * test/trustnet.t: * test/union.t: * test/yahoo.t: Changed test stock to one that is still on the exchange. * test/yahoo_brasil.t: All returned prices (for all stocks I tried) return a price of zero, so comment out the test for non-zero. 2005-10-23 David Hampton * lib/Finance/Quote/VWD.pm: Put back the call to the HTML::TableExtract first_table_state_found() function for now. At some point this should be removed and the 2.0 version of HTML::TableExtract required. * lib/Finance/Quote.pm: Make note of an alternate yahoo URL that can be used to obtain currency quotes. From Gerry Barksdale . 2005-10-22 David Hampton * lib/Finance/Quote/Tiaacref.pm: * test/tiaacref.t: Add Support for TIAA-CREF mutual funds from Brandon . * lib/Finance/Quote/VWD.pm: Remove the thousands separator character from quote values. * lib/Finance/Quote/TSP.pm: * test/tsp.t: Frank Mori Hess's change to add support for the TSP lifecycle L funds. * ChangeLog: Archive pre-2005 data into a separate file. * lib/Finance/Quote/Deka.pm: Add a new module to retrieve German investment fund prices from Deka. Module from Knut Franke * lib/Finance/Quote/USFedBonds.pm: * test/usfedbonds.t: Add a new US Federal Bonds stock quote module from Stephen Langenhoven . 2005-10-21 David Hampton * lib/Finance/Quote.pm: Updated to work with new Yahoo currency conversion pages. * lib/Finance/Quote/Tiaacref.pm: New URL from Kevin Foss. Uses https, so the Crypt::SSLeay module is now required for TIAA-CREF quotes. * lib/Finance/Quote/ZI.pm: Zürich Invest has been purchased by Deutsche Bank and integrated into DWS. The DWS.pm module should now be used in place of the ZI.pm module. * lib/Finance/Quote/VWD.pm: Patch from Rainer Dorsch to return the current price as 'last'. The HTML::TableExtract first_table_state_found() function has been deprecated. Accept both the old and new values as correct answers. * lib/Finance/Quote/ZA.pm: * test/za.t: Add a new South African stock quote module from Stephen Langenhoven . 2005-08-10 David Hampton * lib/Finance/Quote/VWD.pm: Handle invalid ISINs better. VWD delivers a 404 error instead of a blank page. Fix suggested by Uwe Simon 2005-07-04 Paul Fenwick * lib/Finance/Quote.pm: Bumped $VERSION to 1.10, primarily to work around a problem with CPAN distributions. * CVSTAG: finance_quote_1_10 2005-06-29 David Hampton * lib/Finance/Quote/VWD.pm: Updated module from Jörg Sommer . * lib/Finance/Quote/cdnfundlibrary.pm: Changes inspired by kalaleq@users.sourceforge.net allow retrieval of more data. * lib/Finance/Quote.pm: * lib/Finance/Quote/Yahoo/NZ.pm: New module from Stephen Judd . * lib/Finance/Quote/NZX.pm: Tweak to allow both NZX and Yahoo:NZ to get quotes for New Zealand Stocks (use method nz). * CVSTAG: finance_quote_1_09 2005-05-30 Paul Fenwick * MANIFEST: Updated with files intended for distribution. * lib/Finance/Quote.pm: Updated $VERSION to 1.09 * CVSTAG: Updated finance_quote_1_09 tag on MANIFEST and lib/Finace/Quote.pm * Released updated version 1.09 with new MANIFEST and Quote.pm to Sourceforge. * lib/Finance/Quote/VWD.pm: Re-enabled $VERSION and bumped to 1.01 to allow correct indexing on CPAN, however the older version currently remains in the 1.09 release. 2005-05-04 David Hampton * lib/Finance/Quote/FTPortfolios.pm: Update for changes in the website. * t/ftportfolios.t: New test module. * TSP.pm: Replace core parsing with tighter code. Support the symbols used by both Frank Mori Hess' and Trent Piepho's TSP modules. Make the symbols case insensitive. * lib/Finance/Quote/Cdnfundlibrary.pm: Find table by headers instead of by index. * test/asegr.t: New module * lib/Finance/Quote/ASEGR.pm: New module * lib/Finance/Quote/ASX.pm: Skip any blank lines in the table. Pass an extra parameter to TableExtract to keep it from doing unnecessary work that produces warnings. 2005-03-19 David Hampton * lib/Finance/Quote/Trustnet.pm: Encode the '&' character before calling the user agent GET function. Fixes bug 747080. 2005-03-19 David Hampton * almost all files: Collapsed all date parsing code into a single function. This function handles the date formats provided by all current quote sources and converts them all into the F::Q standard of a US date format. It also adds an ISO format date to all quotes in the new isodate field. Added lots of test functions to check date formats. 2005-03-19 David Hampton * lib/Finance/Quote/AEX.pm: Spelling correcting from Frank Mori Hess. * lib/Finance/Quote.pm: Documentation correction from Trent Piepho. * lib/Finance/Quote/Yahoo/Base.pm (yahoo_request): Fix an undefined reference when Yahoo ocassionally returns an empty field. 2005-03-01 David Hampton * lib/Finance/Quote.pm: New modules. New function to parse files separated by semicolons instead of commas. * lib/Finance/Quote/AEX.pm: Worked over modules from Johan van Oostrum. Most of the old AEX data has migrated elsewhere. * lib/Finance/Quote/ASX.pm: * lib/Finance/Quote/Trustnet.pm: Got the modules working again. * lib/Finance/Quote/ManInvestments.pm: * lib/Finance/Quote/Platinum.pm: New modules for Australian investment price sources from Ian Dall . * lib/Finance/Quote/NZX.pm: New modules for fetching quotes the from the New Zealand stock exchange. Provided by Michael Curtis. * lib/Finance/Quote/SEB.pm: New modules for fetching quotes from the Swedish Bank. Submitted by Tomas Carlsson. * lib/Finance/Quote/TSP.pm: New modules for fetching quotes from the US Govt. Thrift Service Plan. Submitted by Frank Mori Hess. * lib/Finance/Quote/Yahoo/Base.pm: Corrected currency tags for Vienna and Valence. * lib/Finance/Quote/Yahoo/Brasil.pm: Add new Yahoo Brasil module from Ismael Orenstein . * t/*: Various new test modules. 2005-02-09 David Hampton * lib/Finance/Quote/Fidelity.pm: * lib/Finance/Quote/Union.pm: Got the modules working again. * lib/Finance/Quote/Yahoo/Base.pm: Extract the currency directly from Yahoo, instead of looking it up in an exchange/currency mapping table. * t/*: Various new test and updated modules. 2005-02-06 David Hampton * lib/Finance/Quote/BMONesbittBurns.pm: Got the modules working again. 2005-01-14 David Hampton * lib/Finance/Quote/Cdnfundlibrary.pm: Got the module working again. cse.t100755001750001750 201613202072256 13530 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 12; # Test CSE functions. my $quoter = Finance::Quote->new(); my %quotes = $quoter->cse("JKH.N0000"); ok(%quotes); # Check that some values are defined. ok($quotes{"JKH.N0000","success"},"success"); ok($quotes{"JKH.N0000","last"} > 0,"last > 0"); ok($quotes{"JKH.N0000","volume"} > 0,"volume > 0"); TODO: { local $TODO = "No 'open' returned when market closed ?" ; ok($quotes{"JKH.N0000","open"},"open is defined"); } ok($quotes{"JKH.N0000","high"},"high is defined"); ok($quotes{"JKH.N0000","low"},"low is defined"); ok($quotes{"JKH.N0000","close"},"close is defined"); # Exercise the fetch function %quotes = $quoter->fetch("cse", "JKH.N0000"); ok(%quotes); ok($quotes{"JKH.N0000","success"}); ok($quotes{"JKH.N0000","last"} > 0); # Check that a bogus fund returns no-success. %quotes = $quoter->cse("BOGUS"); ok( ! $quotes{"BOGUS","success"}); tsp.t100755001750001750 327213202072256 13571 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 22; # Test TSP functions. my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my $quoter = Finance::Quote->new(); my %quotes = $quoter->tsp("c","s","TSPgfund","BOGUS","l2040fund"); ok(%quotes); # Check that some values are defined. ok($quotes{"c","success"}); ok($quotes{"c","nav"} > 0); ok($quotes{"l2040fund","date"}); ok(substr($quotes{"l2040fund","isodate"},0,4) == $year || substr($quotes{"l2040fund","isodate"},0,4) == $lastyear); ok(substr($quotes{"l2040fund","date"},6,4) == $year || substr($quotes{"l2040fund","date"},6,4) == $lastyear); ok($quotes{"s","currency"}); ok($quotes{"s","name"}); ok($quotes{"TSPgfund","success"}); ok($quotes{"TSPgfund","nav"} > 0); ok($quotes{"TSPgfund","date"}); ok(substr($quotes{"TSPgfund","isodate"},0,4) == $year || substr($quotes{"TSPgfund","isodate"},0,4) == $lastyear); ok(substr($quotes{"TSPgfund","date"},6,4) == $year || substr($quotes{"TSPgfund","date"},6,4) == $lastyear); # Check that some values are undefined. ok( !defined($quotes{"c","exchange"}) ); # Check that a bogus fund returns no-success. ok( ! $quotes{"BOGUS","success"}); # Exercise the fetch function %quotes = $quoter->fetch("tsp","g","f","i","tsplincomefund"); ok(%quotes); ok($quotes{"g","success"}); ok($quotes{"f","nav"} > 0); ok($quotes{"i","date"}); ok(substr($quotes{"i","isodate"},0,4) == $year || substr($quotes{"i","isodate"},0,4) == $lastyear); ok(substr($quotes{"i","date"},6,4) == $year || substr($quotes{"i","date"},6,4) == $lastyear); ok($quotes{"tsplincomefund","nav"} > 0); aex.t100755001750001750 216013202072256 13533 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 13; # Test AEX functions. my $quoter = Finance::Quote->new(); my %quotes = $quoter->aex("AH"); ok(%quotes); # Check that some values are defined. ok($quotes{"AH","success"}); ok($quotes{"AH","last"} > 0); ok($quotes{"AH","date"}); ok($quotes{"AH","volume"} > 0); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"AH","isodate"},0,4) == $year || substr($quotes{"AH","isodate"},0,4) == $lastyear); ok(substr($quotes{"AH","date"},6,4) == $year || substr($quotes{"AH","date"},6,4) == $lastyear); # Exercise the fetch function %quotes = $quoter->fetch("aex","AMG"); ok(%quotes); ok($quotes{"AMG","success"}); ok($quotes{"AMG","last"} > 0); # Check fetching on based on ISIN %quotes = $quoter->aex("NL0000009165"); # NL0000009165 == Heineken == HEIA ok(%quotes); ok($quotes{"NL0000009165","success"}); # Check that a bogus fund returns no-success. %quotes = $quoter->aex("BOGUS"); ok( ! $quotes{"BOGUS","success"}); nzx.t100755001750001750 170713202072256 13603 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my %quotes = $q->nzx("TPW","BOGUS"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. TODO: { local $TODO="To be debugged"; ok($quotes{"TPW","price"} > 0); ok(length($quotes{"TPW","name"}) > 0); ok($quotes{"TPW","success"}); ok($quotes{"TPW", "currency"} eq "NZD"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"TPW","isodate"},0,4) == $year || substr($quotes{"TPW","isodate"},0,4) == $lastyear); ok(substr($quotes{"TPW","date"},6,4) == $year || substr($quotes{"TPW","date"},6,4) == $lastyear); } # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); dws.t100755001750001750 157013202072256 13557 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test DWS functions. my $q = Finance::Quote->new("DWS"); my %quotes = $q->fetch("dwsfunds","847402","BOGUS"); ok(%quotes); # Check that the last and date values are defined. ok($quotes{"847402","success"}); ok($quotes{"847402","last"} > 0); ok(length($quotes{"847402","date"}) > 0); ok($quotes{"847402","currency"} eq "EUR"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok((substr($quotes{"847402","isodate"},0,4) == $year) || (substr($quotes{"847402","isodate"},0,4) == $lastyear)); ok((substr($quotes{"847402","date"},6,4) == $year) || (substr($quotes{"847402","date"},6,4) == $lastyear)); # Check that a bogus fund returns no-success. ok(! $quotes{"BOGUS","success"}); hex.t100755001750001750 172013202072256 13543 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 14; # Test HEX functions. my $q = Finance::Quote->new(); my @stocks = ("NOK1V", "RTRKS"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("hex", @stocks); ok(%quotes); # Check that the name and nav are defined for all of the stocks. foreach my $stock (@stocks) { ok($quotes{$stock,"price"} > 0); ok(length($quotes{$stock,"name"})); ok($quotes{$stock,"success"}); ok($quotes{$stock, "currency"} eq "EUR"); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } # Check that a bogus stock returns no-success. %quotes = $q->fetch("hex", "BOGUS"); ok(! $quotes{"BOGUS","success"}); asx.t100755001750001750 412113202072256 13550 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w # 16-Feb-2014 Change RZR (delisted in 2012) to BOQ. # 28-Feb-2014 Add tests with 11 stocks at once. plan tests 11 -> 34. use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 34; # Test ASX functions. my $q = Finance::Quote->new(); $q->timeout(120); # ASX is broken regularly, so timeouts are good. my %quotes = $q->asx("WES","BHP"); ok( %quotes, "Data returned for call to asx" ); # Check the last values are defined. These are the most used and most # reliable indicators of success. ok( $quotes{"WES","success"}, "WES query was successful" ); cmp_ok( $quotes{"WES","last"}, '>', 0 , "Last price for WES was > 0" ); ok( $quotes{"BHP","success"}, "BHP query was successful" ); cmp_ok( $quotes{"BHP","last"}, '>', 0 , "Last price for BHP was > 0" ); # Exercise the fetch function a little. %quotes = $q->fetch("asx","BOQ"); ok( %quotes, "Data returned for call to fetch" ); ok( $quotes{"BOQ","success"}, "BOQ query was successful" ); cmp_ok( $quotes{"BOQ","last"}, '>', 0 , "Last price for BOQ was > 0" ); # Check that we're getting currency information. cmp_ok( $quotes{"BOQ", "currency"}, "eq", "AUD" , "Currency of BOQ is AUD" ); # Check we're not getting bogus percentage signs. unlike( $quotes{"BOQ","p_change"} , qr/%/ , "No percentage sign in p_change value" ); # Check that looking up a bogus stock returns failure: %quotes = $q->asx("BOG"); ok( ! $quotes{"BOG","success"}, "asx call for invalid stock BOG returns failure"); # Check 11 stocks at once to test batching of price enquiries into groups of 10 my @stocks = qw/AMP ANZ BHP BOQ BEN CSR IAG NAB TLS WBC WES/; %quotes = $q->asx(@stocks); ok( %quotes, "Data returned for call to asx" ); # Check the last values are defined. These are the most used and most # reliable indicators of success. foreach my $stock (@stocks) { ok( $quotes{$stock, "success"}, $stock . " query was successful" ); cmp_ok( $quotes{$stock,"last"}, '>', 0 , "Last price for " . $stock . " was > 0" ); } seb.t100755001750001750 200013202072256 13520 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my %quotes = $q->seb_funds("SEB Cancerfonden","BOGUS"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"SEB Cancerfonden","price"} > 0); ok(length($quotes{"SEB Cancerfonden","name"}) > 0); ok($quotes{"SEB Cancerfonden","success"}); ok($quotes{"SEB Cancerfonden", "currency"} eq "SEK"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"SEB Cancerfonden","isodate"},0,4) == $year || substr($quotes{"SEB Cancerfonden","isodate"},0,4) == $lastyear); ok(substr($quotes{"SEB Cancerfonden","date"},6,4) == $year || substr($quotes{"SEB Cancerfonden","date"},6,4) == $lastyear); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); tsx.t100755001750001750 200413202072256 13571 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Data::Dumper; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 26 ; # Test TSX functions. my $q = Finance::Quote->new(); my @stocks = ("STN", "BCE", "BMO"); my %regexps = ( STN => qr/\bStantec\b/, BCE => qr/\b(BCE|Bell)\b/, BMO => qr/\b(BMO|Montreal)\b/, ); my %quotes = $q->fetch("tsx", @stocks); ok(%quotes); foreach my $stock (@stocks) { my $name = $quotes{$stock, "name"}; print "#Testing $stock: $name\n"; my $regexp = $regexps{$stock}; ok($name =~ /$regexp/i); ok($quotes{$stock, "exchange"} eq 'T'); ok($quotes{$stock, "method"} eq 'tsx'); ok($quotes{$stock, "last"} > 0); ok($quotes{$stock, "net"} =~ /^-?\d+\.\d+$/); ok($quotes{$stock, "p_change"} =~ /^-?\d+\.\d+$/); ok($quotes{$stock, "success"}); ok($quotes{$stock, "volume"} >= 0); } # Check that a bogus stock returns no-success. %quotes = $q->fetch("tsx", "BOGUS"); ok(! $quotes{"BOGUS","success"}); vwd.t100755001750001750 365613202072256 13571 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 1 + 3 * 6 + 2; # Test vwd functions. my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my $q = Finance::Quote->new("VWD"); my %quotes = $q->vwd("847402","LU0309191491","971675","BOGUS"); ok(%quotes); # Check that the last and date values are defined. ok($quotes{"847402","success"}); ok($quotes{"847402","last"} > 0); ok(length($quotes{"847402","date"}) > 0); ok(substr($quotes{"847402","isodate"},0,4) == $year || substr($quotes{"847402","isodate"},0,4) == $lastyear); ok(substr($quotes{"847402","date"},6,4) == $year || substr($quotes{"847402","date"},6,4) == $lastyear); ok($quotes{"847402","currency"} eq "EUR"); # Check that the last and date values are defined. ok($quotes{"LU0309191491","success"}); ok($quotes{"LU0309191491","last"} > 0); ok(length($quotes{"LU0309191491","date"}) > 0); ok(substr($quotes{"LU0309191491","isodate"},0,4) == $year || substr($quotes{"LU0309191491","isodate"},0,4) == $lastyear); ok(substr($quotes{"LU0309191491","date"},6,4) == $year || substr($quotes{"LU0309191491","date"},6,4) == $lastyear); ok($quotes{"LU0309191491","currency"} eq "EUR"); # Check that the last and date values are defined. stock 971675 ok($quotes{"971675","success"}); ok($quotes{"971675","last"} > 0); ok(length($quotes{"971675","date"}) > 0); ok(substr($quotes{"971675","isodate"},0,4) == $year || substr($quotes{"971675","isodate"},0,4) == $lastyear); ok(substr($quotes{"971675","date"},6,4) == $year || substr($quotes{"971675","date"},6,4) == $lastyear); ok($quotes{"971675","currency"} eq "DKK","Currency for 971675 (".$quotes{"971675","currency"}.") = DKK"); # Check that a bogus fund returns no-success. ok($quotes{"BOGUS","success"} == 0); ok($quotes{"BOGUS","errormsg"} eq "Parse error"); # invalid symbols not detected anymore LICENSE100644001750001750 4352313202072256 13360 0ustar00ecec000000000000Finance-Quote-1.47This software is Copyright (c) 2013 by Erik Colson . This is free software, licensed under: The GNU General Public License, Version 2, June 1991 GNU GENERAL PUBLIC LICENSE Version 2, June 1991 Copyright (C) 1989, 1991 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The licenses for most software are designed to take away your freedom to share and change it. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change free software--to make sure the software is free for all its users. This General Public License applies to most of the Free Software Foundation's software and to any other program whose authors commit to using it. (Some other Free Software Foundation software is covered by the GNU Lesser General Public License instead.) You can apply it to your programs, too. When we speak of free software, we are referring to freedom, not price. Our General Public Licenses are designed to make sure that you have the freedom to distribute copies of free software (and charge for this service if you wish), that you receive source code or can get it if you want it, that you can change the software or use pieces of it in new free programs; and that you know you can do these things. To protect your rights, we need to make restrictions that forbid anyone to deny you these rights or to ask you to surrender the rights. These restrictions translate to certain responsibilities for you if you distribute copies of the software, or if you modify it. For example, if you distribute copies of such a program, whether gratis or for a fee, you must give the recipients all the rights that you have. You must make sure that they, too, receive or can get the source code. And you must show them these terms so they know their rights. We protect your rights with two steps: (1) copyright the software, and (2) offer you this license which gives you legal permission to copy, distribute and/or modify the software. Also, for each author's protection and ours, we want to make certain that everyone understands that there is no warranty for this free software. If the software is modified by someone else and passed on, we want its recipients to know that what they have is not the original, so that any problems introduced by others will not reflect on the original authors' reputations. Finally, any free program is threatened constantly by software patents. We wish to avoid the danger that redistributors of a free program will individually obtain patent licenses, in effect making the program proprietary. To prevent this, we have made it clear that any patent must be licensed for everyone's free use or not licensed at all. The precise terms and conditions for copying, distribution and modification follow. GNU GENERAL PUBLIC LICENSE TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 0. This License applies to any program or other work which contains a notice placed by the copyright holder saying it may be distributed under the terms of this General Public License. The "Program", below, refers to any such program or work, and a "work based on the Program" means either the Program or any derivative work under copyright law: that is to say, a work containing the Program or a portion of it, either verbatim or with modifications and/or translated into another language. (Hereinafter, translation is included without limitation in the term "modification".) Each licensee is addressed as "you". Activities other than copying, distribution and modification are not covered by this License; they are outside its scope. The act of running the Program is not restricted, and the output from the Program is covered only if its contents constitute a work based on the Program (independent of having been made by running the Program). Whether that is true depends on what the Program does. 1. You may copy and distribute verbatim copies of the Program's source code as you receive it, in any medium, provided that you conspicuously and appropriately publish on each copy an appropriate copyright notice and disclaimer of warranty; keep intact all the notices that refer to this License and to the absence of any warranty; and give any other recipients of the Program a copy of this License along with the Program. You may charge a fee for the physical act of transferring a copy, and you may at your option offer warranty protection in exchange for a fee. 2. You may modify your copy or copies of the Program or any portion of it, thus forming a work based on the Program, and copy and distribute such modifications or work under the terms of Section 1 above, provided that you also meet all of these conditions: a) You must cause the modified files to carry prominent notices stating that you changed the files and the date of any change. b) You must cause any work that you distribute or publish, that in whole or in part contains or is derived from the Program or any part thereof, to be licensed as a whole at no charge to all third parties under the terms of this License. c) If the modified program normally reads commands interactively when run, you must cause it, when started running for such interactive use in the most ordinary way, to print or display an announcement including an appropriate copyright notice and a notice that there is no warranty (or else, saying that you provide a warranty) and that users may redistribute the program under these conditions, and telling the user how to view a copy of this License. (Exception: if the Program itself is interactive but does not normally print such an announcement, your work based on the Program is not required to print an announcement.) These requirements apply to the modified work as a whole. If identifiable sections of that work are not derived from the Program, and can be reasonably considered independent and separate works in themselves, then this License, and its terms, do not apply to those sections when you distribute them as separate works. But when you distribute the same sections as part of a whole which is a work based on the Program, the distribution of the whole must be on the terms of this License, whose permissions for other licensees extend to the entire whole, and thus to each and every part regardless of who wrote it. Thus, it is not the intent of this section to claim rights or contest your rights to work written entirely by you; rather, the intent is to exercise the right to control the distribution of derivative or collective works based on the Program. In addition, mere aggregation of another work not based on the Program with the Program (or with a work based on the Program) on a volume of a storage or distribution medium does not bring the other work under the scope of this License. 3. You may copy and distribute the Program (or a work based on it, under Section 2) in object code or executable form under the terms of Sections 1 and 2 above provided that you also do one of the following: a) Accompany it with the complete corresponding machine-readable source code, which must be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, b) Accompany it with a written offer, valid for at least three years, to give any third party, for a charge no more than your cost of physically performing source distribution, a complete machine-readable copy of the corresponding source code, to be distributed under the terms of Sections 1 and 2 above on a medium customarily used for software interchange; or, c) Accompany it with the information you received as to the offer to distribute corresponding source code. (This alternative is allowed only for noncommercial distribution and only if you received the program in object code or executable form with such an offer, in accord with Subsection b above.) The source code for a work means the preferred form of the work for making modifications to it. For an executable work, complete source code means all the source code for all modules it contains, plus any associated interface definition files, plus the scripts used to control compilation and installation of the executable. However, as a special exception, the source code distributed need not include anything that is normally distributed (in either source or binary form) with the major components (compiler, kernel, and so on) of the operating system on which the executable runs, unless that component itself accompanies the executable. If distribution of executable or object code is made by offering access to copy from a designated place, then offering equivalent access to copy the source code from the same place counts as distribution of the source code, even though third parties are not compelled to copy the source along with the object code. 4. You may not copy, modify, sublicense, or distribute the Program except as expressly provided under this License. Any attempt otherwise to copy, modify, sublicense or distribute the Program is void, and will automatically terminate your rights under this License. However, parties who have received copies, or rights, from you under this License will not have their licenses terminated so long as such parties remain in full compliance. 5. You are not required to accept this License, since you have not signed it. However, nothing else grants you permission to modify or distribute the Program or its derivative works. These actions are prohibited by law if you do not accept this License. Therefore, by modifying or distributing the Program (or any work based on the Program), you indicate your acceptance of this License to do so, and all its terms and conditions for copying, distributing or modifying the Program or works based on it. 6. Each time you redistribute the Program (or any work based on the Program), the recipient automatically receives a license from the original licensor to copy, distribute or modify the Program subject to these terms and conditions. You may not impose any further restrictions on the recipients' exercise of the rights granted herein. You are not responsible for enforcing compliance by third parties to this License. 7. If, as a consequence of a court judgment or allegation of patent infringement or for any other reason (not limited to patent issues), conditions are imposed on you (whether by court order, agreement or otherwise) that contradict the conditions of this License, they do not excuse you from the conditions of this License. If you cannot distribute so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not distribute the Program at all. For example, if a patent license would not permit royalty-free redistribution of the Program by all those who receive copies directly or indirectly through you, then the only way you could satisfy both it and this License would be to refrain entirely from distribution of the Program. If any portion of this section is held invalid or unenforceable under any particular circumstance, the balance of the section is intended to apply and the section as a whole is intended to apply in other circumstances. It is not the purpose of this section to induce you to infringe any patents or other property right claims or to contest validity of any such claims; this section has the sole purpose of protecting the integrity of the free software distribution system, which is implemented by public license practices. Many people have made generous contributions to the wide range of software distributed through that system in reliance on consistent application of that system; it is up to the author/donor to decide if he or she is willing to distribute software through any other system and a licensee cannot impose that choice. This section is intended to make thoroughly clear what is believed to be a consequence of the rest of this License. 8. If the distribution and/or use of the Program is restricted in certain countries either by patents or by copyrighted interfaces, the original copyright holder who places the Program under this License may add an explicit geographical distribution limitation excluding those countries, so that distribution is permitted only in or among countries not thus excluded. In such case, this License incorporates the limitation as if written in the body of this License. 9. The Free Software Foundation may publish revised and/or new versions of the General Public License from time to time. Such new versions will be similar in spirit to the present version, but may differ in detail to address new problems or concerns. Each version is given a distinguishing version number. If the Program specifies a version number of this License which applies to it and "any later version", you have the option of following the terms and conditions either of that version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of this License, you may choose any version ever published by the Free Software Foundation. 10. If you wish to incorporate parts of the Program into other free programs whose distribution conditions are different, write to the author to ask for permission. For software which is copyrighted by the Free Software Foundation, write to the Free Software Foundation; we sometimes make exceptions for this. Our decision will be guided by the two goals of preserving the free status of all derivatives of our free software and of promoting the sharing and reuse of software generally. NO WARRANTY 11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION. 12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES. END OF TERMS AND CONDITIONS How to Apply These Terms to Your New Programs If you develop a new program, and you want it to be of the greatest possible use to the public, the best way to achieve this is to make it free software which everyone can redistribute and change under these terms. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively convey the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Lesser General Public License instead of this License. deka.t100755001750001750 216713202072256 13671 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 13; # Test deka functions. my $q = Finance::Quote->new("Deka"); $q->timeout(60); # Deka appears to be hanging today. my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @stocks = ("DE0008474511","LU0051755006"); my %quotes = $q->deka(@stocks, "BOGUS"); ok(%quotes); TODO: { local $TODO="To be debugged"; # Check that the last and date values are defined. foreach my $stock (@stocks) { ok($quotes{$stock,"success"}); ok($quotes{$stock,"last"} > 0); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } ok($quotes{"DE0008474511","currency"} eq "EUR"); ok($quotes{"LU0051755006","currency"} eq "USD"); } # Check that a bogus fund returns no-success. ok($quotes{"BOGUS","success"} == 0); ok($quotes{"BOGUS","errormsg"} eq "No data returned"); META.yml100644001750001750 336213202072256 13601 0ustar00ecec000000000000Finance-Quote-1.47--- abstract: 'Get stock and mutual fund quotes from various exchanges' author: - 'Dj Padzensky , PadzNet, Inc.' - 'Linas Vepstas ' - 'Yannick LE NY ' - 'Paul Fenwick ' - 'Brent Neal ' - 'Volker Stuerzl ' - 'Keith Refson ' - 'Rob Sessink ' - 'Leigh Wedding ' - 'Tobias Vancura ' - 'James Treacy ' - 'Bradley Dean ' - 'Erik Colson ' build_requires: Data::Dumper: '0' File::Spec: '0' Test::More: '0' configure_requires: ExtUtils::MakeMaker: '0' dynamic_config: 0 generated_by: 'Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150005' license: gpl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: '1.4' name: Finance-Quote requires: CGI: '0' Carp: '0' DateTime: '0' Encode: '0' Exporter: '0' HTML::Parser: '0' HTML::TableExtract: '0' HTML::TokeParser: '0' HTML::TreeBuilder: '0' HTTP::Cookies: '0' HTTP::Headers: '0' HTTP::Request::Common: '0' HTTP::Status: '0' JSON: '0' LWP::Protocol::https: '0' LWP::Simple: '0' LWP::UserAgent: '0' Mozilla::CA: '0' POSIX: '0' Time::Piece: '0' URI: '0' URI::QueryParam: '0' base: '0' constant: '0' perl: '5.010' strict: '0' utf8: '0' vars: '0' warnings: '0' resources: bugtracker: https://rt.cpan.org/Dist/Display.html?Name=Finance-Quote homepage: http://finance-quote.sourceforge.net/ repository: git://github.com/finance-quote/finance-quote version: '1.47' x_serialization_backend: 'YAML::Tiny version 1.70' MANIFEST100644001750001750 674113202072256 13465 0ustar00ecec000000000000Finance-Quote-1.47# This file was automatically generated by Dist::Zilla::Plugin::Manifest v6.010. ChangeLog.1 Changes Documentation/FAQ Documentation/Hackers-Guide Documentation/License Documentation/README Examples/Quote_example.pl Examples/chkshares.pl Examples/currency-lookup.pl Examples/stockdump.pl LICENSE MANIFEST META.json META.yml Makefile.PL README htdocs/Images/Button1.gif htdocs/Images/Button2.gif htdocs/Images/bg.jpg htdocs/Images/bg2.jpg htdocs/Images/logo_big1.gif htdocs/Images/logo_medium1.gif htdocs/Images/logo_small1.gif htdocs/Images/logo_small2.gif htdocs/Stylesheet.css htdocs/developer.html htdocs/discussion.html htdocs/documentation.html htdocs/download.html htdocs/index.html htdocs/tpj/finance-quote-example htdocs/tpj/finance-quote-sidebar htdocs/tpj/finance-quote.txt lib/Finance/Quote.pm lib/Finance/Quote/AEX.pm lib/Finance/Quote/AIAHK.pm lib/Finance/Quote/ASEGR.pm lib/Finance/Quote/ASX.pm lib/Finance/Quote/AlphaVantage.pm lib/Finance/Quote/BMONesbittBurns.pm lib/Finance/Quote/BSERO.pm lib/Finance/Quote/Bourso.pm lib/Finance/Quote/CSE.pm lib/Finance/Quote/Cdnfundlibrary.pm lib/Finance/Quote/Citywire.pm lib/Finance/Quote/Cominvest.pm lib/Finance/Quote/Currencies.pm lib/Finance/Quote/DWS.pm lib/Finance/Quote/Deka.pm lib/Finance/Quote/FTPortfolios.pm lib/Finance/Quote/FTfunds.pm lib/Finance/Quote/Fidelity.pm lib/Finance/Quote/FidelityFixed.pm lib/Finance/Quote/FinanceCanada.pm lib/Finance/Quote/Finanzpartner.pm lib/Finance/Quote/Fool.pm lib/Finance/Quote/GoldMoney.pm lib/Finance/Quote/HEX.pm lib/Finance/Quote/HU.pm lib/Finance/Quote/IndiaMutual.pm lib/Finance/Quote/LeRevenu.pm lib/Finance/Quote/MStaruk.pm lib/Finance/Quote/ManInvestments.pm lib/Finance/Quote/Morningstar.pm lib/Finance/Quote/MorningstarJP.pm lib/Finance/Quote/NZX.pm lib/Finance/Quote/Platinum.pm lib/Finance/Quote/SEB.pm lib/Finance/Quote/SIXfunds.pm lib/Finance/Quote/SIXshares.pm lib/Finance/Quote/StockHouseCanada.pm lib/Finance/Quote/TNetuk.pm lib/Finance/Quote/TSP.pm lib/Finance/Quote/TSX.pm lib/Finance/Quote/Tdefunds.pm lib/Finance/Quote/Tdwaterhouse.pm lib/Finance/Quote/Tiaacref.pm lib/Finance/Quote/Troweprice.pm lib/Finance/Quote/Trustnet.pm lib/Finance/Quote/USFedBonds.pm lib/Finance/Quote/Union.pm lib/Finance/Quote/UserAgent.pm lib/Finance/Quote/VWD.pm lib/Finance/Quote/Yahoo/Asia.pm lib/Finance/Quote/Yahoo/Australia.pm lib/Finance/Quote/Yahoo/Base.pm lib/Finance/Quote/Yahoo/Brasil.pm lib/Finance/Quote/Yahoo/Europe.pm lib/Finance/Quote/Yahoo/NZ.pm lib/Finance/Quote/Yahoo/USA.pm lib/Finance/Quote/YahooJSON.pm lib/Finance/Quote/YahooYQL.pm lib/Finance/Quote/ZA.pm lib/Finance/Quote/ZA_UnitTrusts.pm t/00-use.t t/01-pod.t t/02-pod-coverage.t t/03-kwalitee.t t/04-critic.t t/05-data-dumper.t t/aex.t t/aiahk.t t/alphavantage.t t/asegr.t t/asx.t t/author-pod-syntax.t t/bmonesbittburns.t t/bourso.t t/bsero.t t/cdnfundlibrary.t t/citywire.t t/cominvest.t t/cse.t t/currencies.t t/currency.t t/currency_lookup.t t/deka.t t/dws.t t/fidelity.t t/fidelityfixed.t t/financecanada.t t/finanzpartner.t t/ftfunds.t t/ftportfolios.t t/goldmoney.t t/hex.t t/hu.t t/indiamutual.t t/lerevenu.t t/maninvestments.t t/morningstar.t t/morningstarJP.t t/mstaruk.t t/nzx.t t/platinum.t t/quote.t t/seb.t t/sixfunds.t t/sixshares.t t/stockhousecanada.t t/tdefunds.t t/tdwaterhouse.t t/tiaacref.t t/tnetuk.t t/troweprice.t t/trustnet.t t/tsp.t t/tsx.t t/ukfunds.t t/union.t t/usfedbonds.t t/vanguard.t t/vwd.t t/yahoo.t t/yahoo_asia.t t/yahoo_australia.t t/yahoo_brasil.t t/yahoo_europe.t t/yahoo_nz.t t/yahoo_speed.t t/yahoojson.t t/za.t t/za_unittrusts.t aiahk.t100755001750001750 247713202072256 14046 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 30; # Test Aia functions. my $q = Finance::Quote->new(); # my stocks = stock, fund, warrant, bond, indice my @stocks = ("ABD-AUS.EQ", "AIG-EUSC.U", "FID-JP.ADV", "SCH-HKEQ"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("aiahk", @stocks); ok(%quotes); TODO: { local $TODO="To be debugged"; # Check that the name, last, currency and date are defined for all of the stocks. foreach my $stock (@stocks) { ok($quotes{$stock,"success"}); ok($quotes{$stock,"bid"} > 0); ok($quotes{$stock,"offer"} > 0); ok(length($quotes{$stock,"name"})); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } ok($quotes{"ABD-AUS.EQ", "currency"} eq "AUD"); ok($quotes{"AIG-EUSC.U", "currency"} eq "EUR"); ok($quotes{"FID-JP.ADV", "currency"} eq "JPY"); ok($quotes{"SCH-HKEQ", "currency"} eq "HKD"); } # Check that a bogus stock returns no-success. %quotes = $q->fetch("aiahk", "BOGUS"); ok(! $quotes{"BOGUS","success"}); bsero.t100644001750001750 205213202072256 14065 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 26; # Test BSERO functions. my $q = Finance::Quote->new(); my @stocks = ("TLV", "BRD", "SNP"); my %regexps = ( TLV => qr/\bTLV\b/, BRD => qr/\bBRD\b/, SNP => qr/\bSNP\b/, ); my %quotes = $q->fetch("bsero", @stocks); ok(%quotes); foreach my $stock (@stocks) { my $name = $quotes{$stock, "name"}; print "#Testing $stock: $name\n"; my $regexp = $regexps{$stock}; ok($name =~ /$regexp/i); ok($quotes{$stock, "exchange"} eq 'Bucharest Stock Exchange'); ok($quotes{$stock, "method"} eq 'bsero'); ok($quotes{$stock, "last"} > 0); ok($quotes{$stock, "open"} =~ /^-?\d+\.\d+$/); ok($quotes{$stock, "p_change"} =~ /^-?\d+\.\d+$/); ok($quotes{$stock, "success"}); ok($quotes{$stock, "volume"} >= 0); } # Check that a bogus stock returns no-success. %quotes = $q->fetch("tsx", "BOGUS"); ok(! $quotes{"BOGUS","success"}); quote.t100644001750001750 267713202072256 14125 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; plan tests => 28; my $q = Finance::Quote->new(); # test isoTime function ok($q->isoTime("11:39PM") eq "23:39") ; ok($q->isoTime("9:10 AM") eq "09:10") ; ok($q->isoTime("1.32") eq "01:32") ; ok($q->isoTime("1u32") eq "01:32") ; ok($q->isoTime("19h2") eq "19:02") ; ok($q->isoTime("10:62") eq "00:00" ) ; ok($q->isoTime("8:05am") eq "08:05" ) ; ok($q->isoTime("4:00pm") eq "16:00" ) ; ok($q->isoTime("0:59PM") eq "12:59" ) ; ok($q->isoTime("12:00pm") eq "12:00" ) ; ok($q->isoTime("12:10pm") eq "12:10" ) ; # yahoo might return 12:XXPM ! # decimal_shiftup() is($q->decimal_shiftup('1',1), '10'); is($q->decimal_shiftup('1',2), '100'); is($q->decimal_shiftup('1.',1), '10'); is($q->decimal_shiftup('1.',2), '100'); is($q->decimal_shiftup('1.5',1), '15'); is($q->decimal_shiftup('1.5',2), '150'); is($q->decimal_shiftup('1.5',3), '1500'); is($q->decimal_shiftup('56',1), '560'); is($q->decimal_shiftup('56',2), '5600'); is($q->decimal_shiftup('56.00',-1), '5.600'); # we want to keep precision is($q->decimal_shiftup('56.00',1), '560.0'); is($q->decimal_shiftup('1.2345678901234',3), '1234.5678901234'); is($q->decimal_shiftup('0.12345678',1), '1.2345678'); is($q->decimal_shiftup('0.00001',1), '0.0001'); # _B_to_billions() is($q->B_to_billions('1B'), '1000000000'); is($q->B_to_billions('1.5B'), '1500000000'); is($q->B_to_billions('1.23456789876B'), '1234567898.76'); asegr.t100755001750001750 247413202072256 14067 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 13; # Test ASEGR functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->asegr("ALPHA","ELTON"); ok(%quotes); # Check the last values are defined. These are the most used and most # reliable indicators of success. ok($quotes{"ALPHA","last"} > 0); ok($quotes{"ALPHA","success"}); ok(substr($quotes{"ALPHA","date"},6,4) == $year || substr($quotes{"ALPHA","date"},6,4) == $lastyear); ok($quotes{"ELTON","success"}); ok($quotes{"ELTON","last"} > 0); ok(substr($quotes{"ELTON","date"},6,4) == $year || substr($quotes{"ELTON","date"},6,4) == $lastyear); # Exercise the fetch function a little. %quotes = $q->fetch("asegr","IKONA"); ok(%quotes); ok($quotes{"IKONA","last"} > 0); ok($quotes{"IKONA","success"} > 0); # Check that we're getting currency information. ok($quotes{"IKONA", "currency"} eq "EUR"); # Check we're not getting bogus percentage signs. $quotes{"IKONA","p_change"} ||= ""; # Avoid warning if undefined. ok($quotes{"IKONA","p_change"} !~ /%/); # Check that looking up a bogus stock returns failure: %quotes = $q->asegr("BOGUS"); ok(! $quotes{"BOGUS","success"}); union.t100755001750001750 157313202072256 14115 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 7; # Test TD Waterhouse functions. my $q = Finance::Quote->new(); my %quotes = $q->unionfunds("975792","12345"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"975792","last"} > 0); ok($quotes{"975792","success"}); ok($quotes{"975792", "currency"} eq "EUR"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"975792","isodate"},0,4) eq $year || substr($quotes{"975792","isodate"},0,4) eq $lastyear); ok(substr($quotes{"975792","date"},6,4) eq $year || substr($quotes{"975792","date"},6,4) eq $lastyear); # Check that bogus stocks return failure: ok(! $quotes{"12345","success"}); yahoo.t100755001750001750 212113202072256 14072 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 11; # Test Yahoo functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->yahoo("IBM","CSCO","BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"IBM","last"} > 0); ok($quotes{"IBM","success"}); ok($quotes{"IBM", "currency"} eq "USD"); ok(($quotes{"IBM", "currency"} eq "USD") && !defined($quotes{"IBM","currency_set_by_fq"})); ok(substr($quotes{"IBM","isodate"},0,4) == $year || substr($quotes{"IBM","isodate"},0,4) == $lastyear); ok(substr($quotes{"IBM","date"},6,4) == $year || substr($quotes{"IBM","date"},6,4) == $lastyear); ok($quotes{"CSCO","last"} > 0); ok($quotes{"CSCO","success"}); # Make sure there are no spurious % signs. ok($quotes{"CSCO","p_change"} !~ /%/); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); META.json100644001750001750 546513202072256 13757 0ustar00ecec000000000000Finance-Quote-1.47{ "abstract" : "Get stock and mutual fund quotes from various exchanges", "author" : [ "Dj Padzensky , PadzNet, Inc.", "Linas Vepstas ", "Yannick LE NY ", "Paul Fenwick ", "Brent Neal ", "Volker Stuerzl ", "Keith Refson ", "Rob Sessink ", "Leigh Wedding ", "Tobias Vancura ", "James Treacy ", "Bradley Dean ", "Erik Colson " ], "dynamic_config" : 0, "generated_by" : "Dist::Zilla version 6.010, CPAN::Meta::Converter version 2.150005", "license" : [ "gpl_2" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : 2 }, "name" : "Finance-Quote", "prereqs" : { "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "develop" : { "requires" : { "Test::Pod" : "1.41" } }, "runtime" : { "requires" : { "CGI" : "0", "Carp" : "0", "DateTime" : "0", "Encode" : "0", "Exporter" : "0", "HTML::Parser" : "0", "HTML::TableExtract" : "0", "HTML::TokeParser" : "0", "HTML::TreeBuilder" : "0", "HTTP::Cookies" : "0", "HTTP::Headers" : "0", "HTTP::Request::Common" : "0", "HTTP::Status" : "0", "JSON" : "0", "LWP::Protocol::https" : "0", "LWP::Simple" : "0", "LWP::UserAgent" : "0", "Mozilla::CA" : "0", "POSIX" : "0", "Time::Piece" : "0", "URI" : "0", "URI::QueryParam" : "0", "base" : "0", "constant" : "0", "perl" : "5.010", "strict" : "0", "utf8" : "0", "vars" : "0", "warnings" : "0" } }, "test" : { "requires" : { "Data::Dumper" : "0", "File::Spec" : "0", "Test::More" : "0" } } }, "release_status" : "stable", "resources" : { "bugtracker" : { "web" : "https://rt.cpan.org/Dist/Display.html?Name=Finance-Quote" }, "homepage" : "http://finance-quote.sourceforge.net/", "repository" : { "type" : "git", "url" : "git://github.com/finance-quote/finance-quote", "web" : "https://github.com/finance-quote/finance-quote" } }, "version" : "1.47", "x_serialization_backend" : "Cpanel::JSON::XS version 3.0239" } 00-use.t100755001750001750 662713202072256 14003 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w # Test to see if Finance::Quote can at least be loaded and used. use strict; use Test::More; plan tests => 19; use Finance::Quote; ok(1, "Finance::Quote loaded"); my $quote = Finance::Quote->new(); ok($quote, "quote object created"); # Get Today's date my ($month, $day, $year2) = (localtime())[4,3,5]; $month++; my $year4 += $year2 + 1900; # 2007 my $year4m += $year2 + 1900 - 1;# 2006 $year2 -= 100; # 05 my $isotoday = sprintf("%04d-%02d-%02d", $year4, $month, $day); my $ustoday = sprintf("%02d/%02d/%04d", $month, $day, $year4); # Test date functions my %info; $quote->store_date(\%info, "test", {today => 1}); ok($info{"test","isodate"} eq $isotoday,"test->isodate is today"); ok($info{"test","date"} eq $ustoday,"test->date is today"); # Test various permutions of an ISO Date as input %info = (); $quote->store_date(\%info, "test", {isodate => "2004-12-31"}); ok($info{"test","date"} eq "12/31/2004", "ISO date permutation 1"); %info = (); $quote->store_date(\%info, "test", {isodate => "2004 Dec 31"}); ok($info{"test","date"} eq "12/31/2004","ISO date permutation 2"); %info = (); $quote->store_date(\%info, "test", {isodate => "2004 December 31"}); ok($info{"test","date"} eq "12/31/2004","ISO date permutation 3"); # Test various permutions of an US Date as input %info = (); $quote->store_date(\%info, "test", {usdate => "12/31/2004"}); ok($info{"test","isodate"} eq "2004-12-31","US date permutation 1"); %info = (); $quote->store_date(\%info, "test", {usdate => "Dec 31, 2004"}); ok($info{"test","isodate"} eq "2004-12-31","US date permutation 2"); %info = (); $quote->store_date(\%info, "test", {usdate => "December 31 2004"}); ok($info{"test","isodate"} eq "2004-12-31","US date permutation 3"); # Test various permutions of an European Date as input %info = (); $quote->store_date(\%info, "test", {eurodate => "31/12/2004"}); ok($info{"test","isodate"} eq "2004-12-31","EUR date permutation 1" ); %info = (); $quote->store_date(\%info, "test", {eurodate => "31 December 2004"}); ok($info{"test","isodate"} eq "2004-12-31","EUR date permutation 2"); %info = (); $quote->store_date(\%info, "test", {eurodate => "31 Dec, 2004"}); ok($info{"test","isodate"} eq "2004-12-31","EUR date permutation 3"); # Try some other permutions. A recent change to the date handling # code changes the behavior if a year is not explicitly provided. Now # it will look at the month and decide if the date is in the current # year or is from the previous year. This code still has to handle # being executed on 12/31, thus the dual tests for each date. %info = (); $quote->store_date(\%info, "test", {day=>"31", month=>"12"}); ok($info{"test","date"} eq "12/31/$year4" || $info{"test","date"} eq "12/31/$year4m","test year 1"); ok($info{"test","isodate"} eq "$year4-12-31" || $info{"test","isodate"} eq "$year4m-12-31","test year 2"); %info = (); $quote->store_date(\%info, "test", {day=>"31", month=>"December"}); ok($info{"test","date"} eq "12/31/$year4" || $info{"test","date"} eq "12/31/$year4m","test year 3"); ok($info{"test","isodate"} eq "$year4-12-31" || $info{"test","isodate"} eq "$year4m-12-31","test year 4"); %info = (); $quote->store_date(\%info, "test", {day=>"31", month=>"December", year => $year2}); ok($info{"test","date"} eq "12/31/$year4" || $info{"test","date"} eq "12/31/$year4m","test year 5"); ok($info{"test","isodate"} eq "$year4-12-31" || $info{"test","isodate"} eq "$year4m-12-31","test year 6"); 01-pod.t100755001750001750 43513202072256 13741 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; if (not $ENV{TEST_AUTHOR}) { plan( skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to true to run.'); } eval "use Test::Pod 1.00"; ## no critic plan skip_all => "Test::Pod 1.00 required for testing POD" if $@; all_pod_files_ok(); bourso.t100755001750001750 551313202072256 14274 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if ( not $ENV{ONLINE_TEST} ) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 73; # Test Bourso functions. my $q = Finance::Quote->new(); # my stocks = stock, fund, warrant, bond, indice my @stocks = ( "FR0000441677", # Fund "AF", # Stock, EUR, Nyse Euronext "MSFT", # Stock, USD, NASDAQ "SOLB", # Stock, EUR, BRUXELLES "CNP", # Stock, EUR, Nyse Euronext "FR0010371401", # Bond "FR0012773687", # Warrant "FR0003500008", # Index "LU0207947044", # Bond ); # Bourso tests need to cover all the possible cases: # # Name What Test Case # # cours-action Stock AF # cours-obligation Bond FR0010371401 # opcvm/opcvm Fund FR0000441677 # cours-warrant Warrant FR0012773687 # cours-indice Index FR0003500008 my $year = ( localtime() )[5] + 1900; my $lastyear = $year - 1; my %quotes; #my %quotes = $q->fetch("bourso", @stocks); #ok(%quotes); # Check that the name, last, currency and date are defined for all of the stocks. foreach my $stock (@stocks) { eval { %quotes = $q->fetch( "bourso", $stock ); ok( %quotes, "$stock \%quotes defined" ); my $last = $quotes{ $stock, "last" }; ok( $last > 0, "$stock last ($last) > 0" ); ok( length( $quotes{ $stock, "name" } ), "$stock name is defined" ); ok( $quotes{ $stock, "symbol" } =~ /[A-Z]{2}\d{10}/, "$stock symbol is defined as ".$quotes{ $stock, "symbol" } ); ok( $quotes{ $stock, "success" }, "$stock returned success" ); ok( # indexes are quoted in percents ( $stock eq "FR0003500008" ) || ( ( $stock eq "MSFT" ) && ( $quotes{ $stock, "currency" } eq "USD" ) ) || ( $quotes{ $stock, "currency" } eq "EUR" ), "Index is quoted in percents" ); SKIP: { skip "date is not defined for warrants", 2 if ( $stock eq "FR0012773687" ); ok( substr( $quotes{ $stock, "isodate" }, 0, 4 ) == $year || substr( $quotes{ $stock, "isodate" }, 0, 4 ) == $lastyear, "$stock isodate defined" ); ok( substr( $quotes{ $stock, "date" }, 6, 4 ) == $year || substr( $quotes{ $stock, "date" }, 6, 4 ) == $lastyear, "$stock date defined" ); } }; if ($@) { print STDERR "Error fetching stock ", $stock, "\n", $@; ok( !1 ); } } # Check that a bogus stock returns no-success. %quotes = $q->fetch( "bourso", "BOGUS" ); ok( !$quotes{ "BOGUS", "success" }, "BOGUS failed correctly" ); tnetuk.t100644001750001750 143613202072256 14272 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->tnetuk("GB0031835118","GB0030880032","LU0116926998","BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"GB0031835118","last"} > 0); ok($quotes{"GB0031835118","success"}); ok($quotes{"GB0030880032","last"} > 0); ok($quotes{"GB0030880032","success"}); ok($quotes{"LU0116926998","last"} > 0); ok($quotes{"LU0116926998","success"}); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); ChangeLog.1100644001750001750 5253613202072256 14270 0ustar00ecec000000000000Finance-Quote-1.472000-04-06 Paul Fenwick * CVSTAG: finance_quote_0_16 * Initial public release. 2000-04-08 Paul Fenwick * Integrated TIAA-CREF changes from Brent Neal. * Changes to Makefile.PL to check dependancies, etc. * Updated Examples/Quote_example.pl to include TIAA-CREF examples. * CVSTAG: finance_quote_0_17 2000-04-10 Paul Fenwick * Changed Examples/chkshares.pl to print a pretty table. * Incorporated Cooper Vertz's patch to add high, low and net change to quotes obtained from Yahoo! 2000-04-13 Paul Fenwick * Fidelity private functions renamed to indicate they are private. * Small optimisations in fidelity functions to avoid spurious warnings and un-needed processing of non-useful lines. * Functions now quickly return undef when not passed a list of stocks. Previously they would waste time looking up nothing. * Documentation additions and corrections. * Added test files (Use.t, asx.t, yahoo.t, fidelity.t) * Added experimental function (currency) to look-up conversion rates between currencies. * Added an example script (currency-lookup.pl) to test said currency conversion. 2000-04-14 Paul Fenwick * Added TIAA-CREF testing script. * Added troweprice testing script. 2000-04-16 Paul Fenwick * Added yahoo_europe test script. * Removed depreciated vanguard function. 2000-04-18 Paul Fenwick * Added fetch() function to provide a cleaner interface to fetching quotes from a variety of sources. * Added tests for fetch() to the asx.t test script. 2000-04-20 Paul Fenwick * Removed misleading comments from Finance::Quote.pm 2000-04-21 Paul Fenwick * Added extra methods to fetch (nasdaq, nyse) which act as aliases to yahoo. * Added stockdump.pl example script, which is handy in debugging. * fetch is now an exportable function. * yahoo() function no longer returns entries for fields that used to be returned as 'N/A'. * yahoo() now supports the $stocks{$sym,'success'} notation. 2000-04-21 Brent Neal * Added checking for bogus symbols in tiaacref * Added checking of the LWP::UserAgent->is_success method * tiaacref() now supports $stocks{$sym,'success'} notation. * Updated t/tiaacref.t and Examples/Quote_example.pl for the changes 2000-04-23 Paul Fenwick * Added success/fail tests to asx, fidelity, troweprice, yahoo and yahoo_europe. * Updated appropriate testing functions. * Updated documentation to include fetch and list of known bugs. * Updated yahoo_europe to return undef's instead of N/As. * Removed HTML from returns from yahoo_europe. * Fixed logic bug in process yahoo_* N/As into undefs. 2000-04-24 Paul Fenwick * Updated in-line code regarding checking for Yahoo! successes. * Added meaningful error-messages to Yahoo! when stock lookups fail. 2000-04-24 Brent Neal * Finished updating error-checking for tiaacref. The tiaacref function now returns a success/failure flag for every symbol passed to it. It also checks that the data is valid. Returns meaningful error messages for these failures. 2000-04-25 Paul Fenwick * Rolled changes together when CVS got a little out-of-whack. :) * Return many new fields from yahoo() which we previously fetched but did not use. These include avg_vol, day_range, year_range, div_date, div, and div_yield. * Fixed typo in docs s/yeild/yield/; * Added ex_div for Ex-Divident Date in yahoo(). 2000-04-30 Paul Fenwick * Updated POD. * Improved returned error messages. * Updated the README file. * Updated the INSTALL file. * Tagged files as finance_quote_0_18 for release. 2000-05-13 Paul Fenwick * Added Documentation/FAQ file. 2000-05-14 Paul Fenwick * Huge re-write and change of everything so that it should be easy to plug in new modules without changing any existing code. 2000-05-27 Paul Fenwick * Added Documentation/Hackers-Guide. * Tweaked Quote.pm to provide an AUTOLOAD method for those people who don't want to go through the fetch() methods. 2000-05-31 Paul Fenwick * Added Documentation/TODO. 2000-06-03 Paul Fenwick * Revived dead vanguard method by rolling it through Yahoo. * Added labels method to everything. * Added price labels to everything. * Updated Quote.pm to query new labels methods. * Provided a failover method for fidelity via Yahoo. * Added failover functionality. 2000-06-03 Jacinta Richardson * Changed modules so they return undef in scalar context, empty list in list context, on failure. * Changed modules so they return a hashref when in scalar context, and a hash in list context. * Reviewed/corrected hackers guide. * Added currency tags to existing modules to signal currency type (AUD, EUR, USD) * Added tests to check currency tags. 2000-06-16 Paul Fenwick * Added webpage to CVS repository. 2000-06-17 Paul Fenwick * Re-added currency lookups to Quote.pm * Added regression testing script for currency. * Added automatic currency conversion stub. * Removed TODO file as we now keep track of outstanding jobs in SourceForge. 2000-06-21 Paul Fenwick * Rolled all the Yahoo functions into a base pseudo-class. * Fixed bug whereby large lookups in the yahoo functions would overflow the maximum URL length of some proxies/servers. * Expanded the number of fields available via Yahoo::Europe. 2000-06-22 Paul Fenwick * Added sections on currency conversion to the hacker's guide. Now I just need to write the code. :) # Added currency conversion code, but haven't tested it yet. 2000-06-23 Paul Fenwick * Cleaned up the hacker's guide. * Updated Examples/stockdump.pl to allow currency to be specified. * Automatic currency conversion now works. * Updated ASX and Yahoo::USA to not tag indexes with currency labels. * Updated Yahoo::Base to automatically accomodate suffixes for when we wish to add them automatically. * Added Yahoo::Australia to look up Australian stocks. * Tested failover of Yahoo::Australia to Yahoo::ASX. 2000-06-24 Paul Fenwick * Updated currency regression testing script. * Updated currency fetching routines to handle different date formats returned by Yahoo! * Updated automatic currency conversion routines to avoid spurious warnings. 2000-06-25 Paul Fenwick * Documented many of the new 0.19 functions in the Finance::Quote POD. 2000-07-02 Paul Fenwick * Many more documentation improvements in both the Finance::Quote POD and the sub-modules. 2000-07-08 Paul Fenwick * Added POD for TIAA-CREF and T. Rowe Price sub-modules. 2000-07-13 Paul Fenwick * Improved fidelity module such that it doesn't return information about stocks we did not request. 2000-07-15 Paul Fenwick * Wrote documentation for Yahoo::Europe (incomplete) and Yahoo::USA. Changed modules to require perl 5.005 because we make use of some of its features (like hash slices). * Improved labels documentation in Finance::Quote. * Added exchange and method information (where possible) to the various sub-modules. * Improved chkshares example script to check for errors. * Removed bad test in currency.t and replaced it with a better one. 2000-07-16 Paul Fenwick * Documented the list of possible markets in Yahoo::Europe. * Many many small syntax fixes in documentation. * Expanded and improved webpage. * Updated revision to 1.00 * Updated INSTALL documentation. * CVSTAG: finance_quote_1_00 2000-07-25 Paul Fenwick * Finance::Quote::Yahoo::Base now removes more HTML-ish guff that Yahoo tries to place in CSVs. * Updated yahoo_europe.t to check that stocks from London are in GBP. * Finance::Quote::Yahoo::Europe now returns London stocks in GBP. Previously it was incorrectly returning them in pence and calling it Euros. * Finance::Quote has a new scale_field() function that is used in currency conversion and by some sub-modules (Yahoo::Europe). This may be useful for future module writers. * CVSTAG: finance_quote_1_01 2000-07-31 Paul Fenwick * The currency function no longer makes an expensive HTTP request if both the to and from currencies are identical. 2000-08-04 Paul Fenwick * Patched Yahoo::Base to no longer return spurious percentage signs. 2000-08-06 Paul Fenwick * Updated regression testing scripts to make sure that spurious percentage signs are no longer returned. 2000-08-14 Paul Fenwick * Updated chkshares script so that it can deal with any market, not just the ASX. 2000-08-16 Paul Fenwick * Added DWS.pm module to the CVS repository, courtesy of Volker Stuerzl. This module fetches information from the Deutsche Bank Gruppe. * Updated asx.t script because it really hurts the entire "make test" thing when ASX is unhappy. Now it still hurts (because the ASX module sucks), but less. 2000-08-21 Paul Fenwick * Improved documentation in the yahoo_europe test script. 2000-08-22 Volker Stuerzl * Added DWS test script. 2000-08-29 Paul Fenwick * Rejiggered ASX module to try and make it work again after an ASX site rewrite. * Updated Quote.pm so that if a method was called directly (old-style) not through fetch, then it would do the right thing if called via an object. This means that things like $q->asx(@stocks) work correctly again. * Updated fetch() method so that it returns the empty list rather than undef when called in an array context. * fetch() now returns a hashref if called in a scalar context. 2000-08-31 Paul Fenwick * Added Keith Refson's Trustnet module. * Added .cvsignore file to reduce spam for developers using CVS. * Updated Yahoo/USA.pm to provide more compatible returns when called as a fidelity failover. * Tweaked DWS.t testing script so that it loads the module correctly. 2000-09-01 Paul Fenwick * Tweaked ASX.pm to avoid divide-by-zero errors and dodgy bogus-looking label values. 2000-09-04 Paul Fenwick * Keith Refson's patch to Trustnet to avoid premature returns in case of a bad symbol. 2000-09-12 Paul Fenwick * Mention of Bill Bell's java library in the FAQ. 2000-09-16 Paul Fenwick * Added Volker's VWD module and testing script. * Updated Makefile to check for HTML::TableExtract. * Updated INSTALL file to provide infomation on how to install modules that F::Q depends upon. * Updated Quote.pm to load VWD, DWS and Trustnet by default. * Updated README file to mention the webpage. * Added Trustnet regression testing program. * CVSTAG: finance_quote_1_02 2000-09-27 Paul Fenwick * Updated Trustnet module with patch from Keith Refson. 2000-10-20 Paul Fenwick * Much better discovery of non-existant stocks in ASX.pm. * Checks for possible divide-by-zero problems in ASX.pm. Thanks to Stephen Stebbing for catching this. * Updated ASX testing. * Updated all test scripts to remove spurious warnings under Perl 5.6. * Updated ASX module to deal with stocks when they have market announcements. Previously this would result in garbage being returned for that stock. * Updated VWD module so it can parse information from the new VWD site. * Updated F::Q version to 1.03. * CVSTAG: finance_quote_1_03 2000-10-27 Paul Fenwick * Updated yahoo_europe test suite as one of the symbols we were using for testing has since dissapeared. (Bankrupt? Merged?) 2000-10-29 Paul Fenwick * F::Q now makes use of a custom F::Q::UserAgent to fetch information. This is capable of doing proxy authentication and other arbitary http-headers. 2000-11-05 Paul Fenwick * BUG 121557: Fixed bug where the 40th symbol in a Yahoo lookup would fail. * F::Q::UserAgent is now ready for release, but is still considered experimental. Users must explicitly turn it on by setting $Finance::Quote::USE_EXPERIMENTAL_UA = 1; * Updated the FAQ. * Added MANIFEST file. * CVSTAG: finance_quote_1_04 2000-11-21 Paul Fenwick * Extra code to ensure that currency-fields returned by a Quotelet are unique. This prevents the potential bug of a field undergoing currency conversion multiple times and hence being quite off-track. 2000-11-29 Paul Fenwick * Updated the URL we obtain currency information to http://uk.finance.yahoo.com/m5?" * Updated docs in Yahoo/Europe.pm to note the Xtera exchange moving from FX to DE. * Thanks to Jan Willamowius for the above two changes. 2001-12-05 Paul Fenwick * Updated the Yahoo::USA source to finance.yahoo.com as the quote.yahoo.com may become depreciated in the future. Thanks to Iain Lea for spotting this. 2001-01-22 Paul Fenwick * Updated to respect the FQ_LOAD_QUOTELET environment variable to auto-load custom Quotelet. 2001-02-16 Paul Fenwick * Updated to repsect formatting changes in data fed to the currency function. * Updated Quote.pm to include updated information on FQ_LOAD_QUOTELET * CVSTAG: finance_quote_1_05 2001-04-05 Paul Fenwick * Updated ASX.pm module to reflect changed location of information on the ASX's website. (Still doesn't help when the ASX site is totally broken, as is too often the case.) * Updated Trustnet.pm module to reflect changes to the Trustnet site. 2001-05-08 Paul Fenwick * Applied Leigh Wedding's patch to ASX.pm, after ASX changed their website yet again! All is working happily once more. Thanks Leigh. * Added Tobias Vancura's F::Q::Fool module. * Added Fool as a automatically loaded loaded module from F::Quote.pm. 2001-05-09 Paul Fenwick * Fixed strange behaviour which could occur when using FQ_LOAD_QUOTELET environment variable. This now works as intened. * Added Jasmin Bertovic's Cdnfundlibrary module. 2001-05-10 Volker Stuerzl * Updated VWD.pm to account for changes in VWD website. 2001-05-11 Paul Fenwick * Tweaked VWD.pm to strip whitespace from currency and remove asterisks from names. 2001-06-04 Brent Neal * Fixed Tiaacref.pm to reflect new CGIs at www.tiaa-cref.org New symbols available for the module - check the POD documentation for more info. 2001-06-25 Linas Vepstas * Added Tdwaterhouse module from James A. Treacy. 2001-06-26 Paul Fenwick * Added AEX module courtesy of Rob Sessink. * Updated ASX module to use the new (again!) ASX website. * Updated ASX module to use HTML::TableExtract. Code is much simplier now. * Updated Fidelity module to make use of the new fidelity website. * Updated the Fidelity test to always test the fidelity_direct method. * Bumped version number on F::Q to 1.06. * Updated Trustnet module to assume GBP if no currency explicitly shown. * Updated Trustnet test because one of the funds we were looking for had changed its name, causing the test to fail. * Added AEX test suite to repository. * Removed failover into Fool.pm support, as I'd like to do more testing before it enters the failover system. * Updated the FAQ. * Updated the INSTALL file. * Moved regression tests from /t to /test. Updated MANIFEST file accordingly. This means that autoamtic installs from CPAN won't run the regression tests, which was causing installation to fail on some systems. * Updated lists of copyright holders, SEE ALSO sections in man-pages. * CVSTAG: finance_quote_1_06 2001-07-04 Paul Fenwick * Confirmed debian packages release with Ross Peachey. * Moved cvs tags in debian/* so that finance_quote_1_06 point to the files used in building 1.06, not those building 1.05. 2001-07-23 Paul Fenwick * Updated Yahoo::Europe.pm so that stocks fetched from the Stockholm exhcnage (.ST) are correctly listed as being in Swedish Krona (SEK). 2001-12-19 Paul Fenwick * Added Finance::Quote::Yahoo::Asia to provide lookup of Asian stock quotes (not including Japan). Many thanks to M.R.Muthu Kumar for this patch. 2002-04-18 Paul Fenwick * Patched Quote.pm after currency conversion started to fail. Many thanks to Sean Wenzel for the fix. * Updated documentation in ASX.pm and Trustnet.pm to note their current functional unhappiness. * CVSTAG: finance_quote_1_07 2002-06-25 Paul Fenwick * Added ZI.pm and Union.pm modules. Thanks to Rainer Dorsch for providing these. 2003-02-04 Paul Fenwick * Fixed VWD problem whereby no symbol was being returned. Many thanks to Joachim Breitner for this fix. (#600698) * Updated TrustNet documentation, thanks to David Hampton. (#666349) 2003-07-04 Paul Fenwick * Fixed currency conversion problems. (#232075) * Fixed ASX problems whereby quotes were not being obtained. Thanks to Rik Harris for bringing this issue to light, and providing a correct URL. (#653025) * Fixed problem where no symbol tag was being defined in ASX. Thanks again to Rik Harris. (#653035) * Fixed problem where undefined currencies would be returned as zero, and not undefined as occured in previous versions. * Fixed tests in currency.t which assumed that conversion could be done between EUR and former European currencies. These are no longer supported due to a change in the lookups provided by Yahoo. * Updated Fidelity.pm to indicate its current non-working status. * Added T. Rowe Price patches by David Hampton, which provide a troweprice_direct method. (#666351) * As above, for the Fidelity module. (#666353) * Accepted David Hampton's patch to Yahoo currencies. The correct currency will now be flagged on stocks regardless of the module used to grab them. (#666361) * Added Keith Refson's module to obtain quotes from First Trust Portfolios L.P. Thanks to David Hampton (again!) for supplying this. (#670202) * Added Ganesan Rajagopal's excellent IndiaMutal module. (#720896) * Fixed Cdnfundlibrary to correctly set the success flag when successful. Thanks to Robert Clark for finding this bug. (#752395) * Updated Tdwaterhouse.pm with Robert Clark's changes to work with the new TD Waterhouse website. Many thanks to Robert Clark again. (#750843) * Added the BM Nesbitt Burns module provided by Robert Clark, including test cases. (#752423). * Updated BMONesbittBurns module to provide better date handling, screening out of high-ascii characters from fields, and removal of spurious debug output. * CVSTAG: finance_quote_1_08 2003-07-06 Pawel Konieczny * Update of F::Q::AEX module: added a remap functionality which translates the official stock ticker to AEX CGI symbol * Update of F::Q::AEX module: Distiguishing indices and stocks: indices will have "currency" label undefined, stocks will have value "EUR". This fixes the currency conversion problem for indices. * Update of F::Q::AEX module: Cleanup of labels: "offer" renamed to "ask" ("ask" is more common, besides, it can be currency-converted). Label "offer" stays for backward compatibility. * Update of F::Q::AEX module: Cleanup of garbage in some fields. (Ocassionally, the http fetch & parse will return garbage for some values). 2003-07-07 Pawel Konieczny * AEX module: added label 'symbol' 2003-08-27 Pawel Konieczny * AEX module: following a suffestion of Paul Fenwick, value 'undef' is returned if no valid data could be dowloaded (previously it was returning empty strings in such cases). 2003-08-31 Pawel Konieczny * AEX module: major update: fetching of stock and index options implemented. POD and test script updated as well. 2003-08-31 David Hampton * Yahoo/Base.pm: Added entry for the Lisbon Portugal stock exchange. 2003-09-12 David Hampton * Yahoo/Base.pm: Added suffixes for 1) the US Options, 2) US exchanges when using a non-US Yahoo site, and 3) the Zurich exchange. 2003-09-15 Pawel Konieczny * AEX module: major update: additional labels for options available: volume, oi, and other. Subframes cache implemented, resulting in substantial speedup for repeating (intraday) requests of individual options. 2003-09-20 Pawel Konieczny * AEX module: major update: fetching of futures quotes implemented. POD and test script updated as well. 2004-02-08 David Hampton * Yahoo/Base.pm: Added suffixes for the Brussels and Dublin exchanges. 2004-07-02 Paul Fenwick * Added Finance/Quote/Tdefunds.pm thanks to David Grant. * Added t/tdefunds.t basic regression test (3 tests). * Fixed bug #916966, TASE prices were 100 times their true price. Thanks to Eldad Zack for the patch. ukfunds.t100644001750001750 143713202072256 14440 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->ukfunds("GB0031835118","GB0030880032","LU0116926998","BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"GB0031835118","last"} > 0); ok($quotes{"GB0031835118","success"}); ok($quotes{"GB0030880032","last"} > 0); ok($quotes{"GB0030880032","success"}); ok($quotes{"LU0116926998","last"} > 0); ok($quotes{"LU0116926998","success"}); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); mstaruk.t100644001750001750 143713202072256 14447 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->mstaruk("GB0031835118","GB0030880032","GB0004842737","BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"GB0031835118","last"} > 0); ok($quotes{"GB0031835118","success"}); ok($quotes{"GB0030880032","last"} > 0); ok($quotes{"GB0030880032","success"}); ok($quotes{"GB0004842737","last"} > 0); ok($quotes{"GB0004842737","success"}); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); ftfunds.t100644001750001750 214513202072256 14427 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 12; my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->ftfunds("GB0031835118","GB0030880255","GB0003865176","GB00B7W6PR65","BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"GB0031835118","last"} > 0); ok($quotes{"GB0031835118","success"}); ok($quotes{"GB00B7W6PR65","last"} > 0); ok($quotes{"GB00B7W6PR65","success"}); ok($quotes{"GB00B7W6PR65","currency"} eq "GBP", "Currency (GBP) for GB00B7W6PR65 is ".$quotes{"GB00B7W6PR65","currency"}); ok($quotes{"GB00B7W6PR65","price"}<100,"Price for GB00B7W6PR65 < 100 : ".$quotes{"GB00B7W6PR65","price"}); ok($quotes{"GB0030880255","last"} > 0); ok($quotes{"GB0030880255","success"}); ok($quotes{"GB0003865176","last"} > 0); ok($quotes{"GB0003865176","success"}); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); Makefile.PL100644001750001750 537713202072256 14312 0ustar00ecec000000000000Finance-Quote-1.47# This file was automatically generated by Dist::Zilla::Plugin::MakeMaker v6.010. use strict; use warnings; use 5.010; use ExtUtils::MakeMaker; my %WriteMakefileArgs = ( "ABSTRACT" => "Get stock and mutual fund quotes from various exchanges", "AUTHOR" => "Dj Padzensky , PadzNet, Inc., Linas Vepstas , Yannick LE NY , Paul Fenwick , Brent Neal , Volker Stuerzl , Keith Refson , Rob Sessink , Leigh Wedding , Tobias Vancura , James Treacy , Bradley Dean , Erik Colson ", "CONFIGURE_REQUIRES" => { "ExtUtils::MakeMaker" => 0 }, "DISTNAME" => "Finance-Quote", "LICENSE" => "gpl", "MIN_PERL_VERSION" => "5.010", "NAME" => "Finance::Quote", "PREREQ_PM" => { "CGI" => 0, "Carp" => 0, "DateTime" => 0, "Encode" => 0, "Exporter" => 0, "HTML::Parser" => 0, "HTML::TableExtract" => 0, "HTML::TokeParser" => 0, "HTML::TreeBuilder" => 0, "HTTP::Cookies" => 0, "HTTP::Headers" => 0, "HTTP::Request::Common" => 0, "HTTP::Status" => 0, "JSON" => 0, "LWP::Protocol::https" => 0, "LWP::Simple" => 0, "LWP::UserAgent" => 0, "Mozilla::CA" => 0, "POSIX" => 0, "Time::Piece" => 0, "URI" => 0, "URI::QueryParam" => 0, "base" => 0, "constant" => 0, "strict" => 0, "utf8" => 0, "vars" => 0, "warnings" => 0 }, "TEST_REQUIRES" => { "Data::Dumper" => 0, "File::Spec" => 0, "Test::More" => 0 }, "VERSION" => "1.47", "test" => { "TESTS" => "t/*.t" } ); my %FallbackPrereqs = ( "CGI" => 0, "Carp" => 0, "Data::Dumper" => 0, "DateTime" => 0, "Encode" => 0, "Exporter" => 0, "File::Spec" => 0, "HTML::Parser" => 0, "HTML::TableExtract" => 0, "HTML::TokeParser" => 0, "HTML::TreeBuilder" => 0, "HTTP::Cookies" => 0, "HTTP::Headers" => 0, "HTTP::Request::Common" => 0, "HTTP::Status" => 0, "JSON" => 0, "LWP::Protocol::https" => 0, "LWP::Simple" => 0, "LWP::UserAgent" => 0, "Mozilla::CA" => 0, "POSIX" => 0, "Test::More" => 0, "Time::Piece" => 0, "URI" => 0, "URI::QueryParam" => 0, "base" => 0, "constant" => 0, "strict" => 0, "utf8" => 0, "vars" => 0, "warnings" => 0 ); unless ( eval { ExtUtils::MakeMaker->VERSION(6.63_03) } ) { delete $WriteMakefileArgs{TEST_REQUIRES}; delete $WriteMakefileArgs{BUILD_REQUIRES}; $WriteMakefileArgs{PREREQ_PM} = \%FallbackPrereqs; } delete $WriteMakefileArgs{CONFIGURE_REQUIRES} unless eval { ExtUtils::MakeMaker->VERSION(6.52) }; WriteMakefile(%WriteMakefileArgs); citywire.t100755001750001750 144013202072256 14615 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->citywire("GB0003865390","GB0003865176","GB0033696674","BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"GB0003865390","last"} > 0); ok($quotes{"GB0003865390","success"}); ok($quotes{"GB0003865176","last"} > 0); ok($quotes{"GB0003865176","success"}); ok($quotes{"GB0033696674","last"} > 0); ok($quotes{"GB0033696674","success"}); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); sixfunds.t100755001750001750 207713202072256 14630 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if ( not $ENV{ONLINE_TEST} ) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9; # Test SIXshares functions. my $q = Finance::Quote->new(); my $year = ( localtime() )[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->sixfunds( 'CSSMI', 'BOGUS' ); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok( $quotes{ 'CSSMI', 'last' } > 0 ); ok( length( $quotes{ 'CSSMI', 'name' } ) > 0 ); ok( $quotes{ 'CSSMI', 'success' } ); ok( $quotes{ 'CSSMI', 'currency' } eq 'CHF' ); ok( substr( $quotes{ 'CSSMI', 'isodate' }, 0, 4 ) == $year || substr( $quotes{ 'CSSMI', 'isodate' }, 0, 4 ) == $lastyear ); ok( substr( $quotes{ 'CSSMI', 'date' }, 6, 4 ) == $year || substr( $quotes{ 'CSSMI', 'date' }, 6, 4 ) == $lastyear ); # Make sure we don't have spurious % signs. ok( $quotes{ 'CSSMI', 'p_change' } !~ /%/ ); # Check that a bogus stock returns no-success. ok( !$quotes{ 'BOGUS', 'success' } ); currency.t100755001750001750 274113202072256 14615 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 11; # Test currency conversion, both explicit requests and automatic # conversion. my $q = Finance::Quote->new(); # Explicit conversion... ok($q->currency("USD","AUD")); # Test 1 ok($q->currency("EUR","JPY")); # Test 2 ok(! defined($q->currency("XXX","YYY"))); # Test 3 # test for thousands : GBP -> IQD. This should be > 1000 ok($q->currency("GBP","IQD")>1000) ; # Test 4 # Test 5 ok(($q->currency("10 AUD","AUD")) == (10 * ($q->currency("AUD","AUD")))); # Euros into French Francs are fixed at a conversion rate of # 1:6.559576 . We can use this knowledge to test that a stock is # converting correctly. # Test 6 my %baseinfo = $q->fetch("alphavantage","BA.L"); ok($baseinfo{"BA.L","success"}); $q->set_currency("AUD"); # All new requests in Aussie Dollars. my %info = $q->fetch("alphavantage","BA.L"); ok($info{"BA.L","success"}); # Test 7 ok($info{"BA.L","currency"} eq "AUD"); # Test 8 ok($info{"BA.L","last"} > 0); # Test 9 # Check if inverse is working ok ok(check_inverse("EUR","RUB"),"Inverse is calculated correctly: multiplication should be 1"); ok(check_inverse("CZK","USD"),"Inverse is calculated correctly: multiplication should be 1"); sub check_inverse { my ($cur1,$cur2)=@_; my $a = $q->currency($cur1,$cur2); my $b = $q->currency($cur2,$cur1); return $a*$b; } vanguard.t100755001750001750 167113202072256 14573 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 26; # Test Vanguard functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @funds = qw/VBINX VIVAX VWINX VFIIX/; my %quotes = $q->vanguard(@funds); ok(%quotes); # Check that the name and last are defined for all of the funds. foreach my $fund (@funds) { ok($quotes{$fund,"last"} > 0); ok(length($quotes{$fund,"name"})); ok($quotes{$fund,"success"}); ok($quotes{$fund, "currency"} eq "USD"); ok(substr($quotes{$fund,"isodate"},0,4) == $year || substr($quotes{$fund,"isodate"},0,4) == $lastyear); ok(substr($quotes{$fund,"date"},6,4) == $year || substr($quotes{$fund,"date"},6,4) == $lastyear); } # Make sure we're not getting spurious percentage signs. ok($quotes{"VBINX","p_change"} !~ /%/); trustnet.t100755001750001750 175113202072256 14653 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 12; # Test trustnet functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @stocks = ("ABBEY NATIONAL INTERNATIONAL","MARLBOROUGH INTERNATIONAL EQUITY"); my %quotes = $q->fetch("trustnet",@stocks); ok(%quotes); # For each of our stocks, check to make sure we got back some # useful information. foreach my $stock (@stocks) { ok($quotes{$stock,"success"}); ok($quotes{$stock,"price"}); ok($quotes{$stock,"date"}); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } # Test that a bogus stock gets no success. %quotes = $q->fetch("trustnet","BOGUS"); ok(! $quotes{"BOGUS","success"}); fidelity.t100755001750001750 233013202072256 14566 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 25; # Test Fidelity functions. my $q = Finance::Quote->new(); my @funds = qw/FGRIX FNMIX FASGX/; my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fidelity_direct(@funds); ok(%quotes); # Check that the name and nav are defined for all of the funds. foreach my $fund (@funds) { ok($quotes{$fund,"nav"} > 0); ok(length($quotes{$fund,"name"})); ok($quotes{$fund,"success"}); ok($quotes{$fund, "currency"} eq "USD"); ok(substr($quotes{$fund,"isodate"},0,4) == $year || substr($quotes{$fund,"isodate"},0,4) == $lastyear); ok(substr($quotes{$fund,"date"},6,4) == $year || substr($quotes{$fund,"date"},6,4) == $lastyear); } # Some funds have yields instead of navs. Check one of them too. %quotes = $q->fidelity_direct("FSLXX"); ok(%quotes); ok(length($quotes{"FSLXX","name"})); ok($quotes{"FSLXX","yield"} > 0); ok($quotes{"FSLXX","success"}); ok($quotes{"FSLXX", "currency"} eq "USD"); # Check that a bogus fund returns no-success. %quotes = $q->fidelity_direct("BOGUS"); ok(! $quotes{"BOGUS","success"}); yahoo_nz.t100755001750001750 173213202072256 14610 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9; # Test Yahoo_nz functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->yahoo_nz("AIA","BOGUS"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"AIA","last"} > 0); ok(length($quotes{"AIA","name"}) > 0); ok($quotes{"AIA","success"}); ok($quotes{"AIA", "currency"} eq "NZD"); ok(substr($quotes{"AIA","isodate"},0,4) == $year || substr($quotes{"AIA","isodate"},0,4) == $lastyear); ok(substr($quotes{"AIA","date"},6,4) == $year || substr($quotes{"AIA","date"},6,4) == $lastyear); # Make sure we don't have spurious % signs. ok($quotes{"AIA","p_change"} !~ /%/); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); tdefunds.t100755001750001750 121113202072256 14566 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 5; my $q = Finance::Quote->new; ok($q); my %quotes = $q->tdefunds("TD Canadian Index"); ok(%quotes); ok($quotes{"TD Canadian Index", "nav"}); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"TD Canadian Index","isodate"},0,4) == $year || substr($quotes{"TD Canadian Index","isodate"},0,4) == $lastyear); ok(substr($quotes{"TD Canadian Index","date"},6,4) == $year || substr($quotes{"TD Canadian Index","date"},6,4) == $lastyear); platinum.t100755001750001750 167313202072256 14617 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test Platinum functions. my $q = Finance::Quote->new(); my %quotes = $q->platinum("PLA0001AU","BOGUS"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"PLA0001AU","last"} > 0); ok(length($quotes{"PLA0001AU","name"}) > 0); ok($quotes{"PLA0001AU","success"}); ok($quotes{"PLA0001AU", "currency"} eq "AUD"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"PLA0001AU","isodate"},0,4) == $year || substr($quotes{"PLA0001AU","isodate"},0,4) == $lastyear); ok(substr($quotes{"PLA0001AU","date"},6,4) == $year || substr($quotes{"PLA0001AU","date"},6,4) == $lastyear); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); tiaacref.t100755001750001750 243413202072256 14540 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 45; # Test TIAA-CREF functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @symbols = qw / CREFmony TIAAreal TLSRX TCMVX TLGRX CREFbond /; my %quotes = $q->tiaacref(@symbols,"BOGOname"); ok(%quotes,"quotes got retrieved"); foreach my $symbol (@symbols) { ok($quotes{$symbol,"success"} > 0,"$symbol got retrieved"); ok($quotes{$symbol,"nav"} > 0,"$symbol has a nav"); ok($quotes{$symbol, "currency"} eq "USD","$symbol currency is valid"); ok($quotes{$symbol,"price"} > 0,"$symbol price (".$quotes{$symbol,"price"}.")> 0"); ok(length($quotes{$symbol,"date"}) > 0,"$symbol has a valid date : ".$quotes{$symbol,"date"}); ok(substr($quotes{$symbol,"isodate"},0,4) == $year || substr($quotes{$symbol,"isodate"},0,4) == $lastyear,"$symbol isodate is recent"); ok(substr($quotes{$symbol,"date"},6,4) == $year || substr($quotes{$symbol,"date"},6,4) == $lastyear,"$symbol date is recent"); }; ok($quotes{"BOGOname","success"} == 0,"BOGUS failed"); ok($quotes{"BOGOname","errormsg"} eq "Bad symbol","BOGUS returned errornsg"); lerevenu.t100755001750001750 252513202072256 14610 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 32; # Test LeRevenu functions. my $q = Finance::Quote->new(); # my stocks = stock, fund, warrant, bond, indice my @stocks = ("AF","FR0000441677","FR0010324475","FR0010112052","FR0003500008"); # LeRevenu tests need to cover all the possible cases: # # Name What Test Case # # Actions Stock AF # Obligations Bond FR0010112052 # SICAVetFCP Fund FR0000441677 # Bons&Warrants Warrant FR0010324475 # Indices Index FR0003500008 my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("lerevenu", @stocks); ok(%quotes); # Check that the name, last, currency and date are defined for all of the stocks. foreach my $stock (@stocks) { ok($quotes{$stock,"last"} > 0); ok(length($quotes{$stock,"name"})); ok($quotes{$stock,"success"}); ok($quotes{$stock, "currency"} eq "EUR"); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } # Check that a bogus stock returns no-success. %quotes = $q->fetch("lerevenu", "BOGUS"); ok(! $quotes{"BOGUS","success"}); yahoojson.t100644001750001750 441713202072256 14773 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w # A test script to check for working of the YahooJSON module. use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 67; my $q = Finance::Quote->new(); #List of stocks to fetch. Feel free to change this during testing my @stocks = ( "SUZLON.BO", "ANDHRABANK.BO", "RECLTD.NS", "AMZN", "SOLB.BR", "^DJI", "BEL20.BR", "INGDIRECTFNE.BC", "AENA.MC" ); my %quotes = $q->fetch( "yahoo_json", @stocks ); ok( %quotes, "Data returned" ); foreach my $stock (@stocks) { my $name = $quotes{ $stock, "name" }; ok( $quotes{ $stock, "success" }, "Retrieved $stock" ); if ( !$quotes{ $stock, "success" } ) { my $errmsg = $quotes{ $stock, "errormsg" }; warn "Error Message:\n$errmsg\n"; } else { ok( $name, "Name is defined : $name" ); my $exchange = $quotes{ $stock, "exchange" }; ok( $exchange eq 'Sourced from Yahoo Finance (as JSON)', "correctly retrieved through YahooJSON" ); my $fetch_method = $quotes{ $stock, "method" }; ok( $fetch_method eq 'yahoo_json', "fetch_method is yahoo_json" ); my $last = $quotes{ $stock, "last" }; ok( $last > 0, "Last $last > 0" ); my $volume = $quotes{ $stock, "volume" }; ok( $volume > 0, "Volume $volume > 0" ) if !( grep { $_ eq $stock } ("BEL20.BR","INGDIRECTFNE.BC") ); my $type = $quotes{ $stock, "type" }; ok( $type, "Symbol type $type" ); #TODO: Add a test to raise a warning if the quote is excessively old my $isodate = $quotes{ $stock, "isodate" }; # print "ISOdate: $isodate "; my $date = $quotes{ $stock, "date" }; # currency for .BO stocks ok( $quotes { $stock, "currency" } eq 'INR', 'Bombay stocks have currency INR' ) if $stock =~ /\.BO$/ ; ok( $quotes { $stock, "currency" } eq 'EUR', 'Barcelona stocks have currency EUR' ) if $stock =~ /\.BC$/ ; ok( $quotes { $stock, "currency" } eq 'EUR', 'Madrid stocks have currency EUR' ) if $stock =~ /\.MC$/ ; # print "Date: $date "; } } # Check that a bogus stock returns no-success. %quotes = $q->fetch( "yahoo_json", "BOGUS" ); ok( !$quotes{ "BOGUS", "success" }, "BOGUS failed" ); goldmoney.t100755001750001750 401313202072256 14752 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if ( not $ENV{ONLINE_TEST} ) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 46; # Test GoldMoney functions. my $q = Finance::Quote->new("GoldMoney"); foreach my $currency ( 'EUR', 'USD' ) { $q->set_currency($currency); my %quotes = $q->fetch( "goldmoney", "gold", "silver", "platinum", "BOGUS" ); ok(%quotes); # Check that sound information is returned for gold, silver and platinum. ok( $quotes{ "gold", "success" }, 'gold price lookup' ); ok( $quotes{ "gold", "last" } > 0, "Gold is quoted at " . $quotes{ "gold", "last" } ); ok( $quotes{ "gold", "currency" } eq $currency, "currency is $currency" ); ok( length( $quotes{ "gold", "date" } ) > 0 ); ok( length( $quotes{ "gold", "time" } ) > 0 ); ok( $quotes{ "silver", "success" }, 'silver price lookup' ); ok( $quotes{ "silver", "last" } > 0 ); ok( $quotes{ "silver", "currency" } eq $currency, "currency is $currency" ); ok( length( $quotes{ "silver", "date" } ) > 0 ); ok( length( $quotes{ "silver", "time" } ) > 0 ); ok( $quotes{ "platinum", "success" }, 'platinum price lookup' ); ok( $quotes{ "platinum", "last" } > 0 ); ok( $quotes{ "platinum", "currency" } eq $currency, "currency is $currency" ); ok( length( $quotes{ "platinum", "date" } ) > 0 ); ok( length( $quotes{ "platinum", "time" } ) > 0 ); my $year = ( localtime() )[5] + 1900; ok( ( substr( $quotes{ "gold", "isodate" }, 0, 4 ) == $year ) ); ok( ( substr( $quotes{ "gold", "date" }, 6, 4 ) == $year ) ); ok( ( substr( $quotes{ "silver", "isodate" }, 0, 4 ) == $year ) ); ok( ( substr( $quotes{ "silver", "date" }, 6, 4 ) == $year ) ); ok( ( substr( $quotes{ "platinum", "isodate" }, 0, 4 ) == $year ) ); ok( ( substr( $quotes{ "platinum", "date" }, 6, 4 ) == $year ) ); # Check that a bogus symbol returns no-success. ok( !$quotes{ "BOGUS", "success" } ); } cominvest.t100755001750001750 175513202072256 14776 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9; # Test Cominvest functions. my $q = Finance::Quote->new("Cominvest"); my %quotes = $q->fetch("cominvest","DE0008471178","BOGUS"); ok(%quotes); # Check that the price and date values are defined. ok($quotes{"DE0008471178","success"}); ok($quotes{"DE0008471178","price"} > 0); ok(length($quotes{"DE0008471178","date"}) > 0); ok($quotes{"DE0008471178","currency"}); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok((substr($quotes{"DE0008471178","isodate"},0,4) == $year) || (substr($quotes{"DE0008471178","isodate"},0,4) == $lastyear)); ok((substr($quotes{"DE0008471178","date"},6,4) == $year) || (substr($quotes{"DE0008471178","date"},6,4) == $lastyear)); # Check that a bogus fund returns no-success and has a error message ok(! $quotes{"BOGUS","success"}); ok($quotes{"BOGUS","errormsg"}); 04-critic.t100755001750001750 52113202072256 14433 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use File::Spec; if (not $ENV{TEST_AUTHOR}) { plan( skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to true to run.'); } eval { require Test::Perl::Critic; }; if ($@) { plan( skip_all => 'Test::Perl::Critic required for test.'); } Test::Perl::Critic->import(); all_critic_ok(); sixshares.t100755001750001750 206613202072256 14774 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if ( not $ENV{ONLINE_TEST} ) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9; # Test SIXshares functions. my $q = Finance::Quote->new(); my $year = ( localtime() )[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->sixshares( 'NESN', 'BOGUS' ); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok( $quotes{ 'NESN', 'last' } > 0 ); ok( length( $quotes{ 'NESN', 'name' } ) > 0 ); ok( $quotes{ 'NESN', 'success' } ); ok( $quotes{ 'NESN', 'currency' } eq 'CHF' ); ok( substr( $quotes{ 'NESN', 'isodate' }, 0, 4 ) == $year || substr( $quotes{ 'NESN', 'isodate' }, 0, 4 ) == $lastyear ); ok( substr( $quotes{ 'NESN', 'date' }, 6, 4 ) == $year || substr( $quotes{ 'NESN', 'date' }, 6, 4 ) == $lastyear ); # Make sure we don't have spurious % signs. ok( $quotes{ 'NESN', 'p_change' } !~ /%/ ); # Check that a bogus stock returns no-success. ok( !$quotes{ 'BOGUS', 'success' } ); currencies.t100755001750001750 76713202072256 15113 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote::Currencies; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 1; my $known_currencies = eval { Finance::Quote::Currencies::known_currencies() }; my $live_currencies = eval { Finance::Quote::Currencies::fetch_live_currencies() }; is_deeply( $known_currencies , $live_currencies , "Stored currency list is up to date with live currency list" ); yahoo_asia.t100755001750001750 177613202072256 15106 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->asia("C76.SI","BOGUS.SI"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"C76.SI","last"} > 0); ok(length($quotes{"C76.SI","name"}) > 0); ok($quotes{"C76.SI","success"}); ok($quotes{"C76.SI", "currency"} eq "SGD"); ok(substr($quotes{"C76.SI","isodate"},0,4) == $year || substr($quotes{"C76.SI","isodate"},0,4) == $lastyear); ok(substr($quotes{"C76.SI","date"},6,4) == $year || substr($quotes{"C76.SI","date"},6,4) == $lastyear); # Make sure we don't have spurious % signs. ok($quotes{"C76.SI","p_change"} !~ /%/); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS.SI","success"}); usfedbonds.t100755001750001750 400413202072256 15111 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 19; # Test usfedbonds functions. my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my $q = Finance::Quote->new("USFedBonds"); #my %quotes = $q->usfedbonds("E197001.200606"); my %quotes = $q->usfedbonds("E197001.200606","E194112.200610","E194101.200610","E194001.200610","BOGUS"); ok(%quotes); TODO: { local $TODO="To be debugged"; # Check that the last and date values are defined. ok($quotes{"E197001.200606","success"}); ok($quotes{"E197001.200606","price"} > 0); ok(length($quotes{"E197001.200606","date"}) > 0); ok(substr($quotes{"E197001.200606","isodate"},0,4) eq $year || substr($quotes{"E197001.200606","isodate"},0,4) eq $lastyear); ok(substr($quotes{"E197001.200606","date"},6,4) eq $year || substr($quotes{"E197001.200606","date"},6,4) eq $lastyear); ok($quotes{"E197001.200606","currency"} eq "USD"); ok($quotes{"E194112.200610","success"}); ok($quotes{"E194112.200610","price"} > 0); ok(length($quotes{"E194112.200610","date"}) > 0); ok(substr($quotes{"E194112.200610","isodate"},0,4) eq $year || substr($quotes{"E194112.200610","isodate"},0,4) eq $lastyear); ok(substr($quotes{"E194112.200610","date"},6,4) eq $year || substr($quotes{"E194112.200610","date"},6,4) eq $lastyear); ok($quotes{"E194112.200610","currency"} eq "USD"); } # Check that a non-existent price returns no-success. ok($quotes{"E194101.200610","success"} == 0); TODO: { local $TODO="To be debugged"; ok($quotes{"E194101.200610","errormsg"} eq "No value found"); } # Check that a non-existent price returns no-success. ok($quotes{"E194001.200610","success"} == 0); TODO: { local $TODO="To be debugged"; ok($quotes{"E194001.200610","errormsg"} eq "Date not found"); } # Check that a bogus fund returns no-success. ok($quotes{"BOGUS","success"} == 0); ok($quotes{"BOGUS","errormsg"} eq "Parse error"); troweprice.t100755001750001750 226513202072256 15147 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 13; # Test troweprice functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->troweprice; ok(%quotes); # Check that nav and date are defined as our tests. ok($quotes{"PRFDX","nav"} > 0); ok($quotes{"PRFDX","success"}); ok($quotes{"PRFDX","currency"} eq "USD"); ok(length($quotes{"PRFDX","date"}) > 0); ok(substr($quotes{"PRFDX","isodate"},0,4) == $year || substr($quotes{"PRFDX","isodate"},0,4) == $lastyear); ok(substr($quotes{"PRFDX","date"},6,4) == $year || substr($quotes{"PRFDX","date"},6,4) == $lastyear); ok($quotes{"PRIDX","success"}); ok($quotes{"PRIDX","nav"} > 0); ok(length($quotes{"PRIDX","date"}) > 0); ok(substr($quotes{"PRIDX","isodate"},0,4) == $year || substr($quotes{"PRIDX","isodate"},0,4) == $lastyear); ok(substr($quotes{"PRIDX","date"},6,4) == $year || substr($quotes{"PRIDX","date"},6,4) == $lastyear); # Check a bogus fund returns no-success %quotes = $q->troweprice("BOGUS"); ok(! $quotes{"BOGUS","success"}); 03-kwalitee.t100755001750001750 43613202072256 14767 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; if (not $ENV{TEST_AUTHOR}) { plan( skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to true to run.'); } eval { require Test::Kwalitee; Test::Kwalitee->import() }; plan( skip_all => 'Test::Kwalitee not installed; skipping' ) if $@; yahoo_speed.t100644001750001750 207213202072256 15254 0ustar00ecec000000000000Finance-Quote-1.47/tuse strict; use warnings; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } my $q = Finance::Quote->new(); my @q = qw/ AAPL ADSK AFAM AFSI AHS AIG ALG AMBA AMT AMZN AN AP APOG ARCO ARO ASR ATHN ATVI AVAV BBY BIDU BIIB BKE BLX BMC BOOM BPI BR BRK-B BWLD CACC CBRL CBST CGA CINF CME COH COO COST CRH CROX CTAS CVA DDD DGS DNR DOW DVA DVN EBAY EBIX ERJ ESRX EXEL FB FLPKX GD GHDX GILD GOOG GOOGL GTI HAS HI HY IART IBKR ICON INFN INTC INVN IPGP IRM ISCA IYR JACK JBT KMX KNX KORS LDL LF LL LLL LNKD LOW LTM MA MCD MCF MCO MDP MDT MKL MOD MOV MSFT NFLX NOC NOK NVDA O OME ORCL OTEX PACR PAYX PCAR PEB PERY PHYS PNW POT PRAA RLI ROIC RPXC RRGB SAFM SBUX SCTY SE SH SHFL SINA SKX SLAB SNV SONC SPY SSW STON SUP SWPPX SYNA SZYM TECUA TGH TOL TSLA TTC TTS TUP TWI ULTA UNH USMO VIIIX WFC WFM WM WMT WU XLK YONG ZINC /; my %quotes = $q->yahoo( @q ); ok(%quotes, "Quote hash defined" ); foreach my $q (@q) { my $last = $quotes{$q,"last"}; ok( $last > 0, "$q: $last>0" ); } done_testing( 1+@q ); morningstar.t100644001750001750 211113202072256 15312 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9; # Test Morningstar functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @stocks = ("0P0000J24W","BOGUS"); my %quotes = $q->fetch("morningstar",@stocks); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"0P0000J24W","price"} > 0); ok(length($quotes{"0P0000J24W","name"}) > 0); ok($quotes{"0P0000J24W","success"}); ok($quotes{"0P0000J24W", "currency"} eq "SEK"); ok(substr($quotes{"0P0000J24W","isodate"},0,4) == $year || substr($quotes{"0P0000J24W","isodate"},0,4) == $lastyear); ok(substr($quotes{"0P0000J24W","date"},6,4) == $year || substr($quotes{"0P0000J24W","date"},6,4) == $lastyear); # Make sure we don't have spurious % signs. ok($quotes{"0P0000J24W","p_change"} !~ /%/); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); indiamutual.t100755001750001750 205313202072256 15273 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 50; # Test Fidelity functions. my $q = Finance::Quote->new(); my @funds = ("102676", "103131", "101599", "102732", "100151", "INF194K01W88", "INF090I01FN7", "INF082J01127"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("indiamutual", @funds); ok(%quotes); # Check that the name and nav are defined for all of the funds. foreach my $fund (@funds) { ok($quotes{$fund,"nav"} > 0); ok(length($quotes{$fund,"name"})); ok($quotes{$fund,"success"}); ok($quotes{$fund, "currency"} eq "INR"); ok(substr($quotes{$fund,"isodate"},0,4) == $year || substr($quotes{$fund,"isodate"},0,4) == $lastyear); ok(substr($quotes{$fund,"date"},6,4) == $year || substr($quotes{$fund,"date"},6,4) == $lastyear); } # Check that a bogus fund returns no-success. %quotes = $q->fetch("indiamutual", "BOGUS"); ok(! $quotes{"BOGUS","success"}); ftportfolios.t100755001750001750 210313202072256 15505 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 18; # Test FTPortfolios functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @stocks = ("FKYMRX", "FAEDEX"); my %quotes = $q->ftportfolios(@stocks, "BOGUS"); ok(%quotes); TODO: { local $TODO="To be debugged"; # Check that last and date are defined as our tests. foreach my $stock (@stocks) { ok($quotes{$stock,"pop"} > 0); ok($quotes{$stock,"nav"} > 0); ok($quotes{$stock,"price"} > 0); ok($quotes{$stock,"success"}); ok($quotes{$stock,"currency"} eq "USD"); ok(length($quotes{$stock,"date"}) > 0); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } } # Check that a bogus fund returns no-success. ok( ! $quotes{"BOGUS","success"}); tdwaterhouse.t100755001750001750 207713202072256 15503 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 12; # Test TD Waterhouse functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @stocks = ("TD U.S. MidCap Growth US", "TD Canadian Bond Index"); my %quotes = $q->tdwaterhouse(@stocks, "BOGUS"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. foreach my $stock (@stocks) { ok($quotes{$stock,"last"} > 0); ok($quotes{$stock,"success"}); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } ok($quotes{"TD U.S. MidCap Growth US", "currency"} eq "USD"); ok($quotes{"TD Canadian Bond Index", "currency"} eq "CAD"); # Check that bogus stocks return failure: ok(! $quotes{"BOGUS","success"}); alphavantage.t100755001750001750 354113202072256 15415 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if ( not $ENV{"ONLINE_TEST"} ) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } if ( not $ENV{"ALPHAVANTAGE_API_KEY"} ) { plan skip_all => 'Set $ENV{ALPHAVANTAGE_API_KEY} to run this test; get one at https://www.alphavantage.co'; } my $q = Finance::Quote->new(); my $year = ( localtime() )[5] + 1900; my $lastyear = $year - 1; my @symbols = qw/ IBM CSCO SOLB.BR SAP.DE TD.TO LSE.L VFIAX T DIVO11.SA OGZD.IL/; plan tests => 10*(1+$#symbols)+10; my %quotes = $q->alphavantage( @symbols, "BOGUS" ); ok(%quotes); foreach my $symbol (@symbols) { ok( $quotes{ $symbol, "success" }, "$symbol success" ); ok( $quotes{ $symbol, "symbol" } eq $symbol , "$symbol defined" ); ok( $quotes{ $symbol, "open" } > 0, "$symbol returned open" ); ok( $quotes{ $symbol, "close" } > 0, "$symbol returned close" ); ok( $quotes{ $symbol, "last" } > 0, "$symbol returned last" ); ok( $quotes{ $symbol, "high" } > 0, "$symbol returned high" ); ok( $quotes{ $symbol, "low" } > 0, "$symbol returned low" ); ok( $quotes{ $symbol, "volume" } >= 0, "$symbol returned volume" ); ok( substr( $quotes{ $symbol, "isodate" }, 0, 4 ) == $year || substr( $quotes{ $symbol, "isodate" }, 0, 4 ) == $lastyear ); ok( substr( $quotes{ $symbol, "date" }, 6, 4 ) == $year || substr( $quotes{ $symbol, "date" }, 6, 4 ) == $lastyear ); } is( $quotes{ "IBM", "currency" }, 'USD' ); is( $quotes{ "CSCO", "currency" }, 'USD' ); is( $quotes{ "SOLB.BR", "currency" }, 'EUR' ); is( $quotes{ "SAP.DE", "currency" }, 'EUR' ); is( $quotes{ "TD.TO", "currency" }, 'CAD' ); is( $quotes{ "LSE.L", "currency" }, 'GBP' ); is( $quotes{ "DIVO11.SA", "currency" }, 'BRL' ); is( $quotes{ "OGZD.IL", "currency" }, 'USD' ); ok( !$quotes{ "BOGUS", "success" } ); yahoo_europe.t100755001750001750 767213202072256 15471 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 34; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->yahoo_europe("UG.PA","BOGUS.L"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"UG.PA","last"} > 0); ok(length($quotes{"UG.PA","name"}) > 0); ok($quotes{"UG.PA","success"}); ok($quotes{"UG.PA", "currency"} eq "EUR"); ok(substr($quotes{"UG.PA","isodate"},0,4) == $year || substr($quotes{"UG.PA","isodate"},0,4) == $lastyear); ok(substr($quotes{"UG.PA","date"},6,4) == $year || substr($quotes{"UG.PA","date"},6,4) == $lastyear); # Make sure we don't have spurious % signs. ok($quotes{"UG.PA","p_change"} !~ /%/); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); # London stocks can be returned in a variety of currencies my %londonquotes = $q->fetch("yahoo_europe","RDSB.L"); ok($londonquotes{"RDSB.L","success"}); ok($londonquotes{"RDSB.L","currency"} eq "GBP"); ok(($londonquotes{"RDSB.L","currency"} eq "GBP") && !defined($londonquotes{"RDSB.L","currency_set_by_fq"})); %londonquotes = $q->fetch("yahoo_europe","CCR.L"); ok($londonquotes{"CCR.L","success"}); ok($londonquotes{"CCR.L","currency"} eq "EUR"); ok(($londonquotes{"CCR.L","currency"} eq "EUR") && !defined($londonquotes{"CCR.L","currency_set_by_fq"})); # Copenhangen stocks should be returned in Danisk Krone (DKK). my %copenhagenquotes = $q->fetch("yahoo_europe","TDC.CO"); ok($copenhagenquotes{"TDC.CO","success"}); ok($copenhagenquotes{"TDC.CO","currency"} eq "DKK"); ok(($copenhagenquotes{"TDC.CO","currency"} eq "DKK") && !defined($copenhagenquotes{"TDC.CO","currency_set_by_fq"})); # Two stocks from the German XETRA. One in EUR and one in USD. my %xetraquotes = $q->fetch("yahoo_europe","DBK.DE", "ERM.DE"); ok($xetraquotes{"DBK.DE","success"}); ok($xetraquotes{"DBK.DE","currency"} eq "EUR"); ok(($xetraquotes{"DBK.DE","currency"} eq "EUR") && !defined($xetraquotes{"DBK.DE","currency_set_by_fq"})); # a stock from the Belgium Euronext market. my %belgiumquotes = $q->fetch("yahoo_europe","SOLB.BR"); ok($belgiumquotes{"SOLB.BR","success"}); ok($belgiumquotes{"SOLB.BR","currency"} eq "EUR"); ok(($belgiumquotes{"SOLB.BR","currency"} eq "EUR") && !defined($belgiumquotes{"SOLB.BR","currency_set_by_fq"})); ok($belgiumquotes{"SOLB.BR","last"}>=50); # this expected trades around 60-200 EUR ok($belgiumquotes{"SOLB.BR","last"}<=200); # Check if close is between year_range for LTI.L (expressed in GBp) for checking if conversion is correct my %ltiquotes = $q->fetch("yahoo_europe","LTI.L"); ok($ltiquotes{"LTI.L","success"}); my ($min,$max) = (50,50000); # change this if quotes are not supposed to be in this range anymore if ($ltiquotes{"LTI.L","year_range"}=~ m/([\d\.]+)\s*-\s*([\d\.]+)/) { my ($year_low,$year_high) = ($1,$2) ; ok (($year_low >= $min) && ($year_high <= $max)); # print "$year_low - $year_high\n"; } ok (($ltiquotes{"LTI.L","close"} >= $min) && ($ltiquotes{"LTI.L","close"} <= $max)); # check that A0GFY7.SG returns correctly the currency (reported by GnuCash user) %xetraquotes = $q->fetch("yahoo_europe","A0GFY7.SG"); ok($xetraquotes{"A0GFY7.SG","success"}); ok($xetraquotes{"A0GFY7.SG","currency"} eq "EUR"); ok(($xetraquotes{"A0GFY7.SG","currency"} eq "EUR") && !defined($xetraquotes{"A0GFY7.SG","currency_set_by_fq"})); TODO: { # Yahoo does not provide retrieval of ^DJI.US quotes since it lost # license for it. ^DJI can only be viewed on the html page anymore. We # need to write a HTML page scraper for this case local $TODO = "^DJI not returned by yahoo anymore."; %xetraquotes = $q->fetch("yahoo_europe","%40%5EDJI.US"); ok($xetraquotes{"^DJI","success"}); ok($xetraquotes{"^DJI","currency"} eq "USD"); } yahoo_brasil.t100755001750001750 221313202072256 15430 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 23; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my @stocks = ("PDGR3","PETR4","BAZA3"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("yahoo_brasil", @stocks); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. foreach my $stock (@stocks) { ok($quotes{$stock,"success"}); ok($quotes{$stock,"last"} > 0); ok(length($quotes{$stock,"name"}) > 0); ok($quotes{$stock, "currency"} eq "BRL"); ok((substr($quotes{$stock,"isodate"},0,4) == $year) || (substr($quotes{$stock,"isodate"},0,4) == $lastyear)); ok((substr($quotes{$stock,"date"},6,4) == $year) || (substr($quotes{$stock,"date"},6,4) == $lastyear)); # Make sure we don't have spurious % signs. ok($quotes{$stock,"p_change"} !~ /%/); } # Check that a bogus stock returns no-success. %quotes = $q->yahoo_brasil("BOGUS"); ok(! $quotes{"BOGUS","success"}); morningstarJP.t100644001750001750 333413202072256 15554 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use DateTime; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 9 * 2; # Find out today my $calcDay = DateTime->now(); my $year = $calcDay->year(); my $month = $calcDay->month(); my $day = $calcDay->day(); # Test Morningstar JP functions. my $q = Finance::Quote->new(); my @funds = ( "2009100101", "2002013108" ); my %info = $q->morningstarjp(@funds); ok(%info); # Check that the symbol/name, date, currency and nav defined for all of the funds. foreach my $fund (@funds) { # NAV date should be within 10 days of today, but we will allow +- 1 day # on top of that for running tests outside of Asia/Tokyo timezone my $fndyear = substr( $info{ $fund, "isodate" }, 0, 4 ); my $fndmonth = substr( $info{ $fund, "isodate" }, 5, 2 ); my $fndday = substr( $info{ $fund, "isodate" }, 8, 2 ); my $fnd = DateTime->new(year=>$fndyear,month=>$fndmonth,day=>$fndday); my $deltadays = $calcDay->subtract_datetime($fnd)->in_units('days'); cmp_ok( $deltadays,'<=', 11, 'not more than 11 days before today' ); cmp_ok( $deltadays,'>=', -1, 'not more than 1 day in the future' ); cmp_ok( $info{ $fund, 'currency' }, 'eq', 'JPY', 'currency' ); cmp_ok( $info{ $fund, 'method' }, 'eq', 'MorningstarJP', 'method' ); cmp_ok( $info{ $fund, 'name' }, 'eq', $fund, 'name' ); cmp_ok( $info{ $fund, "nav" }, '>', 0, 'nav' ); ok( $info{ $fund, "success" }, 'success' ); cmp_ok( $info{ $fund, 'symbol' }, 'eq', $fund, 'symbol' ); } # Check that a bogus symbol returns no-success. ok( !$info{ "BOGUS", "success" } ); fidelityfixed.t100644001750001750 164613202072256 15614 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 17; # Test Fidelity functions. my $q = Finance::Quote->new(); my @funds = qw/59333PRJ9 971175PC2 594712RK9/; my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("fidelityfixed",@funds); ok(%quotes); # Check info reported by funds foreach my $fund (@funds) { ok(length($quotes{$fund,"name"})); ok($quotes{$fund,"success"}); ok($quotes{$fund, "currency"} eq "USD"); ok(substr($quotes{$fund,"isodate"},0,4) == $year || substr($quotes{$fund,"isodate"},0,4) == $lastyear); ok(substr($quotes{$fund,"date"},6,4) == $year || substr($quotes{$fund,"date"},6,4) == $lastyear); } # Check that a bogus fund returns no-success. %quotes = $q->fetch("fidelityfixed","BOGUS"); ok(! $quotes{"BOGUS","success"}); finanzpartner.t100644001750001750 167313202072256 15644 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test finanzpartner functions. my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my $q = Finance::Quote->new("Finanzpartner"); my %quotes = $q->finanzpartner("LU0055732977","BOGUS"); ok(%quotes); # Check that the last and date values are defined. ok($quotes{"LU0055732977","success"}); ok($quotes{"LU0055732977","last"} > 0); ok(length($quotes{"LU0055732977","date"}) > 0); ok(substr($quotes{"LU0055732977","isodate"},0,4) == $year || substr($quotes{"LU0055732977","isodate"},0,4) == $lastyear); ok(substr($quotes{"LU0055732977","date"},6,4) == $year || substr($quotes{"LU0055732977","date"},6,4) == $lastyear); ok($quotes{"LU0055732977","currency"} eq "USD"); # Check that a bogus fund returns non-success. ok($quotes{"BOGUS","success"} == 0); za_unittrusts.t100644001750001750 225113202072256 15712 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 10; # Test za_unittrusts functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->za_unittrusts("15740"); ok(%quotes); # Check the last values are defined. These are the most used and most # reliable indicators of success. ok($quotes{"15740","last"} > 0); ok($quotes{"15740","success"}); ok(substr($quotes{"15740","date"},6,4) == $year || substr($quotes{"15740","date"},6,4) == $lastyear); # Exercise the fetch function a little. %quotes = $q->fetch("za_unittrusts","15740"); ok(%quotes); ok($quotes{"15740","last"} > 0); ok($quotes{"15740","success"} > 0); # Check that we're getting currency information. ok($quotes{"15740", "currency"} eq "ZAR"); # Check we're not getting bogus percentage signs. $quotes{"15740","p_change"} ||= ""; # Avoid warning if undefined. ok($quotes{"15740","p_change"} !~ /%/); # Check that looking up a bogus stock returns failure: %quotes = $q->za_unittrusts("BOGUS"); ok(! $quotes{"BOGUS","success"}); financecanada.t100755001750001750 176613202072256 15524 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 26; # Test Finance Canada functions. my $q = Finance::Quote->new(); my @stocks = ("NT","XIU","UUU", "PCA"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("financecanada", @stocks); ok(%quotes); # Check that the name and nav are defined for all of the stocks. foreach my $stock (@stocks) { ok($quotes{$stock,"price"} > 0); ok(length($quotes{$stock,"name"})); ok($quotes{$stock,"success"}); ok($quotes{$stock, "currency"} eq "CAD"); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } # Check that a bogus stock returns no-success. %quotes = $q->fetch("financecanada", "BOGUS"); ok(! $quotes{"BOGUS","success"}); htdocs000755001750001750 013202072256 13450 5ustar00ecec000000000000Finance-Quote-1.47index.html100644001750001750 2064513202072256 15634 0ustar00ecec000000000000Finance-Quote-1.47/htdocs Finance::Quote Homepage
Finance :: Quote
Button Documentation
Button Discussion Groups and Mailing Lists
Button Bugs, Patches and Development
Button Download
Button SourceForge Page

Welcome to the Finance::Quote webpage.

Finance::Quote is a perl module which can be used to obtain information from a variety of sources, including markets in Australia, USA, Canada, Europe, and a number of managed funds.

The latest version of Finance::Quote is (soon to be) available via CPAN, and is currently available on our download page.

News

2017-Nov-05 Releases 1.39 and 1.40 are available both from CPAN and Sourceforge. These releases adds the module AlphaVantage to circumvent the shutdown of yahoo API.

2015-Aug-22 Release 1.38 is available both from CPAN and Sourceforge. This release encloses several website module updates.

2015-Feb-02 Release 1.37 is available both from CPAN and Sourceforge. This removes some dependencies to obtain better compatibility.

2014-Feb-17 Release 1.20 is available both from CPAN and Sourceforge. This autoinstalls Date::Calc if needed.

2014-Feb-16 Release 1.19 is available both from CPAN and Sourceforge. It solves Yahoo quote retrieval changes and adds 2 new modules.

2012-Sep-30 Release 1.18 is available both from CPAN and Sourveforge. It solves most used module errors.

2009-Oct-5 Release 1.17 is available both from CPAN and Sourceforge.

2009-Apr-13 Release 1.16 is available both from CPAN and Sourceforge. Thanks to Bradley Dean a currency_lookup function is available. As usual, some modules were patched due to site modifications.

2008-Oct-26 Release 1.15 is available both from CPAN and Sourceforge. It is a bugfix release. Upgrade is strongly recommended.

2008-Oct-15 Release 1.14 considered as the latest stable release has been uploaded to CPAN and Sourceforge.

2008-Sep-21 The development of Finance::Quote is undergoing a lifting. More information is available on the developer page

2006-Jul-10 Finance::Quote 1.12 has been released. The new version includes support for new information sources, including Bourso and LeRevenu in France, and the Helsinki stock exchange in Finland. This release also fixes the problem with retrieving quotes with the DWS and VWD modules. The full set of release notes are available here. You can download this release from our download page.

2006-Jan-11 Finance::Quote 1.11 has been released. The new version includes support for new information sources, including Sharenet (South Africa) and U.S. Federal Bonds. This release also fixes the problem with retrieving currency quotes from Yahoo Finance. The full set of release notes are available here. You can download this release from our download page.

2005-Jul-04 Finance::Quote 1.10 has been released. The new version includes support for new information sources, including the New Zealand stock exchange, TD Waterhouse Canada Efunds, the Swedish Bank, the U.S. Govt. Thrift Savings Plan, and several Yahoo sources. The full set of release notes are available here. You can download this release from our download page.

2005-Jun-30 Finance::Quote 1.09 has been released. The new version includes support for new information sources, including the New Zealand stock exchange, TD Waterhouse Canada Efunds, the Swedish Bank, the U.S. Govt. Thrift Savings Plan, and several Yahoo sources. The full set of release notes are available here. You can download this release from our download page.

2003-Jul-04 Finance::Quote 1.08 was released.

2002-Apr-18 Finance::Quote 1.07 was released.

2001-Jun-26 Finance::Quote 1.06 has been released. The new version includes support for many new information sources, including Dutch stocks and indexes, UK unit trusts, managed funds from TD waterhouse, and quote lookups from fool.com. The full set of release notes are available here. You can download this release from our download page.

2001-Feb-23 Finance::Quote 1.05 has been released. This version fixes some bugs that people have been experiencing with currency conversion, and also provides easier methods for users to load their custom modules at run-time. The new release is available from our download page.

2000-Nov-05 Finance::Quote 1.04 has been released. This version fixes a bug whereby the 40th symbol of a large Yahoo lookup would fail. It also removes some of the headaches people have been experiencing with the test suite. For the adventurous, support for proxy authentication has also been added. See the FAQ for more details.

2000-Oct-30 An article on Finance::Quote was featured in The Perl Journal, issue number 19. The article is a good introduction to the module and well worth reading if you are beginning to work with Finance::Quote. The draft is available from our documentation page.

Older news items and SourceForge page.


Documentation000755001750001750 013202072256 14775 5ustar00ecec000000000000Finance-Quote-1.47FAQ100644001750001750 531213202072256 15470 0ustar00ecec000000000000Finance-Quote-1.47/DocumentationFinance::Quote FAQ Paul Fenwick (pjf at cpan.org) 0. TABLE OF CONTENTS ==================== 0. Table of Contents. 1. Where's the Finance::Quote webpage? 2. Where can I get a beginner's introduction to F::Q? 3. How can I use proxyauth (experimental)? 4. Is there anything similar to F::Q in other programming languages? 5. Where can I get more help? 6. Is there commercial support for F::Q available? 1. Where is the Finance::Quote webpage? ======================================= http://finance-quote.sourceforge.net/ 2. Where can I get a beginner's introduction to F::Q? ===================================================== A good beginner's guide is the Finance::Quote article in The Perl Journal (http://www.tpj.com/) edition #19. If you don't have a subscription to TPJ, you can also read the final draft of this essay at . 3. How can I use proxyauth (experimental)? ========================================== WARNING: THIS SUPPORT IS EXPERIMENTAL AND SYNTAX _WILL_ CHANGE IN THE FUTURE. If it breaks, you get to keep both pieces. Finance::Quote provides experimental support for authenticated proxies. If you wish to try this, then put the following at the top of your script. use Finance::Quote; $Finance::Quote::USE_EXPERIMENTAL_UA = 1; This adds extra features on top of the regular LWP::UserAgent class. In particular, you can now do things like this: my $q = Finance::Quote->new(); $q->user_agent->default_headers->proxy_authorization_basic($user,$pass); The result of $q->user_agent->default_headers is a HTTP::Headers object, and can use all the regular HTTP::Headers methods. This object is used as a template for any new HTTP requests made by Finance::Quote. 4. Is there anything similar to F::Q in other programming languages? ==================================================================== Vidyut Luther has written a stock-lookup library in PHP. It's available at Bill Bell has written a stock-lookup library in Java. It's available at . Follow the "Code Downloads" link in the left sidebar. 5. Where can I get more help? ============================= If you haven't already done so, try the Finance::Quote webpage at . There are also lots of fun things like bug-tracking systems, support requests, forums, and other goodies at . Finally, you can always try sending mail to the Finance::Quote developer's list, at . The archives of this list are available on-line at . cdnfundlibrary.t100755001750001750 164413202072256 15772 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test Canadian Fund Library functions. my $q = Finance::Quote->new(); my %quotes = $q->fundlibrary("19001","00000"); ok(%quotes); # Check the last values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"19001","last"} > 0); ok($quotes{"19001","success"}); ok($quotes{"19001", "currency"} eq "CAD"); ok(length($quotes{"19001","date"}) > 0); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok(substr($quotes{"19001","isodate"},0,4) == $year || substr($quotes{"19001","isodate"},0,4) == $lastyear); ok(substr($quotes{"19001","date"},6,4) == $year || substr($quotes{"19001","date"},6,4) == $lastyear); # Check that bogus stocks return failure: ok(! $quotes{"00000","success"}); 05-data-dumper.t100755001750001750 71713202072256 15371 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{TEST_AUTHOR}) { plan( skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to true to run.'); } plan tests => 1; # F::Q doesn't load all its code until we actually create # an object. my $fq = Finance::Quote->new; # Sometimes Data::Dumper gets left in code by accident. Make sure # we haven't done so. ok(! exists $INC{'Data/Dumper.pm'}, "Data::Dumper should not be loaded"); maninvestments.t100755001750001750 177713202072256 16046 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 8; # Test ManInvestments functions. my $q = Finance::Quote->new(); my %quotes = $q->maninv("OMIP220","BOGUS"); TODO: { local $TODO="To be debugged"; ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"OMIP220","last"} > 0); ok(length($quotes{"OMIP220","name"}) > 0); ok($quotes{"OMIP220","success"}); ok($quotes{"OMIP220", "currency"} eq "AUD"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; ok((substr($quotes{"OMIP220","isodate"},0,4) == $year) || (substr($quotes{"OMIP220","isodate"},0,4) == $lastyear)); ok((substr($quotes{"OMIP220","date"},6,4) == $year) || (substr($quotes{"OMIP220","date"},6,4) == $lastyear)); } # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); 02-pod-coverage.t100755001750001750 44713202072256 15536 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; if (not $ENV{TEST_AUTHOR}) { plan( skip_all => 'Author test. Set $ENV{TEST_AUTHOR} to true to run.'); } eval "use Test::Pod::Coverage 1.00"; plan skip_all => "Test::Pod::Coverage 1.00 required for testing POD" if $@; all_pod_coverage_ok(); currency_lookup.t100755001750001750 341613202072256 16206 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More tests => 12; use Finance::Quote; # Test overall currency lookup my $currencies = Finance::Quote::currency_lookup(); my %test_currencies = ( AUD => "Australian Dollar" , EUR => "Euro" , CAD => "Canadian Dollar" ); while ( my ($code, $name) = each %test_currencies ) { ok( exists $currencies->{$code}, "Expected currency code (${code}) exists" ); is( $currencies->{$code}->{name} , $name , "Expected currency name (${name}) for code (${code})" ); } # Test selective currency lookup $currencies = Finance::Quote::currency_lookup( name => qr/pound/i ); # Test multiple lookup parameters $currencies = Finance::Quote::currency_lookup( name => "Australia" , code => qr/AU/ ); ok( exists $currencies->{AUD} , "Expected currency code (AUD) exists for matching multiple params" ); cmp_ok( scalar keys %{$currencies}, '==', 1 , "Only one currency returned for matching multiple params" ); $currencies = Finance::Quote::currency_lookup( name => "Euro" , code => "AUD" ); cmp_ok( scalar keys %{$currencies}, '==', 0 , "Expected zero-response for non-matching multiple params" ); # Test non-matching currency lookup $currencies = Finance::Quote::currency_lookup( name => qr/rubbish_value/i ); is( ref $currencies , 'HASH' , 'Hash-ref returned for non-matching lookup' ); cmp_ok( scalar keys %{$currencies} , '==', 0 , "Empty hashref returned for non-matching lookup" ); # Test that an error returns undef $currencies = Finance::Quote::currency_lookup( invalid_param => 1 ); is( $currencies , undef , "Error results in undef response" ); yahoo_australia.t100755001750001750 245313202072256 16147 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 13; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->yahoo_australia("BHP","BOGUS"); ok(%quotes); # Check the nav values are defined. These are the most # used and most reliable indicators of success. ok($quotes{"BHP","last"} > 0); ok(length($quotes{"BHP","name"}) > 0); ok($quotes{"BHP","success"}); ok($quotes{"BHP", "currency"} eq "AUD"); ok(substr($quotes{"BHP","isodate"},0,4) == $year || substr($quotes{"BHP","isodate"},0,4) == $lastyear); ok(substr($quotes{"BHP","date"},6,4) == $year || substr($quotes{"BHP","date"},6,4) == $lastyear); # Make sure we don't have spurious % signs. ok($quotes{"BHP","p_change"} !~ /%/); TODO: { local $TODO = "Get quotes when '.AX' suffix is added"; my %suffix_quotes = $q->yahoo_australia("BHP.AX"); ok(%suffix_quotes); ok($suffix_quotes{"BHP.AX","last"} == $quotes{"BHP","last"}); ok($suffix_quotes{"BHP.AX","name"} eq $quotes{"BHP","name"}); ok($suffix_quotes{"BHP.AX","success"}); } # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); bmonesbittburns.t100755001750001750 263613202072256 16206 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 23; # Test bmonesbittburns functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my @stocks = ("NT,T", "BBD.A,T","MFC598,MF"); my %quotes = $q->bmonesbittburns(@stocks); ok(%quotes); # Check that last and date are defined as our tests. foreach my $stock (@stocks) { ok($quotes{$stock,"last"} > 0); ok($quotes{$stock,"success"}); ok($quotes{$stock,"currency"} eq "CAD"); ok(length($quotes{$stock,"date"}) > 0); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } # Exercise the fetch function %quotes = $q->fetch("bmonesbittburns", "NT,X"); ok(%quotes); ok($quotes{"NT,X","success"}); ok($quotes{"NT,X","last"} > 0); # Check that a bogus fund returns no-success. %quotes = $q->bmonesbittburns("BOGUS"); ok( ! $quotes{"BOGUS","success"}); # Fetching an empty stock does result in an error, and yes # this is bad. But fetching an empty stock isn't normal # behaviour. # %quotes = $q->fetch("bmonesbittburns", ""); # ok( %quotes); # ok( ! $quotes{"NT,X","success"}); # ok( ! $quotes{"NT,X","last"} > 0); stockhousecanada.t100755001750001750 233213202072256 16276 0ustar00ecec000000000000Finance-Quote-1.47/t#!/usr/bin/perl -w use strict; use Test::More; use Finance::Quote; if (not $ENV{ONLINE_TEST}) { plan skip_all => 'Set $ENV{ONLINE_TEST} to run this test'; } plan tests => 20; # Test Stock House Canada functions. my $q = Finance::Quote->new(); my @stocks = ("CIB497", "TDB227", "FID342"); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->fetch("stockhousecanada_fund", @stocks); ok(%quotes); # Check that the name and nav are defined for all of the stocks. foreach my $stock (@stocks) { # print "----------->PRICE: ".$quotes{$stock,"price"}."\n"; ok($quotes{$stock,"price"} > 0); # print "----------->NAME: ".$quotes{$stock,"name"}."\n"; ok(length($quotes{$stock,"name"})); ok($quotes{$stock,"success"}); ok(substr($quotes{$stock,"isodate"},0,4) == $year || substr($quotes{$stock,"isodate"},0,4) == $lastyear); ok(substr($quotes{$stock,"date"},6,4) == $year || substr($quotes{$stock,"date"},6,4) == $lastyear); } ok($quotes{"CIB497", "currency"} eq "CAD"); ok($quotes{"TDB227", "currency"} eq "USD"); ok($quotes{"FID342", "currency"} eq "USD"); # Check that a bogus stock returns no-success. %quotes = $q->fetch("stockhousecanada_fund", "BOGUS"); ok(! $quotes{"BOGUS","success"}); download.html100644001750001750 1005413202072256 16325 0ustar00ecec000000000000Finance-Quote-1.47/htdocs Finance::Quote Downloads
Finance :: Quote
Button Home
Button Documentation
Button Discussion Groups and Mailing Lists
Button Bugs, Patches and Development
Button SourceForge Page

Latest Release

The latest tarball release of Finance::Quote can be downloaded here.

Previous Releases

The previous tarball release of Finance::Quote (version 1.13) can be downloaded here.

Finance::Quote (version 1.12) can be downloaded here.

Finance::Quote (version 1.11) can be downloaded here.

Finance::Quote (version 1.10) can be downloaded here.

Finance::Quote (version 1.08) can be downloaded here. The Debian package of Finance::Quote 1.08 is here.

All Finance::Quote versions can be found here

CVS Tree

Those people who want to play with the development branch of Finance::Quote can should consult the directions regarding anonymous CVS access here. Alternatively, you can download a nightly tarball of the CVS tree.


Images000755001750001750 013202072256 14655 5ustar00ecec000000000000Finance-Quote-1.47/htdocsbg.jpg100644001750001750 1112713202072256 16131 0ustar00ecec000000000000Finance-Quote-1.47/htdocs/ImagesJFIF``C    $.' ",#(7),01444'9=82<.342C  2!!22222222222222222222222222222222222222222222222222" 5R`i=u7#n"+(D4sç4! s[Z̊JrkXYFfF27@gfv-˼tC[?x %4 ȩ$hAhL̾~RҪlB=$a@U^zE&yi044Qw18e:DFYEAaYmxT" --233[(+=rځ2 ^ !!1A" 2Bʮ1 <&`VK$J`Zr/j0[0$qn*m!)PZ[LEu9fC>M)%EPƅU?^TnQßdFW>4-f Q`IM׺SMM èUB!lzqn#^._QHٕm: OZMZ*EQ~^J_m6+T\0+̴j)CE#9OSmug k-fw7e8وev$,eG1Xk%UIV)*gՠɔY=ݖ$E&ْi$MSm4mBJ+ڥDIQ=SD*NS */p$IFiraC%!1AQaq?!HkU%Wa?4Gs5BScy^.QFqݮ$=sf3x*#SS.Xt<| Lb`ȵ;Opz +o,t1hbjSGXsRL1ˀ?vؕI N/`XnVW#KcǹygNF߳2 F۹SS;F1S/PLvsLQXq=ຈuT=Dj\J. -dK_re$BnL\kf%]Ea|g+ ޣ&4KFs VK ]ES5,CȕlSȗ:<|%0#P[5[]=, x:5uF"#|\Cq ]^&y'11NW0p~\`b]C*ܻ+6h]kLqG.`hu22۞2`q[JJ 7p GERp8R6Br,3< =DǨm~e:#Y(mZe!\;1]^b,p.Qh=ia^V^{kj # =UX8C4li{`Eۋ+ Ǒ4S<+˙C 0)lT!`?I !1A0?\UhBhʢ 0hL}_b{}q+Q>M1ɿO%!1AQaq?) j_16\N:0^߸]Z:0Tٚ5pFt x? 3 AY, Q(ٰJK/kiE0!̹hn^״pj W 72?j/gHrxI(apPsG#+r<1{4ޤF"*6V/6}t' syٙ=ݬY(.@3eSGͣ# ! =Xo`Ah߼ z<$Qw]qAM٬zw["  3TAE#qՈGo4ǂ) Zqqv ݉tyZ5¾?8ۜnU=;K cUjTY '=E%X=UR}fV>z l?[ o̓7*'((ie#Q6L)?ΩpG!pEV1CXppf GJbΙ/6њ9[M$߹6N k0TsE-yFq,`P ֩bC6#vb+~Q.i<TΩĶV+Ft3 0׎".XVdxݛ,F=!F ;F@4a Kk+xK`e:++,{e )k+@&E(Q" CXiP+1w?0_ˌ"m*kl:)vt6QN,O,J.,nʡ^ij/.m 06Q5uhD`*89spYr)p&\/gLJ}jXH0H]!V:-QbqNs .0J1Ҁ3_6R/lӈao~@F\WtO+ ܡtY}}c Ҁ½S%nz5gbTFxV:vwO [f,֥#B/Q.6cAZ=Q.[ 4`!^\BUN`j*|~ n^m5[xVOw k^-zdLLS mZ(DxK9E߈|CI|WXqu}"YYH*-P ٕ:{A ^b1#mLq4!w_V^ۏvW&ũpZEnʷQ=2V}ePCb.|{T"{LBjyoCR—qR fͿYUܱ-*w"p9` !j4jK"SK}.ŹFzGrU@_C z mP)շ.Ecܮ Z}bv#$X^WB&N 0.^}f9b9X p!0ܱn" ,"䈰eusH9[)պ@e)5+h5Bх밄J*yYP mq A4ȴ0JIi`U{BT(..*r3(T@!Ph樭\#4xf/%s&+I>`a-_Q`d,L#n*QX9l8ew{.CW9%= MVA/l*J5Z)h㧬 7p5]aPn2!Et;F[)xKTGKyblZBkCATIWV<{}=˥EH4IQϒBf@'{ bUJ ̪i~z\e5_nW|Abi[CN}}ߴgFB*߈Z.$fʪb7QxS3b Erik Colson What does Finance::Quote provide? ================================= Finance::Quote provides access to time-delayed stockquotes from a number of sources. After you've installed the pacakage, try 'perldoc Finance::Quote' for full information. Alternatively, you can 'perldoc lib/Finance/Quote.pm' before the install. How do I install this package? ============================== See the `INSTALL' file. It's very simple. I've found a bug / written a patch / have an idea. What do I do? ================================================================= Well, you could always mail it to , which is read by all the active developers. Alternatively, you might wish to visit . How do I download the most recent copy of Finance::Quote? ========================================================= You can find all releases of Finance::Quote at: . You might also wish to consider subscribing to finance-quote-news, which can be done from: . How can I get a copy of the current CVS development tree? ========================================================= You can't. The CVS repo has been ported to GIT as of version 1.13_01. How can I get a copy of the current GIT development tree? ========================================================= The GIT repository is available at: . Where can I find more information? ================================== Try the Finance::Quote webpage. There are lots of goodies there. http://finance-quote.sourceforge.net/ Finance000755001750001750 013202072256 14275 5ustar00ecec000000000000Finance-Quote-1.47/libQuote.pm100644001750001750 11555513202072256 16144 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance#!/usr/bin/perl -w # # Copyright (C) 1998, Dj Padzensky # Copyright (C) 1998, 1999 Linas Vepstas # Copyright (C) 2000, Yannick LE NY # Copyright (C) 2000, Paul Fenwick # Copyright (C) 2000, Brent Neal # # 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 code was developed as part of GnuCash package Finance::Quote; require 5.005; use strict; use Exporter (); use Carp; use Finance::Quote::UserAgent; use HTTP::Request::Common; use Encode; use JSON qw( decode_json ); # use Data::Dumper; use vars qw/@ISA @EXPORT @EXPORT_OK @EXPORT_TAGS $TIMEOUT %MODULES %METHODS $AUTOLOAD $ALPHAVANTAGE_CURRENCY_URL $USE_EXPERIMENTAL_UA/; # Call on the Yahoo API: # - "f=l1" should return a single value - the "Last Trade (Price Only)" # - "s=" the value of s should be "=X" # where and are currencies # Excample: http://finance.yahoo.com/d/quotes.csv?f=l1&s=AUDGBP=X # Documentation can be found here: # http://code.google.com/p/yahoo-finance-managed/wiki/csvQuotesDownload $ALPHAVANTAGE_CURRENCY_URL = "https://www.alphavantage.co/query?function=CURRENCY_EXCHANGE_RATE"; @ISA = qw/Exporter/; @EXPORT = (); @EXPORT_OK = qw/yahoo yahoo_europe fidelity troweprice asx tiaacref currency_lookup/; @EXPORT_TAGS = ( all => [@EXPORT_OK]); our $VERSION = '1.47'; # VERSION $USE_EXPERIMENTAL_UA = 0; # Autoload method for obsolete methods. This also allows people to # call methods that objects export without having to go through fetch. sub AUTOLOAD { my $method = $AUTOLOAD; $method =~ s/.*:://; # Force the dummy object (and hence default methods) to be loaded. _dummy(); # If the method we want is in %METHODS, then set up an appropriate # subroutine for it next time. if (exists($METHODS{$method})) { eval qq[sub $method { my \$this; if (ref \$_[0]) { \$this = shift; } \$this ||= _dummy(); \$this->fetch("$method",\@_); }]; carp $@ if $@; no strict 'refs'; # So we can use &$method return &$method(@_); } carp "$AUTOLOAD does not refer to a known method."; } # _load_module (private class method) # _load_module loads a module(s) and registers its various methods for # use. sub _load_modules { my $class = shift; my $baseclass = ref $class || $class; my @modules = @_; # Go to each module and use them. Also record what methods # they support and enter them into the %METHODS hash. foreach my $module (@modules) { my $modpath = "${baseclass}::${module}"; unless (defined($MODULES{$modpath})) { # Have to use an eval here because perl doesn't # like to use strings. eval "use $modpath;"; carp $@ if $@; $MODULES{$modpath} = 1; # Methodhash will continue method-name, function ref # pairs. my %methodhash = $modpath->methods; my %labelhash = $modpath->labels; # Find the labels that we can do currency conversion # on. my $curr_fields_func = $modpath->can("currency_fields") || \&default_currency_fields; my @currency_fields = &$curr_fields_func; # @currency_fields may contain duplicates. # This following chunk of code removes them. my %seen; @currency_fields=grep {!$seen{$_}++} @currency_fields; foreach my $method (keys %methodhash) { push (@{$METHODS{$method}}, { function => $methodhash{$method}, labels => $labelhash{$method}, currency_fields => \@currency_fields}); } } } } # ======================================================================= # new (public class method) # # Returns a new Finance::Quote object. If methods are asked for, then # it will load the relevant modules. With no arguments, this function # loads a default set of methods. sub new { my $self = shift; my $class = ref($self) || $self; my $this = {}; bless $this, $class; my @modules = (); my @reqmodules = (); # Requested modules. # If there's no argument list, but we have the appropriate # environment variable set, we'll use that instead. if ($ENV{FQ_LOAD_QUOTELET} and !@_) { @reqmodules = split(' ',$ENV{FQ_LOAD_QUOTELET}); } else { @reqmodules = @_; } # If we get an empty new(), or one starting with -defaults, # then load up the default methods. if (!@reqmodules or $reqmodules[0] eq "-defaults") { shift(@reqmodules) if (@reqmodules); # Default modules @modules = qw/AEX AIAHK AlphaVantage ASEGR ASX BMONesbittBurns BSERO Bourso Cdnfundlibrary Citywire CSE Currencies Deka DWS FTPortfolios Fidelity FidelityFixed FinanceCanada Fool FTfunds HU GoldMoney HEX IndiaMutual LeRevenu ManInvestments Morningstar MorningstarJP MStaruk NZX Platinum SEB SIXfunds SIXshares StockHouseCanada TSP TSX Tdefunds Tdwaterhouse Tiaacref TNetuk Troweprice Trustnet Union USFedBonds VWD ZA Cominvest Finanzpartner YahooJSON Yahoo::Asia Yahoo::Australia Yahoo::Brasil Yahoo::Europe Yahoo::NZ Yahoo::USA YahooYQL ZA_UnitTrusts/; } $this->_load_modules(@modules,@reqmodules); $this->{TIMEOUT} = $TIMEOUT if defined($TIMEOUT); $this->{FAILOVER} = 1; $this->{REQUIRED} = []; return $this; } # ======================================================================= # _dummy (private function) # # _dummy returns a Finance::Quote object. I'd really rather not have # this, but to maintain backwards compatibility we hold on to it. { my $dummy_obj; sub _dummy { return $dummy_obj ||= Finance::Quote->new; } } # ======================================================================= # sources (public object method) # # sources returns a list of sources which can be passed to fetch to # obtain information. # # Usage: @sources = $quoter->sources(); # $sourceref = $quoter->sources(); sub sources { return(wantarray ? keys %METHODS : [keys %METHODS]); } # ======================================================================= # currency (public object method) # # currency allows the conversion of one currency to another. # # Usage: $quoter->currency("USD","AUD"); # $quoter->currency("15.95 USD","AUD"); # # undef is returned upon error. sub currency { my $this = shift if (ref($_[0])); $this ||= _dummy(); my ($from, $to) = @_; return undef unless ($from and $to); $from =~ s/^\s*(\d*\.?\d*)\s*//; my $amount = $1 || 1; # Don't know if these have to be in upper case, but it's # better to be safe than sorry. $to = uc($to); $from = uc($from); return $amount if ($from eq $to); # Trivial case. my $ua = $this->user_agent; my $ALPHAVANTAGE_API_KEY = $ENV{'ALPHAVANTAGE_API_KEY'}; return undef unless ( defined $ALPHAVANTAGE_API_KEY ); my $reply = $ua->request(GET "${ALPHAVANTAGE_CURRENCY_URL}" . "&from_currency=" . ${from} . "&to_currency=" . ${to} . "&apikey=" . ${ALPHAVANTAGE_API_KEY} ); my $code = $reply->code; my $desc = HTTP::Status::status_message($code); return undef unless ($code == 200); my $body = $reply->content; my $json_data = JSON::decode_json $body; if ( !$json_data || $json_data->{'Error Message'} ) { return undef; } my $exchange_rate = $json_data->{'Realtime Currency Exchange Rate'}->{'5. Exchange Rate'}; { local $^W = 0; # Avoid undef warnings. # We force this to a number to avoid situations where # we may have extra cruft, or no amount. return undef unless ($exchange_rate+0); } if ( $exchange_rate < 0.001 ) { # exchange_rate is too little. we'll get more accuracy by using # the inverse rate and inverse it my $inverse_rate = $this->currency( $to, $from ); { local $^W = 0; return undef unless ( $exchange_rate + 0 ); } $exchange_rate = int( 100000000 / $inverse_rate + .5 ) / 100000000; } return ($exchange_rate * $amount); } # ======================================================================= # currency_lookup (public object method) # # search for available currency codes # # Usage: $quoter->currency_lookup({ name => qr/australia/i }); # $quoter->currency_lookup( code => 'EU' ); # $quoter->currency_lookup( name => 'Euro', code => qr/eu/i ); # $quoter->currency_lookup(); # # If more than one lookup parameter is given all must match for # a currency to match. # # undef is returned upon error. sub currency_lookup { my $this = shift if (ref $_[0]); $this ||= _dummy(); # Validate parameters my %valid_params = map { $_ => 1 } qw( name code ); my %params = @_; my $param_errors = 0; for my $key ( keys %params ) { if ( ! exists $valid_params{$key} ) { warn "Invalid parameter: ${key}"; $param_errors++; } } return undef if $param_errors > 0; # Retrieve known currencies my $known_currencies = Finance::Quote::Currencies::known_currencies(); # Return currencies based on parameters my $returned_currencies = {}; if ( scalar keys %params == 0 ) { $returned_currencies = $known_currencies; } else { for my $code ( keys %{$known_currencies} ) { # Make sure all parameters match my $matched = 0; if ( exists $params{name} && _smart_compare( $known_currencies->{$code}->{name}, $params{name} ) ) { $matched++; } if ( exists $params{code} && _smart_compare( $code, $params{code} ) ) { $matched++; } if ( $matched == scalar keys %params ) { $returned_currencies->{$code} = $known_currencies->{$code} } } } return $returned_currencies; } # _smart_compare (private method function) # # This function compares values where the method depends on the # type of the second parameter. # regex : compare as regex # scalar : test for substring match sub _smart_compare { my ($val1, $val2) = @_; if ( ref $val2 eq 'Regexp' ) { return $val1 =~ $val2; } else { return index($val1, $val2) > -1 } } # ======================================================================= # set_currency (public object method) # # set_currency allows information to be requested in the specified # currency. If called with no arguments then information is returned # in the default currency. # # Requesting stocks in a particular currency increases the time taken, # and the likelyhood of failure, as additional operations are required # to fetch the currency conversion information. # # This method should only be called from the quote object unless you # know what you are doing. sub set_currency { my $this = shift if (ref $_[0]); $this ||= _dummy(); unless (defined($_[0])) { delete $this->{"currency"}; } else { $this->{"currency"} = $_[0]; } } # default_currency_fields (public method) # # This is a list of fields that will be automatically converted during # currency conversion. If a module provides a currency_fields() # function then that list will be used instead. sub default_currency_fields { return qw/last high low net bid ask close open day_range year_range eps div cap nav price/; } # _convert (private object method) # # This function converts between one currency and another. It expects # to receive a hashref to the information, a reference to a list # of the stocks to be converted, and a reference to a list of fields # that conversion should apply to. { my %conversion; # Conversion lookup table. sub _convert { my $this = shift; my $info = shift; my $stocks = shift; my $convert_fields = shift; my $new_currency = $this->{"currency"}; # Skip all this unless they actually want conversion. return unless $new_currency; foreach my $stock (@$stocks) { my $currency; # Skip stocks that don't have a currency. next unless ($currency = $info->{$stock,"currency"}); # Skip if it's already in the same currency. next if ($currency eq $new_currency); # Lookup the currency conversion if we haven't # already. unless (exists $conversion{$currency,$new_currency}) { $conversion{$currency,$new_currency} = $this->currency($currency,$new_currency); } # Make sure we have a reasonable currency conversion. # If we don't, mark the stock as bad. unless ($conversion{$currency,$new_currency}) { $info->{$stock,"success"} = 0; $info->{$stock,"errormsg"} = "Currency conversion failed."; next; } # Okay, we have clean data. Convert it. Ideally # we'd like to just *= entire fields, but # unfortunately some things (like ranges, # capitalisation, etc) don't take well to that. # Hence we pull out any numbers we see, convert # them, and stick them back in. That's pretty # yucky, but it works. foreach my $field (@$convert_fields) { next unless (defined $info->{$stock,$field}); $info->{$stock,$field} = $this->scale_field($info->{$stock,$field},$conversion{$currency,$new_currency}); } # Set the new currency. $info->{$stock,"currency"} = $new_currency; } } } # ======================================================================= # Helper function that can scale a field. This is useful because it # handles things like ranges "105.4 - 108.3", and not just straight fields. # # The function takes a string or number to scale, and the factor to scale # it by. For example, scale_field("1023","0.01") would return "10.23". sub scale_field { shift if ref $_[0]; # Shift off the object, if there is one. my ($field, $scale) = @_; my @chunks = split(/([^0-9.])/,$field); for (my $i=0; $i < @chunks; $i++) { next unless $chunks[$i] =~ /\d/; $chunks[$i] *= $scale; } return join("",@chunks); } # ======================================================================= # Timeout code. If called on a particular object, then it sets # the timout for that object only. If called as a class method # (or as Finance::Quote::timeout) then it sets the default timeout # for all new objects that will be created. sub timeout { if (@_ == 1 or !ref($_[0])) { # Direct or class call. return $TIMEOUT = $_[0]; } # Otherwise we were called through an object. Yay. # Set the timeout in this object only. my $this = shift; return $this->{TIMEOUT} = shift; } # ======================================================================= # failover (public object method) # # This sets/gets whether or not it's acceptable to use failover techniques. sub failover { my $this = shift; my $value = shift; return $this->{FAILOVER} = $value if (defined($value)); return $this->{FAILOVER}; } # ======================================================================= # require_labels (public object method) # # Require_labels indicates which labels are required for lookups. Only methods # that have registered all the labels specified in the list passed to # require_labels() will be called. # # require_labels takes a list of required labels. When called with no # arguments, the require list is cleared. # # This method always succeeds. sub require_labels { my $this = shift; my @labels = @_; $this->{REQUIRED} = \@labels; return; } # _require_test (private object method) # # This function takes an array. It returns true if all required # labels appear in the arrayref. It returns false otherwise. # # This function could probably be made more efficient. sub _require_test { my $this = shift; my %available; @available{@_} = (); # Ooooh, hash-slice. :) my @required = @{$this->{REQUIRED}}; return 1 unless @required; for (my $i = 0; $i < @required; $i++) { return 0 unless exists $available{$required[$i]}; } return 1; } # ======================================================================= # fetch (public object method) # # Fetch is a wonderful generic fetcher. It takes a method and stuff to # fetch. It's a nicer interface for when you have a list of stocks with # different sources which you wish to deal with. sub fetch { my $this = shift if ref ($_[0]); $this ||= _dummy(); my $method = lc(shift); my @stocks = @_; unless (exists $METHODS{$method}) { carp "Undefined fetch-method $method passed to ". "Finance::Quote::fetch"; return; } # Failover code. This steps through all availabe methods while # we still have failed stocks to look-up. This loop only # runs a single time unless FAILOVER is defined. my %returnhash = (); foreach my $methodinfo (@{$METHODS{$method}}) { my $funcref = $methodinfo->{"function"}; next unless $this->_require_test(@{$methodinfo->{"labels"}}); my @failed_stocks = (); %returnhash = (%returnhash,&$funcref($this,@stocks)); foreach my $stock (@stocks) { push(@failed_stocks,$stock) unless ($returnhash{$stock,"success"}); } $this->_convert(\%returnhash,\@stocks, $methodinfo->{"currency_fields"}); last unless $this->{FAILOVER}; last unless @failed_stocks; @stocks = @failed_stocks; } return wantarray() ? %returnhash : \%returnhash; } # ======================================================================= # user_agent (public object method) # # Returns a LWP::UserAgent which conforms to the relevant timeouts, # proxies, and other settings on the particular Finance::Quote object. # # This function is mainly intended to be used by the modules that we load, # but it can be used by the application to directly play with the # user-agent settings. sub user_agent { my $this = shift; return $this->{UserAgent} if $this->{UserAgent}; my $ua; if ($USE_EXPERIMENTAL_UA) { $ua = Finance::Quote::UserAgent->new; } else { $ua = LWP::UserAgent->new; } $ua->timeout($this->{TIMEOUT}) if defined($this->{TIMEOUT}); $ua->env_proxy; $this->{UserAgent} = $ua; return $ua; } # ======================================================================= # parse_csv (public object method) # # Grabbed from the Perl Cookbook. Parsing csv isn't as simple as you thought! # sub parse_csv { shift if (ref $_[0]); # Shift off the object if we have one. my $text = shift; # record containing comma-separated values my @new = (); push(@new, $+) while $text =~ m{ # the first part groups the phrase inside the quotes. # see explanation of this pattern in MRE "([^\"\\]*(?:\\.[^\"\\]*)*)",? | ([^,]+),? | , }gx; push(@new, undef) if substr($text, -1,1) eq ','; return @new; # list of values that were comma-separated } # ======================================================================= # parse_csv_semicolon (public object method) # # Grabbed from the Perl Cookbook. Parsing csv isn't as simple as you thought! # sub parse_csv_semicolon { shift if (ref $_[0]); # Shift off the object if we have one. my $text = shift; # record containing comma-separated values my @new = (); push(@new, $+) while $text =~ m{ # the first part groups the phrase inside the quotes. # see explanation of this pattern in MRE "([^\"\\]*(?:\\.[^\"\\]*)*)";? | ([^;]+);? | ; }gx; push(@new, undef) if substr($text, -1,1) eq ';'; return @new; # list of values that were comma-separated } # ======================================================================= # store_date (public object method) # # Given the various pieces of a date, this functions figure out how to # store them in both the pre-existing US date format (mm/dd/yyyy), and # also in the ISO date format (yyyy-mm-dd). This function expects to # be called with the arguments: # # (inforef, symbol_name, data_hash) # # The components of date hash can be any of: # # usdate - A date in mm/dd/yy or mm/dd/yyyy # eurodate - A date in dd/mm/yy or dd/mm/yyyy # isodate - A date in yy-mm-dd or yyyy-mm-dd # year - The year in yyyy # month - The month in mm or mmm format (i.e. 07 or Jul) # day - The day # today - A flag to indicate todays date should be used. # # The separator for the *date forms is ignored. It can be any # non-alphanumeric character. Any combination of year, month, and day # values can be provided. Missing fields are filled in based upon # today's date. # sub store_date { my $this = shift; my $inforef = shift; my $symbol = shift; my $piecesref = shift; my ($year, $month, $day, $this_month, $year_specified); my %mnames = (jan => 1, feb => 2, mar => 3, apr => 4, may => 5, jun => 6, jul => 7, aug => 8, sep => 9, oct =>10, nov =>11, dec =>12); # printf "In store_date\n"; # print "inforef $inforef\n"; # print "piecesref $piecesref\n"; # foreach my $key (keys %$piecesref) { # printf (" %s: %s\n", $key, $piecesref->{$key}); # } # Default to today's date. ($month, $day, $year) = (localtime())[4,3,5]; $month++; $year += 1900; $this_month = $month; $year_specified = 0; # Proces the inputs if (defined $piecesref->{isodate}) { ($year, $month, $day) = ($piecesref->{isodate} =~ m/(\d+)\W+(\w+)\W+(\d+)/); $year += 2000 if $year < 100; $year_specified = 1; # printf ("ISO Date %s: Year %d, Month %s, Day %d\n", $piecesref->{isodate}, $year, $month, $day); } if (defined $piecesref->{usdate}) { ($month, $day, $year) = ($piecesref->{usdate} =~ /(\w+)\W+(\d+)\W+(\d+)/); $year += 2000 if $year < 100; $year_specified = 1; # printf ("US Date %s: Month %s, Day %d, Year %d\n", $piecesref->{usdate}, $month, $day, $year); } if (defined $piecesref->{eurodate}) { ($day, $month, $year) = ($piecesref->{eurodate} =~ /(\d+)\W+(\w+)\W+(\d+)/); $year += 2000 if $year < 100; $year_specified = 1; # printf ("Euro Date %s: Day %d, Month %s, Year %d\n", $piecesref->{eurodate}, $day, $month, $year); } if (defined ($piecesref->{year})) { $year = $piecesref->{year}; $year += 2000 if $year < 100; $year_specified = 1; } $month = $piecesref->{month} if defined ($piecesref->{month}); $month = $mnames{lc(substr($month,0,3))} if ($month =~ /\D/); $day = $piecesref->{day} if defined ($piecesref->{day}); $year-- if (($year_specified == 0) && ($this_month < $month)); $inforef->{$symbol, "date"} = sprintf "%02d/%02d/%04d", $month, $day, $year; $inforef->{$symbol, "isodate"} = sprintf "%04d-%02d-%02d", $year, $month, $day; } sub isoTime { my ($self,$timeString) = @_ ; $timeString =~ tr/ //d ; $timeString = uc $timeString ; my $retTime = "00:00"; # return zero time if unparsable input if ($timeString=~m/^(\d+)[\.:UH](\d+)(AM|PM)?/) { my ($hours,$mins)= ($1-0,$2-0) ; $hours-=12 if ($hours==12); $hours+=12 if ($3 && ($3 eq "PM")) ; if ($hours>=0 && $hours<=23 && $mins>=0 && $mins<=59 ) { $retTime = sprintf ("%02d:%02d", $hours, $mins) ; } } return $retTime; } # If $str ends with a B like "20B" or "1.6B" then expand it as billions like # "20000000000" or "1600000000". # # This is done with string manipulations so floating-point rounding doesn't # produce spurious digits for values like "1.6" which aren't exactly # representable in binary. # # Is "B" for billions the only abbreviation from Yahoo? # Could extend and rename this if there's also millions or thousands. # # For reference, if the value was just for use within perl then simply # substituting to exponential "1.5e9" might work. But expanding to full # digits seems a better idea as the value is likely to be printed directly # as a string. sub B_to_billions { my ($self,$str) = @_; ### B_to_billions(): $str if ($str =~ s/B$//i) { $str = $self->decimal_shiftup ($str, 9); } return $str; } # $str is a number like "123" or "123.45" # return it with the decimal point moved $shift places to the right # must have $shift>=1 # eg. decimal_shiftup("123",3) -> "123000" # decimal_shiftup("123.45",1) -> "1234.5" # decimal_shiftup("0.25",1) -> "2.5" # sub decimal_shiftup { my ($self, $str, $shift) = @_; # delete decimal point and set $after to count of chars after decimal. # Leading "0" as in "0.25" is deleted too giving "25" so as not to end up # with something that might look like leading 0 for octal. my $after = ($str =~ s/(?:^0)?\.(.*)/$1/ ? length($1) : 0); $shift -= $after; # now $str is an integer and $shift is relative to the end of $str if ($shift >= 0) { # moving right, eg. "1234" becomes "12334000" return $str . ('0' x $shift); # extra zeros appended } else { # negative means left, eg. "12345" becomes "12.345" # no need to prepend zeros since demanding initial $shift>=1 substr ($str, $shift,0, '.'); # new '.' at shifted spot from end return $str; } } # Dummy destroy function to avoid AUTOLOAD catching it. sub DESTROY { return; } 1; __END__ =head1 NAME Finance::Quote - Get stock and mutual fund quotes from various exchanges =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; $q->timeout(60); $conversion_rate = $q->currency("AUD","USD"); $q->set_currency("EUR"); # Return all info in Euros. $q->require_labels(qw/price date high low volume/); $q->failover(1); # Set failover support (on by default). %quotes = $q->fetch("nasdaq",@stocks); $hashref = $q->fetch("nyse",@stocks); =head1 DESCRIPTION This module gets stock quotes from various internet sources, including Yahoo! Finance, Fidelity Investments, and the Australian Stock Exchange. There are two methods of using this module -- a functional interface that is deprecated, and an object-orientated method that provides greater flexibility and stability. With the exception of straight currency exchange rates, all information is returned as a two-dimensional hash (or a reference to such a hash, if called in a scalar context). For example: %info = $q->fetch("australia","CML"); print "The price of CML is ".$info{"CML","price"}; The first part of the hash (eg, "CML") is referred to as the stock. The second part (in this case, "price") is referred to as the label. =head2 LABELS When information about a stock is returned, the following standard labels may be used. Some custom-written modules may use labels not mentioned here. If you wish to be certain that you obtain a certain set of labels for a given stock, you can specify that using require_labels(). name Company or Mutual Fund Name last Last Price high Highest trade today low Lowest trade today date Last Trade Date (MM/DD/YY format) time Last Trade Time net Net Change p_change Percent Change from previous day's close volume Volume avg_vol Average Daily Vol bid Bid ask Ask close Previous Close open Today's Open day_range Day's Range year_range 52-Week Range eps Earnings per Share pe P/E Ratio div_date Dividend Pay Date div Dividend per Share div_yield Dividend Yield cap Market Capitalization ex_div Ex-Dividend Date. nav Net Asset Value yield Yield (usually 30 day avg) exchange The exchange the information was obtained from. success Did the stock successfully return information? (true/false) errormsg If success is false, this field may contain the reason why. method The module (as could be passed to fetch) which found this information. type The type of equity returned If all stock lookups fail (possibly because of a failed connection) then the empty list may be returned, or undef in a scalar context. =head1 INSTALLATION To install this module, run the following commands: perl Makefile.PL make make test make install For more detailed instructions, please see the INSTALL file. =head1 SUPPORT AND DOCUMENTATION After installing, you can find documentation for this module with the perldoc command. perldoc Finance::Quote You can also look for information at: =over =item RT, CPAN's request tracker http://rt.cpan.org/NoAuth/Bugs.html?Dist=Finance-Quote =item AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/Finance-Quote =item CPAN Ratings http://cpanratings.perl.org/d/Finance-Quote =item Search CPAN http://search.cpan.org/dist/Finance-Quote =item The Finance::Quote home page http://finance-quote.sourceforge.net/ =item The Finance::YahooQuote home page http://www.padz.net/~djpadz/YahooQuote/ =item The GnuCash home page http://www.gnucash.org/ =back =head1 AVAILABLE METHODS =head2 NEW my $q = Finance::Quote->new; my $q = Finance::Quote->new("ASX"); my $q = Finance::Quote->new("-defaults", "CustomModule"); With no arguents, this creates a new Finance::Quote object with the default methods. If the environment variable FQ_LOAD_QUOTELET is set, then the contents of FQ_LOAD_QUOTELET (split on whitespace) will be used as the argument list. This allows users to load their own custom modules without having to change existing code. If you do not want users to be able to load their own modules at run-time, pass an explicit argumetn to ->new() (usually "-defaults"). When new() is passed one or more arguments, an object is created with only the specified modules loaded. If the first argument is "-defaults", then the default modules will be loaded first, followed by any other specified modules. Note that the FQ_LOAD_QUOTELET environment variable must begin with "-defaults" if you wish the default modules to be loaded. Any modules specified will automatically be looked for in the Finance::Quote:: module-space. Hence, Finance::Quote->new("ASX") will load the module Finance::Quote::ASX. Please read the Finance::Quote hacker's guide for information on how to create new modules for Finance::Quote. =head2 FETCH my %stocks = $q->fetch("usa","IBM","MSFT","LNUX"); my $hashref = $q->fetch("usa","IBM","MSFT","LNUX"); Fetch takes an exchange as its first argument. The second and remaining arguments are treated as stock-names. In the standard Finance::Quote distribution, the following exchanges are recognised: australia Australan Stock Exchange dwsfunds Deutsche Bank Gruppe funds fidelity Fidelity Investments tiaacref TIAA-CREF troweprice T. Rowe Price europe European Markets canada Canadian Markets usa USA Markets nyse New York Stock Exchange nasdaq NASDAQ uk_unit_trusts UK Unit Trusts vanguard Vanguard Investments vwd Vereinigte Wirtschaftsdienste GmbH When called in an array context, a hash is returned. In a scalar context, a reference to a hash will be returned. The structure of this hash is described earlier in this document. The fetch method automatically arranges for failover support and currency conversion if requested. If you wish to fetch information from only one particular source, then consult the documentation of that sub-module for further information. =head2 SOURCES my @sources = $q->sources; my $listref = $q->sources; The sources method returns a list of sources that have currently been loaded and can be passed to the fetch method. If you're providing a user with a list of sources to choose from, then it is recommended that you use this method. =head2 CURRENCY_LOOKUP $currencies_by_name = $q->currency_lookup( name => 'Australian' ); $currencies_by_code = $q->currency_lookup( code => qr/^b/i ); $currencies_by_both = $q->currency_lookup( name => qr/pound/i , code => 'GB' ); The currency_lookup method provides a search against the known currencies. The list of currencies is based on the available currencies in the Yahoo Currency Converter (the list is stored within the module as the list should be fairly static). The lookup can be done by currency name (ie "Australian Dollar"), by code (ie "AUD") or both. You can pass either a scalar or regular expression as a search value - scalar values are matched by substring while regular expressions are matched as-is (no changes are made to the expression). See L (and the C test file) for a way to make sure that the stored currency list is up to date. =head2 CURRENCY $conversion_rate = $q->currency("USD","AUD"); The currency method takes two arguments, and returns a conversion rate that can be used to convert from the first currency into the second. In the example above, we've requested the factor that would convert US dollars into Australian dollars. The currency method will return a false value if a given currency conversion cannot be fetched. At the moment, currency rates are fetched from Yahoo!, and the information returned is governed by Yahoo!'s terms and conditions. See Finance::Quote::Yahoo for more information. =head2 SET_CURRENCY $q->set_currency("FRF"); # Get results in French Francs. The set_currency method can be used to request that all information be returned in the specified currency. Note that this increases the chance stock-lookup failure, as remote requests must be made to fetch both the stock information and the currency rates. In order to improve reliability and speed performance, currency conversion rates are cached and are assumed not to change for the duration of the Finance::Quote object. At this time, currency conversions are only looked up using Yahoo!'s services, and hence information obtained with automatic currency conversion is bound by Yahoo!'s terms and conditions. =head2 FAILOVER $q->failover(1); # Set automatic failover support. $q->failover(0); # Disable failover support. The failover method takes a single argument which either sets (if true) or unsets (if false) automatic failover support. If automatic failover support is enabled (default) then multiple information sources will be tried if one or more sources fail to return the requested information. Failover support will significantly increase the time spent looking for a non-existant stock. If the failover method is called with no arguments, or with an undefined argument, it will return the current failover state (true/false). =head2 USER_AGENT my $ua = $q->user_agent; The user_agent method returns the LWP::UserAgent object that Finance::Quote and its helpers use. Normally this would not be useful to an application, however it is possible to modify the user-agent directly using this method: $q->user_agent->timeout(10); # Set the timeout directly. =head2 SCALE_FIELD my $pounds = $q->scale_field($item_in_pence,0.01); The scale_field() function is a helper that can scale complex fields such as ranges (eg, "102.5 - 103.8") and other fields where the numbers should be scaled but any surrounding text preserved. It's most useful in writing new Finance::Quote modules where you may retrieve information in a non-ISO4217 unit (such as cents) and would like to scale it to a more useful unit (like dollars). =head2 ISOTIME $q->isoTime("11:39PM"); # returns "23:39" $q->isoTime("9:10 AM"); # returns "09:10" This function will return a isoformatted time =head1 ENVIRONMENT Finance::Quote respects all environment that your installed version of LWP::UserAgent respects. Most importantly, it respects the http_proxy environment variable. =head1 BUGS There are no ways for a user to define a failover list. The two-dimensional hash is a somewhat unwieldly method of passing around information when compared to references. A future release is planned that will allow for information to be returned in a more flexible $hash{$stock}{$label} style format. There is no way to override the default behaviour to cache currency conversion rates. =head1 COPYRIGHT & LICENSE Copyright 1998, Dj Padzensky Copyright 1998, 1999 Linas Vepstas Copyright 2000, Yannick LE NY (update for Yahoo Europe and YahooQuote) Copyright 2000-2001, Paul Fenwick (updates for ASX, maintainence and release) Copyright 2000-2001, Brent Neal (update for TIAA-CREF) Copyright 2000 Volker Stuerzl (DWS and VWD support) Copyright 2000 Keith Refson (Trustnet support) Copyright 2001 Rob Sessink (AEX support) Copyright 2001 Leigh Wedding (ASX updates) Copyright 2001 Tobias Vancura (Fool support) Copyright 2001 James Treacy (TD Waterhouse support) Copyright 2008 Erik Colson (isoTime) 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. Currency information fetched through this module is bound by Yahoo!'s terms and conditons. Other copyrights and conditions may apply to data fetched through this module. Please refer to the sub-modules for further information. =head1 AUTHORS Dj Padzensky , PadzNet, Inc. Linas Vepstas Yannick LE NY Paul Fenwick Brent Neal Volker Stuerzl Keith Refson Rob Sessink Leigh Wedding Tobias Vancura James Treacy Bradley Dean Erik Colson The Finance::Quote home page can be found at http://finance-quote.sourceforge.net/ The Finance::YahooQuote home page can be found at http://www.padz.net/~djpadz/YahooQuote/ The GnuCash home page can be found at http://www.gnucash.org/ =head1 SEE ALSO Finance::Quote::AEX, Finance::Quote::ASX, Finance::Quote::Cdnfundlibrary, Finance::Quote::DWS, Finance::Quote::Fidelity, Finance::Quote::FinanceCanada, Finance::Quote::Fool, Finance::Quote::FTPortfolios, Finance::Quote::Tdefunds, Finance::Quote::Tdwaterhouse, Finance::Quote::Tiaacref, Finance::Quote::Troweprice, Finance::Quote::Trustnet, Finance::Quote::VWD, Finance::Quote::Yahoo::Australia, Finance::Quote::Yahoo::Europe, Finance::Quote::Yahoo::USA, LWP::UserAgent You should have also received the Finance::Quote hacker's guide with this package. Please read it if you are interested in adding extra methods to this package. The hacker's guide can also be found on the Finance::Quote website, http://finance-quote.sourceforge.net/ =cut Examples000755001750001750 013202072256 13742 5ustar00ecec000000000000Finance-Quote-1.47chkshares.pl100755001750001750 247413202072256 16424 0ustar00ecec000000000000Finance-Quote-1.47/Examples#!/usr/bin/perl -w use strict; use lib '../lib'; use Finance::Quote qw/asx/; =head1 NAME chkshares.pl - Check share information. =head1 USAGE chkshares.pl australia TLS CML ITE =head1 NOTES Example program. Demonstrates how to use one of the interface to Finance::Quote. The first argument must be the market. =cut my ($name, $date, $last, $p_change, $high, $low, $volume, $close); format STDOUT_TOP = STOCK REPORT TICKER DATE LAST %CHANGE HIGH LOW VOLUME CLOSE ---------------------------------------------------------------------------------- . format STDOUT = @<<<<<< @>>>>>>>>>> @####.### @###.### @####.### @####.### @>>>>>>>> @####.### $name, $date, $last, $p_change, $high, $low, $volume, $close . my $quoter = Finance::Quote->new(); my $market = shift || die "Usage: $0 market stocks\n"; my %quote = $quoter->fetch($market,@ARGV); foreach my $code (@ARGV) { unless ($quote{$code,"success"}) { warn "Lookup of $code failed - ".$quote{$code,"errormsg"}."\n"; next; } $name = $code; $date = $quote{$code,'date'}; $last = $quote{$code,'last'}; $p_change = $quote{$code,'p_change'}; $high = $quote{$code,'high'}; $low = $quote{$code,'low'}; $volume = $quote{$code,'volume'}; $close = $quote{$code,'close'}; write; } stockdump.pl100755001750001750 76413202072256 16442 0ustar00ecec000000000000Finance-Quote-1.47/Examples#!/usr/bin/perl -w use strict; use lib '../lib'; use Finance::Quote; use Data::Dumper; use Getopt::Std; # A very very simple script. Takes a source and a symbol, looks it up, # and dumps it to STDOUT. Useful for debugging. my %options = ('c' => ''); getopts('c:',\%options); die "Usage: $0 [-c currency] source symbol\n" unless (defined $ARGV[1]); my $q = Finance::Quote->new; if ($options{'c'}) { $q->set_currency($options{'c'}); } my %quotes = $q->fetch(@ARGV); print Dumper(\%quotes); developer.html100644001750001750 1312613202072256 16506 0ustar00ecec000000000000Finance-Quote-1.47/htdocs Finance::Quote Homepage
Finance :: Quote
Button Home
Button Documentation
Button Discussion Groups and Mailing Lists
Button Download
Button SourceForge Page

Important note

After the release 1.13 we took two important decisions :

  • Current evolution of development tools made us port the repository to Git
  • Since Finance::Quote releases are available through CPAN we also decided to make full use of the tools available on the Cpan platform.
  • Please note that we are in the early stages of the implementation of these changes. Some of the work has already been done, but some data has still to be ported or disgarded. Please take a look at this page for further evolution. Reports will also be posted to the developers mailing-list. We sincerely apologize for any inconvenience these changes may cause.

    Bug-tracking

    Bugs can be submitted and tracked via Cpan's RT bug-tracking system. Before submitting a bug, please make sure that someone else has not submitted the bug already.

    Bugs posted on the Sourceforge's bug tracking system after 1.7.2007 are ported to RT. Older bug reports (prior to release 1.13) will certainly be disgarded. Don't use the Sourceforge's BTS for new bug reports as those won't be checked.

    Patches

    Patches must be submitted as file attachments to bug reports (see above).

    Patches submitted on Sourceforge's site after 1.7.2007 will eventually be lookad at. Older patches will certainly be disgarded.

    For reference, we'll mention the link to the SourceForge's patch manager. Don't use it for new patches as those won't be checked.

    Before submitting a patch please make sure that you have the most up-to-date version of Finance::Quote, and that nobody has submitted an equivalent patch already.

    Mailing-lists

    A developer's mailing list exists for those people who are using or developing Finance::Quote. For more information, see our Discussion Groups and Mailing Lists page.

    Git

    Anonymous access to the development branch is available for those wishing to use the development branch of Finance::Quote. Details on anonymous Git access can be found here.

    CVS

    The development repository has been ported to Git. Please note that while CVS is still available, updates starting at version 1.13 won't be sent to the CVS repository.

    Details on anonymous CVS access can be found here.

    Hacker's Guide

    The Hacker's Guide contains information on how to extend Finance::Quote to make use of your own custom information sources. The most recent version of the Hacker's Guide can be found here.


    Stylesheet.css100644001750001750 154013202072256 16453 0ustar00ecec000000000000Finance-Quote-1.47/htdocsul { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12pt; font-style: normal; color: #FFFFFF} p,li { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12pt; font-style: normal; color: #FFFFFF} h1 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 18pt; font-style: normal; color: #FFFFFF; background-position: center} h2 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 16pt; font-style: normal; color: #FFFFFF} h3 { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14pt; font-style: normal; color: #FFFFFF} .footer { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9pt; color: #FFFFFF} a { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 12pt; color: #AAAA77} h2[class^=new], p[class^=new], li[class^=new] { color : red }bg2.jpg100644001750001750 2545013202072256 16217 0ustar00ecec000000000000Finance-Quote-1.47/htdocs/ImagesJFIF``C   (1#%(:3=<9387@H\N@DWE78PmQW_bghg>Mqypdx\egcC//cB8Bcccccccccccccccccccccccccccccccccccccccccccccccccc-,"5!1A"Qaq2#BR$3brC!1 ?Smj<13 fLL"*opX1ݬ LHj6fhYfϊ qFϊuu6$cVyA%~`f ¸;Vbi,R5 IR0h\kQx拺՗PRt#";J 9//jwAg `P-mv=0 B@2$LӥU! 1W~3@M'sJ@?6sZ5CH`cPQm\#$aG xڋ69,dwC`HuNd8čΐ@M䞀F4MV,p@(C2+8]f )TeA&ʫp&.1D11AF}l"'r"0c';OA/P2` 2yVke.!h$ݿp0x[ҩd 抟z]vą[.\-P`uЈoTï'ܖk$I5 m=K ɪF#W55Y ǹ:Ayah0'q qedu -'Gg?aYr 6$9MWR].4(;j!U85Chx?k̰UNI.hG#UJE|(p3MdNJ0ә* #H*ld!'HոڬH'pg$%H,d5&3iUƘ;4[\I5&pm HXި O} HrOIس- $̚\j:tm&4b C3{ռ/'Y\ޮ`@T MWMam{BҦl`UmTՕ9W0~N ISV_B`"ȟд 9ZϜ;PP#mLjFx!h1'nu;*n nx$ y ˴-l f1ƒ>N&ă3A$?Ny8*ih榁IkgpE%Zcbj]GRxdRI{V9 v;P0m ] zY"B /,; 8M- 0Wqr\Kchvlm\!:IZDk,`z Nu6jB^&D.!6"@t;V`AEZV#3S&@SD;) ڠZ9ިζKq ΓI. mN-8YN{CXsCN1l4m$|w(DY4 ni TKj~EV+BTmkթ?z U4\ޡJf!V%t̓ĈO'.Np0QKvI:T4[J3M@l),jFM: EDdj{wRx  HT]CڹZ^g{nn K (Y`-1c@dޔ+2f2(.ZoMjvpIV~I)fg d6S1 tu o[,GP1AsHX8}Bӊ Y@’f[cިTޘa@ &1>,'ibaM6☰V'|R ڀ:Li8'xaC |՝a b+#jxA4i`+U?IH,@ 4.HK}38t[Vw50p=cKc(u-X T9$ad?zFreE*jHXs52ŖtRYO{df~ҩ(cQ";&ju]7ͲpNkKth,r8J@ȁޘ(Dާw@ί= E j>65v&+r6`Ft]6 ';T^;@q]mmv Eǃ8J]$5;ezvX]MM@$GR.PMGH$s>hi 9@7rbkI74j$׺@ &@J~7njbY v@A  [Kq*.^7*Kt[p(;*\>tb|oH1 l&v" dj5$hZUZB&;Kq,s6ΧU*e Vղ (s3d,  ~Ns#&84SS@\:bDNP?Dڝ|V"'`yTH$N@EIz㮠"sPZDy6A@Ϛ FzH܍ڏ 1ϊ WXsV'QҎFgS}Fnv)L 2|b1qlg5/oQ c bB>(,حǒʯfwqV5Z (W: 3OސeR Lq&w*v^^0)IT繠-i$KaYQ -6ڐu?P}RFMцP8hp{WQRI$1=%EEd@u\cwP.{L?5狥 nx5e~5pHb:̓R{`WGo]8QE ;A\W6(uf^0޺ ha q9;UJ6hkZI?&QA V֡@8##R4LuYkw}#yY-o])x=N}-ʷ=?L%[P"QK5зH>(w&yo)&ڜ0kA*AgSop*=*v4޶1AF$@w?cT=ŏS Էg8H3*.=$$eĈ '`&6E%<7Emd5~ߦ` ZUa H BC0AOb\. !% 3M}5 1'5Z.Y[`##s^_w#P0 ikCl,oj]*w&mtev*G$p*\5e;M 0IިM[yfR el!usނZյ*4 WbwIl5@%Ac[(m/M=ꖡSmjw {ژhbuÓMB1ёD0kXyZIPNwO0'NdFG4ePI%P8CX *^G,C)sZBX14`~*u$QC9[J0 \{NT˃,YHGUQFE}Pd8"VE9a;xEuW^0ԍmF5He#fAΪGPfI+)Ћ֫=}쒀@*lgT d,Gٿ Uwu#C)~ +-[(\TMA2Dbi-2lA[WCZY2cSkY"=BhV_2\`&PR-fv_pr M(,Yl5kr<⻑n`MqoQ!a8A%Uv׬`zgp!Uq\, fTݨrL(29]oL( F!,IޠyjqNT*>M4"5C#14@ւ09r 7):gk`ic0b]@E! 3*]5pHmr@nPKLhJ2҂tdus@T K+='m^F+;ŧ*Ēvx`A4܉ w"p&Gz( vڪnXF+Ԧ0jJ'"Ƶy[5c,1'Ҧ2T{*k@mn1TJ ~#5`ůˤA7wj 'T@;=UKS1ڀG'vpE+LwKog_RKSO4pr0Go^fzl+K2-';vS^ w}:no-ɨzw?E2I*j7*5k Z:!/|W=mRY'⺘.3{+PT0~{W iX +sF$ѷ-5E}Y"nX)cUD'j Ѱ)t>|P c Sm1D fx3@D1f'j]JJT`80h8+DF 蹤 |T5Pge7uh#@\p8"J6AI #ArJć4vXLFMMP;NI?oZAS;M-?WuqڂDQЎEfLTܟa i6r`G޵'H؝/59&)5ipNLfQ#4m O=G-ɼu:da>€}r&HUvL %Hzk`+30`Uql2F{j[Fz{o21 0JK+6-3QlBfl^`0bn8W2U;'sT1f&2rrSu R_ i銢7}9mSD5J.U-!K$H` 8Ȧ@"2kZYCa@"N7c? SP|( F P qPVa RABөw Ff2 L/5mEc0vw}bF\7NCn`Qw[ 8-8*(WI0x>h*:J…, H#4z+PD|fc"w(+v[I#+[ 1S2>⋎1I:]`fUY+ڔjhE#hS (, }9Lam[kNb f@JO#K`H!q'y3Ojtsgq'z`YdQɩt\G5AE2%l,$JtoԢ0tpW(H&6A"m144  (m/v.}KJOڶ=%DL 85&T,zosBUV"r#4 4TH zSQ3;bQs@!qކT''DysCv'aTAD\emG&g+{zZqXIhPdsLrQ( Ep4 &#xLoA݄aAK,ېFf=n;^ mUk0Ҋ&T]rIJ"$ KG@ }[GjANOJ'Q3 Ӝ)?ȈvwUBkQj{Օ.i;NJ#)9$h4hElE t{ QuP$Q vڃaG5_Qί= (d0* `x<EA F` 9oe:nmGI\f$T̙q j( (22 X:B#W5Q[sm84Lj`ec8̘@Ha?aB;ж4 P z(2f:4mc04m@V?PVH#z*To0/:q'RB"E9 C x+Ãl3rr4  jQR`{ (ݺH3QqeCppUژݛd[:_qS`1ޠ@"6IMNwd0y3`CGOGiH4(FڎiC*)r iQ@6#V4yC% =& iu(̡ <NvUUAc(0,3#T4~ &>GqX}M1%ڥ9(GmDMeTLdCAZVA-BLTQbu"3I{9}v)Slv/Jr)#L-8]RHI.#ā(5B``| qUT&@0jAΨ$f› 0$FsH&uV\})nBp H&̤H;ԂaIo޶:<KZ3ȫ<7F$}'E@=$.8YҬ[pc5b" bNfެq\ޢܻI(sr7=L(ic궊䚣e5`6><{Zي d6v#$>ǑVbQ&{e`7j d cjtV`ADDf4qEcqB 2jP 2|w#9$xʧQ6'EIԻΐS.* TeLֶ`8`RzA"t:qHP*Fj^ݲ RܖRD}(2b }+.l)d@#&rKt"ȦЗ0mV^PU@{D-n{(%qZb8"WKrN(ZcpDj3+] LgT28 Copyright (C) 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 Also add information on how to contact you by electronic and paper mail. If the program is interactive, make it output a short notice like this when it starts in an interactive mode: Gnomovision version 69, Copyright (C) year name of author Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. The hypothetical commands `show w' and `show c' should show the appropriate parts of the General Public License. Of course, the commands you use may be called something other than `show w' and `show c'; they could even be mouse-clicks or menu items--whatever suits your program. You should also get your employer (if you work as a programmer) or your school, if any, to sign a "copyright disclaimer" for the program, if necessary. Here is a sample; alter the names: Yoyodyne, Inc., hereby disclaims all copyright interest in the program `Gnomovision' (which makes passes at compilers) written by James Hacker. , 1 April 1989 Ty Coon, President of Vice This General Public License does not permit incorporating your program into proprietary programs. If your program is a subroutine library, you may consider it more useful to permit linking proprietary applications with the library. If this is what you want to do, use the GNU Library General Public License instead of this License. author-pod-syntax.t100644001750001750 45413202072256 16345 0ustar00ecec000000000000Finance-Quote-1.47/t#!perl BEGIN { unless ($ENV{AUTHOR_TESTING}) { print qq{1..0 # SKIP these tests are for testing by the author\n}; exit } } # This file was automatically generated by Dist::Zilla::Plugin::PodSyntaxTests. use strict; use warnings; use Test::More; use Test::Pod 1.41; all_pod_files_ok(); discussion.html100644001750001750 603113202072256 16661 0ustar00ecec000000000000Finance-Quote-1.47/htdocs Finance::Quote Discussion
    Finance :: Quote
    Button Home
    Button Documentation
    Button Bugs, Patches and Development
    Button Download
    Button SourceForge Page

    Mailing lists.

    There are two Finance::Quote mailing lists. finance-quote-devel is a high-volume list for developers and technical issues. finance-quote-news is a low-volume list for announcements only. Archives of the mailing lists, and details on how to join, can be found here.

    Discussion Forums.

    Public discussion forums, including a general discussion and help forum, can be found here.


    Quote000755001750001750 013202072256 15372 5ustar00ecec000000000000Finance-Quote-1.47/lib/FinanceZA.pm100644001750001750 1437013202072256 16427 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance/Quote#!/usr/bin/perl -w # # ZA.pm # # 2013.05.01 # Changes to table references to correct for new sharenet web page layout # Timothy Boyle # 2008.02.18 # This version corrects the data downloaded by removing spaces and converting # cent values into Rand values – this ensures that the Price Editor in GNUCash # can import the data. The rest of the module and all the hard work # remains that of Stephen Langenhoven! # Rolf Endres # # 2005.07.19 # Download of South African (ZA) stocks from sharenet # This version based largely upon FinanceCanada.pm module [any errors # are my own of course ;-) ] # Stephen Langenhoven package Finance::Quote::ZA; require 5.004; use strict; use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; our $VERSION = '1.47'; # VERSION my $SHARENET_MAINURL = ("http://www.sharenet.co.za/"); my $SHARENET_URL = ( $SHARENET_MAINURL . "jse/" ); sub methods { return ( za => \&sharenet ); } sub labels { my @labels = qw/method source name symbol currency last date isodate high low p_change/; return ( sharenet => \@labels ); } sub sharenet { my $quoter = shift; my @symbols = @_; my %info; my ( $te, $ts, $row ); my @rows; return unless @symbols; my $ua = $quoter->user_agent; foreach my $symbol (@symbols) { my $url = $SHARENET_URL . $symbol; # print "[debug]: ", $url, "\n"; my $response = $ua->request( GET $url); # print "[debug]: ", $response->content, "\n"; if ( !$response->is_success ) { $info{ $symbol, "success" } = 0; $info{ $symbol, "errormsg" } = "Error contacting URL"; next; } $te = HTML::TableExtract->new(); $te->parse( $response->content ); # print "[debug]: (parsed HTML)",$te, "\n"; unless ( $te->first_table_found() ) { # print STDERR "no tables on this page\n"; $info{ $symbol, "success" } = 0; $info{ $symbol, "errormsg" } = "Parse error"; next; } # Debug to dump all tables in HTML... # print "\n \n \n \n[debug]: ++++ ==== ++++ ==== ++++ ==== ++++ ==== START OF TABLE DUMP ++++ ==== ++++ ==== ++++ ==== ++++ ==== \n \n \n \n"; # # foreach $ts ($te->table_states) {; # # printf "\n \n \n \n[debug]: //// \\\\ //// \\\\ //// \\\\ //// \\\\ START OF TABLE %d,%d //// \\\\ //// \\\\ //// \\\\ //// \\\\ \n \n \n \n", # $ts->depth, $ts->count; # # foreach $row ($ts->rows) { # print "[debug]: ", $row->[0], " | ", $row->[1], " | ", $row->[2], " | ", $row->[3], "\n"; # } # } # # print "\n \n \n \n[debug]: ++++ ==== ++++ ==== ++++ ==== ++++ ==== END OF TABLE DUMP ++++ ==== ++++ ==== ++++ ==== ++++ ==== \n \n \n \n"; # GENERAL FIELDS $info{ $symbol, "success" } = 1; $info{ $symbol, "method" } = "sharenet"; $info{ $symbol, "symbol" } = $symbol; $info{ $symbol, "currency" } = "ZAR"; $info{ $symbol, "source" } = $SHARENET_MAINURL; # NAME $ts = $te->table_state( 2, 1 ); # new table reference if ($ts) { (@rows) = $ts->rows; $info{ $symbol, "name" } = $rows[2][1]; } $info{ $symbol, "name" } =~ tr/ //d; # DATE AND CLOSING PRICE $ts = $te->table_state( 3, 0 ); # change table for new sharenet layout # print "[debug]: ", "got this far...", "\n"; # print "[debug]: (table_state)",$ts, "\n"; if ($ts) { (@rows) = $ts->rows; # date for last trade sale, high, low # sharenet only gives the day and month. We could use today's date, but this would not # be correct over weekends and public holidays (if it matters) my $date = substr( $rows[0][0], 16, 5 ) . "/"; #extract the day/month from the string and add / # this does the same as above in a more robust fashion # my $date = $rows[0][0]; # day/month plus time plus text # $date =~ s/[^0-9\/]//g; # remove most unwanted characters # $date =~ s/\d{4}$/\//; # remove last 4 digits = time and add / for the year my $year = ( localtime() )[5] + 1900; # extract year from system time vector $date = $date . $year; # add it to the day/month # print $date, "\n"; # we now have the date of the trades as dd/mm/yyyy $quoter->store_date( \%info, $symbol, { eurodate => $date } ) ; # gives eurodate and isodate symbols # $quoter->store_date(\%info, $symbol, {today => 1}); # could use today's date # last traded price $info{ $symbol, "last" } = $rows[2][1]; $info{ $symbol, "last" } =~ tr/ //d; $info{ $symbol, "last" } = 0.01 * $info{ $symbol, "last" }; # highest price today $info{ $symbol, "high" } = $rows[16][1]; $info{ $symbol, "high" } =~ tr/ //d; $info{ $symbol, "high" } = 0.01 * $info{ $symbol, "high" }; # lowest price today $info{ $symbol, "low" } = $rows[18][1]; $info{ $symbol, "low" } =~ tr/ //d; $info{ $symbol, "low" } = 0.01 * $info{ $symbol, "low" }; # percent change from previous close $info{ $symbol, "p_change" } = $rows[10][1]; $info{ $symbol, "p_change" } =~ tr/ //d; # actual net change from previous close $info{ $symbol, "net" } = $rows[8][1]; $info{ $symbol, "net" } =~ tr/ //d; } } return wantarray() ? %info : \%info; } 1; =head1 NAME Finance::Quote::ZA - Obtain South African stock and prices from www.sharenet.co.za =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; # Don't know anything about failover yet... =head1 DESCRIPTION This module obtains information about South African Stocks from www.sharenet.co.za. =head1 LABELS RETURNED Information available from sharenet may include the following labels: method source name symbol currency date nav last price =head1 SEE ALSO Sharenet website - http://www.sharenet.co.za/ Finance::Quote =cut HU.pm100644001750001750 1526013202072256 16430 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance/Quote#!/usr/bin/perl -w # # HU.pm # # Version 0.3 - Fixed BAMOSZ website scraping and download stocks # directly from www.BET.hu # This version based on ZA.pm module # # Zoltan Levardy 2008, 2009 # Kristof Marussy 2014 package Finance::Quote::HU; require 5.005; use strict; use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; use Encode; our $VERSION = '1.47'; # VERSION my $BAMOSZ_MAINURL = "http://www.bamosz.hu/"; my $BAMOSZ_URL = $BAMOSZ_MAINURL . "alapoldal?isin="; my $BSE_MAINURL = "http://www.bet.hu/"; my $BSE_URL = $BSE_MAINURL . "topmenu/kereskedesi_adatok/product_search?isinquery="; sub methods { return ( hufund => \&bamosz, bamosz => \&bamosz, hustock => \&bse, bse => \&bse, bet => \&bse, hu => \&hu, hungary => \&hu ); } sub labels { my @fundlabels = qw/symbol method source name currency isin date isodate price last/; my @stocklabels = qw/symbol method source currency isin date isodate price open close high low p_change last/; my @alllabels = ( @stocklabels, "name" ); return ( hufund => \@fundlabels, bamosz => \@fundlabels, hustock => \@stocklabels, bse => \@stocklabels, bet => \@stocklabels, hu => \@alllabels, hungary => \@alllabels ); } sub hu { my $quoter = shift; my @symbols = @_; my %info; for my $symbol (@symbols) { my %bse_info = bse( $quoter, $symbol ); if ( $bse_info{ $symbol, "success" } ) { %info = ( %info, %bse_info ); next; } my %bamosz_info = bamosz( $quoter, $symbol ); if ( $bamosz_info{ $symbol, "success" } ) { %info = ( %info, %bamosz_info ); next; } $info{ $symbol, "success" } = 0; $info{ $symbol, "errormsg" } = "Fetch from bse or bamosz failed"; } return wantarray() ? %info : \%info; } sub bse { my $quoter = shift; my @symbols = @_; my %info; my $ua = $quoter->user_agent; for my $symbol (@symbols) { $info{ $symbol, "method" } = "bse"; $info{ $symbol, "source" } = $BSE_MAINURL; $info{ $symbol, "success" } = 0; my $url = $BSE_URL . $symbol; my $response = $ua->request( GET $url); unless ( $response->is_success ) { $info{ $symbol, "errormsg" } = "Request error"; next; } my $te = HTML::TableExtract->new( attribs => { class => "InsAdat_table" } ); $te->parse( decode_utf8( $response->content ) ); unless ( $te->first_table_found ) { $info{ $symbol, "errormsg" } = "No InsAdat_table found"; next; } my @found; TABLE_LOOP: for my $ts ( $te->tables ) { for my $row ( $ts->rows ) { my @trimmed_row = map { trim($_) } @$row; if ( $symbol eq $trimmed_row[1] || $symbol eq $trimmed_row[2] ) { @found = @trimmed_row; last TABLE_LOOP; } } } unless (@found) { $info{ $symbol, "errormsg" } = "No ticker or ISIN found"; next; } # I don't trade stocks, so I am unsure whether the data # extracted here is sensible. Please do improve this if # needed! $info{ $symbol, "symbol" } = $found[1]; $info{ $symbol, "isin" } = $found[2]; $info{ $symbol, "price" } = hu_decimal( $found[3] ); $info{ $symbol, "open" } = hu_decimal( $found[8] ); $info{ $symbol, "close" } = hu_decimal( $found[9] ); $info{ $symbol, "currency" } = $found[10]; $info{ $symbol, "low" } = hu_decimal( $found[13] ); $info{ $symbol, "high" } = hu_decimal( $found[14] ); $info{ $symbol, "p_change" } = hu_decimal( $found[16] ); $info{ $symbol, "last" } = hu_decimal( $found[17] ); $quoter->store_date( \%info, $symbol, { isodate => $found[18] } ); $info{ $symbol, "success" } = 1; } return wantarray() ? %info : \%info; } sub bamosz { my $quoter = shift; my @symbols = @_; my %info; my $ua = $quoter->user_agent; for my $symbol (@symbols) { $info{ $symbol, "method" } = "bamosz"; $info{ $symbol, "source" } = $BAMOSZ_MAINURL; $info{ $symbol, "success" } = 0; my $url = $BAMOSZ_URL . $symbol; my $response = $ua->request( GET $url); unless ( $response->is_success ) { $info{ $symbol, "errormsg" } = "Request error"; next; } my $te = HTML::TableExtract->new( attribs => { class => "dataTable" } ); $te->parse( decode_utf8( $response->content ) ); unless ( $te->first_table_found ) { $info{ $symbol, "errormsg" } = "No dataTable found"; next; } my $ts = $te->table( 0, 0 ); $info{ $symbol, "name" } = $ts->cell( 0, 1 ); my $isin = $ts->cell( 2, 1 ); $info{ $symbol, "symbol" } = $isin; $info{ $symbol, "isin" } = $isin; $info{ $symbol, "currency" } = $ts->cell( 3, 1 ); my $price = hu_decimal( $ts->cell( 5, 1 ) ); $info{ $symbol, "price" } = $price; $info{ $symbol, "last" } = $price; my $date = $ts->cell( 6, 1 ); $quoter->store_date( \%info, $symbol, { isodate => $date } ); $info{ $symbol, "success" } = 1; } return wantarray() ? %info : \%info; } sub trim { my $s = shift; if ($s) { $s =~ s/^\s+//; $s =~ s/\s+$//; return $s; } else { return ''; } } sub hu_decimal { my $s = shift; if ($s) { $s =~ s/[^\d,-]//g; $s =~ s/,/./; return $s; } else { return ''; } } 1; =head1 NAME Finance::Quote::HU - Obtain Hungarian Securities from www.bet.hu and www.bamosz.hu =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; # Don't know anything about failover yet... =head1 DESCRIPTION This module obtains information about Hungarian Securities. Share fetched from www.bet.hu, while mutual funds retrieved from www.bamosz.hu. Stocks may be searched by either ticker or ISIN, while mutual funds may only be search be ISIN. =head1 LABELS RETURNED Information available may include the following labels: method source name symbol currency date last price low high open close p_change =head1 SEE ALSO Budapest Stock Exchange (BET) website - http://www.bet.hu BAMOSZ website - http://www.bamosz.hu/ Finance::Quote =cut DWS.pm100644001750001750 1716613202072256 16560 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance/Quote#!/usr/bin/perl -w # # Copyright (C) 1998, Dj Padzensky # Copyright (C) 1998, 1999 Linas Vepstas # Copyright (C) 2000, Yannick LE NY # Copyright (C) 2000, Paul Fenwick # Copyright (C) 2000, Brent Neal # Copyright (C) 2000, Volker Stuerzl # Copyright (C) 2006, Klaus Dahlke # # 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 code was developed as part of GnuCash # # $Id: DWS.pm,v 1.7 2006/04/08 19:54:55 hampton Exp $ package Finance::Quote::DWS; require 5.005; require LWP::Protocol::https; use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; use LWP::Simple; use strict; use warnings; our $VERSION = '1.47'; # VERSION sub methods { return(dwsfunds => \&dwsfunds); } sub labels { return(dwsfunds => [qw/exchange name date isodate price method/]); } # ======================================================================= # The dwsfunds routine gets quotes of DWS funds (Deutsche Bank Gruppe) # On their website DWS provides a csv file in the format # symbol1,price1,date1 # symbol2,price2,date2 # ... # # This subroutine was written by Volker Stuerzl # # Version 2.0 as new webpage provides the data # 2006-03-19: Klaus Dahlke # Since DWS has changed its format and the data are not available via # csv-file download, the respective web-page is avaluated. There are # some limitations currently, especially with the name # # 2007-01-19: Stephan Ebelt # - fixed thousands and decimal separator handling # - check symbol against ISIN as well # - populate the exchange field with the DWS subsidiary that actually # runs the fund # - "improved" the name extraction (this fix is questionable, but does what I # want for the moment...), falls back to the string length assumption # from the last version if there is no match # - fixed indent # # 2007-01-26: Stephan Ebelt # - fixed 'unitialized value' warnings # sub dwsfunds { my $quoter = shift; my @funds = @_; return unless @funds; my $ua = $quoter->user_agent; my (%fundhash, @q, %info); my ( $html_string, $te, $ts, $row, @cells, $ce, @ce1, @ce2, @ce22, @ce4, $last, $wkn, $isin, $exchange, $date, $name, $type ); # define DWS 'Fondsart' (engl: classifications) as used on the page # - these strings are used to break down the real name later # - hardcoding at its best... but not much choice in order to get more # correct results my @dws_fund_classifications = ( 'Versicherungsfonds', 'Aktienfonds', 'Gemischte Fonds', 'Mitarbeiterfonds', 'Rentenfonds', 'Geldmarktnahe Fonds', 'Dachfonds', 'Kursgewinn-orientierte Fonds', 'AS-Fonds', 'Spezialit.ten', # note the dot ;-) 'Geldmarktfonds', 'Trading Fonds', 'DVG Fonds', 'Wandelanleihen-/ Genussscheinfonds', 'n/a' ); # create hash of all funds requested foreach my $fund (@funds) { $fundhash{$fund} = 0; } # get page containing the tables with prices etc my $DWS_URL = "https://www.deami.de/dps/ff/prices.aspx"; my $response = $ua->request(GET $DWS_URL); if ($response->is_success) { $html_string =$response->content; $te = new HTML::TableExtract->new( depth => 3, count => 1 ); $te->parse($html_string); $ts=$te->table_state(3,1); } else { # retrieval error - flag an error and return right away foreach my $fund (@funds) { %info = _dwsfunds_error(@funds, 'HTTP error: ' . $response->status_line); return wantarray() ? %info : \%info; } return wantarray() ? %info : \%info; } # # loop the table rows... # foreach $row ($ts->rows) { @cells =@$row; # replace line breaks # foreach $ce (@cells) { next unless $ce; $ce =~ s/\n/:/g; } # verify cell count if( $#cells != 4 ) { %info = _dwsfunds_error(@funds, "parse error: cells=$#cells, expected cells=4"); return wantarray() ? %info : \%info; } # get fond name and exchange # @ce1=split(/:/, $cells[1]); $name = $ce1[0]; $exchange = $ce1[1]; # get date and last price # @ce2=split(/:/, $cells[2]); $date = $ce2[0]; $last = $ce2[2]; # # wkn or isin is the source # @ce4=split(/:/, $cells[4]); $wkn=$ce4[1]; $isin=$ce4[2]; # match the fund by symbol foreach my $fund (@funds) { if ( ($wkn eq $fund) or ($isin eq $fund) ) { # attempt to separate the name-classification contruct my $name_ok = 0; foreach my $t (@dws_fund_classifications) { if( $name =~ /$t/ ) { $type = $t; my @n = split(/$t/, $name); $name = $n[0]; $name_ok = 1; last(); } } if( ! $name_ok ) { # fall back - the last 50 characters are either blanks or fond classification $name = substr($name, 0, length($name)-50); $info{$fund, "errormsg"} = "name-classification separation failed, guessing..."; } # mangle last price (thousands/decimal separators, ...) # - note the decimal separator is hardcoded to ',' (comma) # - keep arbitrary precision and any eventually following unit (%, $, ...) if( $last =~ /^(.*),(\d*.{1})$/ ) { my @tmp = ( $1, $2 ); $tmp[0] =~ s/\.//g; $last = join('.', @tmp); } # finaly, build up the result $info{$fund,"exchange"} = $exchange; $info{$fund,"symbol"} = $fund; $quoter->store_date(\%info, $fund, {eurodate => $date}); $info{$fund,"name"} = $name; $info{$fund,"last"} = $last; $info{$fund,"price"} = $last; $info{$fund,"method"} = "dwsfunds"; $info{$fund,"currency"} = "EUR"; $info{$fund,"success"} = 1; $fundhash{$fund} = 1; } } } # make sure a value is returned for every fund requested foreach my $fund (keys %fundhash) { if ($fundhash{$fund} == 0) { $info{$fund, "success"} = 0; $info{$fund, "errormsg"} = 'No data returned'; } } return wantarray() ? %info : \%info; } # - populate %info with errormsg and status code set for all requested symbols # - return a hash ready to pass back to fetch() sub _dwsfunds_error { my @symbols = shift; my $msg = shift; my %info; foreach my $s (@symbols) { $info{$s, "success"} = 0; $info{$s, "errormsg"} = $msg; } return(%info); } 1; =head1 NAME Finance::Quote::DWS - Obtain quotes from DWS (Deutsche Bank Gruppe). =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %fundinfo = $q->fetch("dwsfunds","847402", "DE0008474024", ...); =head1 DESCRIPTION This module obtains information about DWS managed funds. Query it with German WKN and/or international ISIN symbols. Information returned by this module is governed by DWS's terms and conditions. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::DWS: exchange, name, date, price, last. =head1 SEE ALSO DWS (Deutsche Bank Gruppe), http://www.dws.de/ =cut NZX.pm100644001750001750 741313202072256 16554 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance/Quote#!/usr/bin/perl -w # # Copyright (C) 2004, Michael Curtis # Modified from DWS.pm - its copyrights # Copyright (C) 1998, Dj Padzensky # Copyright (C) 1998, 1999 Linas Vepstas # Copyright (C) 2000, Yannick LE NY # Copyright (C) 2000, Paul Fenwick # Copyright (C) 2000, Brent Neal # Copyright (C) 2000, Volker Stuerzl # # 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. # # package Finance::Quote::NZX; require 5.005; use strict; use LWP::UserAgent; use HTTP::Request::Common; our $VERSION = '1.47'; # VERSION sub methods { return (nz => \&nzx, nzx => \&nzx); } sub labels { my @labels = qw/exchange name price last date isodate method/; return (nz => \@labels, nzx => \@labels); } sub nzx { my $nzxurl = "http://www.nzx.com/scripts/portal_pages/p_csv_by_market.csv?code=ALL&board_type=S"; my $quoter = shift; my @symbols = @_; return unless @symbols; my $isLineOne = 1; my $ua = $quoter->user_agent; my $sDate; my (%symbolhash, @q, %info); # create hash of all stocks requested foreach my $symbol (@symbols) { $symbolhash{$symbol} = 0; } # get csv data my $response = $ua->request(GET $nzxurl); if ($response->is_success) { # process csv data foreach (split('\015?\012',$response->content)) { if ($isLineOne == 1) { $isLineOne = 0; ($sDate) = ($_ =~ /([0-9]{4}\/[0-9]{2}\/[0-9]{2})/g); } @q = $quoter->parse_csv($_) or next; if (exists $symbolhash{$q[0]}) { $symbolhash{$q[0]} = 1; $info{$q[0], "exchange"} = "NZX"; $info{$q[0], "name"} = $q[0]; $info{$q[0], "symbol"} = $q[0]; $info{$q[0], "price"} = $q[1]; $info{$q[0], "last"} = $q[7]; $quoter->store_date(\%info, $q[0], {isodate => $sDate}); $info{$q[0], "method"} = "nzx"; $info{$q[0], "currency"} = "NZD"; $info{$q[0], "success"} = 1; } } # check to make sure a value was returned for every stock requested foreach my $symbol (keys %symbolhash) { if ($symbolhash{$symbol} == 0) { $info{$symbol, "success"} = 0; $info{$symbol, "errormsg"} = "No data returned"; } } } else { foreach my $symbol (@symbols) { $info{$symbol, "success"} = 0; $info{$symbol, "errormsg"} = "HTTP error"; } } return wantarray() ? %info : \%info; } 1; =head1 NAME Finance::Quote::NZX - Obtain quotes from NZX (New Zealand stock exchange.) =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %stockinfo = $q->fetch("nzx","TPW"); =head1 DESCRIPTION This module obtains information about NZX companies. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::NZX: exchange, name, date, price, last. =head1 SEE ALSO NZX (New Zealand stock exchange), http://www.nzx.com/ =cut HEX.pm100644001750001750 1311513202072256 16535 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance/Quote#!/usr/bin/perl -w # # Copyright (C) 1998, Dj Padzensky # Copyright (C) 1998, 1999 Linas Vepstas # Copyright (C) 2000, Yannick LE NY # Copyright (C) 2000, Paul Fenwick # Copyright (C) 2000, Brent Neal # Copyright (C) 2001, Leigh Wedding # Copyright (C) 2006, Mika Laari # # 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 code was developed as part of GnuCash require 5.005; use strict; package Finance::Quote::HEX; use HTTP::Request::Common; use LWP::UserAgent; use HTML::TableExtract; use vars qw/$HEX_URL /; our $VERSION = '1.47'; # VERSION $HEX_URL = 'http://omxgroup.is-teledata.com/html/securitypricelistequities.html?language=fi'; # XXX Europe should probably be removed since this module provides only # the Finnish quotes. sub methods {return ('europe' => \&hex, 'finland' => \&hex,'hex' => \&hex)} { my @labels = qw/name last high low date isodate time p_change volume bid ask price method exchange/; sub labels { return ('europe' => \@labels, 'finland' => \@labels, 'hex' => \@labels); } } # Helsinki Stock Exchange (HEX) # The HEX provides free delayed quotes through their webpage. # This module is heavily based on the ASX.pm. # # Maintainer of this section is Mika Laari . sub hex { my $quoter = shift; my @stocks = @_; return unless @stocks; my %info; my $ua = $quoter->user_agent; my $url = $HEX_URL; my $response = $ua->request(GET $url); unless ($response->is_success) { foreach my $stock (@stocks) { $info{$stock,"success"} = 0; $info{$stock,"errormsg"} = "HTTP session failed"; } return wantarray() ? %info : \%info; } # Get a table containing information for all the stocks. my $te = HTML::TableExtract->new(); $te->parse($response->content); # Extract table contents. my @rows; unless (@rows = $te->rows) { foreach my $stock (@stocks) { $info{$stock,"success"} = 0; $info{$stock,"errormsg"} = "Failed to parse HTML table."; } return wantarray() ? %info : \%info; } # Prepare an array for checking whether a symbol is among the wanted ones. my %is_stock = (); for (@stocks) { $is_stock{uc($_)} = 1 } # Pack the resulting data into our structure. foreach my $row (@rows) { my $stock = $$row[1]; next unless $stock; # Delete spaces and high bit characters. $stock =~ tr/ \200-\377//d; next unless $is_stock{$stock}; $info{$stock,'symbol'} = $stock; $info{$stock,'name'} = $$row[0]; $info{$stock,'name'} =~ s/^\s*(.*?)\s*$/$1/; $info{$stock,'p_change'} = $$row[3]; # Remove possible plus and other unnecessary characters. $info{$stock,'p_change'} =~ s/\+?(-?\d+,\d+)%/$1/; $info{$stock,'bid'} = $$row[4]; $info{$stock,'ask'} = $$row[5]; $info{$stock,'high'} = $$row[6]; $info{$stock,'low'} = $$row[7]; $info{$stock,'last'} = $$row[8]; # Again, get rid of nasty high-bit characters. #$info{$stock,'last'} =~ tr/ \200-\377//d; $info{$stock,'volume'} = $$row[9]; $info{$stock,'volume'} =~ tr/ \200-\377//d; # Use deciman point instead of comma. foreach my $label (qw/last bid ask high low p_change/) { $info{$stock,$label} =~ s/,/./; } $info{$stock, "currency"} = "EUR"; $quoter->store_date(\%info, $stock, {today => 1}); # $info{$stock, "time"} = $time; $info{$stock, "method"} = "hex"; $info{$stock, "exchange"} = "Helsinki Stock Exchange"; $info{$stock, "price"} = $info{$stock,"last"}; $info{$stock, "success"} = 1; } # All done. return %info if wantarray; return \%info; } 1; =head1 NAME Finance::Quote::HEX - Obtain quotes from the Helsinki Stock Exchange. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %stockinfo = $q->fetch("hex","NOK1V"); # Only query ASX. %stockinfo = $q->fetch("finland","NOK1V"); # Failover to other sources OK. =head1 DESCRIPTION This module obtains information from the Helsinki Stock Exchange http://www.hex.com/. All Finnish stocks are available. This module is not loaded by default on a Finance::Quote object. It's possible to load it explicity by placing "HEX" in the argument list to Finance::Quote->new(). This module provides both the "hex" and "finland" fetch methods. Please use the "finland" fetch method if you wish to have failover with other sources for Finnish stocks. Using the "hex" method will guarantee that your information only comes from the Helsinki Stock Exchange. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::HEX: name, last, high, low, date, time, p_change, volume, bid, ask, price, method and exchange. =head1 SEE ALSO Helsinki Stock Exchange, http://www.hex.com/ =cut TSP.pm100644001750001750 1427213202072256 16564 0ustar00ecec000000000000Finance-Quote-1.47/lib/Finance/Quote#!/usr/bin/perl -w # # Copyright (C) 1998, Dj Padzensky # Copyright (C) 1998, 1999 Linas Vepstas # Copyright (C) 2000, Yannick LE NY # Copyright (C) 2000, Paul Fenwick # Copyright (C) 2000, Brent Neal # Copyright (C) 2001, Rob Sessink # Copyright (C) 2004, Frank Mori Hess # Trent Piepho # # 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 is derived from version 0.9 of the AEX.pm module. require 5.005; use strict; package Finance::Quote::TSP; use vars qw( $TSP_URL $TSP_MAIN_URL %TSP_FUND_COLUMNS %TSP_FUND_NAMES); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; our $VERSION = '1.47'; # VERSION # URLs of where to obtain information $TSP_URL = 'https://www.tsp.gov/investmentfunds/shareprice/sharePriceHistory.shtml'; $TSP_MAIN_URL=("http://www.tsp.gov"); # ENHANCE-ME: The decade target funds like 2020 appear and disappear. # Better not to hard code them. # %TSP_FUND_COLUMNS = ( TSPL2050FUND => "L 2050", TSPL2040FUND => "L 2040", TSPL2030FUND => "L 2030", TSPL2020FUND => "L 2020", TSPLINCOMEFUND => "L INCOME", TSPGFUND => "G FUND", TSPFFUND => "F FUND", TSPCFUND => "C FUND", TSPSFUND => "S FUND", TSPIFUND => "I FUND" ); %TSP_FUND_NAMES = ( TSPL2050 => 'Lifecycle 2050 Fund', TSPL2040 => 'Lifecycle 2040 Fund', TSPL2030 => 'Lifecycle 2030 Fund', TSPL2020 => 'Lifecycle 2020 Fund', TSPLINCOME => 'Lifecycle Income Fund', TSPGFUND => 'Government Securities Investment Fund', TSPFFUND => 'Fixed Income Index Investment Fund', TSPCFUND => 'Common Stock Index Investment Fund', TSPSFUND => 'Small Capitalization Stock Index Investment Fund', TSPIFUND => 'International Stock Index Investment Fund' ); sub methods { return (tsp => \&tsp) } { my @labels = qw/name nav date isodate currency method last close/; sub labels { return (tsp => \@labels); } } # ============================================================================== sub tsp { my $quoter = shift; my @symbols = @_; # Make sure symbols are requested ##CAN exit more gracefully - add later## return unless @symbols; # Local Variables my(%info, %fundrows); my($ua, $reply, $row, $te, $ts, $second_row); $ua = $quoter->user_agent; $reply = $ua->request(GET $TSP_URL); return unless ($reply->is_success); $te = HTML::TableExtract->new( headers => ["Date", values %TSP_FUND_COLUMNS] ); $te->parse($reply->content); # First row is newest data, older data follows, maybe there # should be some way to get it (in addition to the second_row "close") $ts = $te->first_table_found || die 'TSP data table not recognised'; $row = $ts->row(0); $second_row = $ts->row(1); # Make a hash that maps the order the columns are in for(my $i=1; my $key = each %TSP_FUND_COLUMNS ; $i++) { $fundrows{$key} = $i; } foreach (@symbols) { # Ignore case when looking up the data. Preserve case # when storing the symbol name in the info array. my $tmp = uc $_; $tmp = uc sprintf("TSP%sfund", substr($tmp,0,1)) if (index("GFCSI", substr($tmp,0,1)) >= 0); if (index("LINCOME", substr($tmp,0,7)) >= 0) { $tmp = uc sprintf("TSP%sfund", substr($tmp,0,7)); } elsif (index("L", substr($tmp,0,1)) >= 0) { $tmp = uc sprintf("TSP%sfund", substr($tmp,0,5)); } if(exists $fundrows{$tmp}) { $info{$_, 'success'} = 1; $info{$_, 'method'} = 'tsp'; $info{$_, 'currency'} = 'USD'; $info{$_, 'source'} = $TSP_MAIN_URL; $info{$_, 'symbol'} = $_; $info{$_, 'name'} = $TSP_FUND_NAMES{$tmp}; ($info{$_, 'nav'} = $$row[$fundrows{$tmp}]) =~ s/[^0-9]*([0-9.,]+).*/$1/s; $info{$_, 'last'} = $info{$_, 'nav'}; ($info{$_, 'close'} = $second_row->[$fundrows{$tmp}]) =~ s/[^0-9]*([0-9.,]+).*/$1/s; $quoter->store_date(\%info, $_, {usdate => $$row[0]}); } else { $info{$_, 'success'} = 0; $info{$_, 'errormsg'} = "Fund name unknown"; } } return %info if wantarray; return \%info; } 1; =head1 NAME Finance::Quote::TSP Obtain fund prices for US Federal Government Thrift Savings Plan =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("tsp","c"); #get value of C "Common Stock Index Investment" Fund =head1 DESCRIPTION This module fetches fund information from the "Thrift Savings Plan" http://www.tsp.gov using its fund prices page https://www.tsp.gov/investmentfunds/shareprice/sharePriceHistory.shtml The quote symbols are C common stock fund F fixed income fund G government securities fund I international stock fund S small cap stock fund L2020 lifecycle fund year 2020 L2030 lifecycle fund year 2030 L2040 lifecycle fund year 2040 L2050 lifecycle fund year 2050 LINCOME lifecycle income fund =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::TSP : name eg. "Common Stock Index Investment Fund" date latest date, eg. "21/02/10" isodate latest date, eg. "2010-02-21" last latest price, eg. "16.1053" close previous day's price nav same as "last" currency "USD" method "tsp" C