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   344 use 5.006;
  1         3  
21 1     1   5 use strict;
  1         2  
  1         16  
22 1     1   4 use warnings;
  1         1  
  1         20  
23 1     1   243 use URI::Escape;
  1         1109  
  1         49  
24 1     1   7 use Locale::TextDomain 'App-Chart';
  1         1  
  1         7  
25              
26 1     1   402 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';
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 => 'dmy', # dates like "16/08/2017"
124             };
125              
126             # Column "Dividend Period" for "interim" or "final" not very interesting.
127             # FIXME: what's the "Supp." column?
128             require HTML::TableExtract;
129             my $te = HTML::TableExtract->new
130             (headers => ['Code',
131             'Ex',
132             'Payable',
133             'Amount',
134             'Currency',
135             'Imputation' ]);
136              
137             $te->parse($body);
138             if (! $te->tables) {
139             die "NZX dividend table not matched";
140             }
141              
142             my $count = 0;
143             foreach my $ts ($te->tables) {
144             foreach my $row ($ts->rows) {
145             my ($symbol, $ex_date, $pay_date, $amount, $currency, $imput)
146             = @$row;
147              
148             # dummy footnote row
149             next if ($symbol =~ /cents per share/);
150              
151             push @dividends,
152             dividend_parse ($symbol, $ex_date,$pay_date,$amount, $currency,$imput);
153             }
154             }
155             App::Chart::Download::verbose_message ("NZX dividends total $count found");
156             return $h;
157             }
158              
159             sub dividend_parse {
160             my ($symbol, $ex_date,$pay_date,$amount, $currency,$imput) = @_;
161              
162             # leading and trailing whitespace
163             $amount = App::Chart::collapse_whitespace ($amount);
164             $imput = App::Chart::collapse_whitespace ($imput);
165             $currency = App::Chart::collapse_whitespace ($currency);
166              
167             foreach ($amount, $imput) {
168             # eg. "3.900c" with c for cents
169             if (s/c$//) {
170             $_ = App::Chart::Download::cents_to_dollars ($_);
171             }
172             # discard trailing zeros when a whole number of cents
173             $_ = App::Chart::Download::trim_decimals ($_, 2);
174             }
175              
176             # foreign like AUD or GBP turned into merely a note
177             my $note;
178             if ($currency ne 'NZD') {
179             if ($imput ne '' && $imput != 0) {
180             $note = "$amount + $imput $currency";
181             } else {
182             $note = "$amount $currency";
183             }
184             $amount = undef;
185             $imput = undef;
186             }
187              
188             return { symbol => $symbol,
189             ex_date => $ex_date,
190             pay_date => $pay_date,
191             amount => $amount,
192             imputation => $imput,
193             note => $note };
194             }
195              
196             1;
197             __END__