File Coverage

blib/lib/App/Chart/Suffix/NZ.pm
Criterion Covered Total %
statement 15 17 88.2
branch n/a
condition n/a
subroutine 6 6 100.0
pod n/a
total 21 23 91.3


line stmt bran cond sub pod time code
1             # New Zealand Stock Exchange setups.
2              
3             # Copyright 2007, 2008, 2009, 2010, 2011, 2012, 2017 Kevin Ryde
4              
5             # This file is part of Chart.
6             #
7             # Chart is free software; you can redistribute it and/or modify it under the
8             # terms of the GNU General Public License as published by the Free Software
9             # Foundation; either version 3, or (at your option) any later version.
10             #
11             # Chart is distributed in the hope that it will be useful, but WITHOUT ANY
12             # WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13             # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
14             # details.
15             #
16             # You should have received a copy of the GNU General Public License along
17             # with Chart. If not, see <http://www.gnu.org/licenses/>.
18              
19             package App::Chart::Suffix::NZ;
20 1     1   386 use 5.006;
  1         3  
21 1     1   5 use strict;
  1         1  
  1         17  
22 1     1   4 use warnings;
  1         2  
  1         22  
23 1     1   323 use URI::Escape;
  1         1240  
  1         51  
24 1     1   6 use Locale::TextDomain 'App-Chart';
  1         2  
  1         7  
25              
26 1     1   471 use App::Chart;
  0            
  0            
