Skip to content

Instantly share code, notes, and snippets.

@mark05e
Last active May 19, 2020 19:20
Show Gist options
  • Save mark05e/8d25c3b96b9e44e1fca1284b0d8126cf to your computer and use it in GitHub Desktop.
Save mark05e/8d25c3b96b9e44e1fca1284b0d8126cf to your computer and use it in GitHub Desktop.
# IndiaNSE.pm
#
# Copyright (C) 1998, Dj Padzensky <[email protected]>
# Copyright (C) 1998, 1999 Linas Vepstas <[email protected]>
# Copyright (C) 2000, Yannick LE NY <[email protected]>
# Copyright (C) 2000, Paul Fenwick <[email protected]>
# Copyright (C) 2000, Brent Neal <[email protected]>
# Copyright (C) 2013, Manoj Kumar <https://lists.gnucash.org/pipermail/gnucash-user/2015-August/061672.html>
# Copyright (C) 2020, Mark <https://gist.github.com/mark05e>,
# Philip <https://www.pcnworld.com/>
#
# 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 <http://www.gnucash.org/>
package Finance::Quote::india_nse;
require 5.30.2;
use strict;
use vars qw($VERSION);
use Finance::Quote::SymbolTranslation qw(symbol_translation);
use IO::Uncompress::Unzip qw(unzip $UnzipError);
# Updated downloader requirements
# use File::Basename;
use LWP::UserAgent;
use LWP::Simple qw($ua getstore);
use URI;
use HTTP::Status;
$VERSION = '1.20';
my $URL = 'https://www1.nseindia.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 => \&india_nse,
india_nse => \&india_nse
);
}
{
my @labels = qw/currency date isodate method price success symbol/;
sub labels {
return (
india_shares => \@labels,
india_nse => \@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, $filename);
(undef, undef, undef, $mday, $month, $year, undef, undef, undef) = localtime($time);
$month = $months[$month];
$year += 1900;
$filename = "cm".$mday.$month.$year."bhav.csv.zip";
# sample -- /content/historical/EQUITIES2013/NOV/cm22NOV2013bhav.csv.zip
return("/content/historical/EQUITIES/$year/$month/$filename");
}
sub india_nse {
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 ($url, $reply);
$ua->default_headers(
HTTP::Headers->new(
'Accept' => '*/*',
'Connection' => 'keep-alive',
'Accept-Language' => 'en-US,en;q=0.9',
'User-Agent' => 'Why are you making it hard for us?'
)
);
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 "DEBUG: URL = $url";
}
# Download file
$reply = getstore( $url, $BHAV_ZIP );
printf "\nResult: $reply, URL: $url";
if ($debug) {
print "DEBUG: Reply = ", is_success($reply) ? "Successful" : "Unsuccessful", " : ", $reply, "\n";
}
last if (is_success($reply) || $reply == 200);
}
unless (is_success($reply) or $reply == 200) {
$errormsg = "\nHTTP failure : " . $reply;
}
unless ($errormsg) {
if (! unzip $BHAV_ZIP => $BHAV_CSV) {
$errormsg = "\nUnzip failure : $UnzipError";
}
}
unless ($errormsg) {
if (! open $fh, '<', $BHAV_CSV) {
$errormsg = "\nOpen failure : $!";
}
}
unless ($errormsg) {
(undef, $ref_trans_2) = symbol_translation('india_nse', \@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'} = 'india_nse';
next if (exists $info{$symbol, 'success'});
$info{$symbol, 'success'} = 0;
$info{$symbol, 'errormsg'} = $errormsg;
}
return wantarray ? %info : \%info;
}
1;
=head1 NAME
Finance::Quote::india_nse - 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('india_nse', '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 india_nse.
=head1 SYMBOL TRANSLATION
If failover method india_shares is used with india_nse and india_icici_direct 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
india_icici_direct respectively.
To be able to use symbol INFY with india_source method with NseIndia and
india_icici_direct as sources, create / modify fq_symbol_translation.txt and add
following line -
icici_direct INFY INFTEC
F::Q will ask both NseIndia and india_icici_direct to fetch information about INFY, but
india_icici_direct 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
india_icici_direct as sources, create / modify fq_symbol_translation.txt and add
following line -
india_nse 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 - india_nse
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment