App-Chart

 view release on metacpan or  search on metacpan

lib/App/Chart/Series/Derived/PFE.pm  view on Meta::CPAN

  $smooth_N //= parameter_info()->[1]->{'default'};
  ($smooth_N >= 0) || croak "PFE bad smooth: $smooth_N";

  return $class->SUPER::new
    (parent     => $parent,
     parameters => [ $N, $smooth_N ],
     arrays     => { values => [] });
}
sub warmup_count {
  my ($class_or_self, $N, $smooth_N) = @_;
  return $N-1 + App::Chart::Series::Derived::EMA->warmup_count($N);
}

# hypot(r,e)
# h = sqrt(r^2 + e^2)
# d = sqrt(r^2 + e^2) - r
# d+r = sqrt(r^2 + e^2)
# d^2 + 2dr + r^2 = r^2 + e^2
# d^2 + 2dr = e^2
# d^2 + 2dr - e^2 = 0
# d = (-2r +/- sqrt(4r^2 + 4e^2) ) / 2
# d = -r +/- sqrt(r^2 + e^2)

sub proc {
  my ($class_or_self, $N, $smooth_N) = @_;

  # input is how many days, decrement to get how many differences ... is
  # that right?
  $N--;

  my @values; # previous $N many values
  my $sum_proc = App::Chart::Series::Calculation->sum($N);
  my $ema_proc = App::Chart::Series::Derived::EMA->proc($smooth_N);

  return sub {
    my ($value) = @_;
    my $pfe;

    if (@values) {
      my $prevN = $values[-1];
      my $rocN = ($prevN == 0 ? 0 : 100 * ($value - $prevN) / $prevN);

      my $prev1 = $values[0];
      my $roc1 = ($prev1 == 0 ? 0
                  : 100 * ($value - $prev1) / $prev1);
      my $sum = $sum_proc->(_hypot($roc1,1));

      my $raw = ($sum == 0 ? 0
                 : 100 * _hypot($rocN,scalar @values) / $sum);
      if ($rocN < 0) { $raw = -$raw; }
      $pfe = $ema_proc->($raw);
    }
    unshift @values, $value;
    if (@values > $N) { pop @values }

    return $pfe;
  };
}

# could use Math::Libm hypot() here for a touch more accuracy, but not sure
# how good its portability is on non-Unix systems
sub _hypot {
  my ($x,$y) = @_;
  return sqrt($x*$x + $y*$y);
}

1;
__END__

# =head1 NAME
# 
# App::Chart::Series::Derived::PFE -- polarized fractal efficiency (PFE) indicator
# 
# =head1 SYNOPSIS
# 
#  my $series = $parent->PFE($N);
# 
# =head1 DESCRIPTION
# 
# ...
# 
# =head1 SEE ALSO
# 
# L<App::Chart::Series>
# 
# =cut



( run in 0.987 second using v1.01-cache-2.11-cpan-64ef6c95b5d )