Finance-Quote-1.18/000755 000765 000024 00000000000 12032047712 013631 5ustar00ecstaff000000 000000 Finance-Quote-1.18/ChangeLog000644 000765 000024 00000046200 12032045420 015377 0ustar00ecstaff000000 000000 XXXX-XX-XX 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. Finance-Quote-1.18/ChangeLog.1000644 000765 000024 00000052536 12032045420 015547 0ustar00ecstaff000000 000000 2000-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. Finance-Quote-1.18/Documentation/000755 000765 000024 00000000000 12032047712 016442 5ustar00ecstaff000000 000000 Finance-Quote-1.18/Examples/000755 000765 000024 00000000000 12032047712 015407 5ustar00ecstaff000000 000000 Finance-Quote-1.18/inc/000755 000765 000024 00000000000 12032047712 014402 5ustar00ecstaff000000 000000 Finance-Quote-1.18/INSTALL000644 000765 000024 00000005032 12032045420 014654 0ustar00ecstaff000000 000000 Finance::Quote ============== IMPORTANT ========= Read Documentation/License for the license (GPL) covering this code. Dependancies ------------ Finance::Quote depends upon a number of other perl modules to function correctly. These modules include: LWP::UserAgent HTTP::Request::Common HTML::TableExtract HTML::TreeBuilder You will receive a warning during the make process if one or more of these modules are missing. One easy way to install the modules that Finance::Quote requires is to use perl's CPAN module: hostname$ perl -MCPAN -e shell (as root) If you haven't used the CPAN module before, then it may ask you a few simple configuration questions before you get to the cpan> prompt. You can install any module from CPAN using: cpan> install my::module Indeed, it's possible to install Finance::Quote and all the modules it depends upon using: cpan> install Finance::Quote Install instructions -------------------- $ perl Makefile.PL $ make # make install (as root) Couldn't be easier, could it? Running the Regression Tests ---------------------------- By default, Finance::Quote does not run its regression tests for an automatic install. This is because the tests rely upon a working Internet connection, and for third-party websites to be operating correctly, which is not always the case. If you wish to run the regression tests, then unpack the module as per normal, but instead use the following steps: $ ln -s test t $ perl Makefile.PL $ make $ make test # make install (as root) The tests do take some time to run, so please be patient. Note, there are two modules that are known to currency require maintenance, so expect the asx.t and trustnet.t tests to fail. What if my tests fail? ---------------------- Your tests could fail if your machine does not have a connection to the Internet, if your machine must use an HTTP proxy and you do not have your http_proxy environment variable set, or if one or more of the servers that Finance::Quote uses is down or unhappy. The tests can also fail if you have not installed all the modules that Finance::Quote depends upon. See the section on dependancies above. If you believe you've found a bug, please report it using our bugtracking system at http://rt.cpan.org/Public/Dist/Display.html?Status=Active&Name=Finance-Quote or send mail to . More information? ----------------- Try visiting the Finance::Quote webpage at http://finance-quote.sourceforge.net/ Maintainer ---------- Paul Fenwick Erik Colson Finance-Quote-1.18/lib/000755 000765 000024 00000000000 12032047712 014377 5ustar00ecstaff000000 000000 Finance-Quote-1.18/Makefile.PL000644 000765 000024 00000003467 12032046644 015620 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w use strict; use inc::Module::Install; # Ugly parens are used in this Makefile.PL for backwards compatibility # with some old dh-make-perl systems on Debian. name( 'Finance-Quote'); all_from( 'lib/Finance/Quote.pm'); license( 'gpl'); # We'd like to have multiple authors listed. See future_use below. author('Paul Fenwick '); =begin future_use # Module::Install currently doesn't support multiple authors. # When it does, the following may prove useful. author( 'Dj Padzensky ', 'Linas Vepstas ', 'Yannick LE NY ', 'Paul Fenwick ', 'Brent Neal ', 'Volker Stuerzl ', 'Keith Refson ', 'Rob Sessink ', 'Leigh Wedding ', 'Tobias Vancura ', 'James Treacy ', ); =end future_use =cut requires( 'LWP::UserAgent' => 0); requires( 'Crypt::SSLeay' => 0); requires( 'HTTP::Request::Common' => 0); requires( 'HTML::TableExtract' => 0); requires( 'HTML::TreeBuilder' => 0); test_requires( 'Test::More' => 0); # Lowercase resource names have special meanings in the META.yml spec. resources( repository => 'http://github.com/pfenwick/finance-quote/'); resources( bugtracker => 'http://rt.cpan.org/NoAuth/Bugs.html?Dist=Finance-Quote'); resources( homepage => 'http://finance-quote.sourceforge.net/'); # Uppercase resource names are not special in the spec. resources( MailingList => 'https://lists.sourceforge.net/lists/listinfo/finance-quote-devel'); # And we're done! WriteAll(); Finance-Quote-1.18/MANIFEST000644 000765 000024 00000005307 12032046667 014777 0ustar00ecstaff000000 000000 ChangeLog ChangeLog.1 Documentation/FAQ Documentation/Hackers-Guide Documentation/License Documentation/README Examples/chkshares.pl Examples/currency-lookup.pl Examples/Quote_example.pl Examples/stockdump.pl inc/Module/Install.pm inc/Module/Install/Base.pm inc/Module/Install/Can.pm inc/Module/Install/Fetch.pm inc/Module/Install/Makefile.pm inc/Module/Install/Metadata.pm inc/Module/Install/Win32.pm inc/Module/Install/WriteAll.pm INSTALL 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/BMONesbittBurns.pm lib/Finance/Quote/Bourso.pm lib/Finance/Quote/BSERO.pm lib/Finance/Quote/Cdnfundlibrary.pm lib/Finance/Quote/Cominvest.pm lib/Finance/Quote/Currencies.pm lib/Finance/Quote/Deka.pm lib/Finance/Quote/DWS.pm lib/Finance/Quote/Fidelity.pm lib/Finance/Quote/FinanceCanada.pm lib/Finance/Quote/Finanzpartner.pm lib/Finance/Quote/Fool.pm lib/Finance/Quote/FTPortfolios.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/ManInvestments.pm lib/Finance/Quote/Morningstar.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/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/TSP.pm lib/Finance/Quote/TSX.pm lib/Finance/Quote/Union.pm lib/Finance/Quote/UserAgent.pm lib/Finance/Quote/USFedBonds.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/ZA.pm Makefile.PL MANIFEST This list of files META.yml MYMETA.json MYMETA.yml README 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/asegr.t t/asx.t t/bmonesbittburns.t t/bourso.t t/bsero.t t/cdnfundlibrary.t t/cominvest.t t/currencies.t t/currency.t t/currency_lookup.t t/deka.t t/dws.t t/fidelity.t t/financecanada.t t/finanzpartner.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/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/troweprice.t t/trustnet.t t/tsp.t t/tsx.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/za.t Finance-Quote-1.18/META.yml000644 000765 000024 00000001731 12032046654 015110 0ustar00ecstaff000000 000000 --- abstract: 'Get stock and mutual fund quotes from various exchanges' author: - ', Dj Padzensky' - 'Paul Fenwick ' build_requires: ExtUtils::MakeMaker: 6.36 Test::More: 0 configure_requires: ExtUtils::MakeMaker: 6.36 distribution_type: module dynamic_config: 1 generated_by: 'Module::Install version 1.06' license: gpl meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Finance-Quote no_index: directory: - examples - inc - t requires: Crypt::SSLeay: 0 HTML::TableExtract: 0 HTML::TreeBuilder: 0 HTTP::Request::Common: 0 LWP::UserAgent: 0 perl: 5.005 resources: MailingList: https://lists.sourceforge.net/lists/listinfo/finance-quote-devel bugtracker: http://rt.cpan.org/NoAuth/Bugs.html?Dist=Finance-Quote homepage: http://finance-quote.sourceforge.net/ license: http://opensource.org/licenses/gpl-license.php repository: http://github.com/pfenwick/finance-quote/ version: 1.18 Finance-Quote-1.18/MYMETA.json000644 000765 000024 00000002174 12032046654 015530 0ustar00ecstaff000000 000000 { "abstract" : "Get stock and mutual fund quotes from various exchanges", "author" : [ ", Dj Padzensky, Paul Fenwick " ], "dynamic_config" : 0, "generated_by" : "ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120630", "license" : [ "open_source" ], "meta-spec" : { "url" : "http://search.cpan.org/perldoc?CPAN::Meta::Spec", "version" : "2" }, "name" : "Finance-Quote", "no_index" : { "directory" : [ "t", "inc" ] }, "prereqs" : { "build" : { "requires" : { "ExtUtils::MakeMaker" : "6.36", "Test::More" : "0" } }, "configure" : { "requires" : { "ExtUtils::MakeMaker" : "0" } }, "runtime" : { "requires" : { "Crypt::SSLeay" : "0", "HTML::TableExtract" : "0", "HTML::TreeBuilder" : "0", "HTTP::Request::Common" : "0", "LWP::UserAgent" : "0", "perl" : "5.005" } } }, "release_status" : "stable", "version" : "1.18" } Finance-Quote-1.18/MYMETA.yml000644 000765 000024 00000001232 12032046654 015352 0ustar00ecstaff000000 000000 --- abstract: 'Get stock and mutual fund quotes from various exchanges' author: - ', Dj Padzensky, Paul Fenwick ' build_requires: ExtUtils::MakeMaker: 6.36 Test::More: 0 configure_requires: ExtUtils::MakeMaker: 0 dynamic_config: 0 generated_by: 'ExtUtils::MakeMaker version 6.6302, CPAN::Meta::Converter version 2.120630' license: open_source meta-spec: url: http://module-build.sourceforge.net/META-spec-v1.4.html version: 1.4 name: Finance-Quote no_index: directory: - t - inc requires: Crypt::SSLeay: 0 HTML::TableExtract: 0 HTML::TreeBuilder: 0 HTTP::Request::Common: 0 LWP::UserAgent: 0 perl: 5.005 version: 1.18 Finance-Quote-1.18/README000644 000765 000024 00000005024 12032045420 014504 0ustar00ecstaff000000 000000 NAME Finance::Quote - Get stock and mutual fund quotes from various exchanges 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 depreciated, and an object-orientated method that provides greater flexibility and stability. 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. 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: RT, CPAN's request tracker http://rt.cpan.org/NoAuth/Bugs.html?Dist=Finance-Quote AnnoCPAN, Annotated CPAN documentation http://annocpan.org/dist/Finance-Quote CPAN Ratings http://cpanratings.perl.org/d/Finance-Quote Search CPAN http://search.cpan.org/dist/Finance-Quote The Finance::Quote home page http://finance-quote.sourceforge.net/ The Finance::YahooQuote home page http://www.padz.net/~djpadz/YahooQuote/ The GnuCash home page http://www.gnucash.org/ 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) 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. Finance-Quote-1.18/t/000755 000765 000024 00000000000 12032047712 014074 5ustar00ecstaff000000 000000 Finance-Quote-1.18/t/00-use.t000755 000765 000024 00000006106 12032045420 015272 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # Test to see if Finance::Quote can at least be loaded and used. use strict; use Test; BEGIN {plan tests => 19}; use Finance::Quote; ok(1); # Yup. It loaded okay. Good. :) my $quote = Finance::Quote->new(); ok($quote); # Did we get an object okay? # 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); ok($info{"test","date"} eq $ustoday); # 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"); %info = (); $quote->store_date(\%info, "test", {isodate => "2004 Dec 31"}); ok($info{"test","date"} eq "12/31/2004"); %info = (); $quote->store_date(\%info, "test", {isodate => "2004 December 31"}); ok($info{"test","date"} eq "12/31/2004"); # 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"); %info = (); $quote->store_date(\%info, "test", {usdate => "Dec 31, 2004"}); ok($info{"test","isodate"} eq "2004-12-31"); %info = (); $quote->store_date(\%info, "test", {usdate => "December 31 2004"}); ok($info{"test","isodate"} eq "2004-12-31"); # 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"); %info = (); $quote->store_date(\%info, "test", {eurodate => "31 December 2004"}); ok($info{"test","isodate"} eq "2004-12-31"); %info = (); $quote->store_date(\%info, "test", {eurodate => "31 Dec, 2004"}); ok($info{"test","isodate"} eq "2004-12-31"); # 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"); ok($info{"test","isodate"} eq "$year4-12-31" || $info{"test","isodate"} eq "$year4m-12-31"); %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"); ok($info{"test","isodate"} eq "$year4-12-31" || $info{"test","isodate"} eq "$year4m-12-31"); %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"); ok($info{"test","isodate"} eq "$year4-12-31" || $info{"test","isodate"} eq "$year4m-12-31"); Finance-Quote-1.18/t/01-pod.t000755 000765 000024 00000000435 12032045420 015260 0ustar00ecstaff000000 000000 #!/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(); Finance-Quote-1.18/t/02-pod-coverage.t000755 000765 000024 00000000447 12032045420 017055 0ustar00ecstaff000000 000000 #!/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(); Finance-Quote-1.18/t/03-kwalitee.t000755 000765 000024 00000000436 12032045420 016306 0ustar00ecstaff000000 000000 #!/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 $@; Finance-Quote-1.18/t/04-critic.t000755 000765 000024 00000000521 12032045420 015752 0ustar00ecstaff000000 000000 #!/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(); Finance-Quote-1.18/t/05-data-dumper.t000755 000765 000024 00000000717 12032045420 016710 0ustar00ecstaff000000 000000 #!/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"); Finance-Quote-1.18/t/aex.t000755 000765 000024 00000002160 12032045420 015032 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/aiahk.t000755 000765 000024 00000002477 12032045420 015345 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/asegr.t000755 000765 000024 00000002474 12032045420 015366 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/asx.t000755 000765 000024 00000002713 12032045420 015054 0ustar00ecstaff000000 000000 #!/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 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","RZR"); ok( %quotes, "Data returned for call to fetch" ); ok( $quotes{"RZR","success"}, "RZR query was successful" ); cmp_ok( $quotes{"RZR","last"}, '>', 0 , "Last price for RZR was > 0" ); # Check that we're getting currency information. cmp_ok( $quotes{"RZR", "currency"}, "eq", "AUD" , "Currency of RZR is AUD" ); # Check we're not getting bogus percentage signs. unlike( $quotes{"RZR","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 returns failure"); Finance-Quote-1.18/t/bmonesbittburns.t000755 000765 000024 00000002636 12032045420 017505 0ustar00ecstaff000000 000000 #!/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); Finance-Quote-1.18/t/bourso.t000755 000765 000024 00000003554 12032045420 015576 0ustar00ecstaff000000 000000 #!/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 => 65; # 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 "FR0010707414", # Warrant "FR0003500008", # Index ); # 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 FR0010707414 # 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); ok($quotes{$stock,"last"} > 0); ok(length($quotes{$stock,"name"})); ok(length($quotes{$stock,"symbol"})); ok($quotes{$stock,"success"}); ok( # indexes are quoted in percents ($stock eq "FR0003500008") || (($stock eq "MSFT") && ($quotes{$stock, "currency"} eq "USD")) || ($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); }; 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"}); Finance-Quote-1.18/t/bsero.t000644 000765 000024 00000002052 12032047702 015371 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/cdnfundlibrary.t000755 000765 000024 00000001644 12032045420 017271 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/cominvest.t000755 000765 000024 00000001755 12032045420 016275 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/currencies.t000755 000765 000024 00000000767 12032045420 016432 0ustar00ecstaff000000 000000 #!/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" ); Finance-Quote-1.18/t/currency.t000755 000765 000024 00000002750 12032045420 016114 0ustar00ecstaff000000 000000 #!/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("yahoo_europe","UG.PA"); ok($baseinfo{"UG.PA","success"}); $q->set_currency("AUD"); # All new requests in Aussie Dollars. my %info = $q->fetch("yahoo_europe","UG.PA"); ok($info{"UG.PA","success"}); # Test 7 ok($info{"UG.PA","currency"} eq "AUD"); # Test 8 ok($info{"UG.PA","price"} > 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; } Finance-Quote-1.18/t/currency_lookup.t000755 000765 000024 00000003416 12032045420 017505 0ustar00ecstaff000000 000000 #!/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" ); Finance-Quote-1.18/t/deka.t000755 000765 000024 00000002202 12032045420 015156 0ustar00ecstaff000000 000000 #!/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 "Couldn't parse deka website"); Finance-Quote-1.18/t/dws.t000755 000765 000024 00000001570 12032045420 015056 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/fidelity.t000755 000765 000024 00000002330 12032045420 016065 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/financecanada.t000755 000765 000024 00000001766 12032045420 017023 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/finanzpartner.t000644 000765 000024 00000001673 12032045420 017143 0ustar00ecstaff000000 000000 #!/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); Finance-Quote-1.18/t/ftportfolios.t000755 000765 000024 00000002103 12032045420 017004 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/goldmoney.t000755 000765 000024 00000003012 12032045420 016247 0ustar00ecstaff000000 000000 #!/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 GoldMoney functions. my $q = Finance::Quote->new("GoldMoney"); $q->set_currency('EUR'); 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); ok($quotes{"gold","currency"} eq "EUR"); 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 "EUR"); 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 "EUR"); 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"}); Finance-Quote-1.18/t/hex.t000755 000765 000024 00000001720 12032045420 015042 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/hu.t000644 000765 000024 00000004624 12032045420 014675 0ustar00ecstaff000000 000000 #!/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 "Parse error" || $quotes{"ZOL","errormsg"} eq "The provided ISIN/TICKER is invalid. Your symbol was 'ZOL'." || $quotes{"ZOL","errormsg"} eq "Alternate ISIN pickup also not working..." ); Finance-Quote-1.18/t/indiamutual.t000755 000765 000024 00000002031 12032045420 016566 0ustar00ecstaff000000 000000 #!/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", "102849", "101560", "106524"); 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"}); Finance-Quote-1.18/t/lerevenu.t000755 000765 000024 00000002525 12032045420 016107 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/maninvestments.t000755 000765 000024 00000001777 12032045420 017345 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/morningstar.t000644 000765 000024 00000002111 12032045420 016611 0ustar00ecstaff000000 000000 #!/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 = ("F0GBR069L2","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{"F0GBR069L2","price"} > 0); ok(length($quotes{"F0GBR069L2","name"}) > 0); ok($quotes{"F0GBR069L2","success"}); ok($quotes{"F0GBR069L2", "currency"} eq "USD"); ok(substr($quotes{"F0GBR069L2","isodate"},0,4) == $year || substr($quotes{"F0GBR069L2","isodate"},0,4) == $lastyear); ok(substr($quotes{"F0GBR069L2","date"},6,4) == $year || substr($quotes{"F0GBR069L2","date"},6,4) == $lastyear); # Make sure we don't have spurious % signs. ok($quotes{"F0GBR069L2","p_change"} !~ /%/); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); Finance-Quote-1.18/t/nzx.t000755 000765 000024 00000001707 12032045420 015102 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/platinum.t000755 000765 000024 00000001673 12032045420 016116 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/quote.t000644 000765 000024 00000002677 12032045420 015424 0ustar00ecstaff000000 000000 #!/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'); Finance-Quote-1.18/t/seb.t000755 000765 000024 00000002000 12032045420 015017 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/sixfunds.t000755 000765 000024 00000002077 12032045420 016127 0ustar00ecstaff000000 000000 #!/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' } ); Finance-Quote-1.18/t/sixshares.t000755 000765 000024 00000002066 12032045420 016273 0ustar00ecstaff000000 000000 #!/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' } ); Finance-Quote-1.18/t/stockhousecanada.t000755 000765 000024 00000002332 12032045420 017575 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/tdefunds.t000755 000765 000024 00000001211 12032045420 016065 0ustar00ecstaff000000 000000 #!/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); Finance-Quote-1.18/t/tdwaterhouse.t000755 000765 000024 00000002077 12032045420 017002 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/tiaacref.t000755 000765 000024 00000004061 12032045420 016035 0ustar00ecstaff000000 000000 #!/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 => 27; # Test TIAA-CREF functions. my $q = Finance::Quote->new(); my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my %quotes = $q->tiaacref("CREFmony","TIAAreal","TLSRX","TCMVX","TLGRX","BOGOname","CREFbond"); ok(%quotes); ok($quotes{"CREFmony","nav"} > 0); ok($quotes{"CREFmony", "currency"} eq "USD"); ok(length($quotes{"CREFmony","date"}) > 0); ok(substr($quotes{"CREFmony","isodate"},0,4) == $year || substr($quotes{"CREFmony","isodate"},0,4) == $lastyear); ok(substr($quotes{"CREFmony","date"},6,4) == $year || substr($quotes{"CREFmony","date"},6,4) == $lastyear); ok($quotes{"TIAAreal","nav"} > 0); ok(length($quotes{"TIAAreal","date"}) > 0); ok(substr($quotes{"TIAAreal","isodate"},0,4) == $year || substr($quotes{"TIAAreal","isodate"},0,4) == $lastyear); ok(substr($quotes{"TIAAreal","date"},6,4) == $year || substr($quotes{"TIAAreal","date"},6,4) == $lastyear); ok($quotes{"TLSRX","success"} > 0); ok($quotes{"TLSRX","nav"} > 0); ok(length($quotes{"TLSRX","date"}) > 0); ok(substr($quotes{"TLSRX","isodate"},0,4) == $year || substr($quotes{"TLSRX","isodate"},0,4) == $lastyear); ok(substr($quotes{"TLSRX","date"},6,4) == $year || substr($quotes{"TLSRX","date"},6,4) == $lastyear); ok($quotes{"TCMVX","success"} > 0); ok($quotes{"TCMVX","nav"} > 0); ok(length($quotes{"TCMVX","date"}) > 0); ok(substr($quotes{"TCMVX","isodate"},0,4) == $year || substr($quotes{"TCMVX","isodate"},0,4) == $lastyear); ok(substr($quotes{"TCMVX","date"},6,4) == $year || substr($quotes{"TCMVX","date"},6,4) == $lastyear); ok($quotes{"TLGRX","success"} > 0); ok($quotes{"BOGOname","success"} == 0); ok($quotes{"BOGOname","errormsg"} eq "Bad symbol"); ok($quotes{"CREFbond","success"} > 0); ok($quotes{"CREFbond","nav"} > 0); ok($quotes{"CREFbond", "currency"} eq "USD"); ok(substr($quotes{"CREFbond","date"},6,4) == $year || substr($quotes{"CREFbond","date"},6,4) == $lastyear); Finance-Quote-1.18/t/troweprice.t000755 000765 000024 00000002265 12032045420 016446 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/trustnet.t000755 000765 000024 00000001751 12032045420 016152 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/tsp.t000755 000765 000024 00000003272 12032045420 015070 0ustar00ecstaff000000 000000 #!/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); Finance-Quote-1.18/t/tsx.t000755 000765 000024 00000001774 12032045420 015105 0ustar00ecstaff000000 000000 #!/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 = ("NT", "BCE", "AER"); my %regexps = ( NT => qr/\bNortel\b/, BCE => qr/\b(BCE|Bell)\b/, AER => qr/\bAeroplan\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"}); Finance-Quote-1.18/t/union.t000755 000765 000024 00000001573 12032045420 015414 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/usfedbonds.t000755 000765 000024 00000004004 12032045420 016410 0ustar00ecstaff000000 000000 #!/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"); Finance-Quote-1.18/t/vanguard.t000755 000765 000024 00000001671 12032045420 016072 0ustar00ecstaff000000 000000 #!/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"} !~ /%/); Finance-Quote-1.18/t/vwd.t000755 000765 000024 00000001676 12032045420 015070 0ustar00ecstaff000000 000000 #!/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 vwd functions. my $year = (localtime())[5] + 1900; my $lastyear = $year - 1; my $q = Finance::Quote->new("VWD"); my %quotes = $q->vwd("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(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 a bogus fund returns no-success. ok($quotes{"BOGUS","success"} == 0); ok($quotes{"BOGUS","errormsg"} eq "Parse error"); # invalid symbols not detected anymore Finance-Quote-1.18/t/yahoo.t000755 000765 000024 00000002121 12032045420 015371 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/yahoo_asia.t000755 000765 000024 00000001776 12032045420 016405 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/yahoo_australia.t000755 000765 000024 00000001745 12032045420 017451 0ustar00ecstaff000000 000000 #!/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->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"} !~ /%/); # Check that a bogus stock returns no-success. ok(! $quotes{"BOGUS","success"}); Finance-Quote-1.18/t/yahoo_brasil.t000755 000765 000024 00000002203 12032045420 016726 0ustar00ecstaff000000 000000 #!/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 => 16; # Test Yahoo_europe functions. my $q = Finance::Quote->new(); my @stocks = ("ELUM4","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"}); Finance-Quote-1.18/t/yahoo_europe.t000755 000765 000024 00000006771 12032045420 016767 0ustar00ecstaff000000 000000 #!/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 => 29; # 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","ATG.L"); ok($londonquotes{"ATG.L","success"}); ok($londonquotes{"ATG.L","currency"} eq "GBP"); ok(($londonquotes{"ATG.L","currency"} eq "GBP") && !defined($londonquotes{"ATG.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"})); # Check if close is between year_range for LTI.L (expressed in GBp) for checking if conversion is correct my %ltiquotes = $q->fetch("yahoo","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"); } Finance-Quote-1.18/t/yahoo_nz.t000755 000765 000024 00000001732 12032045420 016107 0ustar00ecstaff000000 000000 #!/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"}); Finance-Quote-1.18/t/za.t000755 000765 000024 00000002337 12032045420 014675 0ustar00ecstaff000000 000000 #!/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 => 15; # 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(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"); Finance-Quote-1.18/lib/Finance/000755 000765 000024 00000000000 12032047712 015742 5ustar00ecstaff000000 000000 Finance-Quote-1.18/lib/Finance/Quote/000755 000765 000024 00000000000 12032047712 017037 5ustar00ecstaff000000 000000 Finance-Quote-1.18/lib/Finance/Quote.pm000644 000765 000024 00000112774 12032045420 017403 0ustar00ecstaff000000 000000 #!/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 Data::Dumper; use vars qw/@ISA @EXPORT @EXPORT_OK @EXPORT_TAGS $VERSION $TIMEOUT %MODULES %METHODS $AUTOLOAD $YAHOO_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 $YAHOO_CURRENCY_URL = "http://finance.yahoo.com/d/quotes.csv?e=.csv&f=l1&s="; @ISA = qw/Exporter/; @EXPORT = (); @EXPORT_OK = qw/yahoo yahoo_europe fidelity troweprice asx tiaacref currency_lookup/; @EXPORT_TAGS = ( all => [@EXPORT_OK]); $VERSION = '1.18'; $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 ASEGR ASX BMONesbittBurns BSERO Bourso Cdnfundlibrary Currencies Deka DWS FTPortfolios Fidelity FinanceCanada Fool HU GoldMoney HEX IndiaMutual LeRevenu ManInvestments Morningstar NZX Platinum SEB SIXfunds SIXshares StockHouseCanada TSP TSX Tdefunds Tdwaterhouse Tiaacref Troweprice Trustnet Union USFedBonds VWD ZA Cominvest Finanzpartner Yahoo::Asia Yahoo::Australia Yahoo::Brasil Yahoo::Europe Yahoo::NZ Yahoo::USA/; } $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; # The response should be a single value (the exchange rate) my $data = $ua->request(GET "${YAHOO_CURRENCY_URL}${from}${to}=X")->content; my $exchange_rate = $data; $exchange_rate =~ s/,// ; # solve a bug when conversion rate # involves thousands. yahoo inserts # a comma when thousands occur { 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; $inforef->{$symbol, "a"} = sprintf ("Defaults: Year %d, Month %s, Day %d\n", $year, $month, $day); # 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. 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 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 Finance-Quote-1.18/lib/Finance/Quote/AEX.pm000644 000765 000024 00000016475 12032045420 020021 0ustar00ecstaff000000 000000 #!/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) 2003, Pawel Konieczny # Copyright (C) 2004, Johan van Oostrum # Copyright (C) 2009, Herman van Rink # # 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::AEX; use vars qw($VERSION $AEX_URL); use LWP::UserAgent; use HTTP::Request::Common qw(POST); use HTML::TableExtract; use CGI; $VERSION = '1.18'; # URLs of where to obtain information my $AEX_URL = "http://www.euronext.com/search/download/trapridownloadpopup.jcsv?pricesearchresults=actif&filter=1&belongsToList=market_EURLS&mep=8626&lan=NL&resultsTitle=Amsterdam+-+Euronext&cha=1800&format=txt&formatDecimal=.&formatDate=dd/MM/yy"; sub methods { return (dutch => \&aex, aex => \&aex) } { my @labels = qw/name symbol price last date time p_change bid ask offer open high low close volume currency method exchange/; sub labels { return (dutch => \@labels, aex => \@labels) } } # ============================================================================== ######################################################################## # Stocks and indices sub aex { my $quoter = shift; my @symbols = @_; return unless @symbols; my (%info,$url,$reply,$te); my ($row, $datarow, $matches); my ($time); $url = $AEX_URL; # base url # Create a user agent object and HTTP headers my $ua = new LWP::UserAgent(agent => 'Mozilla/4.0 (compatible; MSIE 5.5; Windows 98)'); # Compose POST request my $request = new HTTP::Request("GET", $url); $reply = $ua->request( $request ); #print Dumper $reply; if ($reply->is_success) { # Write retreived data to temp file for debugging use POSIX; my $filename = tmpnam(); open my $fw, ">", $filename or die "$filename: $!"; print $fw $reply->content; close $fw; # Open reply to read lins open FP, "<", \$reply->content or die "Unable to read data: $!"; # Open temp file instead while debugging #open FP, "<", $filename or die "Unable to read data: $!"; # Skip the first 4 lines, which are not CSV my $dummy = ; # Typical content: Stocks $dummy = ; # Typical content: Amsterdam - Euronext $dummy = ; # Typical content: $dummy = ; # Typical content: Instrument's name;ISIN;Euronext code;Market;Symbol;ICB Sector (Level 4);Handelsvaluta;Laatst;Aantal;D/D-1 (%);Datum-tijd (CET);Omzet;Totaal aantal aandelen;Capitalisation;Trading mode;Dag Open;Dag Hoog;Dag Hoog / Datum-tijd (CET);Dag Laag;Dag Laag / Datum-tijd (CET); 31-12/Change (%); 31-12/Hoog; 31-12/Hoog/Datum; 31-12/Laag; 31-12/Laag/Datum; 52 weken/Change (%); 52 weken/Hoog; 52 weken/Hoog/Datum; 52 weken/Laag; 52 weken/Laag/Datum;Suspended;Suspended / Datum-tijd (CET);Reserved;Reserved / Datum-tijd (CET) while (my $line = ) { #print Dumper $line; my @row_data = $quoter->parse_csv_semicolon($line); #print Dumper \@row_data; my $row = \@row_data; #print Dumper $row; next unless @row_data; foreach my $symbol (@symbols) { my $found = 0; # Match Fund's name, ISIN or symbol if ( @$row[0] eq $symbol || @$row[1] eq $symbol || @$row[4] eq $symbol ) { $info {$symbol, "exchange"} = "Amsterdam Euronext eXchange"; $info {$symbol, "method"} = "aex"; $info {$symbol, "symbol"} = @$row[4]; ($info {$symbol, "last"} = @$row[7]) =~ s/\s*//g; $info {$symbol, "bid"} = undef; $info {$symbol, "offer"} = undef; $info {$symbol, "low"} = @$row[18]; $info {$symbol, "close"} = undef; $info {$symbol, "p_change"} = @$row[9]; ($info {$symbol, "high"} = @$row[16]) =~ s/\s*//g; ($info {$symbol, "volume"} = @$row[8]) =~ s/\s*//g; # Split the date and time from one table entity my $dateTime = @$row[10]; # Check for "dd mmm yyyy hh:mm" date/time format like "01 Aug 2004 16:34" if ($dateTime =~ m/(\d{2})\/(\d{2})\/(\d{2}) \s (\d{2}:\d{2})/xi ) { $quoter->store_date(\%info, $symbol, {month => $2, day => $1, year => $3}); } $info {$symbol, "currency"} = "EUR"; $info {$symbol, "success"} = 1; } } } } foreach my $symbol (@symbols) { unless ( !defined($info {$symbol, "success"}) || $info {$symbol, "success"} == 1 ) { $info {$symbol,"success"} = 0; $info {$symbol,"errormsg"} = "Fund name $symbol not found"; next; } } #print Dumper \%info; return %info if wantarray; return \%info; } 1; =head1 NAME Finance::Quote::AEX Obtain quotes from Amsterdam Euronext eXchange =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("aex","AAB 93-08 7.5"); # Only query AEX %info = Finance::Quote->fetch("dutch","AAB 93-08 7.5"); # Failover to other sources OK =head1 DESCRIPTION This module fetches information from the "Amsterdam Euronext eXchange AEX" http://www.aex.nl. Only local Dutch investment funds and all traded here options and futures are available. This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "AEX" in the argument list to Finance::Quote->new(). Information obtained by this module may be covered by www.aex.nl terms and conditions See http://www.aex.nl/ for details. =head2 Stocks And Indices This module provides both the "aex" and "dutch" fetch methods for fetching stock and index quotes. Please use the "dutch" fetch method if you wish to have failover with future sources for Dutch stocks. Using the "aex" method will guarantee that your information only comes from the Euronext Amsterdam website. Note that options and futures are not supported by this module. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::AEX : name, last, date, p_change, bid, offer, open, high, low, close, volume, currency, method, exchange, time. =head1 SEE ALSO Amsterdam Euronext eXchange, http://www.aex.nl =cut Finance-Quote-1.18/lib/Finance/Quote/AIAHK.pm000644 000765 000024 00000012146 12032045420 020210 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # This module is based on a perl script from Wouter van Marle # and on the existing # Finance::Quote::ASEGR module. # # The two were compined by David Hampton to # be able to retrieve stock information from the American # International Assurance website in Hong Kong. # # 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 require 5.005; use strict; package Finance::Quote::AIAHK; use vars qw($VERSION $AIAHK_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION = '1.18'; $AIAHK_URL = 'http://www.aia.com.hk/daily/fund_mst_rightb.asp?cat=BR_AC'; sub methods { return (aiahk => \&aiahk); } { my @labels = qw/name code date isodate price bid offer p_change_3m p_change_1y p_change_3y currency method exchange/; sub labels { return (aiahk => \@labels); } } sub aiahk { my $quoter = shift; my @funds = @_; my (%info,$reply,$url,$te,$fund); my $ua = $quoter->user_agent(); $url=$AIAHK_URL; $reply = $ua->request(GET $url); if (!$reply->is_success) { print("1\n"); foreach my $fund (@funds) { print("2\n"); $info{$fund, "success"}=0; $info{$fund, "errormsg"}="Error retreiving fund quote page."; } return wantarray() ? %info : \%info; } #print($reply->content, "\n"); # Now parse the data table contained in the result. This is the # inner of two tables. There are no headers on this table as they # are part of the iframe containing this page. $te= new HTML::TableExtract(depth => 1); $te->parse($reply->content); unless ($te->tables) { foreach $fund (@funds) { $info {$fund,"success"} = 0; $info {$fund,"errormsg"} = "Error parsing fund table"; } return wantarray() ? %info : \%info; } # Was there a parse failure? If so, record an error for each # requested find and get out now. my @rows; unless (@rows = $te->rows) { foreach $fund (@funds) { $info {$fund,"success"} = 0; $info {$fund,"errormsg"} = "Parse error"; } return wantarray() ? %info : \%info; } # Now find the data for the requested funds. This is an O(n^^2) # algorithm; no way around it. foreach $fund (@funds) { my $found = 0; foreach my $row (@rows) { next if $$row[1] ne $fund; my $tmp; $info{$fund, "success"}=1; $info{$fund, "exchange"}="American International Assurance, Hong Kong"; $info{$fund, "method"}="aiahk"; $info{$fund, "name"}=$$row[0]; $info{$fund, "name"} =~ s/^\s*(.*)\s*$/$1/; $info{$fund, "symbol"}=$fund; $quoter->store_date(\%info, $fund, {usdate => $$row[2]}); if ($$row[3] =~ /yield/i) { ($info{$fund, "yield"}) = $$row[3] =~ m/yield = ([0-9.%]+)/i; } else { ($tmp=$$row[3]) =~ s/\s*//g; ($info{$fund, "currency"}, $info{$fund, "bid"}) = $tmp =~ m/([A-Z]+)[^0-9]+([0-9.]+)/; ($tmp=$$row[4]) =~ s/\s*//g; ($tmp, $info{$fund, "offer"}) = $tmp =~ m/([A-Z]+)[^0-9]+([0-9.]+)/; $info{$fund, "price"} = $info{$fund, "bid"}; $info{$fund,"currency"}="USD" if $info{$fund,"currency"} eq "US"; $info{$fund,"currency"}="HKD" if $info{$fund,"currency"} eq "HK"; $info{$fund,"currency"}="JPY" if $info{$fund,"currency"} eq "YEN"; } # $info{$fund, "p_change_3m"}=$$row[5]; # $info{$fund, "p_change_1y"}=$$row[6]; # $info{$fund, "p_change_3y"}=$$row[7]; $found = 1; last; } $info{$fund, "success"}=$found; $info{$fund, "errormsg"}="Fund $fund not found in list " if !$found; } return wantarray() ? %info : \%info; } 1; =head1 NAME Finance::Quote::AIAHK Obtain quotes from American International Assurance =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("aiahk","SCH-HKEQ"); =head1 DESCRIPTION This module fetches information from the American International Assurance http://www.aia.com.hk. All funds are available. This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "AIAHK" in the argument list to Finance::Quote->new(). Information obtained by this module may be covered by www.aia.com.hk terms and conditions See http://www.aia.com.hk/ for details. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::AIAHK : name code date isodate price bid offer p_change_3m p_change_1y p_change_3y currency method exchange =head1 SEE ALSO American International Assurance, http://www.aia.com.hk =cut Finance-Quote-1.18/lib/Finance/Quote/ASEGR.pm000644 000765 000024 00000010465 12032045420 020236 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # This modules is based on the Finance::Quote::AEX module # # The code has been modified by Morten Cools to be able to # retrieve stock information from the Athens Exchange in Greece. # # 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 require 5.005; use strict; package Finance::Quote::ASEGR; use vars qw($VERSION $ASEGR_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION = '1.18'; my $ASEGR_URL = 'http://www.ase.gr/content/en/MarketData/Stocks/Prices/Share_SearchResults.asp?'; sub methods { return ( greece => \&asegr, asegr => \&asegr, europe => \&asegr); } { my @labels = qw/name last date isodate p_change open high low close volume currency method exchange/; sub labels { return (greece => \@labels, asegr => \@labels, europe => \@labels); } } sub asegr { my $quoter = shift; my @stocks = @_; my (%info,$reply,$url,$te); my $ua = $quoter->user_agent(); $url=$ASEGR_URL; foreach my $stocks (@stocks) { $reply = $ua->request(GET $url.join('',"share=",$stocks)); if ($reply->is_success) { $te= new HTML::TableExtract( headers => [("Date","Price","\%Change","Volume","Max","Min","Value","Trades","Open")]); $te->parse($reply->content); unless ( $te->tables) { $info {$stocks,"success"} = 0; $info {$stocks,"errormsg"} = "Stock name $stocks not found"; next; } my @rows; unless (@rows = $te->rows) { $info {$stocks,"success"} = 0; $info {$stocks,"errormsg"} = "Parse error"; next; } $info{$stocks, "success"}=1; $info{$stocks, "exchange"}="Athens Stock Exchange"; $info{$stocks, "method"}="asegr"; $info{$stocks, "name"}=$stocks; ($info{$stocks, "last"}=$rows[0][1]) =~ s/\s*//g; ($info{$stocks, "close"}=$rows[1][1]) =~ s/\s*//g; ($info{$stocks, "p_change"}=$rows[0][2]) =~ s/\s*//g; ($info{$stocks, "volume"}=$rows[0][3]) =~ s/\s*//g; ($info{$stocks, "high"}=$rows[0][4]) =~ s/\s*//g; ($info{$stocks, "low"}=$rows[0][5]) =~ s/\s*//g; ($info{$stocks, "nav"}=$rows[0][6]) =~ s/\s*//g; ($info{$stocks, "open"}=$rows[0][8]) =~ s/\s*//g; $quoter->store_date(\%info, $stocks, {eurodate => $rows[0][0]}); $info{$stocks,"currency"}="EUR"; } else { $info{$stocks, "success"}=0; $info{$stocks, "errormsg"}="Error retreiving $stocks "; } } return wantarray() ? %info : \%info; return \%info; } 1; =head1 NAME Finance::Quote::ASEGR Obtain quotes from Athens Stock Exchange. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("asegr","minoa"); # Only query ASEGR %info = Finance::Quote->fetch("greece","aaak"); # Failover to other sources OK. =head1 DESCRIPTION This module fetches information from the "Athens Stock Exchange", http://www.ase.gr. All stocks are available. This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "ASEGR" in the argument list to Finance::Quote->new(). This module provides both the "asegr" and "greece" fetch methods. Please use the "greece" fetch method if you wish to have failover with future sources for Greek stocks. Using the "asegr" method will guarantee that your information only comes from the Athens Stock Exchange. Information obtained by this module may be covered by www.ase.gr terms and conditions See http://www.ase.gr/ for details. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::ASEGR : name, last, date, p_change, open, high, low, close, volume, currency, method, exchange. =head1 SEE ALSO Athens Stock Exchange, http://www.ase.gr =cut Finance-Quote-1.18/lib/Finance/Quote/ASX.pm000644 000765 000024 00000014771 12032045420 020034 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # # Copyright (C) 1998, Dj Padzensky # Copyright (C) 1998, 1999 Linas Vepstas # Copyright (C) 2000, Yannick LE NY # Copyright (C) 2000, Brent Neal # Copyright (C) 2001, Leigh Wedding # Copyright (C) 2000-2004, Paul Fenwick # # 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::ASX; use HTTP::Request::Common; use LWP::UserAgent; use HTML::TableExtract; use vars qw/$ASX_URL $VERSION/; $VERSION = '1.18'; $ASX_URL = 'http://www.asx.com.au/asx/markets/priceLookup.do?by=asxCodes&asxCodes='; sub methods {return (australia => \&asx,asx => \&asx)} { my @labels = qw/name last p_change bid offer high low volume price method exchange/; sub labels { return (australia => \@labels, asx => \@labels); } } # Australian Stock Exchange (ASX) # The ASX provides free delayed quotes through their webpage. # # Maintainer of this section is Paul Fenwick # 5-May-2001 Updated by Leigh Wedding sub asx { my $quoter = shift; my @stocks = @_; return unless @stocks; my %info; my $ua = $quoter->user_agent; my $response = $ua->request(GET $ASX_URL.join("%20",@stocks)); unless ($response->is_success) { foreach my $stock (@stocks) { $info{$stock,"success"} = 0; $info{$stock,"errormsg"} = "HTTP session failed"; } return wantarray() ? %info : \%info; } my $te = HTML::TableExtract->new( automap => 0, headers => ["Code", "Last", '\+/-', "Bid", "Offer", "Open", "High", "Low", "Vol"]); $te->parse($response->content); # Extract table contents. my @rows; unless (($te->tables > 0) && ( @rows = $te->rows)) { foreach my $stock (@stocks) { $info{$stock,"success"} = 0; $info{$stock,"errormsg"} = "Failed to parse HTML table."; } return wantarray() ? %info : \%info; } # Pack the resulting data into our structure. foreach my $row (@rows) { my $stock = shift(@$row); # Skip any blank lines. next unless $stock; # Delete spaces and '*' which sometimes appears after the code. # Also delete high bit characters. $stock =~ tr/* \200-\377//d; # Delete any whitespace characters $stock =~ s/\s//g; $info{$stock,'symbol'} = $stock; foreach my $label (qw/last p_change bid offer open high low volume/) { $info{$stock,$label} = shift(@$row); # Again, get rid of nasty high-bit characters. $info{$stock,$label} =~ tr/ \200-\377//d unless ($label eq "name"); } # If that stock does not exist, it will have a empty # string for all the fields. The "last" price should # always be defined (even if zero), if we see an empty # string here then we know we've found a bogus stock. if ($info{$stock,'last'} eq '') { $info{$stock,'success'} = 0; $info{$stock,'errormsg'}="Stock does not exist on ASX."; next; } # Drop commas from volume. $info{$stock,"volume"} =~ tr/,//d; # The ASX returns zeros for a number of things if there # has been no trading. This not only looks silly, but # can break things later. "correct" zero'd data. foreach my $label (qw/open high low/) { if ($info{$stock,$label} == 0) { $info{$stock,$label} = $info{$stock,"last"}; } } # We get a dollar plus/minus change, rather than a # percentage change, so we convert this into a # percentage change, as required. We should never have # zero opening price, but if we do warn about it. if ($info{$stock,"open"} == 0) { warn "Zero opening price in p_change calcuation for ". "stock $stock. P_change set to zero."; $info{$stock,"p_change"} = 0; } else { $info{$stock,"p_change"} = sprintf("%.2f", ($info{$stock,"p_change"}*100)/ $info{$stock,"open"}); } # Australian indexes all begin with X, so don't tag them # as having currency info. $info{$stock, "currency"} = "AUD" unless ($stock =~ /^X/); $info{$stock, "method"} = "asx"; $info{$stock, "exchange"} = "Australian 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::ASX - Obtain quotes from the Australian Stock Exchange. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %stockinfo = $q->fetch("asx","BHP"); # Only query ASX. %stockinfo = $q->fetch("australia","BHP"); # Failover to other sources OK. =head1 DESCRIPTION This module obtains information from the Australian Stock Exchange http://www.asx.com.au/. All Australian stocks and indicies are available. Indexes start with the letter 'X'. For example, the All Ordinaries is "XAO". This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "ASX" in the argument list to Finance::Quote->new(). This module provides both the "asx" and "australia" fetch methods. Please use the "australia" fetch method if you wish to have failover with other sources for Australian stocks (such as Yahoo). Using the "asx" method will guarantee that your information only comes from the Australian Stock Exchange. Information returned by this module is governed by the Australian Stock Exchange's terms and conditions. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::ASX: date, bid, ask, open, high, low, last, close, p_change, volume, and price. =head1 SEE ALSO Australian Stock Exchange, http://www.asx.com.au/ Finance::Quote::Yahoo::Australia. =cut Finance-Quote-1.18/lib/Finance/Quote/BMONesbittBurns.pm000644 000765 000024 00000016366 12032045420 022363 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # # Copyright (C) 2003, Rob Clark # # 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. # # require 5.005; use strict; package Finance::Quote::BMONesbittBurns; use vars qw($VERSION $BMO_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION = '1.18'; # URLs of where to obtain information my $BMO_URL = 'http://bmonesbittburns.com/QuickQuote/QuickQuote.asp?Symbol='; sub methods { return (bmonesbittburns => \&bmonesbittburns) } sub labels { return (bmonesbittburns => [qw/name last p_change bid offer open high low volume currency method exchange date isodate time/]) }; # ============================================================================== sub bmonesbittburns { my $quoter = shift; my @symbols = @_; return unless @symbols; my($url, $reply, $te); my(%info); my $ua = $quoter->user_agent; # user_agent $url = $BMO_URL; # base url foreach my $symbol (@symbols) { $reply = $ua->request(GET $url.join('',$symbol)); if ($reply->is_success) { #print STDERR $reply->content,"\n"; $te = new HTML::TableExtract( depth => 2); # parse table $te->parse($reply->content); # check for a page without tables. # This gets returned when a bad symbol name is given. unless ( $te->tables ) { $info {$symbol,"succes"} = 0; $info {$symbol,"errormsg"} = "Fund name $symbol not found, bad symbol name"; next; } if (0) { my ($table, $row); # Old style, using top level methods rather than table state objects. foreach $table ($te->tables) { print "Table (", join(',', $te->table_coords($table)), "):\n"; foreach $row ($te->rows($table)) { print join(',', @$row), "\n"; } } } # extract table contents my($ignored, $stock_info, $data) = $te->table_states; my(@rows) = $data->rows; unless ($stock_info && $rows[0][1] !~ /Error/) { $info {$symbol,"success"} = 0; $info {$symbol,"errormsg"} = "Parse error"; next; } my(@info_row) = $stock_info->rows; if ( $info_row[0][2] !~ /\w/ ) { # No text name associated with the stock, use the symbol name $info {$symbol, "name"} = $symbol; } else { $info {$symbol, "name"} = $info_row[0][2]; } # Strip leading and trailing spaces $info {$symbol, "name"} =~ s/^\s*//; $info {$symbol, "name"} =~ s/\s*$//; $info {$symbol, "success"} = 1; $info {$symbol, "exchange"} = "BMO Nesbitt Burns"; $info {$symbol, "method"} = "bmonesbittburns"; ($info {$symbol, "last"} = $rows[ 1][2]) =~ s/\s*//g; # Remove spaces ($info {$symbol, "p_change"} = $rows[ 2][5]) =~ s/\s*//g; ($info {$symbol, "close"} = $rows[ 3][5]) =~ s/\s*//g; ($info {$symbol, "bid"} = $rows[ 4][2]) =~ s/\s*//g; ($info {$symbol, "offer"} = $rows[ 4][5]) =~ s/\s*//g; ($info {$symbol, "open"} = $rows[ 6][2]) =~ s/\s*//g; ($info {$symbol, "volume"} = $rows[ 6][5]) =~ s/\s*//g; ($info {$symbol, "high"} = $rows[ 7][2]) =~ s/\s*//g; ($info {$symbol, "low"} = $rows[ 7][5]) =~ s/\s*//g; if ($#rows >= 9) { ($info {$symbol, "eps"} = $rows[10][2]) =~ s/\s*//g; ($info {$symbol, "pe"} = $rows[10][5]) =~ s/\s*//g; ($info {$symbol, "div_yield"} = $rows[12][5]) =~ s/\s*//g; $rows[9][2] =~ s/[^\d\.]*//g; # Strip spaces and funky 8-bit characters $rows[9][5] =~ s/[^\d\.]*//g; $info {$symbol, "year_range"} = $rows[9][5] . " - " . $rows[9][2]; } # This site appears to provide either a date or a time but not both my($dt) = $rows[3][2]; if ($dt =~ /:/) { ($info {$symbol, "time"} = "$dt:00") =~ s/\s*//g; $quoter->store_date(\%info, $symbol, {today => 1}); } else { my ($month, $day) = ($dt =~ /([0-9]+)\/([0-9]+)/); $quoter->store_date(\%info, $symbol, {day => $day, month => $month}); $info {$symbol, "time"} = "00:00:00"; } # If this was a US exchange, currency in US$ if ($symbol =~ /,X$/) { $info {$symbol, "currency"} = "USD"; } else { $info {$symbol, "currency"} = "CAD"; } $info {$symbol, "success"} = 1; # Walk through our fields and remove high-ascii # characters which may have snuck in. foreach (@{labels()}) { $info{$symbol,$_} =~ tr/\200-\377//d; } } else { $info {$symbol, "success"} = 0; $info {$symbol, "errormsg"} = "Error retreiving $symbol "; } } return %info if wantarray; return \%info; } 1; =head1 NAME Finance::Quote::BMONesbittBurns Obtain quotes from the BMO NesbittBurns site =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("bmonesbittburns","NT,X"); =head1 DESCRIPTION This module fetches information from the "BMO NesbittBurns Quitre Qote" site. Most Canadiam and US stocks as well as Canadian Mutual Funds are available. The symbolm representing a stock or mutual fund is composed of the stock symbol, a comma, and then the index or type. The following indexes and types are supported: T Toronto Stock Exchange MF Canadian Mutaul Fund V Canadian venture Exchange I Index X U.S Stocks (most exchanges) This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "BMONesbittBurns" in the argument list to Finance::Quote->new(). Information obtained by this module may be covered by BMO Nesbitt Burns terms and conditions. See http://bmonesbittburns.com/ for details. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::BMONesbittBurns : name, last, date, p_change, bid, offer, open, high, low, volume, currency, method, exchange, time, date. =head1 SEE ALSO BMO Nesbitt-Burns http://bmonesbittburns.com/QuickQuote/QuickQuote.asp =cut Finance-Quote-1.18/lib/Finance/Quote/Bourso.pm000644 000765 000024 00000021710 12032045420 020641 0ustar00ecstaff000000 000000 #!/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) 2005, Morten Cools # Copyright (C) 2006, Dominique Corbex # Copyright (C) 2008, Bernard Fuentes # Copyright (C) 2009, Erik Colson # # 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. # # # Changelog # # 2009-04-12 Erik Colson # # * Major site change. # # 2008-11-09 Bernard Fuentes # # * changes on website # # 2006-12-26 Dominique Corbex # # * (1.4) changes on web site # # 2006-09-02 Dominique Corbex # # * (1.3) changes on web site # # 2006-06-28 Dominique Corbex # # * (1.2) changes on web site # # 2006-02-22 Dominique Corbex # # * (1.0) iniial release # require 5.005; use strict; package Finance::Quote::Bourso; use vars qw($VERSION $Bourso_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TreeBuilder; # Boursorama doesn't put data in table elements anymore but uses
$VERSION = '1.18'; my $Bourso_URL = 'http://www.boursorama.com/recherche/index.phtml'; sub methods { return ( france => \&bourso, bourso => \&bourso, europe => \&bourso); } { my @labels = qw/name last date isodate p_change open high low close volume currency method exchange/; sub labels { return (france => \@labels, bourso => \@labels, europe => \@labels); } } sub bourso_to_number { my $x = shift(@_); $x =~ s/\s//g ; # remove spaces etc in number return $x; } sub bourso { my $quoter = shift; my @stocks = @_; my (%info,$reply,$url,$te,$ts,$row,$style); my $ua = $quoter->user_agent(); $url=$Bourso_URL; foreach my $stocks (@stocks) { my $queryUrl = $url.join('',"?search[query]=", $stocks). "&search[type]=rapide&search[categorie]=STK&search[bourse]=country:33"; $reply = $ua->request(GET $queryUrl); # print "URL=".$queryUrl."\n"; if ($reply->is_success) { # print $reply->content; $info{$stocks,"success"} = 1; my $tree = HTML::TreeBuilder->new_from_content($reply->content); # retrieve SYMBOL my @symbolline = $tree->look_down('class','isin'); unless (@symbolline) { $info {$stocks,"success"} = 0; $info {$stocks,"errormsg"} = "Stock name $stocks not found"; next ; }; my $symbol = ($symbolline[0]->content_list)[0]; ($symbol) = ($symbol=~m/(\w+)/); $info{$stocks,"symbol"}=$symbol; # retrieve NAME my @nameline = $tree->look_down('class','nomste'); unless (@nameline) { $info {$stocks,"success"} = 0; $info {$stocks,"errormsg"} = "Stock name $stocks not retrievable"; next ; }; my $name = $nameline[0]->as_text; $info{$stocks,"name"}=$name; # set method $info{$stocks,"method"} = "bourso" ; #holds table data my %tempinfo; # retrieve other data my $infoclass = ($tree->look_down('class','info1'))[0]; unless ($infoclass) { my $opcvm = ($tree->look_down('id','opcvm_headerFund_0'))[0]; unless ($opcvm) { $info {$stocks,"success"} = 0; $info {$stocks,"errormsg"} = "$stocks retrieval not supported."; next ; } # the stock is a delayed OPCVM my $infoelem = ($tree->look_down('id','content-gauche'))[0]; $infoelem = ($infoelem->look_down('class','TabContenu'))[0]; my @rows = $infoelem->look_down('_tag','tr'); foreach my $i (0..$#rows) { my $row = $rows[$i]; unless($row->attr('class')) { next; } my @cells = $row->look_down('_tag','td'); my $keytext = ($cells[0])->as_text; my $valuetext = ($cells[2])->as_text; $tempinfo{$keytext} = $valuetext; } } else { # regular stock my $infoelem = ($infoclass->look_down('class','info-valeur'))[0]; my @rows = $infoelem->look_down('_tag','tr'); foreach my $i (0..$#rows) { my $row = $rows[$i]; my @cells = $row->look_down('_tag','td'); my $j = 0; if ($cells[0]->attr('rowspan')) { $j = 1; } if ($cells[0]->attr('colspan')) { next; } my $keytext = ($cells[$j])->as_text; my $valuetext = ($cells[$j + 1])->as_text; $tempinfo{$keytext} = $valuetext; } } foreach my $key (keys %tempinfo) { # print "$key -> $tempinfo{$key}\n"; ASSIGN: for ( $key ) { # OPCVM /Valeur liquidative/ && do { my ($last, $currency) = ($tempinfo{$key} =~ m/(\d+(?:\s\d+)*(?:\.\d+)?)(?:\(c\))?(?:\s+(\w+))?/); $last = bourso_to_number($last); $info{$stocks,"last"} = $last; $info{$stocks,"currency"} = $currency; }; /Date/ && do { $info{$stocks,"date"} = $tempinfo{$key}; $quoter->store_date(\%info, $stocks, {eurodate => $info{$stocks,"date"}}); }; /Variation Veille/ && do { $info{$stocks,"p_change"}=$tempinfo{$key} }; # REGULAR STOCK /Cours/ && do { my ($last, $currency) = ($tempinfo{$key} =~ m/(\d+(?:\s\d+)*(?:\.\d+)?)(?:\(c\))?(?:\s+(\w+))?/); $last = bourso_to_number($last); $info{$stocks,"last"} = $last; $info{$stocks,"currency"} = $currency||"EUR"; # defaults to EUR my $exchange = $key; $exchange =~ s/.*Cours\s*(\w.*\w)\s*/$1/; # the exchange is in the $key here $info{$stocks,"exchange"} = $exchange ; }; /Variation/ && do { $info{$stocks,"p_change"}=$tempinfo{$key} }; /Dernier .change/ && do { my ($day,$month,$year) = ( $tempinfo{$key} =~ m|(\d\d)/(\d\d)/(\d\d)| ); $year+=2000; $info{$stocks,"date"}= sprintf "%02d/%02d/%04d",$day,$month,$year; $quoter->store_date(\%info, $stocks, {eurodate => $info{$stocks,"date"}}); }; /Volume/ && do { $info{$stocks,"volume"}=bourso_to_number($tempinfo{$key}); }; /Ouverture/ && do { $info{$stocks,"open"}=bourso_to_number($tempinfo{$key}); }; /Haut/ && do { $info{$stocks,"high"}=bourso_to_number($tempinfo{$key}); }; /Bas/ && do { $info{$stocks,"low"}=bourso_to_number($tempinfo{$key}); }; /Cl.ture veille/ && do { $info{$stocks,"previous"}=bourso_to_number($tempinfo{$key}); }; /Valorisation/ && do { $info{$stocks,"cap"}=$tempinfo{$key} ; $info{$stocks,"cap"} =~ s/[A-Z\s]//g ; # remove spaces and 'M' (millions) and currency (when not EUR) $info{$stocks,"cap"} =~ tr/,/./ ; # point instead of comma $info{$stocks,"cap"} *= 1000000 ; # valorisation is in millions }; } } $tree->delete ; } else { $info{$stocks, "success"}=0; $info{$stocks, "errormsg"}="Error retreiving $stocks "; } } return wantarray() ? %info : \%info; return \%info; } 1; =head1 NAME Finance::Quote::Bourso Obtain quotes from Boursorama. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("bourso","ml"); # Only query Bourso %info = Finance::Quote->fetch("france","af"); # Failover to other sources OK. =head1 DESCRIPTION This module fetches information from the "Paris Stock Exchange", http://www.boursorama.com. All stocks are available. This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "bourso" in the argument list to Finance::Quote->new(). This module provides both the "bourso" and "france" fetch methods. Please use the "france" fetch method if you wish to have failover with future sources for French stocks. Using the "bourso" method will guarantee that your information only comes from the Paris Stock Exchange. Information obtained by this module may be covered by www.boursorama.com terms and conditions See http://www.boursorama.com/ for details. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::Bourso : name, last, date, p_change, open, high, low, close, nav, volume, currency, method, exchange, symbol. =head1 SEE ALSO Boursorama (french web site), http://www.boursorama.com =cut Finance-Quote-1.18/lib/Finance/Quote/BSERO.pm000644 000765 000024 00000013056 12032045420 020246 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # This modules is based on the Finance::Quote::ASEGR module # # The code has been modified by Andrei Cipu to be able to # retrieve stock information from the Bucharest Exchange in Romania. # # 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 require 5.005; use strict; package Finance::Quote::BSERO; use vars qw($VERSION $BSERO_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION='0.1'; my $BSERO_URL = 'http://www.bvb.ro/mobile/m_SecurityDetails.aspx?'; sub methods { return ( romania => \&bsero, bsero => \&bsero, europe => \&bsero); } { my @labels = qw/name last date isodate p_change open high low close volume currency method exchange/; sub labels { return (romania => \@labels, bsero => \@labels, europe => \@labels); } } sub bsero { my $quoter = shift; my @stocks = @_; my (%info,$reply,$url,$te,$ts,$row,@cells, $ce); my($my_date,$my_last,$my_p_change,$my_volume,$my_high,$my_low,$my_open); my $ua = $quoter->user_agent(); $url = $BSERO_URL; foreach my $stocks (@stocks) { $reply = $ua->request(GET $url.join('',"s=",$stocks)); if ($reply->is_success) { $te = new HTML::TableExtract(); $te->parse($reply->content); unless ( $te->tables) { $info {$stocks,"success"} = 0; $info {$stocks,"errormsg"} = "Stock name $stocks not found"; next; } $ts = $te->first_table_found(); foreach $row ($ts->rows) { @cells = @$row; # The date is not a number, so we don't bother modifying it if($cells[0] eq 'Data'){ $my_date = $cells[1]; } #The rest of the data needs to be modified else { foreach $ce (@cells) { next unless $ce; $ce =~ s/\.//; #remove thouthand separator $ce =~ s/,/\./g; #replace european decimal separator with american ones } #go through each row and get the data if($cells[0] eq 'Ultimul pret'){ $my_last = $cells[1]; } if($cells[0] eq 'Var (%)'){ $my_p_change = $cells[1]; } if($cells[0] eq 'Volum'){ $my_volume = $cells[1]; } if($cells[0] eq 'Pret maxim'){ $my_high = $cells[1]; } if($cells[0] eq 'Pret minim'){ $my_low = $cells[1]; } if($cells[0] eq 'Pret deschidere'){ $my_open = $cells[1]; } } } $info{$stocks, "success"} =1; $info{$stocks, "exchange"} ="Bucharest Stock Exchange"; $info{$stocks, "method"} ="bsero"; $info{$stocks, "name"} =$stocks; $info{$stocks, "last"} =$my_last; $info{$stocks, "close"} =$my_last; $info{$stocks, "p_change"} =$my_p_change; $info{$stocks, "volume"} =$my_volume; $info{$stocks, "high"} =$my_high; $info{$stocks, "low"} =$my_low; $info{$stocks, "open"} =$my_open; $quoter->store_date(\%info, $stocks, {eurodate => $my_date}); $info{$stocks,"currency"} = "RON"; } else { $info{$stocks, "success"}=0; $info{$stocks, "errormsg"}="Error retreiving $stocks "; } } return wantarray() ? %info : \%info; return \%info; } 1; =head1 NAME Finance::Quote::BSERO Obtain quotes from Bucharest Stock Exchange. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("bsero","tlv"); # Only query BSERO %info = Finance::Quote->fetch("romania","brd"); # Failover to other sources OK. =head1 DESCRIPTION This module fetches information from the "Bucharest Stock Exchange" (Bursa de Valori Bucuresti), http://www.bvb.ro. All stocks are available. This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "BSERO" in the argument list to Finance::Quote->new(). This module provides both the "bsero" and "romania" fetch methods. Please use the "romania" fetch method if you wish to have failover with future sources for Romanian stocks. Using the "bsero" method will guarantee that your information only comes from the Bucharest Stock Exchange. Information obtained by this module may be covered by www.bvb.go terms and conditions See http://www.bvb.ro/ for details. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::BSERO : name, last, date, p_change, open, high, low, close, volume, currency, method, exchange. =head1 SEE ALSO Bucharest Stock Exchange, http://www.bvb.ro =cut Finance-Quote-1.18/lib/Finance/Quote/Cdnfundlibrary.pm000644 000765 000024 00000011224 12032045420 022335 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # Cdnfundlibrary.pm # # Version 0.6 retrieve more data via different fundlibrary.com url # Version 0.5 made functional again # Version 0.4 fixed up multiple lookup (March 3, 2001) # Version 0.3 fixed up yield lookup # Version 0.2 functional with Finance::Quote - added error-checking # Version 0.1 pre trial of parsing of info from www.fundlibrary.com package Finance::Quote::Cdnfundlibrary; require 5.004; use strict; use vars qw($VERSION $FUNDLIB_URL $FUNDLIB_MAIN_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION = '1.18'; # URLs of where to obtain information. $FUNDLIB_URL = ("http://www.fundlibrary.com/funds/db/_fundcard.asp?t=2&id="); $FUNDLIB_MAIN_URL=("http://www.fundlibrary.com"); sub methods { return (canadamutual => \&fundlibrary, fundlibrary => \&fundlibrary); } { my @labels = qw/method source link name currency last date isodate nav yield price net p_change/; sub labels { return (canadamutual => \@labels, fundlibrary => \@labels); } } # # ======================================================================= sub fundlibrary { my $quoter = shift; my @symbols = @_; # Make sure symbols are requested ##CAN exit more gracefully - add later## return unless @symbols; # Local Variables my(%fundquote, $mutual); my($ua, $url, $reply, $ts, $row, $rowhd, $te, @rows, @ts); $ua = $quoter->user_agent; foreach (@symbols) { $mutual = $_; $url = "$FUNDLIB_URL$mutual"; $reply = $ua->request(GET $url); $te = new HTML::TableExtract(headers => ["Date", "NAVPS"], slice_columns => 0); # Make sure something is returned ##CAN exit more gracefully - add later## return unless ($reply->is_success); $te->parse($reply->content); # Check for a page without tables # This gets returned when a bad symbol name is given unless ( $te->tables > 0 ) { $fundquote {$mutual,"success"} = 0; $fundquote {$mutual,"errormsg"} = "Fund name $mutual not found"; next; } # Fund name $reply->content =~ m#([^<]+)
#; $fundquote {$mutual, "name"} = $1; @rows = $te->rows; if(@rows) { $fundquote {$mutual, "symbol"} = $mutual; $fundquote {$mutual, "currency"} = "CAD"; $fundquote {$mutual, "source"} = $FUNDLIB_MAIN_URL; $fundquote {$mutual, "link"} = $url; $fundquote {$mutual, "method"} = "fundlibrary"; # Fund price and date $row = $rows[1]; $fundquote {$mutual, "price"} = $$row[2]; $fundquote {$mutual, "nav"} = $$row[2]; $fundquote {$mutual, "last"} = $$row[2]; $fundquote {$mutual, "net"} = $$row[3]; $fundquote {$mutual, "p_change"} = $$row[4]; $quoter->store_date(\%fundquote, $mutual, {usdate => $$row[0]}); # Assume things are fine here. $fundquote {$mutual, "success"} = 1; # Performance yield $fundquote {$mutual, "yield"} = $$row[5] if ($$row[5] ne "--"); } else { $fundquote {$mutual, "success"} = 0; $fundquote {$mutual, "errormsg"} = "Fund Not Found"; } } #end symbols return %fundquote if wantarray; return \%fundquote; } 1; =head1 NAME Finance::Quote::Cdnfundlibrary - Obtain mutual fund prices from www.fundlibrary.com =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %stockinfo = $q->fetch("canadamutual","fundlib-code"); # Can failover to other methods %stockinfo = $q->fetch("fundlibrary","fundlib-code"); # Use this module only. # NOTE: currently no failover methods exist for canadamutual =head1 DESCRIPTION This module obtains information about Canadian Mutual Fund prices from www.fundlibrary.com. The information source "canadamutual" can be used if the source of prices is irrelevant, and "fundlibrary" if you specifically want to use www.fundlibrary.com. =head1 FUNDLIB-CODE In Canada a mutual fund does not have a unique global symbol identifier. This module uses an id that represents the mutual fund on an id used by www.fundlibrary.com. There is no easy way of fetching the id except to jump onto the fundlibrary website, look up the fund and view the url for clues to its id number. =head1 LABELS RETURNED Information available from fundlibrary may include the following labels: exchange method link source name currency yield last nav price. The link label will be a url location for a one page snapshot that fundlibrary provides on the fund. =head1 SEE ALSO Fundlibrary website - http://www.fundlibrary.com/ Finance::Quote =cut Finance-Quote-1.18/lib/Finance/Quote/Cominvest.pm000644 000765 000024 00000011461 12032045420 021341 0ustar00ecstaff000000 000000 # # 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) 2007, Stephan Ebelt # # 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 initially derived from Padzensky's work on package # Finance::YahooQuote, but extends its capabilites to encompas a greater # number of data sources. # # This module (cominvest) derived from Finance::Quote::Fidelity because # it is technically very similar (they provide a list with all funds in # CSV format...). # # package Finance::Quote::Cominvest; require 5.005; use strict; use vars qw/$COMINVEST_URL $VERSION/; use LWP::UserAgent; use HTTP::Request::Common; $VERSION = '1.18'; $COMINVEST_URL = ('http://www.cominvest.de/_applications/fonds_application/FondsInfos/FondsInfos_PreiseAktuell_CSVFile.asp?b2b=0&noindex=1&noindex=1&lang=49'); sub methods { return ( cominvest => \&cominvest, adig => \&cominvest ); } sub labels { my @labels = qw/exchange name symbol bid ask date isodate yield price method p_change/; return ( cominvest => \@labels, adig => \@labels ); } # ======================================================================== # the cominvest routine gets quotes from "cominvest Asset Management GmbH" # sub cominvest { my $quoter = shift; my @symbols = @_; return unless @symbols; my(%info, @q, $sym, $k, $ua, $reply); # Build a small hash of symbols people want, because it provides a # quick and easy way to only return desired symbols. my %symbolhash; %symbolhash = map{$_, 1} @symbols; # Cominvest serves colon separated values (sort of csv's) $ua = $quoter->user_agent; $reply = $ua->request(GET $COMINVEST_URL); if($reply->is_success) { foreach (split('\015?\012',$reply->content)) { my @q = split(/;/) or next; $sym = ''; # Skip symbols we didn't ask for. next unless ( (defined($symbolhash{$q[1]}) and $sym=$q[1]) # ISIN or (defined($symbolhash{$q[2]}) and $sym=$q[2]) # WKN ); # convert decimal separator to intl. format foreach(@q) { s/,/\./; } $info{$sym, 'exchange'} = 'Cominvest'; $info{$sym, 'method'} = 'cominvest'; $info{$sym, 'name'} = $q[0]; $info{$sym, 'symbol'} = $sym; ($info{$sym, 'p_change'} = $q[8]) =~ s/\%//; $info{$sym, 'yield'} = $q[9]; $info{$sym, 'price'} = $q[7]; $info{$sym, 'bid'} = $q[7]; $info{$sym, 'ask'} = $q[6]; $info{$sym, 'currency'} = $q[3]; $quoter->store_date(\%info, $sym, {eurodate => $q[5]}); $info{$sym, 'success'} = 1; } # always return a status for all requested symbols foreach my $s (@symbols) { if( !$info{$s, 'success'} ) { $info{$s, 'success'} = 0; $info{$s, 'errormsg'} = 'No data returned'; } } } else { # set error on all symbols foreach my $sym (@symbols) { $info{$sym, 'success'} = 0; $info{$sym, 'errormsg'} = 'HTTP error: ' . $reply->status_line; } } return wantarray() ? %info : \%info; } 1; =head1 NAME Finance::Quote::Cominvest - Obtain information from cominvest, formerly known as Adig Investment. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch('cominvest', '637256'); %info = Finance::Quote->fetch('adig', 'DE0006372568'); =head1 DESCRIPTION This module obtains information from cominvest Asset Management http://www.cominvest-am.de/ - a german mutual fund company. It was formerly known as Adig Investments and thus an alias 'adig' is also provided. The name with which this module is called does not change its behavior. It may be asked for german WKNs or international ISINs. Information returned by this module is governed by the terms and conditions of cominvest Asset Management GmbH. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::Cominvest: exchange, name, bid, ask, date, yield, price, p_change. =head1 SEE ALSO cominvest Asset Management, http://www.cominvest-am.de/ =cut Finance-Quote-1.18/lib/Finance/Quote/Currencies.pm000644 000765 000024 00000034706 12032045420 021503 0ustar00ecstaff000000 000000 # 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 # package Finance::Quote::Currencies; use strict; use warnings; use base 'Exporter'; use vars qw/@EXPORT_OK $VERSION $YAHOO_CURRENCY_CONV_URL/; @EXPORT_OK = qw( known_currencies fetch_live_currencies ); $VERSION = '1.18'; use HTTP::Request::Common; use LWP::UserAgent; use HTML::Parser; use Encode; # This is the URL used to extract the currency list $YAHOO_CURRENCY_CONV_URL = 'http://uk.finance.yahoo.com/currency-converter'; # ======================================================================= # methods used by Finance::Quote to import public functions sub methods { return ( known_currencies => \&known_currencies , fetch_live_currencies => \&fetch_live_currencies ); } sub labels { return () }; # ======================================================================= # The current static currency list. # This list is generated using fetch_live_currencies my %currencies = ( ALL => { name => qq{Albanian Lek} } , DZD => { name => qq{Algerian Dinar} } , XAL => { name => qq{Aluminium Ounces} } , ARS => { name => qq{Argentine Peso} } , AWG => { name => qq{Aruba Florin} } , AUD => { name => qq{Australian Dollar} } , BSD => { name => qq{Bahamian Dollar} } , BHD => { name => qq{Bahraini Dinar} } , BDT => { name => qq{Bangladesh Taka} } , BBD => { name => qq{Barbados Dollar} } , BYR => { name => qq{Belarus Ruble} } , BZD => { name => qq{Belize Dollar} } , BMD => { name => qq{Bermuda Dollar} } , BTN => { name => qq{Bhutan Ngultrum} } , BOB => { name => qq{Bolivian Boliviano} } , BWP => { name => qq{Botswana Pula} } , BRL => { name => qq{Brazilian Real} } , GBP => { name => qq{British Pound} } , BND => { name => qq{Brunei Dollar} } , BGN => { name => qq{Bulgarian Lev} } , BIF => { name => qq{Burundi Franc} } , KHR => { name => qq{Cambodia Riel} } , CAD => { name => qq{Canadian Dollar} } , CVE => { name => qq{Cape Verde Escudo} } , KYD => { name => qq{Cayman Islands Dollar} } , XOF => { name => qq{CFA Franc (BCEAO)} } , XAF => { name => qq{CFA Franc (BEAC)} } , CLP => { name => qq{Chilean Peso} } , CNY => { name => qq{Chinese Yuan} } , COP => { name => qq{Colombian Peso} } , KMF => { name => qq{Comoros Franc} } , XCP => { name => qq{Copper Pounds} } , CRC => { name => qq{Costa Rica Colon} } , HRK => { name => qq{Croatian Kuna} } , CUP => { name => qq{Cuban Peso} } , CZK => { name => qq{Czech Koruna} } , DKK => { name => qq{Danish Krone} } , DJF => { name => qq{Dijibouti Franc} } , DOP => { name => qq{Dominican Peso} } , XCD => { name => qq{East Caribbean Dollar} } , ECS => { name => qq{Ecuador Sucre} } , EGP => { name => qq{Egyptian Pound} } , SVC => { name => qq{El Salvador Colon} } , ERN => { name => qq{Eritrea Nakfa} } , EEK => { name => qq{Estonian Kroon} } , ETB => { name => qq{Ethiopian Birr} } , EUR => { name => qq{Euro} } , FKP => { name => qq{Falkland Islands Pound} } , FJD => { name => qq{Fiji Dollar} } , GMD => { name => qq{Gambian Dalasi} } , GHC => { name => qq{Ghanian Cedi} } , GIP => { name => qq{Gibraltar Pound} } , XAU => { name => qq{Gold Ounces} } , GTQ => { name => qq{Guatemala Quetzal} } , GNF => { name => qq{Guinea Franc} } , GYD => { name => qq{Guyana Dollar} } , HTG => { name => qq{Haiti Gourde} } , HNL => { name => qq{Honduras Lempira} } , HKD => { name => qq{Hong Kong Dollar} } , HUF => { name => qq{Hungarian Forint} } , ISK => { name => qq{Iceland Krona} } , INR => { name => qq{Indian Rupee} } , IDR => { name => qq{Indonesian Rupiah} } , IRR => { name => qq{Iran Rial} } , IQD => { name => qq{Iraqi Dinar} } , ILS => { name => qq{Israeli Shekel} } , JMD => { name => qq{Jamaican Dollar} } , JPY => { name => qq{Japanese Yen} } , JOD => { name => qq{Jordanian Dinar} } , KZT => { name => qq{Kazakhstan Tenge} } , KES => { name => qq{Kenyan Shilling} } , KRW => { name => qq{South Korean Won} } , KWD => { name => qq{Kuwaiti Dinar} } , LAK => { name => qq{Lao Kip} } , LVL => { name => qq{Latvian Lat} } , LBP => { name => qq{Lebanese Pound} } , LSL => { name => qq{Lesotho Loti} } , LRD => { name => qq{Liberian Dollar} } , LYD => { name => qq{Libyan Dinar} } , LTL => { name => qq{Lithuanian Lita} } , MOP => { name => qq{Macau Pataca} } , MKD => { name => qq{Macedonian Denar} } , MWK => { name => qq{Malawi Kwacha} } , MYR => { name => qq{Malaysian Ringgit} } , MVR => { name => qq{Maldives Rufiyaa} } , MTL => { name => qq{Maltese Lira} } , MRO => { name => qq{Mauritania Ougulya} } , MUR => { name => qq{Mauritius Rupee} } , MXN => { name => qq{Mexican Peso} } , MDL => { name => qq{Moldovan Leu} } , MNT => { name => qq{Mongolian Tugrik} } , MAD => { name => qq{Moroccan Dirham} } , MMK => { name => qq{Myanmar Kyat} } , NAD => { name => qq{Namibian Dollar} } , NPR => { name => qq{Nepalese Rupee} } , ANG => { name => qq{Neth Antilles Guilder} } , TRY => { name => qq{Turkish Lira} } , NZD => { name => qq{New Zealand Dollar} } , NIO => { name => qq{Nicaragua Cordoba} } , NGN => { name => qq{Nigerian Naira} } , KPW => { name => qq{North Korean Won} } , NOK => { name => qq{Norwegian Krone} } , OMR => { name => qq{Omani Rial} } , XPF => { name => qq{Pacific Franc} } , PKR => { name => qq{Pakistani Rupee} } , XPD => { name => qq{Palladium Ounces} } , PAB => { name => qq{Panama Balboa} } , PGK => { name => qq{Papua New Guinea Kina} } , PYG => { name => qq{Paraguayan Guarani} } , PEN => { name => qq{Peruvian Nuevo Sol} } , PHP => { name => qq{Philippine Peso} } , XPT => { name => qq{Platinum Ounces} } , PLN => { name => qq{Polish Zloty} } , QAR => { name => qq{Qatar Rial} } , RON => { name => qq{Romanian New Leu} } , RUB => { name => qq{Russian Rouble} } , RWF => { name => qq{Rwanda Franc} } , WST => { name => qq{Samoa Tala} } , STD => { name => qq{Sao Tome Dobra} } , SAR => { name => qq{Saudi Arabian Riyal} } , SCR => { name => qq{Seychelles Rupee} } , SLL => { name => qq{Sierra Leone Leone} } , XAG => { name => qq{Silver Ounces} } , SGD => { name => qq{Singapore Dollar} } , SKK => { name => qq{Slovak Koruna} } , SIT => { name => qq{Slovenian Tolar} } , SBD => { name => qq{Solomon Islands Dollar} } , SOS => { name => qq{Somali Shilling} } , ZAR => { name => qq{South African Rand} } , LKR => { name => qq{Sri Lanka Rupee} } , SHP => { name => qq{St Helena Pound} } , SZL => { name => qq{Swaziland Lilageni} } , SEK => { name => qq{Swedish Krona} } , CHF => { name => qq{Swiss Franc} } , SYP => { name => qq{Syrian Pound} } , TWD => { name => qq{Taiwan Dollar} } , TZS => { name => qq{Tanzanian Shilling} } , THB => { name => qq{Thai Baht} } , TOP => { name => qq{Tonga Pa'ang} } , TTD => { name => qq{Trinidad & Tobago Dollar} } , TND => { name => qq{Tunisian Dinar} } , USD => { name => qq{United States Dollar} } , AED => { name => qq{UAE Dirham} } , UGX => { name => qq{Ugandan Shilling} } , UAH => { name => qq{Ukraine Hryvnia} } , UYU => { name => qq{Uruguayan New Peso} } , VUV => { name => qq{Vanuatu Vatu} } , VEF => { name => qq{Venezuelan Bolivar Fuerte}} , VND => { name => qq{Vietnam Dong} } , YER => { name => qq{Yemen Riyal} } , ZMK => { name => qq{Zambian Kwacha} } , ZWD => { name => qq{Zimbabwe dollar} } , SDG => { name => qq{Sudanese Pound} } ); # ======================================================================= # known_currencies (public function) # # This function returns the known currency list. This is based on the # cached currency list in this module. Use fetch_live_currencies for the # live list. sub known_currencies { return \%currencies; } # ======================================================================= # fetch_live_currencies (public function) # # This function retrieved the live currency list from the Yahoo Finance # website. This function should really only be used to test if the known # currency list in this module is out of date. sub fetch_live_currencies { my $ua = LWP::UserAgent->new(); my $data = $ua->request(GET $YAHOO_CURRENCY_CONV_URL)->content; my $p = HTML::Parser->new( start_h => [\&_start_handler, "tagname, attr"] , end_h => [\&_end_handler, "tagname"] , text_h => [\&_text_handler, "dtext"] ); # Avoid the "Parsing of undecoded UTF-8 will give garbage when decoding # entities" warning by forcing utf mode and encoding to utf8 $p->utf8_mode(1); $p->parse( Encode::encode_utf8($data) ); return _live_currencies(); } # Store state variables in a closure { # The currency hash my %live_currencies = (); # Keep track of being within a valid option tag (for text gathering) my $in_currency_list = 0; my $in_currency_option = 0; my $currency_text = ''; my $currency_code = ''; # _start_handler (private function) # # This is a HTML::Parser start tag handler sub _start_handler { my ($tagname, $attr) = @_; if ( lc $tagname eq 'select' && exists $attr->{name} && lc $attr->{name} eq 'currency-1' ) { # Reset status %live_currencies = (); # We're in the list $in_currency_list = 1; } elsif ( $in_currency_list == 1 && lc $tagname eq 'option' ) { $in_currency_option = 1; $currency_code = $attr->{value}; $currency_text = ''; } } # _end_handler (private function) # # This is a HTML::Parser end tag handler sub _end_handler { my ($tagname) = @_; if ( lc $tagname eq 'select' && $in_currency_list == 1 ) { # We're leaving the currency list $in_currency_list = 0; } elsif ( $in_currency_list == 1 && $in_currency_option == 1 && lc $tagname eq 'option' ) { # We're leaving an option # Build currency list item (strip code from name) $currency_text =~ s/\s*\([A-Z]+\)\s*$//; $live_currencies{$currency_code} = { name => $currency_text }; $in_currency_option = 0; } } # _text_handler (private function) # # This is a HTML::Parser text handler sub _text_handler { my ($dtext) = @_; if ( $in_currency_list == 1 && $in_currency_option == 1 ) { $currency_text .= $dtext; } } # _live_currencies (private function) # # Return data from within the closure sub _live_currencies { return \%live_currencies; } } 1; =head1 NAME Finance::Quote::Currencies - List of currencies from Yahoo Finance =head1 SYNOPSIS use Finance::Quote::Currencies; my $currencies = Finance::Quote::Currencies::known_currencies(); # Grab the latest from Yahoo my $live_currencies = Finance::Quote::Currencies::fetch_live_currencies(); =head1 DESCRIPTION This module provides a list of known currencies from Yahoo Currency Converter. The converter website includes a list of known currencies - this module includes a stored list =head1 LAST EXTRACT The currency list stored in this module was last copied from the live site: Sun Feb 15 18:01:12 GMT 2009 =head1 LICENSE 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. =head1 AUTHORS Bradley Dean =head1 SEE ALSO Yahoo Currency Converter - http://uk.finance.yahoo.com/currency-converter =cut Finance-Quote-1.18/lib/Finance/Quote/Deka.pm000644 000765 000024 00000006502 12032045420 020236 0ustar00ecstaff000000 000000 # Finance::Quote Perl module to retrieve prices of Deka funds # Copyright (C) 2005 Knut Franke # # 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 St, Fifth Floor, Boston, MA 02110-1301 USA package Finance::Quote::Deka; use strict; use HTML::TableExtract; require Crypt::SSLeay; use vars qw($VERSION); $VERSION = '1.18'; my $DEKA_URL = "https://www.deka.de/dn/useCases/fundsearch/UCFundsSearch.shtml?ACTION_FIELD=quickSearch"; sub methods {return (deka => \&deka);} sub labels { return (deka=>[qw/name date price last method/]); } # Trim leading and tailing whitespaces (also non-breakable whitespaces) sub trim { $_ = shift(); s/^\s*//; s/\s*$//; s/ //g; return $_; } # Convert number separators to US values sub convert_price { $_ = shift; s/\./@/g; s/,/\./g; s/@/,/g; return $_; } sub deka { my $quoter = shift; # The Finance::Quote object. my @stocks = @_; my $ua = $quoter->user_agent(); my %info; foreach my $stock (@stocks) { my $response = $ua->get($DEKA_URL . "&isin=" . $stock); # print $response->content, "\n"; $info{$stock,"success"} = 0; if (!$response -> is_success()) { $info{$stock,"errormsg"} = "HTTP failure"; } else { my @headers = [qw(Name ISIN Whg Datum)]; my $te = new HTML::TableExtract(headers => @headers, slice_columns => 0); $te->parse($response->content); foreach my $ts ($te->table_states) { # foreach my $row ($ts->rows) { # next if !defined $$row[0] || !defined $$row[1]; # print "Row: ", join('|', @$row), "\n"; # } foreach my $row ($ts->rows) { next if !defined $$row[0] || !defined $$row[1]; $info{$stock,"name"} = $$row[0]; $info{$stock,"currency"} = $$row[2]; $quoter->store_date(\%info, $stock, {eurodate => $$row[6]}); $info{$stock,"price"} = convert_price(trim($$row[4])); $info{$stock,"last"} = $info{$stock,"price"}; $info{$stock,"success"} = 1; $info{$stock,"method"} = "deka"; $info{$stock,"symbol"} = $stock; } } $info{$stock,"errormsg"} = "Couldn't parse deka website" if ($info{$stock,"success"} == 0); } } return wantarray ? %info : \%info; } 1; =head1 NAME Finance::Quote::Deka - Obtain fonds quotes from DekaBank. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new("Deka"); %info = Finance::Quote->fetch("deka","DE0008474511"); =head1 DESCRIPTION This module obtains fund prices from DekaBank, http://www.deka.de/. Deka website supports retrieval by name, WKN or ISIN. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::Deka: name, date, price, last, method. =head1 SEE ALSO DekaBank, http://www.deka.de/ Finance::Quote; =cut Finance-Quote-1.18/lib/Finance/Quote/DWS.pm000644 000765 000024 00000017172 12032045420 020034 0ustar00ecstaff000000 000000 #!/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 Crypt::SSLeay; use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; use LWP::Simple; use strict; use warnings; use vars qw/$VERSION/; $VERSION = '1.18'; 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 Finance-Quote-1.18/lib/Finance/Quote/Fidelity.pm000644 000765 000024 00000011271 12032045420 021142 0ustar00ecstaff000000 000000 #!/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::Fidelity; require 5.005; use strict; use vars qw/$FIDELITY_URL $VERSION/; use LWP::UserAgent; use HTTP::Request::Common; $VERSION = '1.18'; $FIDELITY_URL = ("http://activequote.fidelity.com/nav/fulllist.csv"); sub methods {return (fidelity => \&fidelity, fidelity_direct => \&fidelity);} { my @labels = qw/exchange name number nav change ask date isodate yield price method/; sub labels { return (fidelity => \@labels, fidelity_direct => \@labels); } } # ======================================================================= # the fidelity routine gets quotes from fidelity investments # sub fidelity { my $quoter = shift; my @symbols = @_; return unless @symbols; my(%aa, @q, $sym, $k, $ua, $reply); # Build a small hash of symbols people want, because it provides a # quick and easy way to only return desired symbols. my %symbolhash; %symbolhash = map{$_, 1} @symbols; # the fidelity pages are comma-separated-values (csv's) # Grab the page with all funds listed $ua = $quoter->user_agent; $reply = $ua->request(GET $FIDELITY_URL); if ($reply->is_success) { foreach (split('\015?\012',$reply->content)) { my @q = $quoter->parse_csv($_) or next; $sym = $q[2] or next; $sym =~ s/^ +//; # Skip symbols we didn't ask for. next unless (defined($symbolhash{$sym})); $aa {$sym, "exchange"} = "Fidelity"; # Fidelity $aa {$sym, "method"} = "fidelity_direct"; ($aa {$sym, "name"} = $q[0]) =~ s/^\s+//; $aa {$sym, "name"} =~ s/\s+$//; $aa {$sym, "symbol"} = $sym; ($aa {$sym, "number"} = $q[1]) =~ s/^\s+//; ($aa {$sym, "nav"} = $q[4]) =~ s/^\s+// if defined($q[4]); ($aa {$sym, "div"} = $q[5]) =~ s/^\s+// if defined($q[5]); ($aa {$sym, "net"} = $q[6]) =~ s/^\s+// if defined($q[6]); ($aa {$sym, "p_change"} = $q[8]) =~ s/^\s+// if defined($q[8]); ($aa {$sym, "yield"} = $q[9]) =~ s/^\s+// if defined($q[9]); ($aa {$sym, "yield"} = $q[17]) =~ s/^\s+// if defined($q[17]); $aa {$sym, "price"} = $aa{$sym, "nav"} if defined($q[4]); $aa {$sym, "success"} = 1; $aa {$sym, "currency"} = "USD"; $quoter->store_date(\%aa, $sym, {usdate => $q[19]}); } } return %aa if wantarray; return \%aa; } 1; =head1 NAME Finance::Quote::Fidelity - Obtain information from Fidelity Investments. =head1 NOTE NOTE NOTE NOTE NOTE This module is currently non-functional. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %info = Finance::Quote->fetch("fidelity","FBGRX"); %info = Finance::Quote->fetch("fidelity_direct","FBGRX"); =head1 DESCRIPTION This module obtains information from Fidelity Investments, http://www.fidelity.com/. This module is loaded by default on the Finance::Quote object. It is also possible to load this module explicitly by passing "Fidelity" as one of Finance::Quote->new()'s parameters. The "fidelity" fetch method may make use of failover modules. The "fidelity_direct" method will only obtain information directly from Fidelity. Information returned by this module is governed by Fidelity Investment's terms and conditions. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::Fidelity: exchange, name, number, nav, change, ask, date, yield, price. =head1 SEE ALSO Fidelity Investments, http://www.fidelity.com/ Finance::Quote::Yahoo::USA; =cut Finance-Quote-1.18/lib/Finance/Quote/FinanceCanada.pm000644 000765 000024 00000013444 12032045420 022030 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # # FinanceCanada.pm # # Version 0.1 Initial version # # Version 0.2 Rewrite by David Hampton for # changed web site. # package Finance::Quote::FinanceCanada; require 5.004; use strict; use vars qw/ $VERSION / ; use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION = '1.18'; my $FINANCECANADA_MAINURL = ("http://finance.canada.com/"); my $FINANCECANADA_URL = "http://stockgroup.canada.com/sn_overview.asp?symbol=T."; sub methods { return (canada => \&financecanada, financecanada => \&financecanada); } sub labels { my @labels = qw/method source name symbol currency last date isodate nav price/; return (canada => \@labels, financecanada => \@labels); } sub financecanada { my $quoter = shift; my @symbols = @_; my %info; return unless @symbols; my $ua = $quoter->user_agent; foreach my $symbol (@symbols) { my ($day_high, $day_low, $year_high, $year_low); $info{$symbol, "success"} = 0; $info{$symbol, "symbol"} = $symbol; $info{$symbol, "method"} = "financecanada"; $info{$symbol, "source"} = $FINANCECANADA_MAINURL; # Pull the data from the web site my $url = $FINANCECANADA_URL.$symbol; # print $url; my $response = $ua->request(GET $url); # print $response->content; if (!$response->is_success) { $info{$symbol, "errormsg"} = "Error contacting URL"; next; } # Parse the page looking for the table containing the full # name of the stock my $te = new HTML::TableExtract( depth => 2, count => 0); $te->parse($response->content); # debug # foreach my $ts ($te->table_states) { # print "\n***\n*** Table (", join(',', $ts->coords), "):\n***\n"; # foreach my $row ($ts->rows) { # print join(',', @$row), "\n"; # } # } foreach my $ts ($te->table_states) { my $row = $ts->row(0); $info{$symbol, "name"} = $row->[0] if ($row->[0] =~ s/^.([\w\s]+).*/$1/); } if (!defined($info{$symbol, "name"})) { $info{$symbol, "errormsg"} = "Invalid symbol"; next; } # Parse the page looking for the table containing the quote # details $te = new HTML::TableExtract(headers => [qw(Quote)], slice_columns => 0); $te->parse($response->content); # debug # foreach my $ts ($te->table_states) { # print "\n***\n*** Table (", join(',', $ts->coords), "):\n***\n"; # foreach my $row ($ts->rows) { # print join(',', @$row), "\n"; # } # } # Now parse the quote details. This method of parsing is # independent of which row contains which data item, so if the # web site reorders these it won't impact this code. foreach my $ts ($te->table_states) { foreach my $row ($ts->rows) { # Remove leading and trailing white space $row->[0] =~ s/^\s*(.+?)\s*$/$1/ if defined($row->[0]); $row->[1] =~ s/^\s*(.+?)\s*$/$1/ if defined($row->[1]); # Map the row into our data array for ($row->[0]) { /^Last Traded/ && do { s/Last Traded: (.*) ../$1/; $quoter->store_date(\%info, $symbol, { usdate => $_}); }; /^Last$/ && do { $info{$symbol, "last"} = $row->[1]; $info{$symbol, "price"} = $row->[1]; $info{$symbol, "nav"} = $row->[1]; last; }; /^Open$/ && do { $info{$symbol, "open"} = $row->[1]; last; }; /^Bid$/ && do { $info{$symbol, "bid"} = $row->[1]; last; }; /^Ask$/ && do { $info{$symbol, "ask"} = $row->[1]; last; }; /^% Change/ && do { $info{$symbol, "p_change"} = $row->[1]; $info{$symbol, "p_change"} =~ s/%//; last; }; /^Volume/ && do { $info{$symbol, "volume"} = $row->[1]; last; }; /^Close/ && do { $info{$symbol, "close"} = $row->[1]; last; }; /^Day High$/ && do { $info{$symbol, "high"} = $row->[1]; last; }; /^Day Low$/ && do { $info{$symbol, "low"} = $row->[1]; last; }; /^Year High$/ && do { $year_high = $row->[1]; last; }; /^Year Low$/ && do { $year_low = $row->[1]; last; }; $info{$symbol, "success"} = 1; }; } } if ($info{$symbol, "success"} == 1) { $info{$symbol, "currency"} = "CAD"; foreach (keys %info) { $info{$_} =~ s/\$//; } $info{$symbol, "day_range"} = $info{$symbol, "low"} . " - " . $info{$symbol, "high"} if (defined($info{$symbol, "high"}) && defined($info{$symbol, "low"})); if (defined($year_high) && defined($year_low)) { $info{$symbol, "year_range"} = "$year_low - $year_high"; } } else { $info{$symbol, "errormsg"} = "Cannot parse quote data"; } } return wantarray() ? %info : \%info; } 1; =head1 NAME Finance::Quote::FinanceCanada - Obtain stock and mutual fund prices from finance.canada.com =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; # Can failover to other methods %quotes = $q->fetch("canada", "stock_fund-code"); # Use this module only %quotes = $q->fetch("financecanada", "stock_fund-code"); =head1 DESCRIPTION This module obtains information about Canadian Stock and Mutual Funds from finanace.canada.com. The information source "canada" can be used if the information source is unimportant, or "financecanada" to specifically use finance.canada.com. =head1 STOCK_FUND-CODE Canadian stocks/mutual funds do not have a unique symbol identifier. This module uses the symbols as used on finance.canada.com. The simplest way to fetch the ID for a particular stock/fund is to go to finance.canada.com, search for your particular stock or mutual fund, and note the symbol ID. This is helpfully provided by the site in their returned HTML quote. =head1 LABELS RETURNED Information available from financecanada may include the following labels: method source name symbol currency date nav last price =head1 SEE ALSO Finance Canada.com website - http://finance.canada.com/ Finance::Quote =cut Finance-Quote-1.18/lib/Finance/Quote/Finanzpartner.pm000644 000765 000024 00000006300 12032045420 022207 0ustar00ecstaff000000 000000 # Finance::Quote Perl module to retrieve quotes from Finanzpartner.de # Copyright (C) 2007 Jan Willamowius # # 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 St, Fifth Floor, Boston, MA 02110-1301 USA package Finance::Quote::Finanzpartner; use strict; use HTML::TableExtract; use vars qw($VERSION); $VERSION = '1.18'; my $FINANZPARTNER_URL = "http://www.finanzpartner.de/fi/"; sub methods {return (finanzpartner => \&finanzpartner);} sub labels { return (finanzpartner=>[qw/name date price last method/]); } # TODO # Trim leading and tailing whitespaces (also non-breakable whitespaces) sub trim { $_ = shift(); s/^\s*//; s/\s*$//; s/ //g; return $_; } # Convert number separators to US values sub convert_price { $_ = shift; tr/.,/,./ ; return $_; } sub finanzpartner { my $quoter = shift; # The Finance::Quote object. my @stocks = @_; my $ua = $quoter->user_agent(); my %info; foreach my $stock (@stocks) { $ua->agent('Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 1.1.4322)'); my $response = $ua->get($FINANZPARTNER_URL . $stock . '/'); $info{$stock,"success"} = 0; if (!$response -> is_success()) { $info{$stock,"errormsg"} = "HTTP failure"; } else { my $te = new HTML::TableExtract(depth => 0, count => 2); $te->parse($response->content); my $table = $te->first_table_found; if (trim($table->cell(1,0)) ne 'Fondsname:') { $info{$stock,"errormsg"} = "Couldn't parse website"; } else { $info{$stock,"name"} = $table->cell(1,1); my $quote = $table->cell(6,1); my @part = split(/\s/, $quote); $info{$stock,"currency"} = $part[1]; $part[2] =~ s/\(//g; $part[2] =~ s/\)//g; $quoter->store_date(\%info, $stock, {eurodate => $part[2]}); $info{$stock,"price"} = convert_price(trim($part[0])); $info{$stock,"last"} = $info{$stock,"price"}; $info{$stock,"success"} = 1; $info{$stock,"method"} = "finanzpartner"; $info{$stock,"symbol"} = $stock; } } } return wantarray ? %info : \%info; } 1; =head1 NAME Finance::Quote::Finanzpartner - Obtain quotes from Finanzpartner.de. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new("Finanzpartner"); %info = $q->fetch("finanzpartner","LU0055732977"); =head1 DESCRIPTION This module obtains quotes from Finanzpartner.de (http://www.finanzpartner.de) by WKN or ISIN. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::Finanzpartner: name, date, price, last, method. =head1 SEE ALSO Finanzpartner, http://www.finanzpartner.de/ Finance::Quote; =cut Finance-Quote-1.18/lib/Finance/Quote/Fool.pm000644 000765 000024 00000010663 12032045420 020274 0ustar00ecstaff000000 000000 #!/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, Tobias Vancura # # 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::Fool; use HTTP::Request::Common; use LWP::UserAgent; use Exporter; use vars qw/$FOOL_URL $VERSION @FIELDS $MAX_REQUEST_SIZE @ISA/; $VERSION = '1.18'; $FOOL_URL = 'http://quote.fool.com/quotes.csv?symbols='; # This is the maximum number of stocks we'll batch into one operation. # If this gets too big (>50 or thereabouts) things will break because # some proxies and/or webservers cannot handle very large URLS. $MAX_REQUEST_SIZE = 40; @FIELDS = qw/symbol price change open close high low yhigh ylow div yield vol avg_vol pe/; sub methods {return (fool => \&fool)} # The follow methods are valid, but not enabled for this release until further # testing has been performed. # usa => \&fool, # nasdaq => \&fool, # nyse => \&fool )} # { my @labels = (base_fool_labels(), "p_change", "currency", "method"); sub labels { return (fool => \@labels); } } sub base_fool_labels { return (@FIELDS) } # Query the stocks from the Motley Fool website (www.fool.com). The # data is returned as comma separated values, similar to Yahoo!Finance sub fool { my $quoter = shift; my @stocks = splice(@_, 0, $MAX_REQUEST_SIZE); return unless @stocks; my %info; my $ua = $quoter->user_agent; my $response = $ua->request(GET $FOOL_URL.join(",",@stocks)); return unless $response->is_success; # Okay, the data is here my $reply = $response->content; my $i=0; foreach (split('\x0D', $reply)) { if ( $i++ ) { # the first line only contains info about # the requested data, so we just skip it. my @q = $quoter->parse_csv($_); my $symbol = $q[0]; # print "Symbol: $symbol\n"; if ($#q != 13) { $info{$symbol, "success"} = 0; $info{$symbol, "errormsg"} = "Stock lookup failed"; # print "ERROR\n"; } else { for (my $j=1; $j < @FIELDS; $j++) { # print "j = $j, $FIELDS[$j], $q[$j]\n"; $info{$symbol, $FIELDS[$j]} = $q[$j]; } $info{$symbol, "currency"} = "USD"; $info{$symbol, "method"} = "fool"; # change_p = change / prev_cl * 100% $info{$symbol, "p_change"} = $q[2]/$q[4]*100; } } } return %info if wantarray; return \%info; } 1; =head1 NAME Finance::Quote::Fool - Obtain quotes from the Motley Fool web site. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %stockinfo = $q->fetch("fool","GE", "INTC"); =head1 DESCRIPTION This module obtains information from the Motley Fool website (www.fool.com). The site provides date from NASDAQ, NYSE and AMEX. This module is loaded by default on a Finance::Quote object. It's also possible to load it explicity by placing "Fool" in the argument list to Finance::Quote->new(). Information returned by this module is governed by the Motley Fool's terms and conditions. =head1 LABELS RETURNED The following labels may be returned by Finance::Quote::Fool: symbol, price, change, open, close, high, low, yhigh, ylow, div, yield, vol, avg_vol, pe, change_p, currency, method. =head1 SEE ALSO Motley Fool, http://www.fool.com Finance::Quote. =cut Finance-Quote-1.18/lib/Finance/Quote/FTPortfolios.pm000644 000765 000024 00000013237 12032045420 021767 0ustar00ecstaff000000 000000 #!/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, Keith Refson # # 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::FTPortfolios; require 5.004; use strict; use vars qw($VERSION $FTPORTFOLIOS_URL $FTPORTFOLIOS_ALL); use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; $VERSION = '1.18'; # URLs of where to obtain information. $FTPORTFOLIOS_URL = ('http://www.ftportfolios.com/retail/productsearch.aspx'); $FTPORTFOLIOS_ALL="http://www.ftportfolios.com"; sub methods { return (ftportfolios => \&ftportfolios, ftportfolios_direct => \&ftportfolios); } { my @labels = qw/exchange method source name currency nav pop price/; sub labels { return (ftportfolios => \@labels, ftportfolios_direct => \@labels); } } # ======================================================================= sub ftportfolios { my $quoter = shift; my @symbols = @_; return unless @symbols; my(@q,%aa,$ua,$url,$sym,$ts,$date,$price,$currency,$reply,$trust); my ($row, $datarow, $matches); my %curr_iso = ("\$" => "USD"); my %symbolhash; @symbolhash{@symbols} = map(1,@symbols); # for (@symbols) { my $te = new HTML::TableExtract( ); $trust = $_; $url = "$FTPORTFOLIOS_URL"; # print STDERR "Retrieving \"$trust\" from $url\n"; $ua = $quoter->user_agent; # The web site now redirects to a different page which uses a # fund code number instead of the ticker symbol. push @{ $ua->requests_redirectable }, 'POST'; $reply = $ua->request(POST $url, [searchfor => $trust]); return unless ($reply->is_success); # print STDERR $reply->content,"\n"; $te->utf8_mode(1); $te->parse($reply->content); # foreach $ts ($te->table_states) { # print "***\n***Table (", join(',', $ts->coords), "):\n***\n"; # foreach $row ($ts->rows) { # print join(',', @$row), "\n"; # } # } $aa {$trust, "symbol"} = $trust; # Parse the fund name and the ticker symbol. $ts = $te->table(2, 2); if( !defined ($ts)) { $aa {$trust, "success"} = 0; $aa {$trust, "errormsg"} = "Fund name $trust is not found. See \"$FTPORTFOLIOS_ALL\""; next; } my $row = $ts->row(0); my ($a, $b) = (@$row[0]) =~ /^([-+.,\w\s]+).*Ticker: ([\w]+)/; # print STDERR "name |$a|, ticker |$b|\n"; if (!defined($a)) { $aa {$trust, "success"} = 0; $aa {$trust, "errormsg"} = "Failure parsing fund name."; next; } $aa {$trust, "name"} = $a; # Now parse the NAV and POP values $ts = $te->table(6, 1); foreach $row ($ts->rows) { # Remove leading and trailing white space $row->[0] =~ s/^\s*(.+?)\s*$/$1/ if defined($row->[0]); $row->[1] =~ s/^\s*(.+?)\s*$/$1/ if defined($row->[1]); # Map the row into our data array for ($row->[0]) { /^NAV/ && do { $aa{$trust, "nav"} = $row->[1]; last; }; /^POP/ && do { $aa{$trust, "pop"} = $row->[1]; $aa{$trust, "price"} = $row->[1]; last; }; $aa{$trust, "success"} = 1; }; } $aa {$trust, "exchange"} = "Ftportfolios"; $aa {$trust, "method"} = "ftportfolios"; $aa {$trust, "source"} = "http://www.ftportfolios.com/"; if ($aa{$trust, "success"} == 1) { $aa{$trust, "currency"} = "USD"; $aa{$_} =~ s/\$// foreach (keys %aa); # Parse out the transaction date. $reply->content =~ m/Trade Date:[^0-9]+([0-9\/]+)/s; # print STDERR "Date: $1\n"; $quoter->store_date(\%aa, $trust, {usdate => $1}); } else { $aa{$trust, "errormsg"} = "Cannot parse quote data"; } } return %aa if wantarray; return \%aa; } 1; =head1 NAME Finance::Quote::FTPortfolios - Obtain unit trust prices from www.ftportfolios.com =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %stockinfo = $q->fetch("ftportfolios","FKYGTX"); # Can failover to other methods %stockinfo = $q->fetch("ftportfolios_direct","FKYGTX"); # Use this module only. =head1 DESCRIPTION This module obtains information about unit trust prices from www.ftportfolios.com. The information source "ftportfolios" can be used if the source of prices is irrelevant, and "ftportfolios_direct" if you specifically want to use ftportfolios.com. =head1 LABELS RETURNED Information available from Ftportfolios may include the following labels: exchange method source name currency nav pop price. =head1 SEE ALSO First Trust Portfolios website - http://www.ftportfolios.com/ =cut Finance-Quote-1.18/lib/Finance/Quote/GoldMoney.pm000644 000765 000024 00000016711 12032045420 021272 0ustar00ecstaff000000 000000 #!/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 # Copyright (C) 2008, Stephan Ebelt # # 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 # # $Id: $ package Finance::Quote::GoldMoney; require 5.005; require Crypt::SSLeay; use HTTP::Request::Common; use HTML::TableExtract; use strict; use warnings; use vars qw/$VERSION/; $VERSION = '1.18'; sub methods { return(goldmoney => \&goldmoney); } sub labels { return(goldmoney => [qw/exchange name date isodate price method/]); } # goldmoney($quoter, @symbols) # # - get 'gold' and 'silver' spot rates from goldmoney.com # - error out properly (that is: ignore) all other symbols # sub goldmoney { my $quoter = shift; my @symbols = @_; return unless @symbols; my $ua = $quoter->user_agent; my (%symbolhash, @q, %info); my ( $html_string, $te, $table_gold, $table_silver, $table_platinum, $gold_gg, $gold_oz, $silver_oz, $platinum_oz, $platinum_pg, $currency ); my $_want_gold = 0; my $_want_silver = 0; my $_want_platinum = 0; # - feed all requested symbols into %info (to be returned later) # - set error state to false by default # - see if a gold or silver rate is requested foreach my $s (@symbols) { $info{$s,'success'} = 0; $info{$s,'exchange'} = 'goldmoney.com'; $info{$s,'method'} = 'goldmoney'; $info{$s,'symbol'} = $s; if($s eq 'gold') { $_want_gold = 1; } elsif($s eq 'silver') { $_want_silver = 1; } elsif($s eq 'platinum') { $_want_platinum = 1; } else { $info{$s,'errormsg'} = "No data returned (note: this module only works for 'gold' and 'silver')"; } } # get the page # - but only if we want either gold, silver or platinum (there is nothing else there) if( $_want_gold or $_want_silver or $_want_platinum) { my $GOLDMONEY_URL = "http://goldmoney.com"; my $response = $ua->request(GET $GOLDMONEY_URL); if ($response->is_success) { $html_string =$response->content; # we want the 'Current Spot Rates' table $te = new HTML::TableExtract->new( attribs=>{class=>'spot'}, subtables=>1); $te->parse($html_string); $table_gold=$te->table(3,0); $table_silver=$te->table(3,1); $table_platinum=$te->table(3,2); } else { # retrieval error - flag an error and return right away foreach my $s (@symbols) { %info = _goldmoney_error(@symbols, 'HTTP error: ' . $response->status_line); return wantarray() ? %info : \%info; } return wantarray() ? %info : \%info; } # get list of currencies # FIXME: # - assume euro since the site change in 01/2009 # - currency is JavaScript()ed since then and therefore hard to parse, if you # know how please tell me # - this assumption causes trouble when the module is used outside the # european region (F::Q considers every number it gets as EUR and converts it...) $currency = 'EUR'; # get gold rate # if( $_want_gold ) { $_ = $table_gold->cell(0,0); if( /(\d*\.\d*).*\/gg/ ) { $gold_gg = $1; } $_ = $table_gold->cell(0,0); if( /(\d*\.\d*).*\/oz/ ) { $gold_oz = $1; # assemble final dataset # - take "now" as date/time as the site is always current and does # not provide this explicitly - so there is a time-slip $quoter->store_date(\%info, 'gold', {isodate => _goldmoney_time('isodate')}); $info{'gold','time'} = _goldmoney_time('time'); $info{'gold','name'} = 'Gold Spot'; $info{'gold','last'} = $gold_oz; $info{'gold','price'} = $gold_oz; $info{'gold','price_gg'} = $gold_gg; $info{'gold','currency'} = $currency; $info{'gold','success'} = 1; } } # get silver rate # if( $_want_silver ) { $_ = $table_silver->cell(0,0); if( /(\d*\.\d*).*\/oz/ ) { $silver_oz = $1; $quoter->store_date(\%info, 'silver', {isodate => _goldmoney_time('isodate')}); $info{'silver','time'} = _goldmoney_time('time'); $info{'silver','name'} = 'Silver Spot'; $info{'silver','last'} = $silver_oz; $info{'silver','price'} = $silver_oz; $info{'silver','currency'} = $currency; $info{'silver','success'} = 1; } } # get platinum rate # if( $_want_platinum ) { $_ = $table_platinum->cell(0,0); if( /(\d*\.\d*).*\/pg/ ) { $platinum_pg = $1; } $_ = $table_platinum->cell(0,0); if( /(\d*\.\d*).*\/oz/ ) { $platinum_oz = $1; # assemble final dataset # - take "now" as date/time as the site is always current and does # not provide this explicitly - so there is a time-slip $quoter->store_date(\%info, 'platinum', {isodate => _goldmoney_time('isodate')}); $info{'platinum','time'} = _goldmoney_time('time'); $info{'platinum','name'} = 'Platinum Spot'; $info{'platinum','last'} = $platinum_oz; $info{'platinum','price'} = $platinum_oz; $info{'platinum','price_pg'} = $platinum_pg; $info{'platinum','currency'} = $currency; $info{'platinum','success'} = 1; } } } 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 _goldmoney_error { my @symbols = shift; my $msg = shift; my %info; foreach my $s (@symbols) { $info{$s, "success"} = 0; $info{$s, "errormsg"} = $msg; } return(%info); } # - return current 'isodate' and 'time' string sub _goldmoney_time { my $want = shift; my @now = localtime(); my $str; if($want eq 'isodate') { $str = sprintf('%4d-%02d-%02d', $now[5]+1900, $now[4]+1, $now[3]); } elsif($want eq 'time') { $str = sprintf('%02d:%02d:%02d', $now[2], $now[1], $now[0]); } return($str); } 1; =head1 NAME Finance::Quote::GoldMoney - obtain spot rates from GoldMoney. =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new; %rates = $q->fetch('goldmoeny','gold', 'silver', 'platinum'); =head1 DESCRIPTION This module obtains current spot rates for 'gold', 'silver' and 'platinum' from Goldmoney (http://www.goldmoney.com). All other symbols are ignored. Information returned by this module is governed by Net Transactions Ltd.'s terms and conditions. This module is *not* affiliated with the company in any way. Use at your own risk. =head1 LABELS RETURNED The following labels are returned by Finance::Quote::GoldMoney: - exchange - name - date, time - price (per ounce), price_gg (per goldgram, gold only), price_pg (per platinumgram, platinum only) - currency =head1 SEE ALSO GoldMoney (Net Transactions Ltd.), http://www.goldmoney.com/ =cut Finance-Quote-1.18/lib/Finance/Quote/HEX.pm000644 000765 000024 00000013107 12032045420 020015 0ustar00ecstaff000000 000000 #!/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 $VERSION/; $VERSION = '1.18'; $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 Finance-Quote-1.18/lib/Finance/Quote/HU.pm000644 000765 000024 00000043314 12032045420 017710 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # # HU.pm # # Version 0.2 - Download of Hungarian (HU) stocks from www.MAGYARTOKEPIAC.hu # This version based on ZA.pm module # # Zoltan Levardy # 2008,2009 # Comments on work in progress by Zoltan posted on 3 Jul 2009 # Current implementation does the next steps: # (1) trying to find ISIN online. # (2) reading stock page to get quote # (3) if failed then trying to find as ETF on different page # (4) if not found as ETF, then trying to get ISIN from local map, and reading stock page again. package Finance::Quote::HU; require 5.004; use strict; use vars qw /$VERSION/ ; use LWP::UserAgent; use HTTP::Request::Common; use HTML::TableExtract; use Encode; use Storable qw(dclone); $VERSION = '1.18'; my %MONTHS = ( "JAN","01","FEB","02","MAR","03","APR","04","MAY","05","JUN","06","JUL","07","AUG","08","SEP","09","OCT","10","NOV","11","DEC","12"); my %XMONTHS = ( "01","JAN","02","FEB","03","MAR","04","APR","05","MAY","06","JUN","07","JUL","08","AUG","09","SEP","10","OCT","11","NOV","12","DEC"); ### STOCK urls my $MAGYARTOKEPIAC_MAINURL = ("http://www.magyartokepiac.hu/"); my $MAGYARTOKEPIAC_URL = ($MAGYARTOKEPIAC_MAINURL."cegadatok/reszletek.php"); ### ETF,Funds urls my $BAMOSZ_MAINURL = ("http://www.bamosz.hu/"); my $BAMOSZ_URL = ($BAMOSZ_MAINURL."adatok/napiadatok/index.ind?do=show"); ### ISIN urls: my $BET_MAINURL = ("http://www.bet.hu/"); my $BET_ISINURL = ($BET_MAINURL."topmenu/kereskedesi_adatok/product_search"); #print "[debug]: URL=", $MAGYARTOKEPIAC_URL, "\n"; #print "[debug]: URL=", $BAMOSZ_URL, "\n"; sub methods { return (hu => \&main, hungary => \&main, bse => \&main, bux => \&main); } sub labels { my @labels = qw/method source name symbol currency last date isodate high low p_change/; return (hu => \@labels, hungary => \@labels, magyartokepiac => \@labels, bse => \@labels, bux => \@labels); } ### main program ###################### sub main { my $quoter = shift; my @symbols = @_; my %info; #print "[debug]: main() symbols=",@symbols,"\n"; return unless @symbols; my $ua = $quoter->user_agent; my $isin; foreach my $symbol (@symbols) { #print "[debug]: main() ticker=",$symbol,"\n"; my %iinfo = ticker2isin($symbol,$ua); $isin=$iinfo{$symbol,"isin"}; #print "[debug]: isin found: ", $isin, "\n"; #$isin = ticker2isin_by_map($symbol); #print "[debug]: hungary() ticker=",$symbol,", isin=",$isin,"\n"; #TODO: call magyartokepiac() here my %minfo = magyartokepiac($quoter,$ua,$isin,$symbol); #print "[debug] main(): ",$minfo{$symbol,"success"},"\n"; if ($minfo{$symbol,"success"}) { #%info = %minfo; #%info = %{ dclone(\%minfo) }; #append minfo to info: %info = (%minfo, %info); #print "[debug] main: minfo copied into info\n"; } else { ### in some cases the ISIN provided by BET.HU is good, but the quotes page using an old one a MAGYARTOKEPIAC.HU my $isin_alt = ticker2isin_by_map($symbol); if (!$isin || ($isin ne $isin_alt)) { #print "[debug]: alternate lookup of isin: $isin\n"; $isin=$isin_alt; my %info2 = magyartokepiac($quoter,$ua,$isin,$symbol); unless ($info2{$symbol,"success"}) { # print STDERR "Alternate ISIN pickup also not working..."; $info2{$symbol,"errormsg"}="Alternate ISIN pickup also not working..." ; %info = (%info2, %info); } else { #%info = dclone %info2; #print "[debug]: new isin found: $isin_alt\n"; #%info = %{ dclone(\%info2) }; %info = (%info2, %info); } } } } #print "[debug] main(): done.\n\n"; return wantarray() ? %info : \%info; } ### this method is fetching STOCK quotes by ISIN - www.magyartokepiac.hu ############################################# sub magyartokepiac { #print "[debug]: magyartokepiac()"; my $quoter = $_[0]; my $ua = $_[1]; my $isin = $_[2]; my $symbol = $_[3]; my %minfo; if (!$isin) { $minfo{$symbol, "success"} = 0; $minfo{$symbol, "errormsg"} = "No ISIN specified"; return wantarray() ? %minfo : \%minfo; } my ($te, $ts, $row); my @rows; my $url = $MAGYARTOKEPIAC_URL."?isin=".$isin; #print "[debug]: ", $url, "\n"; my $response = $ua->request(GET $url); #print "[debug]: ", $response->content, "\n"; if (!$response->is_success) { $minfo{$symbol, "success"} = 0; $minfo{$symbol, "errormsg"} = "Error contacting URL"; return wantarray() ? %minfo : \%minfo; # next; } #PARSING $te = HTML::TableExtract->new( depth => 1, count => 0 ); $te->parse(decode_utf8($response->content)); foreach $ts ($te->tables) { my $cell = $ts->rows->[0][0]; my $status = 1; my $price = 0; my $close = 0; my $c=0; foreach (split(/\n/,$cell)) { my $line = trim($_); $c++; #if ($line ne "") { print " [debug] myline ",$c,"::",$line; } if ($c == 4) { #4th line is the name $line =~ s/\(.*folyamok\)//; #print "[debug]: name=",$line,"\n"; $minfo{$symbol, "name"} = $line; if (!$line) { #print "[debug]: name is empty!\n"; $status = 0; $minfo{$symbol, "errormsg"} = "The provided ISIN/TICKER is invalid. Your symbol was '$symbol'."; } } if ($status && $c == 6) { #6th "last" $price = $line; $minfo{$symbol, "last"} = $price; $minfo{$symbol, "price"} = $price; #$info{$symbol, "nav"} = $line; } if ($status && $c == 7) { #7th "net" ("p_change") my @values = split('\s\(.?\s', $line); #print "[debug]: line=",$line,"\n"; #print "[debug]: v[0]=",$values[0],"\n"; $minfo{$symbol, "net"} = $values[0]; #print "[debug]: v[1]=",$values[1],"\n"; $values[1] =~ s/\s%\)//; #print "[debug]: v[1]=",$values[1],"\n"; $minfo{$symbol, "p_change"} = $values[1]; } if ($status && $c == 8) { #7th "date" "time" my @values = split('\s', $line); #$info{$symbol, "date"} = $MONTHS{uc $values[1]}."/".$values[0]."/".substr($values[2],2); $minfo{$symbol, "time"} = $values[3]; $quoter->store_date(\%minfo, $symbol, {eurodate => $line}); #my @values = split('\s', $line); #print "SHARE DATE: ",$MONTHS{uc $values[1]}."/".$values[0]."/".substr($values[2],2)." ".$values[3],"\n"; #print "SHARE DATE: '",$line,"'\n"; } if ($status && $c == 13) { #13th "open" $minfo{$symbol, "open"} = $line; } if ($status && $c == 15) { #15th "volume" $minfo{$symbol, "volume"} = $line; } if ($status && $c == 17) { #17th "pe" $minfo{$symbol, "pe"} = $line; } if ($status && $c == 20) { #20th "close" $close = $line; $minfo{$symbol, "close"} = $close; } if ($status && $c == 22) { #22th "avg_vol" $minfo{$symbol, "avg_vol"} = $line; } if ($status && $c == 24) { #24th "eps" $minfo{$symbol, "eps"} = $line; } if ($status && $c == 27) { #27th "high" $minfo{$symbol, "high"} = $line; } if ($status && $c == 34) { #34th "eps" $minfo{$symbol, "low"} = $line; } if ($status && $c == 38) { #38th "cap" $minfo{$symbol, "cap"} = $line; } #if ($line ne "") { print " ==>> ",$line, [debug]"\n"; } } #POST PROCESSING (out of trade price is the last closing price): if ($price eq 0) { $minfo{$symbol, "price"} = $close; } #if status is 0, then going to find on another website: if ($status) { # GENERAL FIELDS $minfo{$symbol, "method"} = "magyartokepiac"; $minfo{$symbol, "symbol"} = $symbol; $minfo{$symbol, "currency"} = "HUF"; $minfo{$symbol, "source"} = $MAGYARTOKEPIAC_MAINURL; } else { #print "[debug] magyartokepiac(): call bamosz(): isin=",$isin,"\n"; my %binfo = bamosz($quoter,$ua,$isin); $status = $binfo{$isin,"success"}; # GENERAL FIELDS $minfo{$symbol, "method"} = "bamosz"; $minfo{$symbol, "symbol"} = $isin; $minfo{$symbol, "currency"} = "HUF"; $minfo{$symbol, "source"} = $BAMOSZ_MAINURL; #LAST and DATE: if ($status) { $minfo{$symbol, "date"} = $binfo{$isin,"date"}; $minfo{$symbol, "isodate"} = $binfo{$isin,"isodate"}; #$info{$symbol, "time"} = $binfo{$isin,"time"}; $minfo{$symbol, "last"} = $binfo{$isin,"last"}; $minfo{$symbol, "price"} = $binfo{$isin,"last"}; $minfo{$symbol, "volume"} = $binfo{$isin,"volume"}; $minfo{$symbol, "nav"} = $binfo{$isin,"nav"}; $minfo{$symbol, "net"} = $binfo{$isin,"net"}; $minfo{$symbol, "p_change"} = $binfo{$isin,"p_change"}; #print "\n",$binfo{$isin,"last"}," ",$binfo{$isin,"date"},"\n"; } } $minfo{$symbol, "success"} = $status; #print "[debug]: status set to ",$status,"\n"; } return wantarray() ? %minfo : \%minfo; } ### this method is about fetching ETF, funds by ISIN ############################### sub bamosz { my $quoter = $_[0]; my $ua = $_[1]; my $x = $_[2]; #print "[debug]: bamosz(): param=",$x,"\n"; my %binfo; my ($te, $ts, $row); my @rows; return unless $x; my $url = $BAMOSZ_URL."&fund_id=".$x.bamosz_date()."&show=arf&show=nee&show=cf&show=d_cf"; #&fund_id=HU0000704366&from_year=2008&from_month=12&from_day=3&until_year=2008&until_month=12&until_day=4&show=arf" #print "[debug]: bamosz(): ", $url, "\n"; my $resp = $ua->request(POST $url); #print "[debug]: bamosz() :", $resp->content, "\n"; #DiGGING SESSION ID: my $data = $resp->content; my $key="targetString = '\/adatok\/napiadatok\/index.ind\?isFlashCompliant="; my $sessionid= substr( $data, index($data, $key)+length($key)); $sessionid= substr( $sessionid, 0, index ($sessionid, "\n")); $sessionid= substr( $sessionid, index($sessionid,'session_id=')); $sessionid= substr( $sessionid, 0, index($sessionid,"';")); #print "\nsession-id=$sessionid.\n"; #CALL PAGE WITH SESSION AGAIN: my $response = $ua->get($url."&isFlashCompliant=false&".$sessionid); #print "\n",$url."&isFlashCompliant=false;".$sessionid,"\n"; #print "\nPAGE:\n",$response->content,"\n"; if (!$response->is_success) { #print STDERR "[debug] bamosz(): page unavailable\n"; $binfo{$x, "success"} = 0; $binfo{$x, "errormsg"} = "Error contacting URL"; return; } #PARSING $te = new HTML::TableExtract()->new( depth => 2, count => 2 ); $te->parse(decode_utf8($response->content)); #print "[debug]: (parsed HTML)",$te, "\n"; unless ($te->first_table_found()) { #print STDERR "[debug] bamosz(): no tables on this page\n"; $binfo{$x, "success"} = 0; $binfo{$x, "errormsg"} = "Parse error"; return; } # 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"; foreach $ts ($te->tables) { my $lastdate = $ts->rows->[1][0]; my $lastrate = bamosz_number( $ts->rows->[1][1] ); #print "[debug]: bamosz(): last available price is $lastrate at $lastdate.\n"; $binfo{$x, "last"} = $lastrate; #$binfo{$x, "date"} = substr($lastdate,5,2)."/".substr($lastdate,8,2)."/".substr($lastdate,2,2); my $lastfulldate = substr($lastdate,8,2)." ".$XMONTHS{substr($lastdate,5,2)}." ".substr($lastdate,0,4); #." 16:00"; #print "\n",$x,": ",$lastdate," >> '",$lastfulldate,"'\n"; $quoter->store_date(\%binfo, $x, {eurodate => $lastfulldate}); #$binfo{$x, "isodate"} = substr($lastdate,0,4)."-".substr($lastdate,5,2)."-".substr($lastdate,8,2); #print "isodate: ",substr($lastdate,0,4)."-".substr($lastdate,5,2)."-".substr($lastdate,8,2); my $lastnav = bamosz_number( $ts->rows->[1][2] ); my $lastnet = bamosz_number( $ts->rows->[1][3] ); my $lastpch = bamosz_number( $ts->rows->[1][4] ); #print "[debug]: bamosz(): lastnav=$lastnav, lastnet=$lastnet, lastpch=$lastpch, volume=",($lastnet*$lastrate),".\n"; $binfo{$x, "nav"} = $lastnav; $binfo{$x, "net"} = $lastnet; $binfo{$x, "volume"} = $lastnet*$lastrate; $binfo{$x, "p_change"} = $lastpch; #DONE: $binfo{$x, "success"} = 1; } return %binfo; } sub bamosz_number { my $x = $_[0]; #if ( index( $lastrate, ".")<0 ) { $lastrate =~ s/,/./; } if ($x =~ m/(\d*.?\d*)*,?\d*%?$/) { #print "\nHUN:$x\n"; $x =~ s/\.//g; $x =~ s/,/\./; } $x =~ s/%$//; #print "TEST:$x\n"; #convert HTML minus, to number minus: if ($x =~ m/^\D+\d+(.?\d)/) { $x =~ s/^\D+/-/; } #print "RET:$x\n"; return $x; } sub bamosz_date { # "&from_year=2008&from_month=12&from_day=3&until_year=2008&until_month=12&until_day=4" my @T = localtime; #current date my @B = localtime(time()-7*86400); #date before n*day, a day is 86400 return "&from_year=".(1900 + $B[5])."&from_month=".(1+$B[4])."&from_day=".$B[3]. "&until_year=".(1900 + $T[5])."&until_month=".(1+$T[4])."&until_day=".$T[3]; } ### this methods is mapping STOCK TICKERS into ISIN by an internal mapping table ################################################# sub ticker2isin { my $ticker = $_[0]; my $ua = $_[1]; my %iinfo; my $isin; my ($te, $ts, $row); my @rows; #print "[debug]: ticker2isin(): ticker=", $ticker, "\n"; #$BET_ISINURL my $url = $BET_ISINURL."?isinquery=".$ticker; #print "[debug]: ticker2isin(): url=", $url, "\n"; my $response = $ua->request(GET $url); #print "[debug]: ", $response->content, "\n"; if (!$response->is_success) { print STDERR "[debug] ticker2isin(): isin url cannot be read.\n"; $iinfo{$ticker, "success"} = 0; $iinfo{$ticker, "errormsg"} = "Error contacting isin URL"; next; } #PARSING $te = HTML::TableExtract->new( depth => 9, count => 0 ); $te->parse(decode_utf8($response->content)); unless ($te->first_table_found()) { print STDERR "[debug] ticker2isin(): no tables on this page\n"; $iinfo{$ticker, "success"} = 0; $iinfo{$ticker, "errormsg"} = "Parse error"; return; } # 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 "[debug]: ", $row->[0], "\n"; # } #} #print "\n \n \n \n[debug]: ++++ ==== ++++ ==== ++++ ==== ++++ ==== END OF TABLE DUMP ++++ ==== \n \n \n \n"; my $status = 1; foreach $ts ($te->tables) { #my $cell_ticker = $ts->rows->[4][1]; #my $cell_isin = $ts->rows->[4][2]; foreach $row ($ts->rows) { my $cell_ticker = uc trim($row->[1]); my $cell_isin = uc trim($row->[2]); #print "[debug]: ", $cell_ticker, " | ", $cell_isin, "\n"; if ($cell_ticker eq uc $ticker) { #print "[debug]: found ISIN: ",$cell_isin," for ticker: ", $cell_ticker, "\n"; foreach (split(/\n/,$cell_isin)) { my $line = trim($_); #if ($line ne "") { print " [debug]: ticker2isin(): myline ::",$line,"::\n"; } if ($line eq "") { $status=0; } $isin=$line; #print " [debug]: ticker2isin(): isin ::",$isin,"::\n"; } } } } if (!$isin) { #print "[debug]: ticker2isin(): no isin found for ticker: $ticker \n"; $isin=$ticker; } else { $iinfo{$ticker, "success"} = $status; $iinfo{$ticker, "isin"} = $isin; } return wantarray() ? %iinfo : \%iinfo; } ### this map is used by next method ticker2isin_by_map ### @deprecated ############################ my %ISINS = ( "AAA", "NL0006033375", "ANY", "HU0000079835", "BIF", "HU0000074083", "BOOK", "HU0000065008", "CSEPEL", "HU0000085618", "DANUBIUS", "HU0000074067", "ECONET", "HU0000058987", "EGIS", "HU0000053947", "EHEP", "HU0000067582", "ELMU", "HU0000074513", "EMASZ", "HU0000074539", "FEVITAN", "HU0000071972", "FHB", "HU0000078175", "FORRAS/T", "HU0000066071", "FORRAS/OE", "HU0000066394", "FOTEX", "HU0000075189", "FREESOFT", "HU0000071030", "GENESIS", "HU0000071865", "GSPARK", "HU0000083696", "HUMET", "HU0000073176", "KPACK", "HU0000075692", "KONZUM", "HU0000072939", "LINAMAR", "HU0000074851", "MTELEKOM", "HU0000073507", "MOL", "HU0000068952", "ORC", "LU0122624777", "OTP", "HU0000061726", "PANNERGY", "HU0000089867", "PFLAX", "HU0000075296", "PVALTO", "HU0000072434", "PANNUNION", "HU0000092960", "PHYLAXIA", "HU0000088414", "QUAESTOR", "HU0000074000", "RABA", "HU0000073457", "RFV", "HU0000086640", "RICHTER", "HU0000067624", "SYNERGON", "HU0000069950", "TVK", "HU0000073119", "TVNETWORK", "HU0000072715", "ZWACK", "HU0000074844"); ### this methods is mapping STOCK TICKERS into ISIN by an internal mapping table ### @deprecated by the ticker2isin which is fetching ISIN from BET.HU ################################################# sub ticker2isin_by_map { my $ticker = $_[0]; my $isin; #print "[debug]: ticker2isin(): ticker=", $ticker, "\n"; $isin = $ISINS{uc $ticker}; #print "[debug]: ticker2isin(): isin=", $isin, "\n"; if (!$isin) { #print "[debug]: ticker2isin(): NE\n"; $isin=$ticker; } return $isin; } sub trim { my $str = $_[0]; if ($str) { $str =~ s/^\s+//; $str =~ s/\s+$//; } return $str; } 1; =head1 NAME Finance::Quote::HU - Obtain Hungarian Securities from www.magyartokepiac.hu 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.magyartokepiac.hu, while mutual funds retrieved from www.napi.hu. Searching is based on ISIN codes, but for main shares it is mapping the ticker-codes to ISIN. =head1 LABELS RETURNED Information available from magyartokepiac may include the following labels: method source name symbol currency date time last price low high open close pe pse cap volume avg_vol =head1 SEE ALSO Magyartokepiac website - http://www.magyartokepiac.hu/ Napi Gazdasag website - http://www.bamosz.hu/ Finance::Quote =cut Finance-Quote-1.18/lib/Finance/Quote/IndiaMutual.pm000644 000765 000024 00000010723 12032045420 021606 0ustar00ecstaff000000 000000 #!/usr/bin/perl -w # Version 0.1 preliminary version using Cdnfundlibrary.pm v0.4 as an example package Finance::Quote::IndiaMutual; require 5.004; use strict; use vars qw($VERSION $AMFI_URL $AMFI_NAV_LIST $AMFI_MAIN_URL); use LWP::UserAgent; use HTTP::Request::Common; use HTTP::Status; use HTML::TableExtract; $VERSION = '1.18'; # URLs of where to obtain information. #$AMFI_MAIN_URL = ("http://localhost/"); $AMFI_MAIN_URL = ("http://www.amfiindia.com/"); $AMFI_URL = ("${AMFI_MAIN_URL}NavReport.aspx?type=0"); #$AMFI_URL = ("${AMFI_MAIN_URL}spages/NAV0.txt"); #This page seems to do the job also. Keep for reference # amfinavlist.txt is a cache-file. keep it until updated on the website since this is a 1meg file. my $cachedir = $ENV{TMPDIR} // $ENV{TEMP} // '/tmp/'; $AMFI_NAV_LIST = $cachedir."amfinavlist.txt"; sub methods { return (indiamutual => \&amfiindia, amfiindia => \&amfiindia); } { my @labels = qw/method source link name currency date isodate nav rprice sprice/; sub labels { return (indiamutual => \@labels, amfiindia => \@labels); } } # # ======================================================================= sub amfiindia { my $quoter = shift; my @symbols = @_; # Make sure symbols are requested ##CAN exit more gracefully - add later## return unless @symbols; # Local Variables my(%fundquote, %allquotes); my($ua, $url, $reply); $ua = $quoter->user_agent; $url = "$AMFI_URL"; $reply = $ua->mirror($url, $AMFI_NAV_LIST); # Make sure something is returned unless ($reply->is_success or $reply->code == RC_NOT_MODIFIED) { foreach my $symbol (@symbols) { $fundquote{$symbol,"success"} = 0; $fundquote{$symbol,"errormsg"} = "HTTP failure"; } return wantarray ? %fundquote : \%fundquote; } open NAV, $AMFI_NAV_LIST or die "Unexpected error in opening file: $!\n"; # Scheme Code;Scheme Name;Net Asset Value;Repurchase Price;Sale Price;Date while (