App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Series/Derived/Adjust.pm view on Meta::CPAN
use base 'App::Chart::Series::OHLCVI';
# uncomment this to run the ### lines
#use Smart::Comments;
sub longname { __('Adjustments') }
sub shortname { __('Adj') }
sub manual { __p('manual-node','Dividends and Splits') }
use constant { type => 'special',
parameter_info => [ { name => __('Splits'),
key => 'adj_splits',
type => 'boolean',
default => 1 },
{ name => __('Divs'),
key => 'adj_dividends',
type => 'boolean',
default => 1 },
{ name => __('Imp'),
key => 'adj_imputation',
type => 'boolean',
default => 1 },
{ name => __('Roll'),
key => 'adj_rollovers',
type => 'boolean',
default => 0 }],
};
sub name {
my ($self) = @_;
return __x('{parent} - Adj {list}',
parent => $self->{'parent'}->name,
list =>
join (',',
($self->{'adjust_splits'} ? __('Splits') : ()),
($self->{'adjust_dividends'} ? __('Divs') : ()),
($self->{'adjust_dividends'} && $self->{'adjust_imputation'}
? __('Imp') : ())));
}
sub symbol_name {
my ($self) = @_;
if (my $parent = $self->{'parent'}) {
if (defined (my $symbol = $parent->{'symbol'})) {
return App::Chart::Database->symbol_name ($symbol);
}
}
return undef;
}
sub derive {
my ($class, $parent, %options) = @_;
my $adjust_splits = $options{'adjust_splits'};
my $adjust_dividends = $options{'adjust_dividends'};
if (! $adjust_splits && ! $adjust_dividends) { return $parent; }
# Only go up to today (in the symbol's timezone) for adjustments. Stuff
# in the future shouldn't be applied until then. Decide this at init time
# in case we live long enough for the time to reach a new day.
#
my $symbol = $parent->{'symbol'};
my $timezone = App::Chart::TZ->for_symbol ($symbol);
my $hi_iso = $timezone->iso_date;
my $timebase = $parent->timebase;
my $lo_iso = $timebase->to_iso (0);
# if for each option it's either not wanted or there's no data for it,
# then can just return unmodified $parent
#
if ((! $adjust_splits
|| ! App::Chart::DBI->read_single ('SELECT date FROM split
WHERE (symbol=? AND (date BETWEEN ? AND ?))
LIMIT 1', $symbol, $lo_iso, $hi_iso))
&&
(! $adjust_dividends
|| ! App::Chart::DBI->read_single ('SELECT ex_date FROM dividend
WHERE (symbol=? AND (ex_date BETWEEN ? AND ?))
LIMIT 1', $symbol, $lo_iso, $hi_iso))) {
### Adjust no splits or dividends to apply
return $parent;
}
return $class->SUPER::new (parent => $parent,
adj_hi_iso => $hi_iso,
%options);
}
sub fill_part {
my ($self, $lo, $hi) = @_;
### Adjust fill_part() "$lo $hi"
my $dbh = App::Chart::DBI->instance;
my $timebase = $self->timebase;
my $parent = $self->{'parent'};
my $symbol = $parent->{'symbol'};
my $lo_iso = $timebase->to_iso ($lo); # requested $lo
my $hi_iso = $self->{'adj_hi_iso'}; # all splits/divs to today
my $splits = [];
if ($self->{'adjust_splits'}) {
my $sth = $dbh->prepare_cached
('SELECT date, new, old
FROM split WHERE (symbol=? AND (date BETWEEN ? AND ?))
ORDER BY date DESC');
$splits = $dbh->selectall_arrayref ($sth, {Slice=>{}},
$symbol, $lo_iso, $hi_iso);
$sth->finish;
foreach my $row (@$splits) {
$row->{'date'} = $timebase->from_iso_floor ($row->{'date'});
}
}
push @$splits, { date => $lo-1 }; # sentinel
### $splits
my $dividends = [];
if ($self->{'adjust_dividends'}) {
my $sth = $dbh->prepare_cached
( run in 0.567 second using v1.01-cache-2.11-cpan-39bf76dae61 )