1#!/usr/bin/perl -w 2 3# 4# Initial version based on NSEIndia.pm 5# 6 7package Finance::Quote::BSEIndia; 8require 5.010; 9 10use strict; 11use POSIX qw(strftime); 12use IO::Uncompress::Unzip qw(unzip $UnzipError); 13 14our $VERSION = '1.51'; # VERSION 15 16use vars qw($BSE_URL); 17$BSE_URL = "https://www.bseindia.com"; 18 19my $cachedir = $ENV{TMPDIR} // $ENV{TEMP} // '/tmp/'; 20my $BSE_ZIP = $cachedir.'bseindia.zip'; 21my $BSE_CSV = $cachedir.'bseindia.csv'; 22 23sub methods { return ( 'india' => \&bseindia, 24 'bseindia' => \&bseindia ); } 25 26sub labels { 27 my @labels = qw/close last high low open prevclose exchange name/; 28 return ( 29 india => \@labels, 30 bseindia => \@labels 31 ); 32} 33 34sub bseindia { 35 my $quoter = shift; 36 my @symbols = @_; 37 return unless @symbols; 38 39 my (%info, $errormsg, $fh, $ua, $url, $reply); 40 41 $ua = $quoter->user_agent; 42 # Set the ua to be blank. Server blocks default useragent. 43 $ua->agent(''); 44 45 # Try to fetch last 10 days 46 for (my ($days, $now) = (0, time()); $days < 10; $days++) { 47 # Ex: https://www.bseindia.com/download/BhavCopy/Equity/EQ_ISINCODE_150520.zip 48 my @lt = localtime($now - $days*24*60*60); 49 my ($date, $url); 50 $date = strftime "%d%m%y", @lt; 51 $url = $BSE_URL . "/download/BhavCopy/Equity/EQ_ISINCODE_${date}.zip"; 52 $reply = $ua->mirror($url, $BSE_ZIP); 53 # print "$url", $reply->is_success, $reply->status_line, "\n"; #DEBUG 54 if ($reply->is_success or $reply->code == 304) { 55 last; 56 } 57 } 58 59 if (!$reply->is_success and $reply->code != 304) { 60 $errormsg = "HTTP failure : " . $reply->status_line; 61 } 62 63 if (!$errormsg) { 64 if (! unzip $BSE_ZIP => $BSE_CSV) { 65 $errormsg = "Unzip error : $UnzipError"; 66 } 67 } 68 69 if (!$errormsg) { 70 if (! open $fh, '<', $BSE_CSV) { 71 $errormsg = "CSV open error: $!"; 72 } 73 } 74 75 if ($errormsg) { 76 foreach my $symbol (@symbols) { 77 $info{$symbol, "success"} = 0; 78 $info{$symbol, "errormsg"} = $errormsg; 79 } 80 return wantarray() ? %info : \%info; 81 } 82 83 # Create a hash of all stocks requested 84 my %symbolhash; 85 foreach my $symbol (@symbols) 86 { 87 $symbolhash{$symbol} = 0; 88 } 89 my $csvhead; 90 my @headhash; 91 92 # SC_CODE,SC_NAME,SC_GROUP,SC_TYPE,OPEN,HIGH,LOW,CLOSE,LAST,PREVCLOSE,NO_TRADES,NO_OF_SHRS,NET_TURNOV,TDCLOINDI,ISIN_CODE,TRADING_DATE,FILLER2,FILLER3 93 $csvhead = <$fh>; 94 chomp $csvhead; 95 @headhash = split /\s*,s*/, $csvhead; 96 while (<$fh>) { 97 my @data = split /\s*,s*/; 98 my %datahash; 99 my $symbol; 100 @datahash{@headhash} = @data; 101 if (exists $symbolhash{$datahash{"SC_CODE"}}) { 102 $symbol = $datahash{"SC_CODE"}; 103 } 104 elsif(exists $symbolhash{$datahash{"ISIN_CODE"}}) { 105 $symbol = $datahash{"ISIN_CODE"}; 106 } 107 else { 108 next; 109 } 110 $info{$symbol, 'symbol'} = $symbol; 111 $info{$symbol, 'close'} = $datahash{"CLOSE"}; 112 $info{$symbol, 'last'} = $datahash{"LAST"}; 113 $info{$symbol, 'high'} = $datahash{"HIGH"}; 114 $info{$symbol, 'low'} = $datahash{"LOW"}; 115 $info{$symbol, 'open'} = $datahash{"OPEN"}; 116 $info{$symbol, 'prevclose'} = $datahash{"PREVCLOSE"}; 117 $info{$symbol, 'name'} = $datahash{"SC_NAME"}; 118 $quoter->store_date(\%info, $symbol, {eurodate => $datahash{"TRADING_DATE"}}); 119 $info{$symbol, 'method'} = 'bseindia'; 120 $info{$symbol, 'currency'} = 'INR'; 121 $info{$symbol, 'exchange'} = 'BSE'; 122 $info{$symbol, 'success'} = 1; 123 } 124 close($fh); 125 126 foreach my $symbol (@symbols) { 127 unless (exists $info{$symbol, 'success'}) { 128 print "$symbol not found\n"; 129 $info{$symbol, 'success'} = 0; 130 $info{$symbol, 'errormsg'} = 'Stock not found on BSE.'; 131 } 132 } 133 134 return wantarray ? %info : \%info; 135} 136 137 1381; 139 140 141=head1 NAME 142 143Finance::Quote::BSEIndia - Obtain quotes from BSE (India). 144 145=head1 SYNOPSIS 146 147 use Finance::Quote; 148 149 $q = Finance::Quote->new(); 150 151 %info = $q->fetch('bseindia', 'INE001A01036'); # Only query BSE. 152 %info = $q->fetch('india', 'INE001A01036'); # Failover to other sources OK. 153 154=head1 DESCRIPTION 155 156This module obtains information about shares listed on the BSE (India). 157Source is the daily bhav copy (zipped CSV). 158 159This module provides both the "bseindia" and "india" fetch methods. Please use the "india" fetch method if you wish to have failover with other sources for Indian stocks (such as NSE). 160 161=head1 LABELS RETURNED 162 163The following labels may be returned by Finance::Quote::BSEIndia: 164close, last, high, low, open, prevclose, exchange, name 165 166=head1 SEE ALSO 167 168BSE (formerly known as Bombay Stock Exchange Ltd.), http://www.bseindia.com/ 169 170=cut 171