package App::FinanceUtils;

our $DATE = '2017-03-13'; # DATE
our $VERSION = '0.001'; # VERSION

use 5.010001;
use strict;
use warnings;

our %SPEC;

$SPEC{calc_fv_future_value} = {
    v => 1.1,
    summary => 'Calculate future value (FV) from present value (PV), rate of return (r), and number of periods (n)',
    description => <<'_',

The formula is:

    FV = PV*(1+r)^n

But if you use simple interest (`--simple`) where the interest is not
compounded, the formula is:

    FV = PV*(1+r*n)

_
    args => {
        pv => {
            summary => 'Present value',
            schema => ['float*'],
            req => 1,
            pos => 0,
        },
        r => {
            summary => 'Rate of return, in percent',
            schema => ['float*'],
            req => 1,
            pos => 1,
        },
        n => {
            summary => 'Number of periods',
            schema => ['float*'],
            req => 1,
            pos => 2,
        },
        simple => {
            summary => 'Use simple interest (interest not compounded)',
            schema => 'bool*',
        },
    },
    examples => [
        {
            summary => 'Invest $100 at 6% annual return rate for 5 years',
            args => {pv=>100, r=>6, n=>5},
        },
        {
            summary => 'Invest $100 at 6% annual return rate for 5 years, simple interest',
            args => {pv=>100, r=>6, n=>5, simple=>1},
        },
    ],
    result_naked => 1,
};
sub calc_fv_future_value {
    my %args = @_;

    $args{simple} ? $args{pv}*(1+$args{r}/100*$args{n}) : $args{pv}*(1+$args{r}/100)**$args{n};
}

$SPEC{calc_fv_present_value} = {
    v => 1.1,
    summary => 'Calculate present value (PV) from future value (FV), rate of return (r), and number of periods (n)',
    description => <<'_',

The formula is:

    PV = FV/(1+r)^n

But if you use simple interest (`--simple`) where the interest is not
compounded, the formula is:

    PV = FV/(1+r*n)

_
    args => {
        fv => {
            summary => 'Future value',
            schema => ['float*'],
            req => 1,
            pos => 0,
        },
        r => {
            summary => 'Rate of return, in percent',
            schema => ['float*'],
            req => 1,
            pos => 1,
        },
        n => {
            summary => 'Number of periods',
            schema => ['float*'],
            req => 1,
            pos => 2,
        },
        simple => {
            summary => 'Use simple interest (interest not compounded)',
            schema => 'bool*',
        },
    },
    examples => [
        {
            summary => 'Want to get $100 after 5 years at 6% annual return rate, how much to invest?',
            args => {fv=>100, r=>6, n=>5},
        },
        {
            summary => 'Want to get $100 after 5 years at 6% annual return rate, with simple interest, how much to invest?',
            args => {fv=>100, r=>6, n=>5, simple=>1},
        },
    ],
    result_naked => 1,
};
sub calc_fv_present_value {
    my %args = @_;

    $args{simple} ? $args{fv}/(1+$args{r}/100*$args{n}) : $args{fv}/(1+$args{r}/100)**$args{n};
}

$SPEC{calc_fv_return_rate} = {
    v => 1.1,
    summary => 'Calculate return rate (r) from future value (FV), present value (PV), and number of periods (n)',
    description => <<'_',

The formula is:

    r = (FV/PV)^(1/n) - 1

_
    args => {
        fv => {
            summary => 'Future value',
            schema => ['float*'],
            req => 1,
            pos => 0,
        },
        pv => {
            summary => 'Present value',
            schema => ['float*'],
            req => 1,
            pos => 1,
        },
        n => {
            summary => 'Number of periods',
            schema => ['float*'],
            req => 1,
            pos => 2,
        },
    },
    examples => [
        {
            summary => 'Want to get $120 in 5 years using $100 investment, what is the required return rate (in percentage)?',
            args => {fv=>120, pv=>100, n=>5},
        },
    ],
    result_naked => 1,
};
sub calc_fv_return_rate {
    my %args = @_;

    (($args{fv}/$args{pv})**(1/$args{n}) - 1)*100;
}

$SPEC{calc_fv_periods} = {
    v => 1.1,
    summary => 'Calculate number of periods (n) from present value (FV), present value (PV), and return rate (r)',
    description => <<'_',

The formula is:

    n = ln(FV/PV) / ln(1+r)

_
    args => {
        fv => {
            summary => 'Future value',
            schema => ['float*'],
            req => 1,
            pos => 0,
        },
        pv => {
            summary => 'Present value',
            schema => ['float*'],
            req => 1,
            pos => 1,
        },
        r => {
            summary => 'Return rate, in percentage',
            schema => ['float*'],
            req => 1,
            pos => 2,
        },
    },
    examples => [
        {
            summary => 'Want to get $120 using $100 investment with annual 6% return rate, how many years must we wait?',
            args => {fv=>120, pv=>100, r=>6},
        },
    ],
    result_naked => 1,
};
sub calc_fv_periods {
    my %args = @_;

    log($args{fv}/$args{pv})/log(1+$args{r}/100);
}

