File Coverage

blib/lib/Finance/Quote/BSEIndia.pm
Criterion Covered Total %
statement 21 82 25.6
branch 0 26 0.0
condition 0 6 0.0
subroutine 8 9 88.8
pod 0 3 0.0
total 29 126 23.0


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