# # 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) 2013, Manoj Kumar # # 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 is derived from Finance::Quote::IndiaMutual 1.18 # # This code was developed as part of GnuCash package Finance::Quote::NseIndia; require 5.005; use strict; use vars qw($VERSION); use Finance::Quote::SymbolTranslation qw(symbol_translation); use IO::Uncompress::Unzip qw(unzip $UnzipError); $VERSION = '1.18'; my $URL = 'http://www.nse-india.com'; my $BHAV_ZIP = $ENV{TEMP} ? "$ENV{TEMP}/nse_bhav.zip" : '/tmp/nse_bhav.zip'; my $BHAV_CSV = $ENV{TEMP} ? "$ENV{TEMP}/nse_bhav.csv" : '/tmp/nse_bhav.csv'; sub methods { return ( india_shares => \&nse_india, nse_india => \&nse_india ); } { my @labels = qw/currency date isodate method price success symbol/; sub labels { return ( india_shares => \@labels, nse_india => \@labels ); } } sub get_bhav_url { my $time = shift; my @months = ('JAN', 'FEB', 'MAR', 'APR', 'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'); my ($mday, $month, $year); (undef, undef, undef, $mday, $month, $year, undef, undef, undef) = localtime($time); $month = $months[$month]; $year += 1900; # /content/historical/EQUITIES2013/NOV/cm22NOV2013bhav.csv.zip return("/content/historical/EQUITIES/$year/$month/cm$mday$month${year}bhav.csv.zip"); } sub nse_india { my $quoter = shift; my @symbols = @_; my $debug = 0; if (@symbols && $symbols[0] eq 'Debug') { # if first symbol is Debug, enable debugging $debug = 1; shift @symbols; } return unless @symbols; my (%info, $errormsg, $fh, $ref_trans_2); my ($ua, $url, $reply); $ua = $quoter->user_agent->clone; $ua->default_header('Accept' => '*/*', 'User-Agent' => 'FQ/1.18'); for (my ($nb_days, $time) = (0, time); $nb_days < 7; $nb_days++, $time -= 24 * 60 * 60) { $url = $URL . get_bhav_url($time); if ($debug) { print "URL = $url\n"; } $reply = $ua->mirror($url, $BHAV_ZIP); if ($debug) { print "Reply = ", $reply->is_success ? "Successful" : "Unsuccessful", " : ", $reply->status_line, "\n"; } last if ($reply->is_success || $reply->code == 304); } unless ($reply->is_success or $reply->code == 304) { $errormsg = "HTTP failure : " . $reply->status_line; } unless ($errormsg) { if (! unzip $BHAV_ZIP => $BHAV_CSV) { $errormsg = "Unzip failure : $UnzipError"; } } unless ($errormsg) { if (! open $fh, '<', $BHAV_CSV) { $errormsg = "Open failure : $!"; } } unless ($errormsg) { (undef, $ref_trans_2) = symbol_translation('nse_india', \@symbols, 1); # SYMBOL,SERIES,OPEN,HIGH,LOW,CLOSE,LAST,PREVCLOSE,TOTTRDQTY,TOTTRDVAL,TIMESTAMP,TOTALTRADES,ISIN, while (<$fh>) { my @data = split /\s*,s*/; next unless (@data > 10); my $symbol = uc($data[0]); next unless exists $ref_trans_2->{$symbol}; $symbol = $ref_trans_2->{$symbol}; $info{$symbol, 'symbol'} = $data[0]; $info{$symbol, 'currency'} = 'INR'; $info{$symbol, 'price'} = $data[5]; $quoter->store_date(\%info, $symbol, {eurodate => $data[10]}); $info{$symbol, 'success'} = 1; } close($fh); } unless ($errormsg) { $errormsg = 'Stock lookup failed'; } foreach my $symbol (@symbols) { $info{$symbol, 'method'} = 'nse_india'; next if (exists $info{$symbol, 'success'}); $info{$symbol, 'success'} = 0; $info{$symbol, 'errormsg'} = $errormsg; } return wantarray ? %info : \%info; } 1; =head1 NAME Finance::Quote::NseIndia - Fetch quotes from NSE, India http://www.nseindia.com =head1 SYNOPSIS use Finance::Quote; $q = Finance::Quote->new(); %info = $q->fetch('india_shares', 'TCS'); # Failover to other methods ok. %info = $q->fetch('nse_india', 'TCS'); # Use this module only. =head1 DESCRIPTION This module obtains information about shares listed on NSE, India from NSE, India web site http://www.nseindia.com. The information is taken from the Bahv copy file (zipped CSV) prepared by NSE at the end of the trading day. This file is mirrored in a local file. This module uses Finance::Quote::SymbolTranslation for symbol translation. Source name for this purpose is nse_india. =head1 SYMBOL TRANSLATION If failover method india_shares is used with NseIndia and IciciDirect as sources, the same symbol can not be used with both these providers. In order to use the same symbol for both these sources, Finance::Quote::SymbolTranslation can be used to translate common symbol name to one specific to each source. For example, the symbol used for Infosys is INFY and INFTEC for NseIndia and IciciDirect respectively. To be able to use symbol INFY with india_source method with NseIndia and IciciDirect as sources, create / modify fq_symbol_translation.txt and add following line - icici_direct INFY INFTEC F::Q will ask both NseIndia and IciciDirect to fetch information about INFY, but IciciDirect will translate INFY to INFTEC, fetch information about INFTEC and return data as if it fetched data for INFY. Similarly, to be able to use symbol INFTEC with india_source method with NseIndia and IciciDirect as sources, create / modify fq_symbol_translation.txt and add following line - nse_india INFTEC INFY fq_symbol_translation.txt file should be either in the current directory or in the home directory (on windows machines, in the directory given by USERPROFILE environment varibale) =head1 LABELS RETURNED this source returns following lables on success: currency - INR date - date in US (mm/dd/yyyy) format isodate - date in ISO (yyyy-mm-dd) format method - nse_india price - closing price in INR symbol - NSE symbol success - 0 = failure / 1 = success errormsg - only if success is 0 =head1 SEE ALSO NSE, India web site http://www.nseindia.com. Finance::Quote, Finance::Quote::SymbolTranslation =cut