1;
# ABSTRACT: Calculate present value (PV) from future value (FV), rate of return (r), and number of periods (n)

__END__

=pod

=encoding UTF-8

=head1 NAME

App::FinanceUtils - Calculate present value (PV) from future value (FV), rate of return (r), and number of periods (n)

=head1 VERSION

This document describes version 0.001 of App::FinanceUtils (from Perl distribution App-FinanceUtils), released on 2017-03-13.

=head1 DESCRIPTION

This distribution contains some CLI's to do financial calculations:

# INSERT_EXECS_LIST

=head1 FUNCTIONS


=head2 calc_fv_future_value

Usage:

 calc_fv_future_value(%args) -> any

Calculate future value (FV) from present value (PV), rate of return (r), and number of periods (n).

Examples:

=over

=item * Invest $100 at 6% annual return rate for 5 years:

 calc_fv_future_value(pv => 100, r => 6, n => 5); # -> 133.82255776

=item * Invest $100 at 6% annual return rate for 5 years, simple interest:

 calc_fv_future_value(pv => 100, r => 6, n => 5, simple => 1); # -> 130

=back

The formula is:

 FV = PV*(1+r)^n

But if you use simple interest (C<--simple>) where the interest is not
compounded, the formula is:

 FV = PV*(1+r*n)

This function is not exported.

Arguments ('*' denotes required arguments):

=over 4

=item * B<n>* => I<float>

Number of periods.

=item * B<pv>* => I<float>

Present value.

=item * B<r>* => I<float>

Rate of return, in percent.

=item * B<simple> => I<bool>

Use simple interest (interest not compounded).

=back

Return value:  (any)


=head2 calc_fv_periods

Usage:

 calc_fv_periods(%args) -> any

Calculate number of periods (n) from present value (FV), present value (PV), and return rate (r).

Examples:

=over

=item * Want to get $120 using $100 investment with annual 6% return rate, how many years must we wait?:

 calc_fv_periods(fv => 120, pv => 100, r => 6); # -> 3.12896813521953

=back

The formula is:

 n = ln(FV/PV) / ln(1+r)

This function is not exported.

Arguments ('*' denotes required arguments):

=over 4

=item * B<fv>* => I<float>

Future value.

=item * B<pv>* => I<float>

Present value.

=item * B<r>* => I<float>

Return rate, in percentage.

=back

Return value:  (any)


=head2 calc_fv_present_value

Usage:

 calc_fv_present_value(%args) -> any

Calculate present value (PV) from future value (FV), rate of return (r), and number of periods (n).

Examples:

=over

=item * Want to get $100 after 5 years at 6% annual return rate, how much to invest?:

 calc_fv_present_value(fv => 100, r => 6, n => 5); # -> 74.7258172866057

=item * Want to get $100 after 5 years at 6% annual return rate, with simple interest, how much to invest?:

 calc_fv_present_value(fv => 100, r => 6, n => 5, simple => 1); # -> 76.9230769230769

=back

The formula is:

 PV = FV/(1+r)^n

But if you use simple interest (C<--simple>) where the interest is not
compounded, the formula is:

 PV = FV/(1+r*n)

This function is not exported.

Arguments ('*' denotes required arguments):

=over 4

=item * B<fv>* => I<float>

Future value.

=item * B<n>* => I<float>

Number of periods.

=item * B<r>* => I<float>

Rate of return, in percent.

=item * B<simple> => I<bool>

Use simple interest (interest not compounded).

=back

Return value:  (any)


=head2 calc_fv_return_rate

Usage:

 calc_fv_return_rate(%args) -> any

Calculate return rate (r) from future value (FV), present value (PV), and number of periods (n).

Examples:

=over

=item * Want to get $120 in 5 years using $100 investment, what is the required return rate (in percentage)?:

 calc_fv_return_rate(fv => 120, pv => 100, n => 5); # -> 3.71372893366482

=back

The formula is:

 r = (FV/PV)^(1/n) - 1

This function is not exported.

Arguments ('*' denotes required arguments):

=over 4

=item * B<fv>* => I<float>

Future value.

=item * B<n>* => I<float>

Number of periods.

=item * B<pv>* => I<float>

Present value.

=back

Return value:  (any)

=head1 HOMEPAGE

Please visit the project's homepage at L<https://metacpan.org/release/App-FinanceUtils>.

=head1 SOURCE

Source repository is at L<https://github.com/perlancar/perl-App-FinanceUtils>.

=head1 BUGS

Please report any bugs or feature requests on the bugtracker website L<https://rt.cpan.org/Public/Dist/Display.html?Name=App-FinanceUtils>

When submitting a bug or request, please include a test-file or a
patch to an existing test-file that illustrates the bug or desired
feature.

=head1 AUTHOR

perlancar <perlancar@cpan.org>

=head1 COPYRIGHT AND LICENSE

This software is copyright (c) 2017 by perlancar@cpan.org.

This is free software; you can redistribute it and/or modify it under
the same terms as the Perl 5 programming language system itself.

=cut