27             use App::Chart::Database;
28             use App::Chart::Google;
29             use App::Chart::Download;
30             use App::Chart::DownloadHandler;
31             use App::Chart::DownloadHandler::DividendsPage;
32             use App::Chart::Sympred;
33             use App::Chart::TZ;
34             use App::Chart::Weblink;
35             use App::Chart::Yahoo;
36              
37             # uncomment this to run the ### lines
38             # use Smart::Comments;
39              
40              
41             our $timezone_newzealand = App::Chart::TZ->new
42             (name => __('New Zealand'),
43             choose => [ 'Pacific/Auckland' ],
44             fallback => 'NST-12');
45              
46             # http://au.finance.yahoo.com/nzindices
47             # ^NZ50
48             # ^NZC50
49             # ^NZ10G
50             # ^NZMGC
51             # ^NZGI
52             # ^NZSCG
53             # ^NZ50G
54             # ^NZ30G
55             my $pred_shares = App::Chart::Sympred::Suffix->new ('.NZ');
56             my $pred_any = App::Chart::Sympred::Regexp->new (qr/^\^NZ|\.NZ$/);
57             $timezone_newzealand->setup_for_symbol ($pred_any);
58              
59             App::Chart::setup_source_help
60             ($pred_any, __p('manual-node','New Zealand Stock Exchange'));
61              
62             # See http://www.nzx.com/markets/key-dates/trading-hours
63             # pre-open 9am-10am, trading 10am-5pm, adjust 5:30pm, then enquiry
64             # NZAX shares are only 10am to 4:30pm, but don't worry about that
65             # (yahoo-quote-lock! newzealand-symbol?
66             # #,(hms->seconds 9 0 0) #,(hms->seconds 17 30 0))
67             # Yahoo index values based on last trades, so they should only update
68             # during trading 10am to 5pm.
69             # (yahoo-quote-lock! yahoo-index-symbol-newzealand?
70             # #,(hms->seconds 10 0 0) #,(hms->seconds 17 0 0))
71              
72             $App::Chart::Google::google_web_pred->add ($pred_shares);
73              
74              
75             #------------------------------------------------------------------------------
76             # weblink - NZX company info
77             #
78             # Eg. https://www.nzx.com/markets/NZSX/securities/FBU
79             #
80             # cf top by value traded,
81             # https://www.nzx.com/markets/NZSX/securities/values
82              
83             App::Chart::Weblink->new
84             (pred => $pred_shares,
85             name => __('NZX _Company Information'),
86             desc => __('Open web browser at the New Zealand Stock Exchange page for this stock'),
87             proc => sub {
88             my ($symbol) = @_;
89             return 'https://www.nzx.com/markets/NZSX/securities/'
90             . URI::Escape::uri_escape (App::Chart::symbol_sans_suffix ($symbol));
91             });
92              
93              
94             #------------------------------------------------------------------------------
95             # dividends
96             #
97             # This uses the dividend page at
98             #
99             use constant DIVIDENDS_URL =>
100             'https://www.nzx.com/markets/NZSX/dividends';
101              
102             App::Chart::DownloadHandler::DividendsPage->new
103             (name => __('NZX dividends'),
104             pred => $pred_shares,
105             url => DIVIDENDS_URL,
106             parse => \&dividends_parse,
107             key => 'NZ-dividends',
108             # low priority so prices fetched first
109             priority => -10);
110              
111             sub dividends_parse {
112             my ($resp) = @_;
113              
114             # note: want wide-chars for HTML::TableExtract parse
115             my $body = $resp->decoded_content (raise_error => 1);
116              
117             my @dividends = ();
118             my $h = { source => __PACKAGE__,
119             resp => $resp,
120             dividends => \@dividends,
121             copyright_key => 'NZ-dividends-copyright',
122             copyright => 'http://www.nzx.com/terms',
123             date_format => 'mdy', # dates like "October 19, 2017"
124             prefer_decimals => 2,
125             };
126              
127             # Column "Dividend Period" for "interim" or "final" not very interesting.
128             # FIXME: what's the "Supp." column?
129             require HTML::TableExtract;
130             my $te = HTML::TableExtract->new
131             (headers => ['Code',
132             'Ex',
133             'Payable',
134             'Amount',
135             'Currency',
136             'Imputation' ]);
137              
138             $te->parse($body);
139             if (! $te->tables) {
140             die "NZX dividend table not matched";
141             }
142              
143             my $count = 0;
144             foreach my $ts ($te->tables) {
145             foreach my $row ($ts->rows) {
146             my ($symbol, $ex_date, $pay_date, $amount, $currency, $imput)
147             = @$row;
148              
149             # dummy footnote row
150             next if ($symbol =~ /cents per share/);
151              
152             push @dividends,
153             dividend_parse ($symbol, $ex_date,$pay_date,$amount, $currency,$imput);
154             }
155             }
156             App::Chart::Download::verbose_message ("NZX dividends total $count found");
157             return $h;
158             }
159              
160             sub dividend_parse {
161             my ($symbol, $ex_date,$pay_date,$amount, $currency,$imput) = @_;
162              
163             # leading and trailing whitespace
164             $symbol = App::Chart::collapse_whitespace($symbol);
165             $amount = App::Chart::collapse_whitespace ($amount);
166             $imput = App::Chart::collapse_whitespace ($imput);
167             $currency = App::Chart::collapse_whitespace ($currency);
168              
169             foreach ($amount, $imput) {
170             # eg. "3.900c" with c for cents, or latin-1 0xA2 cents symbol
171             if (s/ *[c\xA2]$//) {
172             $_ = App::Chart::Download::cents_to_dollars ($_);
173             }
174             # discard trailing zeros, when a whole number of cents
175             $_ = App::Chart::Download::trim_decimals ($_, 2);
176             }
177              
178             # foreign like AUD or GBP turned into merely a note
179             my $note;
180             if ($currency ne 'NZD') {
181             if ($imput ne '' && $imput != 0) {
182             $note = "$amount + $imput $currency";
183             } else {
184             $note = "$amount $currency";
185             }
186             $note = App::Chart::collapse_whitespace ($note);
187             $amount = undef;
188             $imput = undef;
189             }
190              
191             return { symbol => "$symbol.NZ",
192             ex_date => $ex_date,
193             pay_date => $pay_date,
194             amount => $amount,
195             imputation => $imput,
196             note => $note };
197             }
198              
199             1;
200             __END__