finance_solution/tvm/future_value.rs
1//! **Future value calculations.** Given an initial investment amount, a number of periods such as
2//! periods, and fixed or varying interest rates, what is the value of the investment at the end?
3//!
4//! For most common usages, we recommend the [future_value_solution](./fn.future_value_solution.html) function, which provides a better debugging experience and additional features.
5//!
6//! For more complex scenarios, which involve varying rates in each period, we recommend the [future_value_schedule_solution](./fn.future_value_schedule_solution.html) function.
7//!
8//! To simply return an f64 value of the future value answer, use the [future_value](./fn.future_value.html) function.
9//!
10// ! If you need to calculate the present value given a future value, a number of periods, and one
11// ! or more rates use [`present_value`] or related functions.
12// !
13// ! If you need to calculate a fixed rate given a present value, future value, and number of periods
14// ! use [`rate`] or related functions.
15// !
16// ! If you need to calculate the number of periods given a fixed rate and a present and future value
17// ! use [`periods`] or related functions.
18//!
19//! ## Example
20//!
21//! ```
22//! let (rate, periods, present_value, continuous_compounding) = (0.034, 10, 1_000, false);
23//! let fv = finance_solution::future_value_solution(rate, periods, present_value, continuous_compounding).unwrap();
24//! dbg!(fv);
25//! ```
26//! Outputs to terminal:
27//! ```text
28//! {
29//! calculated_field: FutureValue,
30//! continuous_compounding: false,
31//! rate: 0.034,
32//! periods: 10,
33//! fractional_periods: 10.0,
34//! present_value: 1000.0,
35//! future_value: 1397.0288910795477,
36//! formula: "1397.0289 = 1000.0000 * (1.034000 ^ 10)",
37//! symbolic_formula: "fv = pv * (1 + r)^n",
38//! }
39//! ```
40//! # Formulas
41//!
42//! ## Simple Compounding
43//!
44//! With simple compound interest, the future value is calculated with:
45//!
46//! > <img src="http://i.upmath.me/svg/future%5C_value%20%3D%20present%5C_value%20%5Ctimes%20(1%2Brate)%5E%7Bperiods%7D" />
47//!
48//! Or with some more commonly-used variable names:
49//!
50//! > <img src="http://i.upmath.me/svg/fv%20%3D%20pv%20%5Ctimes%20(1%2Br)%5En" />
51//!
52//! `n` is often used for the number of periods, though it may be `t` for time if each period is
53//! assumed to be one year as in continuous compounding. `r` is the periodic rate, though this may
54//! appear as `i` for interest.
55//!
56//! Throughout this crate we use `pv` for present value and `fv` for future value. You may see these
57//! values called `P` for principal in some references.
58//!
59//! Within the [TvmSolution](./struct.TvmSolution.html) struct we record the formula used for the particular calculation
60//! using both concrete values and symbols. For example with $1,000 growing at 3.5% per period for
61//! 12 periods using simple compounding the struct contains these fields:
62//! ```text
63//! formula: "1511.0687 = 1000.0000 * (1.035000 ^ 12)",
64//! symbolic_formula: "fv = pv * (1 + r)^n",
65//! ```
66//!
67//! ## Continuous Compounding
68//!
69//! With continuous compounding the formula is:
70//!
71//! > <img src="http://i.upmath.me/svg/future%5C_value%20%3D%20%7Bpresent%5C_value%20%5Ctimes%20e%5E%7Brate%20%5Ctimes%20periods%7D" />
72//!
73//! or:
74//!
75//! > <img src="http://i.upmath.me/svg/fv%20%3D%20pv%20%5Ctimes%20e%5E%7Br%20%5Ctimes%20n%7D" />
76//!
77//! With continuous compounding the period is assumed to be years and `t` (time) is often used as
78//! the variable name. Within this crate we stick with `n` for the number of periods so that it's
79//! easier to compare formulas when they're printed as simple text as part of the [TvmSolution](./struct.TvmSolution.html)
80//! struct. For example with $1,000 growing at 3.5% per period for 12 periods using continuous
81//! compounding the struct contains these fields:
82//! ```text
83//! formula: "1521.9616 = 1000.0000 * 2.718282^(0.035000 * 12)",
84//! symbolic_formula: "fv = pv * e^(rt)",
85//! ```
86//! This is the same as the example in the previous section except that it uses continuous
87//! compounding.
88use log::warn;
89
90use super::tvm::*;
91
92#[allow(unused_imports)]
93use crate::{periods::*, present_value::*, rate::*};
94
95/// Returns the value of an investment after it has grown or shrunk over time, using a fixed rate.
96///
97/// See the [future_value](./index.html) module page for the formulas.
98///
99/// Related functions:
100/// * To calculate a future value with a fixed rate and return a struct that shows the formula and
101/// optionally produces the the period-by-period values use [`future_value_solution`].
102/// * To calculate the future value if the rates vary by period use [`future_value_schedule`] or
103/// [`future_value_schedule_solution`].
104///
105/// # Arguments
106/// * `rate` - The rate at which the investment grows or shrinks per period, expressed as a
107/// floating point number. For instance 0.05 would mean 5% growth. Often appears as `r` or `i` in
108/// formulas.
109/// * `periods` - The number of periods such as quarters or periods. Often appears as `n` or `t`.
110/// * `present_value` - The starting value of the investment. May appear as `pv` in formulas, or `C`
111/// for cash flow or `P` for principal.
112/// * `continuous_compounding` - True for continuous compounding, false for simple compounding.
113///
114/// # Errors
115/// The call returns [`FinanceError`] if `rate` is less than -1.0 as this would mean the investment is
116/// losing more than its full value every period.
117///
118/// # Examples
119/// Investment that grows quarter by quarter.
120/// ```
121/// use finance_solution::*;
122///
123/// // The investment grows by 3.4% per quarter.
124/// let rate = 0.034;
125///
126/// // The investment will grow for 5 quarters.
127/// let periods = 5;
128///
129/// // The initial investment is $250,000.
130/// let present_value = -250_000;
131///
132/// let continuous_compounding = false;
133///
134/// let future_value = future_value(rate, periods, present_value, continuous_compounding).unwrap();
135/// // Confirm that the future value is correct to four decimal places (one
136/// // hundredth of a cent).
137/// assert_rounded_4(295_489.9418, future_value);
138/// ```
139/// Investment that loses money each year.
140/// ```
141/// # use finance_solution::*;
142/// // The investment loses 5% per year.
143/// let rate = -0.05;
144///
145/// // The investment will shrink for 6 periods.
146/// let periods = 6;
147///
148/// // The initial investment is $10,000.75.
149/// let present_value = -10_000.75;
150///
151/// let continuous_compounding = false;
152///
153/// let future_value = future_value(rate, periods, present_value, continuous_compounding).unwrap();
154/// // Confirm that the future value is correct to the penny.
155/// assert_rounded_2(7351.47, future_value);
156/// ```
157/// Error case: rate less than −100% per period is outside the domain.
158/// ```
159/// # use finance_solution::{future_value, FinanceError};
160/// let err = future_value(-1.05, 6, 10_000.75, false).unwrap_err();
161/// assert!(matches!(err, FinanceError::InvalidRate { .. }));
162/// ```
163///
164/// # Errors
165/// Returns [`FinanceError::InvalidRate`] if `rate < -1.0`, or [`FinanceError::NonFinite`]
166/// if inputs or the computed result are not finite.
167///
168/// # Examples
169/// ```
170/// use finance_solution::{future_value, FinanceError, FinanceResult};
171///
172/// match future_value(0.05, 10, -1_000.0, false) {
173/// Ok(fv) => assert!(fv > 0.0),
174/// Err(FinanceError::InvalidRate { rate }) => panic!("unexpected bad rate {rate}"),
175/// Err(e) => panic!("{e}"),
176/// }
177///
178/// assert!(matches!(
179/// future_value(-1.5, 10, 1000.0, false),
180/// Err(FinanceError::InvalidRate { .. })
181/// ));
182///
183/// fn project(pv: f64, years: u32) -> FinanceResult<f64> {
184/// future_value(0.07, years, pv, false)
185/// }
186/// assert!(project(-5_000.0, 5).is_ok());
187/// ```
188pub fn future_value<T, C>(
189 rate: f64,
190 periods: u32,
191 present_value: T,
192 compounding: C,
193) -> crate::FinanceResult<f64>
194where
195 T: Into<f64> + Copy,
196 C: Into<crate::Compounding>,
197{
198 future_value_internal(
199 rate,
200 periods as f64,
201 present_value.into(),
202 compounding.into().is_continuous(),
203 )
204}
205
206/// Calculates the value of an investment after it has grown or shrunk over time and returns a
207/// struct with the inputs and the calculated value. This is used for keeping track of a collection
208/// of financial scenarios so that they can be examined later.
209///
210/// See the [future_value](./index.html) module page for the formulas.
211///
212/// Related functions:
213/// * For simply calculating a single future value using a fixed rate use [`future_value`].
214/// * To calculate the future value if the rates vary by period use [`future_value_schedule`].
215/// * To calculate the future value with varying rates and return a struct that can produce the
216/// period-by-period values use [`future_value_schedule_solution`].
217///
218/// # Arguments
219/// * `rate` - The rate at which the investment grows or shrinks per period, expressed as a
220/// floating point number. For instance 0.05 would mean 5% growth. Often appears as `r` or `i` in
221/// formulas.
222/// * `periods` - The number of periods such as quarters or periods. Often appears as `n` or `t`.
223/// * `present_value` - The starting value of the investment. May appear as `pv` in formulas, or `C`
224/// for cash flow or `P` for principal.
225/// * `continuous_compounding` - True for continuous compounding, false for simple compounding.
226///
227/// # Errors
228/// Same domain rules as [`future_value`]: invalid rate or non-finite inputs yield
229/// [`crate::FinanceError`].
230///
231/// # Examples
232/// Calculate a future value and examine the period-by-period values.
233/// ```
234/// use finance_solution::*;
235/// // The rate is 1.2% per month.
236/// let rate = 0.012;
237///
238/// // The investment will grow for 8 months.
239/// let periods = 8;
240///
241/// // The initial investment is $200,000.
242/// let present_value = -200_000.0;
243///
244/// let continuous_compounding = false;
245///
246/// let solution = future_value_solution(rate, periods, present_value, continuous_compounding).unwrap();
247/// dbg!(&solution);
248///
249/// let future_value = solution.future_value();
250/// assert_rounded_4(future_value, 220_026.0467);
251///
252/// // Examine the formulas.
253/// let formula = solution.formula();
254/// dbg!(&formula);
255/// assert_eq!(formula, "220026.0467 = 200000.0000 * (1.012000 ^ 8)");
256/// let symbolic_formula = solution.symbolic_formula();
257/// dbg!(&symbolic_formula);
258/// assert_eq!(symbolic_formula, "fv = -pv * (1 + r)^n");
259///
260/// // Calculate the value at the end of each period.
261/// let series = solution.series();
262/// dbg!(&series);
263/// ```
264/// Create a collection of future value calculations ranging over several interest rates.
265/// ```
266/// # use finance_solution::*;
267///
268/// // The initial investment is $100,000.
269/// let present_value = -100_000.0;
270///
271/// // The investment will grow for 12 periods.
272/// let periods = 12;
273///
274/// let continuous_compounding = false;
275///
276/// // We'll keep a collection of the calculated future values along with their inputs.
277/// let mut scenarios = vec![];
278///
279/// for i in 2..=15 {
280/// // The rate is between 2% and 15% per year.
281/// let rate = f64::from(i) / 100.0;
282/// // Calculate the future value for this periodic rate and add the details to the collection.
283/// scenarios.push(future_value_solution(rate, periods, present_value, continuous_compounding).unwrap());
284/// }
285/// dbg!(&scenarios);
286/// assert_eq!(14, scenarios.len());
287///
288/// // Keep only the scenarios where the future value was between $200,000 and $400,000.
289/// scenarios.retain(|x| x.future_value() >= 200_000.00 && x.future_value() <= 400_000.00);
290/// dbg!(&scenarios);
291/// assert_eq!(7, scenarios.len());
292///
293/// // Check the formulas for the first of the remainingc scenarios.
294/// let formula = scenarios[0].formula();
295/// dbg!(&formula);
296/// assert_eq!("201219.6472 = 100000.0000 * (1.060000 ^ 12)", formula);
297/// let symbolic_formula = scenarios[0].symbolic_formula();
298/// dbg!(&symbolic_formula);
299/// assert_eq!("fv = -pv * (1 + r)^n", symbolic_formula);
300/// ```
301pub fn future_value_solution<T, C>(
302 rate: f64,
303 periods: u32,
304 present_value: T,
305 compounding: C,
306) -> crate::FinanceResult<TvmSolution>
307where
308 T: Into<f64> + Copy,
309 C: Into<crate::Compounding>,
310{
311 future_value_solution_internal(
312 rate,
313 periods as f64,
314 present_value.into(),
315 compounding.into().is_continuous(),
316 )
317}
318
319/// Calculates a future value based on rates that change for each period.
320///
321/// Related functions:
322/// * To calculate the future value with varying rates and return a struct that can produce the
323/// period-by-period values use [`future_value_schedule_solution`].
324/// * If there is a single fixed rate use [`future_value`] or [`future_value_solution`].
325///
326/// # Arguments
327/// * `rates` - A collection of rates, one for each period.
328/// * `present_value` - The starting value of the investment.
329///
330/// # Errors
331/// The call returns [`FinanceError`] if any of the rates is less than -1.0 as this would mean the investment is
332/// losing more than its full value.
333///
334/// # Examples
335/// Calculate the value of an investment whose rates vary by year.
336/// ```
337/// use finance_solution::*;
338/// // The rates vary by year: 4% followed by -3.9%, 10.6%, and -5.7%.
339/// let rates = [0.04, -0.039, 0.106, -0.057];
340///
341/// // The initial investment is $75,000.
342/// let present_value = -75_000.00;
343///
344/// let future_value = future_value_schedule(&rates, present_value).unwrap();
345/// dbg!(&future_value);
346/// assert_rounded_4(78_178.0458, future_value);
347/// ```
348/// Error case: One of the rates shows a drop of over 100%.
349/// ```
350/// # use finance_solution::{future_value_schedule, FinanceError};
351/// let rates = [0.116, -100.134, -0.09, 0.086];
352/// let present_value = -4_000.00;
353/// let err = future_value_schedule(&rates, present_value).unwrap_err();
354/// assert!(matches!(err, FinanceError::InvalidRate { .. }));
355/// ```
356///
357/// # Errors
358/// Returns [`FinanceError::InvalidRate`] if any rate is out of domain, or
359/// [`FinanceError::NonFinite`] for non-finite inputs/results.
360/// An empty `rates` slice is valid and means zero periods (returns `-present_value`).
361pub fn future_value_schedule<T>(rates: &[f64], present_value: T) -> crate::FinanceResult<f64>
362where
363 T: Into<f64> + Copy,
364{
365 let present_value = present_value.into();
366 crate::util::error::require_rates(rates)?;
367 crate::util::error::require_money("present_value", present_value)?;
368 let periods = rates.len();
369
370 let mut future_value = -present_value;
371 for i in 0..periods {
372 future_value *= 1.0 + rates[i];
373 }
374
375 if future_value.is_finite() {
376 Ok(future_value)
377 } else {
378 Err(crate::FinanceError::NonFinite {
379 field: "future_value",
380 value: future_value,
381 })
382 }
383}
384
385/// Calculates a future value based on rates that change for each period, returning a struct with
386/// all of the inputs and results.
387///
388/// Related functions:
389/// * For simply calculating a single future value using a fixed rate use [`future_value`].
390/// * To calculate a future value with a fixed rate and return a struct that shows the formula and
391/// optionally produces the the period-by-period values use [`future_value_solution`].
392/// * To calculate the future value if the rates vary by period use [`future_value_schedule`].
393///
394/// # Arguments
395/// * `rates` - A collection of rates, one for each period.
396/// * `present_value` - The starting value of the investment.
397///
398/// # Errors
399/// The call returns [`FinanceError`] if any of the rates is less than -1.0 as this would mean the investment is
400/// losing more than its full value.
401///
402/// # Examples
403/// Calculate the value of an investment whose rates vary by year.
404/// ```
405/// use finance_solution::*;
406/// // The rates vary by year: 8.1% followed by 11%, 4%, and -2.3%.
407/// let rates = [0.081, 0.11, 0.04, -0.023];
408///
409/// // The initial investment is $10,000.
410/// let present_value = -10_000.00;
411///
412/// let solution = future_value_schedule_solution(&rates, present_value).unwrap();
413/// dbg!(&solution);
414///
415/// let future_value = solution.future_value();
416/// dbg!(&future_value);
417/// assert_rounded_4(future_value, 12_192.0455);
418///
419/// // Calculate the value for each period.
420/// let series = solution.series();
421/// dbg!(&series);
422/// ```
423pub fn future_value_schedule_solution<T>(
424 rates: &[f64],
425 present_value: T,
426) -> crate::FinanceResult<TvmScheduleSolution>
427where
428 T: Into<f64> + Copy,
429{
430 let present_value = present_value.into();
431 let future_value = future_value_schedule(rates, present_value)?;
432 Ok(TvmScheduleSolution::new(
433 TvmVariable::FutureValue,
434 rates,
435 present_value,
436 future_value,
437 ))
438}
439
440pub(crate) fn future_value_internal(
441 rate: f64,
442 periods: f64,
443 present_value: f64,
444 continuous_compounding: bool,
445) -> crate::FinanceResult<f64> {
446 crate::util::error::require_rate(rate)?;
447 crate::util::error::require_money("present_value", present_value)?;
448 if rate.abs() > 1.0 {
449 warn!(
450 "You provided a periodic rate ({}) greater than 1. Are you sure you expect a {}% return?",
451 rate,
452 rate * 100.0
453 );
454 }
455 let future_value = if continuous_compounding {
456 // http://www.edmichaelreggie.com/TMVContent/rate.htm
457 -present_value * std::f64::consts::E.powf(rate * periods)
458 } else {
459 -present_value * (1.0 + rate).powf(periods)
460 };
461 if future_value.is_finite() {
462 Ok(future_value)
463 } else {
464 Err(crate::FinanceError::NonFinite {
465 field: "future_value",
466 value: future_value,
467 })
468 }
469}
470
471pub(crate) fn future_value_solution_internal(
472 rate: f64,
473 periods: f64,
474 present_value: f64,
475 continuous_compounding: bool,
476) -> crate::FinanceResult<TvmSolution> {
477 let future_value = future_value_internal(rate, periods, present_value, continuous_compounding)?;
478 let (formula, symbolic_formula) = if continuous_compounding {
479 let formula = format!(
480 "{:.4} = {:.4} * {:.6}^({:.6} * {})",
481 future_value,
482 -present_value,
483 std::f64::consts::E,
484 rate,
485 periods
486 );
487 let symbolic_formula = "fv = -pv * e^(rt)";
488 (formula, symbolic_formula)
489 } else {
490 let rate_multiplier = 1.0 + rate;
491 let formula = format!(
492 "{:.4} = {:.4} * ({:.6} ^ {})",
493 future_value, -present_value, rate_multiplier, periods
494 );
495 let symbolic_formula = "fv = -pv * (1 + r)^n";
496 (formula, symbolic_formula)
497 };
498 Ok(TvmSolution::new_fractional_periods(
499 TvmVariable::FutureValue,
500 continuous_compounding,
501 rate,
502 periods,
503 present_value,
504 future_value,
505 &formula,
506 symbolic_formula,
507 ))
508}
509
510#[cfg(test)]
511mod tests {
512 use super::*;
513 use crate::initialized_vector;
514
515 #[test]
516 fn test_future_value_error_rate_low() {
517 assert!(future_value(-101.0, 5, 250_000.00, false).is_err());
518 }
519
520 #[test]
521 fn test_future_value_solution_6() {
522 let rate_of_return = 1.0f64 / 0.0f64;
523 let periods = 6;
524 let present_value = 5_000.00;
525 assert!(future_value_solution(rate_of_return, periods, present_value, false).is_err());
526 }
527
528 #[test]
529 fn test_future_value_solution_7() {
530 let rate_of_return = 0.03;
531 let periods = 6;
532 let present_value = 1.0f64 / 0.0f64;
533 assert!(future_value_solution(rate_of_return, periods, present_value, false).is_err());
534 }
535
536 /*
537 macro_rules! compare_to_excel {
538 ( $r:expr, $n:expr, $pv:expr, $fv_excel:expr, $fv_manual_simple:expr, $fv_manual_cont:expr ) => {
539 println!("$r = {}, $n = {}, $pv = {}, $fv_excel: {}, $fv_manual_simple = {}, $fv_manual_cont = {}", $r, $n, $pv, $fv_excel, $fv_manual_simple, $fv_manual_cont);
540 assert_approx_equal!($fv_excel, $fv_manual_simple);
541
542 let fv_calc_simple = future_value($r, $n, $pv, false);
543 println!("fv_calc_simple = {}", fv_calc_simple);
544 assert_approx_equal!($fv_excel, fv_calc_simple);
545
546 let fv_calc_cont = future_value($r, $n, $pv, true);
547 println!("fv_calc_cont = {}", fv_calc_cont);
548 assert_approx_equal!($fv_manual_cont, fv_calc_cont);
549
550 let ratio = fv_calc_cont / fv_calc_simple;
551 println!("ratio = {}", ratio);
552 assert!(ratio >= 1.0);
553 assert!(ratio < 2.0);
554 }
555 }
556 */
557
558 fn compare_to_excel(
559 test_case: usize,
560 r: f64,
561 n: u32,
562 pv: f64,
563 fv_excel: f64,
564 fv_manual_simple: f64,
565 fv_manual_cont: f64,
566 ) {
567 let display = false;
568
569 if display {
570 println!("test_case = {}, r = {}, n = {}, pv = {}, fv_excel: {}, fv_manual_simple = {}, fv_manual_cont = {}", test_case, r, n, pv, fv_excel, fv_manual_simple, fv_manual_cont);
571 }
572 assert_approx_equal!(fv_excel, fv_manual_simple);
573
574 let fv_calc_simple = future_value(r, n, pv, false).unwrap();
575 if display {
576 println!("fv_calc_simple = {}", fv_calc_simple)
577 };
578 assert_approx_equal!(fv_excel, fv_calc_simple);
579
580 let fv_calc_cont = future_value(r, n, pv, true).unwrap();
581 if display {
582 println!("fv_calc_cont = {}", fv_calc_cont)
583 };
584 assert_approx_equal!(fv_manual_cont, fv_calc_cont);
585
586 let ratio = fv_calc_cont / fv_calc_simple;
587 if display {
588 println!("ratio = {}", ratio)
589 };
590 assert!(ratio >= 1.0);
591 assert!(ratio < 2.0);
592
593 // Solution with simple compounding.
594 let solution = future_value_solution(r, n, pv, false).unwrap();
595 if display {
596 dbg!(&solution);
597 }
598 solution.invariant();
599 assert!(solution.calculated_field().is_future_value());
600 assert_eq!(false, solution.continuous_compounding());
601 assert_approx_equal!(r, solution.rate());
602 assert_eq!(n, solution.periods());
603 assert_approx_equal!(n as f64, solution.fractional_periods());
604 assert_approx_equal!(pv, solution.present_value());
605 assert_approx_equal!(fv_excel, solution.future_value());
606
607 // Solution with continuous compounding.
608 let solution = future_value_solution(r, n, pv, true).unwrap();
609 if display {
610 dbg!(&solution);
611 }
612 solution.invariant();
613 assert!(solution.calculated_field().is_future_value());
614 assert!(solution.continuous_compounding());
615 assert_approx_equal!(r, solution.rate());
616 assert_eq!(n, solution.periods());
617 assert_approx_equal!(n as f64, solution.fractional_periods());
618 assert_approx_equal!(pv, solution.present_value());
619 assert_approx_equal!(fv_manual_cont, solution.future_value());
620
621 let rates = initialized_vector(n as usize, r);
622
623 // Schedule solution.
624 let solution = future_value_schedule_solution(&rates, pv).unwrap();
625 if display {
626 dbg!(&solution);
627 }
628 solution.invariant();
629 assert!(solution.calculated_field().is_future_value());
630 assert_eq!(n, solution.periods());
631 assert_approx_equal!(pv, solution.present_value());
632 assert_approx_equal!(fv_excel, solution.future_value());
633 }
634
635 #[test]
636 fn test_future_value_against_excel() {
637 compare_to_excel(
638 1,
639 0.01f64,
640 90,
641 1f64,
642 -2.44863267464848f64,
643 -2.44863267464848f64,
644 -2.45960311115695f64,
645 );
646 compare_to_excel(
647 2,
648 -0.01f64,
649 85,
650 -1.5f64,
651 0.638385185082981f64,
652 0.638385185082981f64,
653 0.64112239792309f64,
654 );
655 compare_to_excel(3, 0f64, 80, 2.25f64, -2.25f64, -2.25f64, -2.25f64);
656 compare_to_excel(
657 4,
658 0.05f64,
659 75,
660 -3.375f64,
661 131.060314992675f64,
662 131.060314992675f64,
663 143.508651750212f64,
664 );
665 compare_to_excel(
666 5,
667 -0.05f64,
668 70,
669 5.0625f64,
670 -0.139642432836174f64,
671 -0.139642432836174f64,
672 -0.152874253575487f64,
673 );
674 compare_to_excel(
675 6,
676 0.01f64,
677 65,
678 -7.59375f64,
679 14.499251769574f64,
680 14.499251769574f64,
681 14.5461381703243f64,
682 );
683 compare_to_excel(
684 7,
685 -0.01f64,
686 60,
687 11.390625f64,
688 -6.23245612973226f64,
689 -6.23245612973226f64,
690 -6.25130754238352f64,
691 );
692 compare_to_excel(
693 8,
694 0f64,
695 55,
696 -17.0859375f64,
697 17.0859375f64,
698 17.0859375f64,
699 17.0859375f64,
700 );
701 compare_to_excel(
702 9,
703 0.05f64,
704 50,
705 25.62890625f64,
706 -293.896914040351f64,
707 -293.896914040351f64,
708 -312.223995610061f64,
709 );
710 compare_to_excel(
711 10,
712 -0.05f64,
713 45,
714 -38.443359375f64,
715 3.82281753569715f64,
716 3.82281753569715f64,
717 4.05190026767808f64,
718 );
719 compare_to_excel(
720 11,
721 0.01f64,
722 40,
723 57.6650390625f64,
724 -85.8553853561044f64,
725 -85.8553853561044f64,
726 -86.0261294638861f64,
727 );
728 compare_to_excel(
729 12,
730 -0.01f64,
731 35,
732 -86.49755859375f64,
733 60.8465082158636f64,
734 60.8465082158636f64,
735 60.9537993307622f64,
736 );
737 compare_to_excel(
738 13,
739 0f64,
740 30,
741 129.746337890625f64,
742 -129.746337890625f64,
743 -129.746337890625f64,
744 -129.746337890625f64,
745 );
746 compare_to_excel(
747 14,
748 0.05f64,
749 25,
750 -194.619506835937f64,
751 659.050728569279f64,
752 659.050728569279f64,
753 679.288825069511f64,
754 );
755 compare_to_excel(
756 15,
757 -0.05f64,
758 20,
759 291.929260253906f64,
760 -104.652530140165f64,
761 -104.652530140165f64,
762 -107.3947731238f64,
763 );
764 compare_to_excel(
765 16,
766 0.01f64,
767 15,
768 -437.893890380859f64,
769 508.381212478371f64,
770 508.381212478371f64,
771 508.760116525988f64,
772 );
773 compare_to_excel(
774 17,
775 -0.01f64,
776 12,
777 656.840835571289f64,
778 -582.213779775772f64,
779 -582.213779775772f64,
780 -582.56556073855f64,
781 );
782 compare_to_excel(
783 18,
784 0f64,
785 10,
786 -985.261253356933f64,
787 985.261253356933f64,
788 985.261253356933f64,
789 985.261253356933f64,
790 );
791 compare_to_excel(
792 19,
793 0.05f64,
794 7,
795 1477.8918800354f64,
796 -2079.54228903805f64,
797 -2079.54228903805f64,
798 -2097.22840728772f64,
799 );
800 compare_to_excel(
801 20,
802 -0.05f64,
803 5,
804 -2216.8378200531f64,
805 1715.34684668614f64,
806 1715.34684668614f64,
807 1726.47503019966f64,
808 );
809 compare_to_excel(
810 21,
811 0.01f64,
812 4,
813 3325.25673007965f64,
814 -3460.27548760037f64,
815 -3460.27548760037f64,
816 -3460.96303162265f64,
817 );
818 compare_to_excel(
819 22,
820 -0.01f64,
821 3,
822 -4987.88509511947f64,
823 4839.73991990933f64,
824 4839.73991990933f64,
825 4840.47081241187f64,
826 );
827 compare_to_excel(
828 23,
829 0f64,
830 2,
831 7481.82764267921f64,
832 -7481.82764267921f64,
833 -7481.82764267921f64,
834 -7481.82764267921f64,
835 );
836 compare_to_excel(
837 24,
838 0.05f64,
839 1,
840 -11222.7414640188f64,
841 11783.8785372198f64,
842 11783.8785372198f64,
843 11798.1437232237f64,
844 );
845 compare_to_excel(
846 25,
847 -0.05f64,
848 0,
849 16834.1121960282f64,
850 -16834.1121960282f64,
851 -16834.1121960282f64,
852 -16834.1121960282f64,
853 );
854 }
855}