App-Chart
view release on metacpan or search on metacpan
lib/App/Chart/Series/Derived/Adjust.pm view on Meta::CPAN
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
('SELECT ex_date, amount, imputation
FROM dividend WHERE (symbol=? AND (ex_date BETWEEN ? AND ?))
ORDER BY ex_date DESC');
$dividends = $dbh->selectall_arrayref ($sth, {Slice=>{}},
$symbol, $lo_iso, $hi_iso);
$sth->finish;
foreach my $row (@$dividends) {
$row->{'ex_date'} = $timebase->from_iso_floor ($row->{'ex_date'});
}
}
push @$dividends, { ex_date => $lo-1 }; # sentinel
### $dividends
$hi = $parent->find_after($hi,1);
$parent->fill ($lo, $hi);
my $p_opens = $parent->array('opens');
my $p_closes = $parent->array('closes');
my $p_highs = $parent->array('highs');
my $p_lows = $parent->array('lows');
my $p_volumes = $parent->array('volumes');
my $p_openints = $parent->array('openints');
my $s_opens = $self->{'opens'};
my $s_closes = $self->{'closes'};
my $s_highs = $self->{'highs'};
my $s_lows = $self->{'lows'};
my $s_volumes = $self->{'volumes'};
my $s_openints = $self->{'openints'};
my $factor = 1;
my $post_close;
for (my $t = $hi; $t >= $lo; $t--) {
if ($p_opens->[$t]) { $s_opens->[$t] = $p_opens->[$t] * $factor; }
if ($p_highs->[$t]) { $s_highs->[$t] = $p_highs->[$t] * $factor; }
if ($p_lows->[$t]) { $s_lows->[$t] = $p_lows->[$t] * $factor; }
if ($p_closes->[$t]) { $post_close = $p_closes->[$t];
$s_closes->[$t] = $post_close * $factor;
}
if ($p_volumes->[$t]) { $s_volumes->[$t] = $p_volumes->[$t] / $factor;}
if ($p_openints->[$t]){ $s_openints->[$t] = $p_openints->[$t] / $factor;}
for ( ; $splits->[0]->{'date'} >= $t; shift @$splits) {
$factor *= ($splits->[0]->{'old'} / $splits->[0]->{'new'});
### factor now: $factor
}
for ( ; $dividends->[0]->{'ex_date'} >= $t; shift @$dividends) {
my $div = $dividends->[0]->{'amount'};
Scalar::Util::looks_like_number ($div) or next;
if ($self->{'adjust_imputation'}) {
my $imp = $dividends->[0]->{'imputation'};
if (Scalar::Util::looks_like_number ($imp)) { $div += $imp; }
}
if (defined $post_close) {
# factor chosen so if prev=post+div then prev*factor==post
$factor *= $post_close / ($post_close + $div);
### dividend: $div
### $post_close
### factor now: $factor
}
}
}
}
sub dividends {
my ($self) = @_;
return $self->{'parent'}->dividends;
}
sub splits {
my ($self) = @_;
return $self->{'parent'}->splits;
}
sub annotations {
my ($self) = @_;
return $self->{'parent'}->annotations;
}
sub Alerts_arrayref {
my ($self) = @_;
my $parent = $self->{'parent'};
if (my $func = $parent->can('Alerts_arrayref')) {
return $parent->$func;
} else {
return [];
}
}
# FIXME: Adjust endpoints per display
sub AnnLines_arrayref {
my ($self) = @_;
my $parent = $self->{'parent'};
if (my $func = $parent->can('AnnLines_arrayref')) {
return $parent->$func;
} else {
return [];
}
}
1;
__END__
=head1 NAME
App::Chart::Series::Derived::Adjust -- series adjustments for dividends, splits, etc
=for test_synopsis my ($series)
=head1 SYNOPSIS
use App::Chart::Series::Derived::Adjust;
my $adj_series = App::Chart::Series::Derived::Adjust->derive
( run in 1.005 second using v1.01-cache-2.11-cpan-39bf76dae61 )