pub struct TvmSolution { /* private fields */ }Implementations§
Source§impl TvmSolution
impl TvmSolution
Sourcepub fn series(&self) -> TvmSeries
pub fn series(&self) -> TvmSeries
Calculates the value of an investment after each period.
§Examples
Calculates the period-by-period details of a future value calculation. Uses
future_value_solution.
// The initial investment is $10,000.12, the interest rate is 1.5% per month, and the
// investment will grow for 24 months using simple compounding.
let solution = finance_solution::future_value_solution(0.015, 24, 10_000.12, false);
// Calculate the value at the end of each period.
let series = solution.series();
dbg!(&series);
// Confirm that we have one entry for the initial value and one entry for each period.
assert_eq!(25, series.len());
// Print the period-by-period numbers in a formatted table.
series.print_table();
// Create a vector with every fourth period.
let filtered_series = series
.iter()
.filter(|x| x.period() % 4 == 0)
.collect::<Vec<_>>();
dbg!(&filtered_series);
assert_eq!(7, filtered_series.len());Calculate a present value with a fixed rate then examine the period-by-period values. Uses
present_value_solution.
// The interest rate is 7.8% per year, the investment will grow for 10 years using simple
// compounding, and the final value will be 8_112.75.
let solution = finance_solution::present_value_solution(0.078, 10, 8_112.75, false);
// Calculate the value at the end of each period.
let series = solution.series();
dbg!(&series);
// Confirm that we have one entry for the present value, that is the
// initial value before any interest is applied, and one entry for each
// period.
assert_eq!(11, series.len());
// Create a reduced vector with every other period not including period 0,
// the initial state.
let filtered_series = series
.iter()
.filter(|x| x.period() % 2 == 0 && x.period() != 0)
.collect::<Vec<_>>();
dbg!(&filtered_series);
assert_eq!(5, filtered_series.len());Calculate a present value with varying rates then examine the period-by-period values. Uses
present_value_schedule.
// The annual rate varies from -12% to 11%.
let rates = [0.04, 0.07, -0.12, -0.03, 0.11];
// The value of the investment after applying all of these periodic rates
// will be $100_000.25.
let future_value = 100_000.25;
// Calculate the present value and keep track of the inputs and the formula
// in a struct.
let solution = finance_solution::present_value_schedule_solution(&rates, future_value);
dbg!(&solution);
// Calculate the value at the end of each period.
let series = solution.series();
dbg!(&series);
// There is one entry for each period and one entry for period 0 containing
// the present value.
assert_eq!(6, series.len());
// Create a filtered list of periods, only those with a negative rate.
let filtered_series = series
.iter()
.filter(|x| x.rate() < 0.0)
.collect::<Vec<_>>();
dbg!(&filtered_series);
assert_eq!(2, filtered_series.len());Sourcepub fn print_series_table(&self)
pub fn print_series_table(&self)
Prints a formatted table with the period-by-period details of a time-value-of-money calculation.
Money amounts are rounded to four decimal places, rates to six places, and numbers are formatted similar to Rust constants such as “10_000.0322”. For more control over formatting use [`TvmSolution::print_series_table_locale’].
§Examples
finance_solution::future_value_solution(0.045, 5, 10_000, false)
.print_series_table();Output:
period rate value
------ -------- -----------
0 0.000000 10_000.0000
1 0.045000 10_450.0000
2 0.045000 10_920.2500
3 0.045000 11_411.6612
4 0.045000 11_925.1860
5 0.045000 12_461.8194Sourcepub fn print_series_table_locale(&self, locale: &Locale, precision: usize)
pub fn print_series_table_locale(&self, locale: &Locale, precision: usize)
Prints a formatted table with the period-by-period details of a time-value-of-money calculation.
For a simpler function that doesn’t require a locale use [`TvmSolution::print_series_table’].
§Arguments
locale- A locale constant from thenum-formatcrate such asLocale::enfor English orLocale::vifor Vietnamese. The locale determines the thousands separator and decimal separator.precision- The number of decimal places for money amounts. Rates will appear with at least six places regardless of this argument.
§Examples
// English formatting with "," for the thousands separator and "." for the decimal
// separator.
let locale = finance_solution::num_format::Locale::en;
// Show money amounts to two decimal places.
let precision = 2;
finance_solution::future_value_solution(0.11, 4, 5_000, false)
.print_series_table_locale(&locale, precision);Output:
period rate value
------ -------- --------
0 0.000000 5,000.00
1 0.110000 5,550.00
2 0.110000 6,160.50
3 0.110000 6,838.16
4 0.110000 7,590.35Sourcepub fn calculated_field(&self) -> &TvmVariable
pub fn calculated_field(&self) -> &TvmVariable
Returns a variant of TvmVariable showing which value was calculated, either the periodic
rate, number of periods, present value, or future value. To test for the enum variant use
functions like TvmVariable::is_rate.
§Examples
// Calculate the future value of $25,000 that grows at 5% for 12 yeors.
let solution = finance_solution::future_value_solution(0.05, 12, 25_000, false);
assert!(solution.calculated_field().is_future_value());Sourcepub fn continuous_compounding(&self) -> bool
pub fn continuous_compounding(&self) -> bool
Returns true if the value is compounded continuously rather than period-by-period.
Sourcepub fn rate(&self) -> f64
pub fn rate(&self) -> f64
Returns the periodic rate which is a calculated value if this TvmSolution struct is the
result of a call to rate_solution and otherwise is one of the input values.
Sourcepub fn periods(&self) -> u32
pub fn periods(&self) -> u32
Returns the number of periods as a whole number. This is a calculated value if this
TvmSolution struct is the result of a call to periods_solution and otherwise it’s
one of the input values. If the value was calculated the true result may not have been a
whole number so this is that number rounded away from zero.
Sourcepub fn fractional_periods(&self) -> f64
pub fn fractional_periods(&self) -> f64
Returns the number of periods as a floating point number. This is a calculated value if this
TvmSolution struct is the result of a call to periods_solution and otherwise it’s
one of the input values.
Sourcepub fn present_value(&self) -> f64
pub fn present_value(&self) -> f64
Returns the present value which is a calculated value if this TvmSolution struct is the
result of a call to present_value_solution and otherwise is one of the input values.
Sourcepub fn future_value(&self) -> f64
pub fn future_value(&self) -> f64
Returns the future value which is a calculated value if this TvmSolution struct is the
result of a call to future_value_solution and otherwise is one of the input values.
Sourcepub fn formula(&self) -> &str
pub fn formula(&self) -> &str
Returns a text version of the formula used to calculate the result which may have been the periodic rate, number of periods, present value, or future value depending on which function was called. The formula includes the actual values rather than variable names. For the formula with variables such as r for rate call symbolic_formula.
Sourcepub fn symbolic_formula(&self) -> &str
pub fn symbolic_formula(&self) -> &str
Returns a text version of the formula used to calculate the result which may have been the periodic rate, number of periods, present value, or future value depending on which function was called. The formula uses variables such as n for the number of periods. For the formula with the actual values rather than variables call formula.
pub fn rate_solution( &self, continuous_compounding: bool, compounding_periods: Option<u32>, ) -> TvmSolution
pub fn periods_solution(&self, continuous_compounding: bool) -> TvmSolution
pub fn present_value_solution( &self, continuous_compounding: bool, compounding_periods: Option<u32>, ) -> TvmSolution
pub fn future_value_solution( &self, continuous_compounding: bool, compounding_periods: Option<u32>, ) -> TvmSolution
Sourcepub fn present_value_vary_compounding_periods(
&self,
compounding_periods: &[u32],
include_continuous_compounding: bool,
) -> ScenarioList
pub fn present_value_vary_compounding_periods( &self, compounding_periods: &[u32], include_continuous_compounding: bool, ) -> ScenarioList
Returns a struct with a set of what-if scenarios for the present value needed with a variety of compounding periods.
§Arguments
compounding_periods- The compounding periods to include in the scenarios. The result will have a computed present value for each compounding period in this list.include_continuous_compounding- If true, adds one scenario at the end of the results with continuous compounding instead of a given number of compounding periods.
§Examples
For a more detailed example with a related function see future_value_vary_compounding_periods
// Calculate the future value of an investment that starts at $83.33 and grows 20% in one
// year using simple compounding. Note that we're going to examine how the present value
// varies by the number of compounding periods but we're starting with a future value
// calculation. It would have been fine to start with a rate, periods, or present value
// calculation as well. It just depends on what information we have to work with.
let solution = finance_solution::future_value_solution(0.20, 1, -83.333, false);
dbg!(&solution);
// The present value of $83.33 gives us a future value of about $100.00.
finance_solution::assert_rounded_2!(100.00, solution.future_value());
// We'll experiment with compounding annually, quarterly, monthly, weekly, and daily.
let compounding_periods = [1, 4, 12, 52, 365];
// Add a final scenario with continuous compounding.
let include_continuous_compounding = true;
// Compile a list of the present values needed to arrive at the calculated future value of $100
// each of the above compounding periods as well a continous compounding.
let scenarios = solution.present_value_vary_compounding_periods(&compounding_periods, include_continuous_compounding);
dbg!(&scenarios);
// Print the results in a formatted table.
scenarios.print_table();
Output from the last line:
Periods Present Value
------- -------------
1 83.3330
4 82.2699
12 82.0078
52 81.9042
365 81.8772
inf 81.8727As we compound the interest more frequently we need a slightly smaller initial value to reach the same final value of $100 in one year. With more frequent compounding the required initial value approaches $81.87, the present value needed with continuous compounding.
If we plot this using between 1 and 12 compounding periods it’s clear that the required present value drops sharply if we go from compounding annually to compounding semiannually or quarterly but then is affected less and less as we compound more frequently:
Sourcepub fn future_value_vary_compounding_periods(
&self,
compounding_periods: &[u32],
include_continuous_compounding: bool,
) -> ScenarioList
pub fn future_value_vary_compounding_periods( &self, compounding_periods: &[u32], include_continuous_compounding: bool, ) -> ScenarioList
Returns a struct with a set of what-if scenarios for the future value of an investment given a variety of compounding periods.
§Arguments
compounding_periods- The compounding periods to include in the scenarios. The result will have a computed future value for each compounding period in this list.include_continuous_compounding- If true, adds one scenario at the end of the results with continuous compounding instead of a given number of compounding periods.
§Examples
// The interest rate is 5% per quarter.
let rate = 0.05;
// The interest will be applied once per quarter for one year.
let periods = 4;
// The starting value is $100.00.
let present_value = 100;
let continuous_compounding = false;
let solution = finance_solution::future_value_solution(rate, periods, present_value, continuous_compounding);
dbg!(&solution);
// We'll experiment with compounding annually, quarterly, monthly, weekly, and daily.
let compounding_periods = [1, 4, 12, 52, 365];
// Add a final scenario with continuous compounding.
let include_continuous_compounding = true;
// Compile a list of the future values with each of the above compounding periods as well as
// continous compounding.
let scenarios = solution.future_value_vary_compounding_periods(&compounding_periods, include_continuous_compounding);
// The description in the `setup` field states that the rate is 20% since that's 5% times the
// number of periods in the original calculation. The final entry has `input: inf` indicating
// that we used continuous compounding.
dbg!(&scenarios);
// Print the results in a formatted table.
scenarios.print_table();Output:
&solution = FutureValueSolution {
tvm_solution: TvmSolution {
calculated_field: FutureValue,
continuous_compounding: false,
rate: 0.05,
periods: 4,
fractional_periods: 4.0,
present_value: 100.0,
future_value: 121.55062500000003,
formula: "121.5506 = 100.0000 * (1.050000 ^ 4)",
symbolic_formula: "fv = pv * (1 + r)^n",
},
&scenarios = ScenarioList {
setup: "Compare future values with different compounding periods where the rate is 0.200000 and the present value is 100.0000.",
input_variable: Periods,
output_variable: FutureValue,
entries: [
{ input: 1, output: 120.0000 },
{ input: 4, output: 121.5506 },
{ input: 12, output: 121.9391 },
{ input: 52, output: 122.0934 },
{ input: 365, output: 122.1336 },
{ input: inf, output: 122.1403 },
],
}
Periods Future Value
------- ------------
1 120.0000
4 121.5506
12 121.9391
52 122.0934
365 122.1336
inf 122.1403With the same interest rate and overall time period, an amount grows faster if we compound the interest more frequently. As the number of compounding periods grows the future value approaches the limit of $122.14 that we get with continuous compounding.
As a chart it looks like this, here using only 1 through 12 compounding periods for clarity:
pub fn print_ab_comparison(&self, other: &TvmSolution)
pub fn print_ab_comparison_locale( &self, other: &TvmSolution, locale: &Locale, precision: usize, )
Trait Implementations§
Source§impl Clone for TvmSolution
impl Clone for TvmSolution
Source§fn clone(&self) -> TvmSolution
fn clone(&self) -> TvmSolution
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more