this repo has no description
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

feat(growth): better calculation

+14 -46
+14 -16
src/app/growth/page.tsx
··· 1 1 "use client"; 2 2 3 - import { useEffect, useState } from "react"; 3 + import { useMemo, useState } from "react"; 4 4 import { Bar, BarChart, CartesianGrid, XAxis, YAxis } from "recharts"; 5 5 import { 6 6 Card, ··· 18 18 } from "@/components/ui/chart"; 19 19 import { Field, FieldGroup, FieldLabel } from "@/components/ui/field"; 20 20 import { Input } from "@/components/ui/input"; 21 - import { getTotalFv } from "@/lib/math"; 22 21 23 22 const chartConfig = { 24 23 contribution: { label: "Contribution" }, ··· 34 33 return Array.from({ length: periods }).map((_, i) => { 35 34 const period = i + 1; 36 35 const contribution = principal + payment * period; 37 - const projected = getTotalFv(principal, payment, rate, period); 38 - return { period, contribution, interest: projected - contribution }; 36 + const pow = (1 + rate) ** period; 37 + const totalValue = principal * pow + (payment * (pow - 1)) / rate; 38 + const interest = Math.max(0, totalValue - contribution); 39 + 40 + return { 41 + period, 42 + contribution, 43 + interest: Math.round(interest * 100) / 100, 44 + }; 39 45 }); 40 46 } 41 47 ··· 44 50 const [payment, setPayment] = useState(20000); 45 51 const [rate, setRate] = useState(10 / 100); 46 52 const [periods, setPeriods] = useState(15); 47 - const [history, setHistory] = useState<ReturnType<typeof calculate>>([]); 48 53 49 - useEffect(() => { 50 - if ( 51 - Number.isNaN(principal) || 52 - Number.isNaN(periods) || 53 - Number.isNaN(payment) || 54 - Number.isNaN(rate) 55 - ) 56 - return; 57 - 58 - setHistory(calculate(principal, payment, rate, periods)); 59 - }, [principal, periods, payment, rate]); 54 + const history = useMemo(() => { 55 + if ([principal, payment, rate, periods].some(Number.isNaN)) return []; 56 + return calculate(principal, payment, rate, periods); 57 + }, [principal, payment, rate, periods]); 60 58 61 59 return ( 62 60 <main className="flex flex-1 items-center justify-center p-4">
-30
src/lib/math.ts
··· 1 - // Future Value of a single sum 2 - export const getFv = (p: number, r: number, n: number): number => 3 - p * (1 + r) ** n; 4 - 5 - // Future Value of an Annuity (regular contributions) 6 - export const getFva = (pmt: number, r: number, n: number): number => 7 - r === 0 ? pmt * n : pmt * (((1 + r) ** n - 1) / r); 8 - 9 - // Total Future Value (Principal + Annuity) 10 - export const getTotalFv = ( 11 - p: number, 12 - pmt: number, 13 - r: number, 14 - n: number, 15 - ): number => getFv(p, r, n) + getFva(pmt, r, n); 16 - 17 - // Real Rate of Return (Fisher Equation) 18 - export const getRealRate = (r: number, i: number): number => 19 - (1 + r) / (1 + i) - 1; 20 - 21 - // Target Capital (Perpetuity formula) 22 - export const getTarget = (pmt: number, r: number): number => pmt / r; 23 - 24 - // Calculate exact number of periods (n) to reach a target capital 25 - export const getPeriodsToTarget = ( 26 - target: number, 27 - p: number, 28 - pmt: number, 29 - r: number, 30 - ): number => Math.log((target * r + pmt) / (p * r + pmt)) / Math.log(1 + r);