App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Suffix/TSP.pm view on Meta::CPAN
my $lo_tdate = App::Chart::Download::start_tdate_for_update (@$symbol_list);
if ($lo_tdate > $avail_tdate) {
App::Chart::Download::verbose_message
(__('TSP nothing further expected yet'));
return;
}
# ask for extra in case available_tdate() is a bit short
$avail_tdate += 2;
my $resp = get_chunk ($symbol_list, $lo_tdate, $avail_tdate);
my $h = parse ($resp);
$h->{'last_download'} = 1;
App::Chart::Download::write_daily_group ($h);
}
sub backto {
my ($symbol_list, $backto_tdate) = @_;
my $hi_tdate = App::Chart::Download::start_tdate_for_backto (@$symbol_list);
my $resp = get_chunk ($backto_tdate, $hi_tdate);
my $h = parse ($resp);
App::Chart::Download::write_daily_group ($h);
}
# return a HTTP::Response for data $lo_tdate to $hi_tdate, inclusive
sub get_chunk {
my ($symbol_list, $lo_tdate, $hi_tdate) = @_;
App::Chart::Download::status
(__x('TSP data {date_range}',
date_range =>
App::Chart::Download::tdate_range_string ($lo_tdate, $hi_tdate)));
my ($lo_year, $lo_month, $lo_day) = App::Chart::tdate_to_ymd ($lo_tdate);
my ($hi_year, $hi_month, $hi_day) = App::Chart::tdate_to_ymd ($hi_tdate);
my $startdate = sprintf "%04d-%02d-%02d", $lo_year, $lo_month, $lo_day;
my $enddate = sprintf "%04d-%02d-%02d", $hi_year, $hi_month, $hi_day;
return App::Chart::Download->get
(TSP_SHARE_PRICES_URL
. "?startdate=$startdate&enddate=$enddate&Lfunds=1&InvFunds=1&download=1",
user_agent => TSP_USER_AGENT);
}
# $resp is a HTTP::Response object, return a hashref of data
sub parse {
my ($resp, $symbol_list) = @_;
# From 1 Jul 2008 prices are 4 decimal places, and old data is padded with
# zeros. Could prefer_decimals to strip them, but may as well leave at
# current precision.
#
my @data = ();
my $h = { source => __PACKAGE__,
currency => 'USD',
date_format => 'ymd',
suffix => '.TSP',
data => \@data };
my $content = $resp->decoded_content (raise_error=>1);
### $content
my @lines = App::Chart::Download::split_lines ($content);
my ($date, @symbols) = split /,/, $lines[0];
lc($date) eq 'date'
or die 'TSP csv doesn\'t start with "date": ', $lines[0];
shift @lines;
### @symbols
# "L Income" becomes uppercase "LINCOME.TSP" (documented in chart.texi
# that way)
@symbols = map { my $symbol = $_;
$symbol =~ s/ Fund//i;
$symbol =~ s/ //g;
"\U$symbol.TSP" }
@symbols;
### @symbols
$symbol_list //= \@symbols;
my %symbol_list = map {$_ => 1} @$symbol_list;
foreach my $line (@lines) {
my ($date, @prices) = split /,/, $line;
foreach my $c (0 .. $#prices) {
my $symbol = $symbols[$c];
next unless exists $symbol_list{$symbol};
push @data, { symbol => $symbol,
date => $date,
close => $prices[$c],
};
}
}
if (DEBUG) {
require List::Util;
print "min date ",List::Util::minstr(map {$_->{'date'}} @data),"\n";
print "max date ",List::Util::maxstr(map {$_->{'date'}} @data),"\n";
}
return $h;
}
1;
__END__
# Finance::Quote::TSP no longer has a %TSP_FUND_NAMES table.
#
# # $symbol is like "L2050.TSP", return a name from the table in
# # Finance::Quote::TSP, or undef if unknown. The names table there is not a
# # documented feature, so guard with an eval.
# #
# sub symbol_to_name {
# my ($symbol) = @_;
# # eg. "TSPL2050" or "TSPGFUND"
# $symbol = 'TSP'.App::Chart::symbol_sans_suffix($symbol);
# return eval {
# require Finance::Quote::TSP;
# $Finance::Quote::TSP::TSP_FUND_NAMES{$symbol}
# || $Finance::Quote::TSP::TSP_FUND_NAMES{$symbol.'FUND'}
# };
# }
# Old code parsing HTML table.
# {
# my ($resp) = @_;
#
# # From 1 Jul 2008 prices are 4 decimal places, and old data is padded with
# # zeros. Could prefer_decimals to strip them, but may as well leave at
# # current precision.
# #
# my @data = ();
# my $h = { source => __PACKAGE__,
# currency => 'USD',
# date_format => 'mdy',
# suffix => '.TSP',
# data => \@data };
#
# my $content = $resp->decoded_content (raise_error=>1);
# ### $content
#
# require HTML::TableExtract;
# my $te = HTML::TableExtract->new (headers => [qr/^Date$/i],
# keep_headers => 1,
# slice_columns => 0);
# $te->parse($content);
# my $ts = $te->first_table_found();
# #### $ts
# if (! $ts) { die 'TSP price table not found'; }
#
# my $rows = $ts->rows();
# my $lastrow = $#$rows;
# my $lastcol = $#{$rows->[0]};
#
# my @symbol = map { my $symbol = $_;
# $symbol =~ s/ Fund//i;
# $symbol =~ s/ //g;
# # upper case for "LINCOME.TSP" (documented in
# # chart.texi that way)
# $symbol eq 'Date' ? undef : "\U$symbol.TSP" } @{$rows->[0]};
#
# require Finance::Quote::TSP;
# my @name = map { my $key = $_;
# $key =~ s/ //g;
# $Finance::Quote::TSP::TSP_FUND_NAMES{"TSP$key"} }
# @{$rows->[0]};
#
# foreach my $r (1 .. $lastrow) {
# my $row = $rows->[$r];
# if (DEBUG) { require Data::Dumper;
# print Data::Dumper::Dumper($row); }
# my $date = $row->[0];
#
# foreach my $c (1 .. $lastcol) {
# my $price = $row->[$c];
#
# push @data, { symbol => $symbol[$c],
# name => $name[$c],
# date => $date,
# close => $price,
# };
# }
# }
# if (DEBUG) {
# require List::Util;
# print "min date ",List::Util::minstr(map {$_->{'date'}} @data),"\n";
# print "max date ",List::Util::maxstr(map {$_->{'date'}} @data),"\n";
# }
# return $h;
# }
( run in 0.942 second using v1.01-cache-2.11-cpan-437f7b0c052 )