App-Chart

 view release on metacpan or  search on metacpan

unused/CommSec.pm  view on Meta::CPAN

    my $elem
      = (List::Util::first {$_->[0] >= $months } @indiv_months_list)
        || $indiv_months_list[-1];
    my $period_str = $elem->[1];

    my $url
      = 'http://charts.commsec.com.au/HistoryData/HistoryData.dll/GetData'
        . '?Symbol='
          . URI::Escape::uri_escape (App::Chart::symbol_sans_suffix ($symbol))
            . '&TimePeriod=' . $period_str
              . '&.csv';

    App::Chart::Download::status (__x('CommSec {symbol} {period}',
                                     symbol => $symbol,
                                     period => $period_str));

    my $resp = App::Chart::Download->get($url);
    my $h = indiv_parse ($resp, $months);
    if ($h) {
      $h->{'last_download'} = 1;
      App::Chart::Download::write_daily_group ($h);
    }
  }
}

# return number of months needed to cover back to TDATE
sub indiv_tdate_to_months {
  my ($tdate) = @_;
  $tdate -= 5;  # bit of leeway
  my ($now_year, $now_month, $now_day)
    = App::Chart::TZ->sydney->ymd;
  my ($td_year, $td_month, $td_day) = App::Chart::tdate_to_ymd ($tdate);

  my $now_mdate
    = App::Chart::Timebase::Months::ymd_to_mdate ($now_year, $now_month, 1);
  my $td_mdate
    = App::Chart::Timebase::Months::ymd_to_mdate ($td_year, $td_month, 1);

  return $now_mdate - $td_mdate + ($now_day >= $td_day ? 1 : 0);
}

sub indiv_cost_proc {
  my ($tdate) = @_;
  my $months = indiv_tdate_to_months ($tdate);
  return $months
    * App::Chart::DownloadCost::cost_get (INDIV_PERMONTH_COST_KEY,
                                         INDIV_PERMONTH_COST_DEFAULT);
}

sub indiv_parse {
  my ($resp, $months) = @_;
  my @data = ();
  my $h = { source          => __PACKAGE__,
            currency        => 'AUD',
            suffix          => '.AX',
            prefer_decimals => 2,
            date_format     => 'dmy',
            resp            => $resp,
            data            => \@data };

  my $body = $resp->decoded_content(raise_error=>1);
  if ($body =~ /server error/i) {
    # an unknown symbol
    return $h;
  }

  $h->{'cost_key'} = INDIV_PERMONTH_COST_KEY;
  $h->{'cost_value'} = int (length($body) / $months);

  # Sample line
  #
  #     AEZ,"01 Jun 2007",1.35,1.37,1.305,1.325,4008329\r\n
  #
  # trailing zeros are omitted, like 4.30 or 95.00 in
  # 
  #     ETR,"29 May 2007",4.26,4.3,4.25,4.3,50942\r\n
  #     NABHA,"27 Dec 2000",94.41,95,94.41,94.99,3495\r\n
  #
  foreach my $line (App::Chart::Download::split_lines($body)) {
    my ($symbol, $date, $open, $high, $low, $close, $volume)
      = split (/,/, $line);

    $symbol .= '.AX';
    $open  = pad_decimals ($open, 2);
    $high  = pad_decimals ($high, 2);
    $low   = pad_decimals ($low, 2);
    $close = pad_decimals ($close, 2);

    push @data, { symbol => $symbol,
                  date   => $date,
                  open   => $open,
                  high   => $high,
                  low    => $low,
                  close  => $close,
                  volume => $volume };
  }
  return $h;
}

sub pad_decimals {
  my ($str, $want) = @_;
  if ($str =~ /\.([0-9]*)$/) {
    my $got = length ($1);
    if ($got < $want) {
      $str .= '0' x ($want - $got);
    }
  } else {
    # no decimal point at all
    $str .= '.' . ('0' x $want);
  }
  return $str;
}

#-----------------------------------------------------------------------------
# download - by whole day files
#
# Commsec offers the following formats,
#
#     metastock - prices in dollars, date yymmdd
#     metastock - prices in dollars, date yymmdd, volume in 100s
#     ezychart  - prices in cents, date yymmdd
#     insight   - prices in cents, date mm/dd/yy, space separated
#     stockeasy - prices in dollars, date yyyymmdd
#
# Ezychart is used because it's the most compact -- there's no decimal
# points in most prices, and no century on the date.
#
# The web page says only the past 20 days are available and that's all the
# little menu presents, but the server actually goes back beyond that,
# apparently unlimited.

# return a url string
sub wholeday_url {
  my ($tdate) = @_;
  my ($year, $month, $day) = App::Chart::tdate_to_ymd ($tdate);
   return sprintf 'http://charts.commsec.com.au/HistoryData/HistoryData.dll/EzyChart-%d%02d%02d?DownloadDate=%d%02d%02d&DownloadFormat=EzyChart&.txt',
     $year, $month, $day,
     $year, $month, $day;
}

sub wholeday_download {
  my ($start_tdate, $avail_tdate) = @_;
  foreach my $tdate ($start_tdate .. $avail_tdate) {
    App::Chart::Download::status
        (__x('CommSec data {date}',
             date => App::Chart::Download::tdate_range_string ($tdate)));

    my $url = wholeday_url($tdate);
    my $resp = App::Chart::Download->get ($url);

    # when public holiday, date too old, etc, still get a successful
    # download, with an error message in the body
    my $h = ezychart_parse ($resp);
    App::Chart::Download::write_daily_group ($h);
  }
}

sub ezychart_parse {
  my ($resp) = @_;
  my @data = ();
  my $h = { source          => __PACKAGE__,
            currency        => 'AUD',
            prefer_decimals => 2,
            date_format     => 'ymd',
            resp            => $resp,
            data            => \@data,
            cost_key        => WHOLEDAY_COST_KEY };

  my $body = $resp->decoded_content(raise_error=>1);
  if ($body =~ /server error/i) {
    # an unknown symbol
    return $h;
  }

  # Sample line, 5 Sep 2008
  # BHP,080905,3640,3720,3630,3700,14390282
  #
  foreach my $line (App::Chart::Download::split_lines($body)) {
    my ($symbol, $date, $open, $high, $low, $close, $volume)
      = split (/,/, $line);

    $open  = App::Chart::Download::cents_to_dollars ($open);
    $high  = App::Chart::Download::cents_to_dollars ($high);
    $low   = App::Chart::Download::cents_to_dollars ($low);
    $close = App::Chart::Download::cents_to_dollars ($close);

    push @data, { symbol => "$symbol.AX",
                  date   => $date,
                  open   => $open,
                  high   => $high,
                  low    => $low,
                  close  => $close,
                  volume => $volume };
  }
  return $h;
}

1;
__END__



( run in 4.057 seconds using v1.01-cache-2.11-cpan-5837b0d9d2c )