Files
fire/src/app/components/charts/FourPercentRuleChart.tsx
2025-12-06 20:58:42 +01:00

118 lines
3.9 KiB
TypeScript

'use client';
import { Area, AreaChart, CartesianGrid, XAxis, YAxis } from 'recharts';
import {
Card,
CardContent,
CardDescription,
CardFooter,
CardHeader,
CardTitle,
} from '@/components/ui/card';
import {
ChartContainer,
ChartLegend,
ChartLegendContent,
ChartTooltip,
ChartTooltipContent,
type ChartConfig,
} from '@/components/ui/chart';
import BlurThing from '../blur-thing';
// Simulation data for 4% rule
const storyData = [
{ year: 0, w3: 100, w4: 100, w5: 100 },
{ year: 1, w3: 105, w4: 104, w5: 103 },
{ year: 2, w3: 90, w4: 88, w5: 86 }, // Crash
{ year: 3, w3: 95, w4: 92, w5: 89 },
{ year: 4, w3: 102, w4: 98, w5: 94 },
{ year: 5, w3: 110, w4: 105, w5: 100 },
{ year: 10, w3: 150, w4: 130, w5: 110 },
{ year: 15, w3: 200, w4: 160, w5: 100 }, // 5% starts dragging
{ year: 20, w3: 280, w4: 200, w5: 80 },
{ year: 25, w3: 380, w4: 250, w5: 40 },
{ year: 30, w3: 500, w4: 300, w5: 0 },
];
const chartConfig = {
year: {
label: 'Year',
},
w3: {
label: '3% Withdrawal (Safe)',
color: 'var(--chart-1)',
},
w4: {
label: '4% Withdrawal (Standard)',
color: 'var(--chart-2)',
},
w5: {
label: '5% Withdrawal (Risky)',
color: 'var(--chart-3)',
},
} satisfies ChartConfig;
export function FourPercentRuleChart() {
return (
<Card className="w-full">
<BlurThing />
<CardHeader>
<CardTitle>Portfolio Survival Scenarios</CardTitle>
<CardDescription>
Impact of initial withdrawal rate on portfolio longevity (Start: $1M)
</CardDescription>
</CardHeader>
<CardContent>
<ChartContainer config={chartConfig} className="aspect-auto h-[300px] w-full">
<AreaChart data={storyData}>
<defs>
<linearGradient id="fillW3" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-w3)" stopOpacity={0.8} />
<stop offset="95%" stopColor="var(--color-w3)" stopOpacity={0.1} />
</linearGradient>
<linearGradient id="fillW4" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-w4)" stopOpacity={0.8} />
<stop offset="95%" stopColor="var(--color-w4)" stopOpacity={0.1} />
</linearGradient>
<linearGradient id="fillW5" x1="0" y1="0" x2="0" y2="1">
<stop offset="5%" stopColor="var(--color-w5)" stopOpacity={0.8} />
<stop offset="95%" stopColor="var(--color-w5)" stopOpacity={0.1} />
</linearGradient>
</defs>
<CartesianGrid vertical={false} />
<XAxis dataKey="year" tickLine={false} axisLine={false} tickMargin={8} />
<YAxis
tickLine={false}
axisLine={false}
tickMargin={8}
tickFormatter={(value) => `${String(value)}%`}
/>
<ChartTooltip
cursor={false}
content={
<ChartTooltipContent
labelFormatter={(value) => `Year ${String(value)}`}
indicator="line"
/>
}
/>
<Area dataKey="w3" type="natural" fill="url(#fillW3)" stroke="var(--color-w3)" />
<Area dataKey="w4" type="natural" fill="url(#fillW4)" stroke="var(--color-w4)" />
<Area dataKey="w5" type="natural" fill="url(#fillW5)" stroke="var(--color-w5)" />
<ChartLegend content={<ChartLegendContent />} />
</AreaChart>
</ChartContainer>
</CardContent>
<CardFooter>
<div>
<p className="font-medium">4% balances safety and spending power</p>
<p className="text-muted-foreground leading-none">
A 5% withdrawal rate risks depleting your portfolio within 30 years, while 3% leaves a large
surplus. The 4% rule is widely considered the safe &quot;sweet spot.&quot;
</p>
</div>
</CardFooter>
</Card>
);
}