@pyverret/ratejs 1.0.0 → 1.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -8,10 +8,62 @@ Lightweight, dependency-free TypeScript financial math library providing pure ca
8
8
  npm i @pyverret/ratejs
9
9
  ```
10
10
 
11
+ ## Live Demo
12
+
13
+ - GitHub Pages URL: `https://pyverret.github.io/ratejs/`
14
+ - Demo source: [`demo/`](./demo)
15
+
16
+ Run locally:
17
+
18
+ ```bash
19
+ cd demo
20
+ npm install
21
+ npm run dev
22
+ ```
23
+
11
24
  ## Usage
12
25
 
13
26
  All functions take a single options object (no positional args). Rates are decimals (e.g. `0.05` = 5%).
14
27
 
28
+ Cash-flow sign convention (Excel-style):
29
+ - Cash paid out is negative, cash received is positive.
30
+ - Loan example: `presentValue > 0` and `payment < 0`.
31
+ - Investment withdrawal example: `presentValue < 0` and `payment > 0`.
32
+
33
+ ### Excel-style TVM formulas
34
+
35
+ - **`pmt`** - Excel `PMT`: payment per period for a loan/investment.
36
+ - **`pv`** - Excel `PV`: present value from payment stream and future value.
37
+ - **`fv`** - Excel `FV`: future value from present value and payment stream.
38
+ - **`nper`** - Excel `NPER`: number of periods required.
39
+ - **`rate`** - Excel `RATE`: implied rate per period. Supports optional `guess`, `maxIterations`, `lowerBound`, and `upperBound`.
40
+ - **`npv`** - Excel `NPV`: net present value of a cash flow series.
41
+
42
+ ```ts
43
+ const payment = pmt({
44
+ ratePerPeriod: 0.06 / 12,
45
+ periods: 360,
46
+ presentValue: 250000,
47
+ futureValue: 0,
48
+ timing: "end",
49
+ });
50
+
51
+ const impliedRate = rate({
52
+ periods: 360,
53
+ payment,
54
+ presentValue: 250000,
55
+ futureValue: 0,
56
+ timing: "end",
57
+ lowerBound: -0.99, // optional
58
+ upperBound: 10, // optional
59
+ });
60
+ ```
61
+
62
+ Edge cases:
63
+ - `nper` throws `RangeError` when `ratePerPeriod <= -1`.
64
+ - `rate` throws `RangeError` when no root is found within search bounds.
65
+ - `pmt`, `pv`, and `fv` throw `RangeError` when `ratePerPeriod <= -1`.
66
+
15
67
  ### Interest & growth
16
68
 
17
69
  - **`compound`** - Final amount for a lump sum with compound interest.
@@ -67,6 +119,7 @@ periodsToReachGoal({
67
119
  Edge cases:
68
120
  - Returns `Infinity` when the goal is unreachable.
69
121
  - Throws `RangeError` when `rate / timesPerYear <= -1`.
122
+ - Throws `RangeError` when `maxPeriods` is exceeded for contribution-based iteration.
70
123
 
71
124
  - **`rateToReachGoal`** - Rate per period required to reach a target future value in a given number of periods.
72
125
 
@@ -77,9 +130,14 @@ rateToReachGoal({
77
130
  periods: 24,
78
131
  contributionPerPeriod: 0,
79
132
  contributionTiming: "end",
133
+ lowerBound: -0.99, // optional
134
+ upperBound: 10, // optional
80
135
  });
81
136
  ```
82
137
 
138
+ Edge cases:
139
+ - Throws `RangeError` when no root is found within search bounds.
140
+
83
141
  - **`ruleOf72`** - Approximate years to double a lump sum at a given annual rate. Optional `constant: 69` for rule of 69.
84
142
 
85
143
  ```ts
@@ -95,12 +153,23 @@ ruleOf72({ rate: 0.07, constant: 69 });
95
153
  cagr({ startValue: 1000, endValue: 2000, years: 10 });
96
154
  ```
97
155
 
98
- - **`irr`** - Internal rate of return: discount rate that makes NPV of cash flows zero. `cashFlows[0]` is typically the initial outlay (negative).
156
+ - **`irr`** - Internal rate of return: discount rate that makes NPV of cash flows zero. `cashFlows[0]` is typically the initial outlay (negative). Supports optional `guess`, `maxIterations`, `lowerBound`, and `upperBound`.
99
157
 
100
158
  ```ts
101
- irr({ cashFlows: [-1000, 300, 400, 500], guess: 0.1, maxIterations: 100 });
159
+ irr({
160
+ cashFlows: [-1000, 300, 400, 500],
161
+ guess: 0.1,
162
+ maxIterations: 100,
163
+ lowerBound: -0.99, // optional
164
+ upperBound: 10, // optional
165
+ });
102
166
  ```
103
167
 
168
+ Edge cases:
169
+ - Throws `RangeError` when `cashFlows` is empty.
170
+ - Throws `RangeError` when `cashFlows` does not contain at least one positive and one negative value.
171
+ - Throws `RangeError` when no root is found within search bounds.
172
+
104
173
  ### Inflation
105
174
 
106
175
  - **`realReturn`** - Real (inflation-adjusted) return from nominal return and inflation rate.
@@ -163,6 +232,9 @@ loanPayment({
163
232
  });
164
233
  ```
165
234
 
235
+ Edge cases:
236
+ - Throws `RangeError` when `annualRate / paymentsPerYear <= -1`.
237
+
166
238
  - **`amortizationSchedule`** - Full schedule: `{ paymentPerPeriod, schedule, totalPaid, totalInterest }`. Optional `extraPaymentPerPeriod`.
167
239
 
168
240
  ```ts