App-Chart

 view release on metacpan or  search on metacpan

lib/App/Chart/Suffix/NZ.pm  view on Meta::CPAN

#------------------------------------------------------------------------------
# weblink - NZX company info
#
# Eg. https://www.nzx.com/markets/NZSX/securities/FBU
# 
# cf top by value traded,
# https://www.nzx.com/markets/NZSX/securities/values

App::Chart::Weblink->new
  (pred => $pred_shares,
   name => __('NZX _Company Information'),
   desc => __('Open web browser at the New Zealand Stock Exchange page for this stock'),
   proc => sub {
     my ($symbol) = @_;
     return 'https://www.nzx.com/markets/NZSX/securities/'
       . URI::Escape::uri_escape (App::Chart::symbol_sans_suffix ($symbol));
   });


#------------------------------------------------------------------------------
# Dividends
#
# This uses the dividend page at
# 
#     https://www.nzx.com/markets/NZSX/dividends
#     
# The dividend table is buried in a JSON data structure in <script>
# so as minimise the number browsers which will display it.
# As of Sept 2024 the page was about 100 kbytes with 50 dividends
# (declared or to be paid).
# So set to weekly downloads.
#
use constant DIVIDENDS_URL =>
  'https://www.nzx.com/markets/NZSX/dividends';

App::Chart::DownloadHandler::DividendsPage->new
  (name         => __('NZX dividends'),
   pred         => $pred_shares,
   url          => DIVIDENDS_URL,
   parse        => \&dividends_parse,
   key          => 'NZ-dividends',
   recheck_days => 7,
   # low priority so prices fetched first
   priority => -10);

sub dividends_parse {
  my ($resp) = @_;
  ### NZ dividends_parse() ...

  my @dividends = ();
  my $h = { source          => __PACKAGE__,
            resp            => $resp,
            dividends       => \@dividends,
            copyright_key   => 'NZ-dividends-copyright',
            copyright       => 'https://www.nzx.com/meta-pages/terms-of-use',
            date_format     => 'ymd', # ISO 2024-09-09
            prefer_decimals => 2,
          };

  # note: want wide-chars for HTML::TableExtract parse
  my $content = $resp->decoded_content (raise_error => 1);
  $content =~ /<script id="__NEXT_DATA__".*?>(.*?)<\/script>/i
    or die "NZX dividends cannot find JSON table";
  my $str = $1;
  my $json = JSON::from_json($1) // {};

  my $props           = $json->{'props'} // {};
  my $pageProps       = $props->{'pageProps'} // {};
  my $data            = $pageProps->{'data'} // {};

  # marketInstruments array of hashrefs like
  #   "code" : "AFI",
  #   "isin" : "AU000000AFI5",
  #   "name" : "Australian Foundation Investment Company Limited Ord Shares",
  #   "currencyCode" : "NZD",
  # Maps "isin" to exchange "code".
  # "name" is longer than want to display, so stay with Yahoo "shortname".
  #
  my $marketInstruments = $data->{'marketInstruments'} // [];
  my %isin_to_symbol;
  foreach my $href (@$marketInstruments) {
    my $isin = $href->{'isin'} // next;
    my $code = $href->{'code'} // next;
    $isin_to_symbol{$isin} = "$code.NZ";
  }
  # print JSON->new->pretty->encode($marketInstruments), "\n"; exit 0;

  my $marketDividends = $data->{'marketDividends'}
    // die "NZX dividends parse failed";
  # print JSON->new->pretty->encode($marketDividends), "\n"; exit 0;

  # eg. "amount" : "23.000000000",
  #     "currencyCode" : "NZD",
  #     "imputationCreditAmount" : "0.08166667",
  #     "baseQuantity" : "100",
  #     "expectedDate" : 1724673600
  #     "payableDate"  : 1727352000,
  #     "supplementaryAmount" : "0.03705882",
  # Dates are Unix seconds since 1970 GMT and in NZ timezone is
  # midnight on the relevant date.
  #
  foreach my $href (@$marketDividends) {
    my $isin = $href->{'isin'};
    my $symbol = $isin_to_symbol{$href->{'isin'}}
      // die "NZX dividends, no symbol for ISIN $isin";

    my $amount = App::Chart::Download::trim_decimals
      (App::Chart::Download::cents_to_dollars($href->{'amount'}),
       2);
    my $imput  = $href->{'imputationCreditAmount'};
    my $ex_date  = $timezone_newzealand->iso_date($href->{'expectedDate'});
    my $pay_date = $timezone_newzealand->iso_date($href->{'payableDate'});

    # Dividends not in NZD shown just as note.
    # Can have AUD for dual-listed Aust/NZ shares, eg. DOW.AX = DOW.NZ
    # In the past had some GBP.
    my $note;
    my $currency = $href->{'currencyCode'} // '';
    if ($currency ne 'NZD') {
      if ($imput ne '' && $imput != 0) {
        $note = "$amount + $imput $currency";



( run in 1.834 second using v1.01-cache-2.11-cpan-437f7b0c052 )