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 )