rust_finprim/derivatives.rs
1//! This module contains various derivatives of financial calculations.
2//! Useful for sensitivity analysis and optimization problems.
3
4use crate::ONE;
5use rust_decimal::prelude::*;
6
7/// PV'(r) - Derivative of the present value of a cash flow with respect to the rate.
8///
9/// # Arguments
10/// * `rate` - The discount rate per period
11/// * `n` - The nth period
12/// * `cash_flow` - The cash flow at period n
13///
14/// # Returns
15/// * The derivative of the present value (PV) with respect to the rate
16///
17/// Via the sum and difference property, this can be used for finding the derivative of
18/// an NPV calculation with respect to the rate.
19pub fn pv_prime_r(rate: Decimal, n: Decimal, cash_flow: Decimal) -> Decimal {
20 -cash_flow * n / (rate + ONE).powd(n + ONE)
21}
22
23/// PV''(r) - Second derivative of the present value of a cash flow with respect to the rate.
24///
25/// # Arguments
26/// * `rate` - The discount rate per period
27/// * `n` - The nth period
28/// * `cash_flow` - The cash flow at period n
29///
30/// # Returns
31/// * The second derivative of the present value (PV) with respect to the rate
32///
33/// Via the sum and difference property, this can be used for finding the 2nd derivative of
34/// an NPV calculation with respect to the rate.
35pub fn pv_prime2_r(rate: Decimal, n: Decimal, cash_flow: Decimal) -> Decimal {
36 cash_flow * n * (n + ONE) / (rate + ONE).powd(n + Decimal::TWO)
37}
38
39/// WACC'(D/E) - First derivative of WACC with respect to the debt to equity ratio.
40///
41/// # Arguments
42/// * `r_e` - The Cost of Equity
43/// * `r_d` - The Cost of Debt
44/// * `de_ratio` - The Debt to Equity Ratio (market value where D + E = V)
45/// * `tax` - The tax rate
46///
47/// # Returns
48/// * The first derivative of the WACC with respect to the D/E ratio.
49///
50/// # WACC Formula
51/// $$\mathrm{WACC} = R_e (\frac{1}{1+D/E}) + R_d (\frac{D/E}{1+D/E})(1-T_C)$$
52///
53/// Where:
54/// * \\(R_e\\) = Cost of Equity
55/// * \\(R_d\\) = Cost of Debt
56/// * \\(D/E\\) = The Debt to Equity Ratio (market value)
57/// * \\(T_C)\\) = The tax rate
58pub fn wacc_prime_de(r_e: Decimal, r_d: Decimal, de_ratio: Decimal, tax: Decimal) -> Decimal {
59 -(tax * r_d + r_e - r_d) / (de_ratio + ONE).powd(Decimal::TWO)
60}
61
62/// WACC''(D/E) - Second derivative of WACC with respect to the debt to equity ratio.
63///
64/// # Arguments
65/// * `r_e` - The Cost of Equity
66/// * `r_d` - The Cost of Debt
67/// * `de_ratio` - The Debt to Equity Ratio (market value where D + E = V)
68/// * `tax` - The tax rate
69///
70/// # Returns
71/// * The first derivative of the WACC with respect to the D/E ratio.
72///
73/// # WACC Formula
74/// $$\mathrm{WACC} = R_e (\frac{1}{1+D/E}) + R_d (\frac{D/E}{1+D/E})(1-T_C)$$
75///
76/// Where:
77/// * \\(R_e\\) = Cost of Equity
78/// * \\(R_d\\) = Cost of Debt
79/// * \\(D/E\\) = The Debt to Equity Ratio
80/// * \\(T_C)\\) = The tax rate
81pub fn wacc_prime2_de(r_e: Decimal, r_d: Decimal, de_ratio: Decimal, tax: Decimal) -> Decimal {
82 Decimal::TWO * (tax * r_d + r_e - r_d) / (de_ratio + ONE).powd(Decimal::from_u8(3u8).unwrap())
83}
84
85#[cfg(test)]
86mod tests {
87 use super::*;
88 #[cfg(not(feature = "std"))]
89 extern crate std;
90 use rust_decimal_macros::dec;
91 #[cfg(not(feature = "std"))]
92 use std::assert;
93 #[cfg(not(feature = "std"))]
94 use std::prelude::v1::*;
95
96 #[test]
97 fn test_pv_prime() {
98 let rate = dec!(0.05);
99 let n = dec!(5);
100 let cash_flow = dec!(1000);
101
102 let result = pv_prime_r(rate, n, cash_flow);
103 let expected = dec!(-3731.07698);
104 assert!(
105 (result - expected).abs() < dec!(1e-5),
106 "Failed on case: {}. Expected: {}, Result: {}",
107 "Rate of 5%, 5th period, cash flow of $1000",
108 expected,
109 result
110 );
111 }
112
113 #[test]
114 fn test_pv_double_prime() {
115 let rate = dec!(0.05);
116 let n = dec!(5);
117 let cash_flow = dec!(1000);
118
119 let result = pv_prime2_r(rate, n, cash_flow);
120 let expected = dec!(21320.43990);
121 assert!(
122 (result - expected).abs() < dec!(1e-5),
123 "Failed on case: {}. Expected: {}, Result: {}",
124 "Rate of 5%, 5th period, cash flow of $1000",
125 expected,
126 result
127 );
128 }
129
130 #[test]
131 fn test_wacc_prime() {
132 let r_e = dec!(0.05);
133 let r_d = dec!(0.07);
134 let de_ratio = dec!(0.7);
135 let tax = dec!(0.25);
136
137 let result = wacc_prime_de(r_e, r_d, de_ratio, tax);
138 let expected = dec!(0.00086);
139 assert!(
140 (result - expected).abs() < dec!(1e-5),
141 "Failed on case: {}. Expected{}, Result: {}",
142 "Cost of Equity 5%, Cost of Debt 7%, D/E 0.7, Tax Rate 25%",
143 expected,
144 result
145 );
146 }
147}