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}