finance_math/
lib.rs

1//! finance-rust is a simple common finance mathematics in rust.
2//! Its cloning form [http://financejs.org/] .
3//! The create includes some finance mathematics theory & formula (eg: CAGR,CI,LR,PI,AM etc.).
4///
5
6
7/*
8Copyright (c) <2016> <copyright pow2n10>
9
10Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
11
12The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
13
14THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
15*/
16
17
18/// In business, amortization refers to spreading payments over multiple periods.
19/// The term is used for two separate processes: amortization of loans and assets.
20/// It also refers to allocating the cost of an intangible asset over a period of time.
21/// see definition: https://en.wikipedia.org/wiki/Amortization_%28business%29
22pub fn am(principal:f64,rate:f64,period:f64,
23          year_or_month:bool,pay_at_beginning:bool) -> f64 {
24
25    let rate_perperiod = rate / 12_f64 / 100_f64;
26
27    let numerator;
28    let denominator;
29
30    let build_num = |num:f64| -> f64 {
31        if pay_at_beginning {
32            num - 1_f64
33        }else{
34            rate_perperiod * ((1_f64 + rate_perperiod).powf(num))
35        }
36    };
37
38    if year_or_month {
39        numerator = build_num(period);
40        denominator = ((1_f64 + rate_perperiod).powf(period)) - 1_f64
41
42    }else{
43        numerator = build_num(period * 12_f64);
44        denominator = ((1_f64 + rate_perperiod).powf(period*12_f64)) - 1_f64;
45    }
46
47    ((principal * (numerator / denominator ) * 100_f64).round()) / 100_f64
48}
49
50/// Compound annual growth rate (CAGR) is a business and investing specific term for the geometric progression ratio that provides a constant rate of return over the time period.
51/// [1][2] CAGR is not an accounting term, but it is often used to describe some element of the business, for example revenue, units delivered, registered users, etc.
52/// CAGR dampens the effect of volatility of periodic returns that can render arithmetic means irrelevant.
53/// It is particularly useful to compare growth rates from various data sets of common domain such as revenue growth of companies in the same industry.
54/// see definition: http://pages.uoregon.edu/rgp/PPPM613/class8a.htm
55pub fn cagr(beging_val:f64,end_val:f64,num_of_periods:f64) -> f64 {
56
57    (((end_val / beging_val).powf(1_f64 / num_of_periods) -1_f64)*10000_f64).round() / 100_f64
58}
59
60/// he addition of interest to the principal sum of a loan or deposit is called compounding.
61/// Compound interest is interest on interest.
62/// It is the result of reinvesting interest, rather than paying it out, so that interest in the next period is then earned on the principal sum plus previously-accumulated interest.
63/// Compound interest is standard in finance and economics.
64/// see definition: https://en.wikipedia.org/wiki/Compound_interest
65pub fn ci(rate:f64,num_of_compoundings:f64,principal:f64,num_of_periods:f64) -> f64 {
66    ((principal
67     *
68     (
69         (1_f64 +
70          ((rate / 100_f64) / num_of_compoundings)
71          )
72          .powf(num_of_compoundings * num_of_periods))
73    ) * 100_f64).round() / 100_f64
74}
75
76/// Discounting is a financial mechanism in which a debtor obtains the right to delay payments to a creditor, for a defined period of time, in exchange for a charge or fee.
77/// Essentially, the party that owes money in the present purchases the right to delay the payment until some future date.
78/// The discount, or charge, is the difference (expressed as a difference in the same units (absolute) or in percentage terms (relative), or as a ratio) between the original amount owed in the present and the amount that has to be paid in the future to settle the debt.
79/// see definition: https://en.wikipedia.org/wiki/Discounting
80pub fn df(rate:f64,num_of_periods:i32) -> Vec<f64>{
81
82    let mut dfs:Vec<f64> = Vec::new();
83
84    for i in 1..num_of_periods {
85        dfs.push(
86            ((1_f64/(1_f64 + rate/100_f64).powi(i-1)) * 1000_f64).ceil()
87                / 1000_f64
88        );
89    }
90
91    dfs
92}
93
94/// Future value is the value of an asset at a specific date.
95/// It measures the nominal future sum of money that a given sum of money is "worth" at a specified time in the future assuming a certain interest rate, or more generally, rate of return; it is the present value multiplied by the accumulation function.
96/// The value does not include corrections for inflation or other factors that affect the true value of money in the future.
97/// This is used in time value of money calculations.
98/// see definition: https://en.wikipedia.org/wiki/Future_value
99pub fn fv(rate:f64,cf0:f64,num_of_period:f64) -> f64 {
100    (cf0 * (1_f64 + rate/100_f64).powf(num_of_period) * 100_f64 ).round() / 100_f64
101}
102
103
104/// The internal rate of return (IRR) or external rate of return (ERR) is a method of calculating rate of return.
105/// The term internal refers to the fact that its calculation does not incorporate environmental factors (e.g., the interest rate or inflation).
106/// see definition: https://en.wikipedia.org/wiki/Internal_rate_of_return
107pub fn irr(cfs:&[f64]) -> f64{
108
109    let mut num_of_tries = 1;
110
111    let npv_res  = |rate:f64| -> f64 {
112        num_of_tries = num_of_tries + 1;
113        if num_of_tries > 1000 {
114            panic!("IRR can't find a result");
115        }
116        npv(rate,cfs)
117    };
118    (seek_zero(npv_res) * 100_f64).round() / 100_f64
119}
120
121
122/// In finance, the net present value (NPV) or net present worth (NPW)[1] is a measurement of the profitability of an undertaking that is calculated by subtracting the present values (PV) of cash outflows (including initial cost) from the present values of cash inflows over a period of time.
123/// Incoming and outgoing cash flows can also be described as benefit and cost cash flows, respectively.
124/// see definition: https://en.wikipedia.org/wiki/Net_present_value
125pub fn npv(rate:f64,vals:&[f64]) -> f64 {
126    let r = 1_f64 + rate / 100_f64;
127    ((vals.iter().enumerate().fold(0_f64,|p,(i,&v)|{
128        match i {
129            0 => v,
130            _ => {
131                p + v / (r).powi(i as i32)
132            }
133        }
134    }
135    ))
136    * 100_f64).round() / 100_f64
137}
138
139/// Payback period in capital budgeting refers to the period of time required to recoup the funds expended in an investment, or to reach the break-even point.
140/// see definition: https://en.wikipedia.org/wiki/Payback_period
141pub fn pp(num_of_periods:f64,cfs:&[f64]) -> f64{
142
143    if cfs.len() < 2 {
144        panic!("slice:cfs can't lt 2")
145    }
146
147    if num_of_periods == 0_f64 {
148        return (cfs[0] / cfs[1]).abs()
149    }
150
151    let mut years = 1_f64;
152
153    let mut cumulative_cash_flow = cfs[0];
154
155    for v in cfs[1..].iter() {
156        cumulative_cash_flow = cumulative_cash_flow + v;
157         if cumulative_cash_flow > 0_f64 {
158                years = years + (cumulative_cash_flow - v) / v;
159             return  (years * 100_f64).round() /100_f64
160            }else{
161                years = years + 1_f64;
162            }
163    }
164    (years * 100_f64).round() /100_f64
165}
166
167/// In economics, present value, also known as present discounted value, is the value of an expected income stream determined as of the date of valuation.
168/// The present value is always less than or equal to the future value because money has interest-earning potential, a characteristic referred to as the time value of money, except during times of negative interest rates, when the present value will be more than the future value.
169/// Time value can be described with the simplified phrase, "A dollar today is worth more than a dollar tomorrow".
170/// Here, 'worth more' means that its value is greater. A dollar today is worth more than a dollar tomorrow because the dollar can be invested and earn a day's worth of interest, making the total accumulate to a value more than a dollar by tomorrow.
171/// Interest can be compared to rent.[2] Just as rent is paid to a landlord by a tenant, without the ownership of the asset being transferred, interest is paid to a lender by a borrower who gains access to the money for a time before paying it back.
172/// By letting the borrower have access to the money, the lender has sacrificed the exchange value of this money, and is compensated for it in the form of interest.
173/// The initial amount of the borrowed funds (the present value) is less than the total amount of money paid to the lender.
174/// see definition: https://en.wikipedia.org/wiki/Present_value
175pub fn pv(rate:f64,cf1:f64) -> f64{
176    (cf1 / (1_f64 + rate/(100_f64))).round()
177}
178
179/// Profitability index (PI), also known as profit investment ratio (PIR) and value investment ratio (VIR), is the ratio of payoff to investment of a proposed project.
180/// It is a useful tool for ranking projects because it allows you to quantify the amount of value created per unit of investment.
181/// see definition: https://en.wikipedia.org/wiki/Profitability_index
182pub fn pi(rate:f64,cfs:&[f64]) -> f64{
183
184    if cfs.len() < 2 {
185        panic!("slice:cfs.len() can't lt 2");
186    }
187
188    (((cfs[1..].iter().enumerate().fold(0_f64,|p,(i,&v)|{
189       p + ( v * (1_f64 / ((1_f64 + rate/100_f64).powi((i+1) as i32))))
190    })) / cfs[0].abs()) * 100_f64).round() / 100_f64
191}
192
193/// Return on Investment (ROI) is the benefit to an investor resulting from an investment of some resource.
194/// A high ROI means the investment gains compare favorably to investment cost.
195/// As a performance measure, ROI is used to evaluate the efficiency of an investment or to compare the efficiency of a number of different investments.
196/// In purely economic terms, it is one way of considering profits in relation to capital invested.
197/// see definition: https://en.wikipedia.org/wiki/Return_on_investment
198pub fn roi(cf0:f64,earnings:f64) -> f64{
199    (((earnings - cf0.abs()) / cf0.abs() * 100_f64) * 100_f64).round() / 100_f64
200}
201
202/// In finance, leverage (sometimes referred to as gearing in the United Kingdom and Australia) is any technique involving the use of borrowed funds in the purchase of an asset, with the expectation that the after tax income from the asset and asset price appreciation will exceed the borrowing cost.
203/// Normally, the finance provider would set a limit on how much risk it is prepared to take and will set a limit on how much leverage it will permit, and would require the acquired asset to be provided as collateral security for the loan.
204/// see definition: https://en.wikipedia.org/wiki/Leverage_(finance)
205pub fn lr(total_liabilities:f64,total_debts:f64,total_income:f64) -> f64 {
206    (total_liabilities + total_debts) / total_income
207}
208
209
210/// In finance, the rule of 72, the rule of 70 and the rule of 69.3 are methods for estimating an investment's doubling time. The rule number (e.g., 72) is divided by the interest percentage per period to obtain the approximate number of periods (usually years) required for doubling
211/// see definition: https://en.wikipedia.org/wiki/Rule_of_72
212pub fn r72(rate:f64) -> f64 {
213    72_f64 /rate
214}
215
216/// The weighted average cost of capital (WACC) is the rate that a company is expected to pay on average to all its security holders to finance its assets.
217/// The WACC is commonly referred to as the firm’s cost of capital.
218/// Importantly, it is dictated by the external market and not by management.
219/// The WACC represents the minimum return that a company must earn on an existing asset base to satisfy its creditors, owners, and other providers of capital, or they will invest elsewhere.
220/// see definition: https://en.wikipedia.org/wiki/Weighted_average_cost_of_capital
221pub fn wacc(market_val_of_equity:f64,market_val_of_debt:f64,cost_of_equity:f64,cost_of_debt:f64,tax_rate:f64) -> f64{
222
223    (((
224        (market_val_of_equity / (market_val_of_equity + market_val_of_debt)) * cost_of_equity / 100_f64)
225     +
226      ((
227          (market_val_of_debt /(market_val_of_equity + market_val_of_debt))* cost_of_debt/100_f64)
228      *
229      (1_f64 - tax_rate/100_f64))
230    )* 1000_f64).round() / 10_f64
231}
232
233fn seek_zero<F>(mut f:F) -> f64 where  F:FnMut(f64) -> f64 {
234
235    let mut x = 1.0_64;
236
237    loop {
238        x =  if f(x) > 0_f64{
239            x + 1_f64
240        }else{
241            break
242        }
243    }
244
245    loop {
246        x = if f(x) < 0_f64 {
247           x - 0.01_f64
248        }else{
249            break
250        }
251    }
252    
253    x
254}
255
256
257#[cfg(test)]
258    mod tests {
259    use super::*;
260    #[test]
261    fn test_am() {
262        assert_eq!(am(20000_f64, 7.5_f64, 5_f64, false,false),400.76);
263    }
264    #[test]
265    fn test_cagr() {
266        assert_eq!(cagr(10000_f64, 19500_f64, 3_f64),24.93);
267    }
268
269    #[test]
270    fn test_ci() {
271        assert_eq!(ci(4.3_f64,4_f64,1500_f64,6_f64),1938.84);
272    }
273
274    #[test]
275    fn test_df() {
276        assert_eq!(df(10_f64,6),vec![1_f64, 0.91, 0.827, 0.752, 0.684]);
277    }
278
279    #[test]
280    fn test_fv(){
281        assert_eq!(fv(0.5_f64,1000_f64,12_f64),1061.68);
282    }
283
284    #[test]
285    fn test_npv() {
286        assert_eq!(npv(10_f64,&[ -500000_f64, 200000_f64, 300000_f64, 200000_f64]),80015.03);
287    }
288    #[test]
289    fn test_irr() {
290        assert_eq!(irr(&[-500000_f64, 200000_f64, 300000_f64, 200000_f64]),18.82);
291    }
292
293    #[test]
294    fn test_lr() {
295        assert_eq!(lr(25_f64, 10_f64, 20_f64),1.75);
296    }
297
298    #[test]
299    fn test_pp() {
300        assert_eq!(pp(0_f64,&[-105_f64,25_f64]),4.2);
301        assert_eq!(pp(5_f64,&[-50_f64, 10_f64, 13_f64, 16_f64, 19_f64, 22_f64]),3.42);
302    }
303    
304    #[test]
305    fn test_pi() {
306        assert_eq!(pi(10_f64,&[ -40000_f64,18000_f64, 12000_f64, 10000_f64, 9000_f64, 6000_f64]),1.09);
307    }
308
309    #[test]
310    fn test_roi() {
311        assert_eq!(roi(-55000_f64,60000_f64),9.09);
312    }
313
314    #[test]
315    fn test_r72(){
316        assert_eq!(r72(10_f64),7.2);
317    }
318
319    #[test]
320    fn test_wacc() {
321        assert_eq!(wacc(600000_f64, 400000_f64, 6_f64, 5_f64, 35_f64),4.9);
322    }
323
324}