File Coverage

blib/lib/Finance/Quote/BSEIndia.pm
Criterion Covered Total %
statement 15 77 19.4
branch 0 26 0.0
condition 0 6 0.0
subroutine 6 7 85.7
pod 0 3 0.0
total 21 119 17.6


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