Quotemonster or qm is perl script that downloads historical quotes from the internet. It was working fine with Os 8.5.1 until all of a sudden it stared truncating the quotesout dates. For example a normal quotesout ( output) looks like this: AOL,061799,106.5,113.75,103,110.6875,31982600 AOL,061899,112,113.5,109.5625,112,22946900 the faulty quotesout looks like this: AOL,0617,106.5,113.75,103,110.6875,31982600 AOL,0618,112,113.5,109.5625,112,22946900 note the disappearance of the year-99. I cannot figure it out. I upgraded to os 8.6-still same problem. your help will be most appreciated. I have attached the qm script.
#!/usr/bin/perl # # IMPORTANT: READ THIS IN ITS ENTIRETY. YOU ARE THE FINAL AUTHORITY IN DETERMINING # WHAT HAPPENS ON YOUR COMPUTER. YOU SHOULD READ ALL DOCUMENTATION PERTAINING TO # THE INSTALLATION AND USE OF ALL SOFTWARE YOU INSTALL AND USE AND SHOULD MAKE # REGULAR AND COMPLETE BACKUPS OF YOUR IMPORTANT DATA. # # QuoteMonster - Download and parsing script for retrieving # stock quote data from Yahoo. # # -------------------------LEGAL INFO-------------------------------------------- # # This script is Copyright (C) 1998 Jim Michael and XMLWorks All Rights Reserved # # This is version 1.0.2m (16 Dec 1998) By G Michel # # 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., 675 Mass Ave, Cambridge, MA 02139, USA. # # Download and parsing script for www.yahoo.com. This script will most # assuredly NOT work with other quote sources. Contact us for assistance # if you would like to use this script for other quote sources. # # ------------------------------USAGE INFO------------------------------------- # # USAGE: qm start_date end_date # # REQUIRED FORMAT OF START AND END DATES: yymmdd # # IMPORTANT USAGE NOTES: This script resulted from the merging of the QuoteMonster # Daily and QuoteMonster Historical scripts. You can now download both your daily # and historical data using just this script. The date arguments start_date and # end_date are now OPTIONAL. If no date argument is given then QuoteMonster will # default to today's date. If only one date argument is given then QuoteMonster will # download data for that date only. If both start_date and end_date are given then # QuoteMonster will download data for that date range. If no date argument is given # then QuoteMonster will use its group download mode and send several quote requests # at once, greatly increasing the speed of daily downloads of large numbers of quotes. # # YEAR 2000 NOTE: Date formats of Y2K compliant charting programs are not know yet. # Until it is known what the new format, if any, might be it is impossible to produce # a Y2K compliant version of the program. Once a year format is established and charting # programs are updated to use the new format, QuoteMonster may be modified to handle the # new date format, probably by making the year field use four digits, per the configuration # option below. # # IMPORTANT NOTE RE MUTUAL FUNDS: Only the closing price is available using QuoteMonster # to download mutual fund prices. Consequently you should not mix mutual fund tickers # with stock and index ticker in the same ticker file or your import program may generate # errors. To handle both types of data, keep a copy of the QuoteMonster script in two # different directories, using one for stocks and index downloads and one for mutual funds. # You may also need to use a header at the top of your data file such as: # # <date>,<ticker>,<close> # # Note to Windows NT/95 users: # # If you are on a Win32 platform (NT or Windows95/98) then we HIGHLY recommend that you # use Gurusamy Sarathy's Standard Win32 port of Perl 5.04 or higher. The ActiveState port # is newer, but this version is known to be stable and included all of the modules used # by QuoteMonster. You may download the free perl interpreter from # http://www.perl.com/ or see the XMLWorks website for location of the binary download. # # # ----------------------------------SUPPORT INFO-------------------------------------- # # A newsgroup for QuoteMonster has been created on DejaNews. You can access it at: # # # #http://www.dejanews.com/[LB=http://xmlworks.com/quotemonster/,LBT=Return%20to%2 0XM#LWorks]/group/dejanews.members.biz.quotemonster.quotemonster # # Email: quotemonster@xmlworks.com # # Since this is free software, no support is offered. However, suggestions for improvements # to the program are always welcome. If you are using the program and find it useful, # please drop us a line sometime. We would enjoy hearing from you. # # Snail Mail: XMLWorks # PO Box 941124 # Atlanta, GA 31141-1124 # USA # Web: http://www.xmlworks.com/ # # Custom modifications to this script or other custom Internet programming # in Perl are also available. # # # ----------------------- Enter your custom settings here ----------------------------- # # # Instructions: # # Lines with comments are preceded by the hash symbol (#). The following lines assign # values to variables. Some values are numerical and some are not. The numerical values # are not enclosed in single quotes, the non-numerical entries are enclosed in # single quotes ('like this'). All perl statements must end with a semicolon (;) and a # comment may follow on the same line by placing the hash symbol (#) before the comment. # QuoteMonster reads the tickers to download from a tickers file, outputs the raw data # to a temporary file, then converts the data in the temporary file into a format # suitable for importing to Metastock or other charting programs and stores the data # in a data file. You may use the default settings here or change as needed: #MacPerl #Still needs some date work - gm $ARGV[0] = MacPerl::Ask("What is the start date (yymmdd)?","$date1"); $ARGV[1] = MacPerl::Ask("What is the end date (yymmdd)?","$date2"); # my $tickerfile = 'tickers.txt'; # file containing tickers - one ticker per line my $tickerfile = MacPerl::Ask("What is the name of the tickers file?","tickers.txt"); my $inputFile = 'quotes.csv'; # temporary file to store quote data before parsing my $outputFile = 'quotesout'; # file to store quote data after parsing # Enter the order in which the price, date, and volume information should be stored. # If you do not want an item to be saved, enter a zero (0). my $t = 1; my $d = 2; # date my $o = 3; # open my $h = 4; # high my $l = 5; # low my $c = 6; # close my $v = 7; # volume # Some charting programs may require the date year to be expressed as either a two or four # digit year. Enter the number of digits to represent the year - enter either 2 or 4. my $y = 4; # If your data file must contain a header, enter it here. An example of an optional # Metastock header is on the next line following the #. You must make sure you have the # correct order and number of data fields: # my $header = '<date>,<ticker>,<open>,<high>,<low>,<close>,<vol>'; my $header = ''; # QuoteMonster can remove carets (^) from tickers of indices, such as ^OEX. # If you do not want to remove carets, set the following value to 1. If you want # to remove the carets, set the following value to 0 (default): my $donotremovecarets = 0; # Some chart programs want quotes in a particular date order. If you need to reverse the order # of dates in the QuoteMonster output file set the following value to 1. If the date order # does not matter you can leave it set at the default of 0. my $reverse_order = 0; # Enter domain and port information # ONLY if you must go through a proxy server: my $proxy = ''; # proxy server my $port = ''; # proxy server port my $noproxy = ''; # local domain # ---- Do not change anything below this line unless you know what you are doing ---- # print "QuoteMonster has started...\n"; use LWP::UserAgent; use HTTP::Request; use HTTP::Response; my $ticker; my $last; my $date; my $time; my $change; my $open; my $high; my $low; my $vol; my $data; my @quotes; my $startdate = shift; my $enddate = shift; my $daily = 0; unless (defined($startdate)) { my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime(time); $mon++; $mday = '0' . "$mday" unless $mday > 9; $mon = '0' . "$mon" unless $mon > 9; $startdate = $year . $mon . $mday; $daily = 1; print "No date arguments given so using fast daily update mode\n"; } $enddate = $startdate unless defined($enddate); my $startday = substr($startdate,4,2); my $startmonth = substr($startdate,2,2); my $startyear = substr($startdate,0,2); my $endday = substr($enddate,4,2); my $endmonth = substr($enddate,2,2); my $endyear = substr($enddate,0,2); my $request; my $day; my $month; my $year; my $line; my $i; # RESET HISTORY FILE TO ZERO AND ADD HEADER IF REQUIRED: unlink $inputFile, $outputFile; open (HISTORY, ">$outputFile") || die("Can't clear history file - $outputFile: $!"); if (length($header)>0) { print "Adding header to $outputFile\n"; print HISTORY "$header\n"; } close HISTORY; my %mon = ('Jan','1','Feb','2','Mar','3','Apr','4','May','5','Jun','6','Jul','7','Aug','8' ,'Sep','9','Oct','10','Nov','11','Dec','12'); my $product_id="Mozilla/3.0"; my $ua = new LWP::UserAgent; $ua->agent($product_id); if ($proxy ne '' && $port ne '' && $noproxy ne '') { $ua->proxy('http', "http://$proxy:$port/"); $ua->no_proxy("$noproxy"); } open (TICKERS,"$tickerfile") || die("Can't open ticker file - $!"); my @tickers = (<TICKERS>); close TICKERS; chomp @tickers; if ($daily == 0) { my $URL = 'http://chart.yahoo.com/table.csv?s='; foreach $ticker (@tickers) { $URL .= $ticker . '&a=' . $startmonth . '&b=' . $startday . '&c=' . $startyear . '&d=' . $endmonth . '&e=' . $endday . '&f=' . $endyear . '&g=d&q=q'; print "Retrieving $URL\n"; $request = new HTTP::Request('GET', $URL); $data = $ua->request($request)->as_string;print "BEFORE DATA:$data\n"; # Changes a unix return to a Mac return - all \n are not equal $data =~ s/\012/\015/gs;print "AFTER DATA:$data\n"; open (OUT, ">$inputFile"); print OUT "$data"; close OUT; open (IN,"$inputFile") || die("Can't open $inputFile - $!"); (@quotes) = (<IN>); chomp @quotes; open (HISTORY, ">>$outputFile") || die("Can't open output file for writing - $!"); foreach (@quotes) { if (/^\d/) { ($date,$open,$high,$low,$last,$vol) = split(/,/); $ticker =~ tr/a-z/A-Z/; $donotremovecarets || $ticker =~ s/\^//; ($day,$month,$year) = split(/\-/, $date); $day = ('0' . "$day") if ($day < 10 && $day !~ /^0/); $month = $mon{$month}; $month = ('0' . "$month") if ($month < 10 && $month !~ /^0/); $year = substr($year,2,2); $date = "$year$month$day"; $line = ''; if (defined($high)) { for ($i = 1; $i < 8; $i++) { $line .= $ticker . ',' if ($t == $i); $line .= $date . ',' if ($d == $i); $line .= $open . ',' if ($o == $i); $line .= $high . ',' if ($h == $i); $line .= $low . ',' if ($l == $i); $line .= $last . ',' if ($c == $i); $line .= $vol . ',' if ($v == $i && defined($vol)); } $line =~ s/,+$//; } else { $line = $ticker . ',' . $open; } print HISTORY "$line\n"; } } close HISTORY; close IN; $URL = 'http://chart.yahoo.com/table.csv?s='; sleep 5; } } else { my $URL = 'http://quote.yahoo.com/d/quotes.csv?s='; my $testLength = length($URL); my $count = 0; foreach $ticker (@tickers) { $ticker =~ tr/A-Z/a-z/; $URL .= $ticker.'+'; $count++; if ($count == 20) { qet_quotes($URL); $count = 0; $URL = 'http://quote.yahoo.com/d/quotes.csv?s='; } } if (length($URL) > $testLength) { qet_quotes($URL); } open (IN,"$inputFile") || die("Can't open $inputFile - $!"); @quotes = <IN>; chomp @quotes; open (DAILY, ">$outputFile") || die("Can't open output file for writing - $!"); if ($header ne '') { print DAILY "$header\n"; } foreach (@quotes) { if (/^"/) { ($ticker,$last,$date,$time,$change,$open,$high,$low,$vol) = split(/,/); $ticker =~ s/"//g; $ticker =~ tr/a-z/A-Z/; $date =~ s/"//g; if ($date ne 'N/A') { ($month,$day,$year) = split(/\//, $date); if ($month > 12) { die("FATAL ERROR: Improper date format."); } $year = substr($year,2,2) if ($y == 2); $day = ('0' . "$day") if ($day < 10); $month = ('0' . "$month") if ($month < 10); $date = "$year$month$day"; $line = ''; for ($i = 1; $i < 8; $i++) { $line .= $ticker . ',' if ($t == $i); $line .= $date . ',' if ($d == $i); $line .= $open . ',' if ($o == $i); $line .= $high . ',' if ($h == $i); $line .= $low . ',' if ($l == $i); $line .= $last . ',' if ($c == $i); $line .= $vol . ',' if ($v == $i && $vol ne 'N/A'); } $line =~ s/,$//; print DAILY "$line\n"; } } } close DAILY; close IN; } if ($reverse_order) { print "Reversing date sequence\n"; my $tempfile = 'quotes.~mp'; unlink $tempfile; rename $outputFile, $tempfile || die "Could not rename $outputFile $!"; open (IN,$tempfile) || die "Could not open $tempfile $!"; open (OUT, ">$outputFile") || die "Could not open $outputFile $!"; my @quotes = (<IN>); if ($header ne '') { $header = shift @quotes; push @quotes, $header; } @quotes = reverse @quotes; print OUT @quotes; close IN; close OUT; } sub qet_quotes { $URL = shift; $URL =~ s/\+$//; $URL .= '&f=sl1d1t1c1ohgv&e=.csv'; print "Retrieving $URL\n"; my $ua = new LWP::UserAgent; my $request = new HTTP::Request('GET', $URL); my $response = $ua->request($request); if ($response->is_success) { $data = $ua->request($request)->as_string; $data =~ s/\x0D//g; open (OUT, ">>$inputFile"); print OUT "$data"; close OUT; sleep 5; } else { open (OUT,">>error.log") || die("Can't open error log: $!"); print OUT "\nError retrieving $URL \n"; print OUT $response->error_as_HTML; close OUT; } } __END__