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 )