App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Download.pm view on Meta::CPAN
return __x('{symbol} no data at all, marked historical',
symbol => $symbol);
}
my $days = iso_timestamp_days_ago ($date, $last_download_timestamp);
if ($days > 21) {
return __x('{symbol} no data for {days} days, marked historical',
days => $days,
symbol => $symbol);
}
return undef;
}
sub iso_timestamp_days_ago {
my ($iso, $prev_timestamp) = @_;
my ($prev_year,$prev_month,$prev_day) = timestamp_to_ymdhms($prev_timestamp);
return Date::Calc::Delta_Days (App::Chart::iso_to_ymd($iso),
$prev_year, $prev_month, $prev_day);
}
sub consider_latest_from_daily {
my ($h) = @_;
my $dbh = App::Chart::DBI->instance;
my %latest_changed;
my $timestamp;
my $database_symbols_hash = App::Chart::Database::database_symbols_hash();
# find the newest and second newest data record of each symbol
my %data_newest;
my %data_second;
foreach my $data (@{$h->{'data'}}) {
my $symbol = $data->{'symbol'};
if ($data->{'date'} ge ($data_newest{$symbol}->{'date'} // '')) {
$data_second{$symbol} = $data_newest{$symbol};
$data_newest{$symbol} = $data;
} elsif ($data->{'date'} ge ($data_second{$symbol}->{'date'} // '')) {
$data_second{$symbol} = $data;
}
}
foreach my $symbol (keys %data_newest) {
my $newest = $data_newest{$symbol};
my $date = $newest->{'date'};
# For symbols in the database, if newest daily is >= latest quote then
# delete that quote in order to prefer the daily data in the database.
if (exists $database_symbols_hash->{$symbol}) {
my $latest_delete_sth = $dbh->prepare_cached
('DELETE FROM latest WHERE symbol=? AND quote_date < ?');
if ($latest_delete_sth->execute ($symbol, $date)) {
$latest_changed{$symbol} = 1;
}
next;
}
# For symbols not in the database, if the newest daily is >= latest quote
# then replace that quote with the daily.
#
# Times in the latest record are not considered, so it's possible a
# quote taken after close of trading will be deleted or overwritten.
# Would want something in the latest to say it's after the close ...
my $latest_get_sth = $dbh->prepare_cached
('SELECT last_date, name FROM latest WHERE symbol=?');
my ($last_date, $name, $dividend)
= $dbh->selectrow_array ($latest_get_sth, undef, $symbol);
if (defined $last_date && $last_date gt $date) { next; }
# "name" from the daily, or retain name from existing latest record.
$name = $h->{'names'}->{$symbol} // $name;
# "dividend" from existing latest record retained, but only if same date.
unless (defined $last_date && $last_date eq $date) {
undef $dividend;
}
# change by difference from second newest daily, if have one
my $change = undef;
if (defined(my $second_close = $data_second{$symbol}->{'close'})) {
$change = App::Chart::decimal_sub ($newest->{'close'}, $second_close);
}
$timestamp ||= timestamp_now();
my $latest_set_sth = $dbh->prepare_cached
('INSERT OR REPLACE INTO latest
(symbol, name, currency, exchange, dividend,
last_date, open, high, low, last, change, volume,
source, fetch_timestamp)
VALUES (?,?,?,?,?, ?,?,?,?,?,?,?, ?,?)');
$latest_set_sth->execute
($symbol,
$name,
$h->{'currencies'}->{$symbol},
$h->{'exchanges'}->{$symbol},
$dividend,
#
$newest->{'date'},
$newest->{'open'},
$newest->{'high'},
$newest->{'low'},
$newest->{'close'},
$change,
$newest->{'volume'},
#
$h->{'source'},
$timestamp);
$latest_changed{$symbol} = 1;
}
foreach my $dividend (@{$h->{'dividends'}}) {
my $latest_dividend_sth = $dbh->prepare_cached
('UPDATE latest SET dividend=? WHERE symbol=? AND last_date=?');
my $symbol = $dividend->{'symbol'};
if ($latest_dividend_sth->execute ($dividend->{'amount'},
$symbol,
$dividend->{'ex_date'})) {
$latest_changed{$symbol} = 1;
}
}
( run in 0.477 second using v1.01-cache-2.11-cpan-d7a12ab2c7f )