@jjlmoya/utils-finance 1.16.0 → 1.18.0

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.
Files changed (54) hide show
  1. package/package.json +1 -1
  2. package/src/category/index.ts +3 -1
  3. package/src/entries.ts +7 -1
  4. package/src/tests/locale_completeness.test.ts +1 -1
  5. package/src/tests/tool_validation.test.ts +2 -2
  6. package/src/tool/financialFreedom/bibliography.astro +14 -0
  7. package/src/tool/financialFreedom/bibliography.ts +12 -0
  8. package/src/tool/financialFreedom/component.astro +253 -0
  9. package/src/tool/financialFreedom/entry.ts +27 -0
  10. package/src/tool/financialFreedom/financial-freedom-calculator.css +346 -0
  11. package/src/tool/financialFreedom/i18n/de.ts +123 -0
  12. package/src/tool/financialFreedom/i18n/en.ts +182 -0
  13. package/src/tool/financialFreedom/i18n/es.ts +182 -0
  14. package/src/tool/financialFreedom/i18n/fr.ts +123 -0
  15. package/src/tool/financialFreedom/i18n/id.ts +123 -0
  16. package/src/tool/financialFreedom/i18n/it.ts +123 -0
  17. package/src/tool/financialFreedom/i18n/ja.ts +123 -0
  18. package/src/tool/financialFreedom/i18n/ko.ts +123 -0
  19. package/src/tool/financialFreedom/i18n/nl.ts +123 -0
  20. package/src/tool/financialFreedom/i18n/pl.ts +123 -0
  21. package/src/tool/financialFreedom/i18n/pt.ts +123 -0
  22. package/src/tool/financialFreedom/i18n/ru.ts +123 -0
  23. package/src/tool/financialFreedom/i18n/sv.ts +123 -0
  24. package/src/tool/financialFreedom/i18n/tr.ts +123 -0
  25. package/src/tool/financialFreedom/i18n/zh.ts +123 -0
  26. package/src/tool/financialFreedom/index.ts +10 -0
  27. package/src/tool/financialFreedom/logic.ts +68 -0
  28. package/src/tool/financialFreedom/seo.astro +13 -0
  29. package/src/tool/financialFreedom/ui.ts +26 -0
  30. package/src/tool/profitability/bibliography.astro +14 -0
  31. package/src/tool/profitability/bibliography.ts +12 -0
  32. package/src/tool/profitability/component.astro +249 -0
  33. package/src/tool/profitability/entry.ts +27 -0
  34. package/src/tool/profitability/i18n/de.ts +116 -0
  35. package/src/tool/profitability/i18n/en.ts +165 -0
  36. package/src/tool/profitability/i18n/es.ts +152 -0
  37. package/src/tool/profitability/i18n/fr.ts +112 -0
  38. package/src/tool/profitability/i18n/id.ts +112 -0
  39. package/src/tool/profitability/i18n/it.ts +112 -0
  40. package/src/tool/profitability/i18n/ja.ts +112 -0
  41. package/src/tool/profitability/i18n/ko.ts +112 -0
  42. package/src/tool/profitability/i18n/nl.ts +112 -0
  43. package/src/tool/profitability/i18n/pl.ts +112 -0
  44. package/src/tool/profitability/i18n/pt.ts +112 -0
  45. package/src/tool/profitability/i18n/ru.ts +112 -0
  46. package/src/tool/profitability/i18n/sv.ts +112 -0
  47. package/src/tool/profitability/i18n/tr.ts +112 -0
  48. package/src/tool/profitability/i18n/zh.ts +112 -0
  49. package/src/tool/profitability/index.ts +10 -0
  50. package/src/tool/profitability/logic.ts +43 -0
  51. package/src/tool/profitability/profitability-calculator.css +263 -0
  52. package/src/tool/profitability/seo.astro +15 -0
  53. package/src/tool/profitability/ui.ts +20 -0
  54. package/src/tools.ts +3 -1
@@ -0,0 +1,249 @@
1
+ ---
2
+ import type { KnownLocale } from '../../types';
3
+ import type { ProfitabilityUI } from './ui';
4
+
5
+ interface Props {
6
+ locale?: KnownLocale;
7
+ ui?: Record<string, unknown>;
8
+ }
9
+
10
+ const { ui } = Astro.props;
11
+ const t = (ui ?? {}) as ProfitabilityUI;
12
+ ---
13
+
14
+ <div
15
+ class="prof-root"
16
+ data-label-positive={t.labelPositiveResult}
17
+ data-label-negative={t.labelNegativeResult}
18
+ data-label-linear={t.labelLinearGrowth}
19
+ data-label-exponential={t.labelExponentialGrowth}
20
+ data-label-copied={t.labelCopied}
21
+ data-label-copy={t.labelCopyResult}
22
+ data-locale={Astro.props.locale || 'en'}
23
+ >
24
+ <div id="prof-card" class="prof-card positive">
25
+ <div class="prof-grid">
26
+ <div class="prof-inputs">
27
+ <div class="prof-input-group">
28
+ <div class="prof-label-row">
29
+ <label class="prof-label">{t.labelInitialInvestment}</label>
30
+ <select id="prof-currency-select" class="prof-currency-select">
31
+ <option value="USD">USD ($)</option>
32
+ <option value="EUR">EUR (€)</option>
33
+ <option value="GBP">GBP (£)</option>
34
+ <option value="JPY">JPY (¥)</option>
35
+ <option value="CNY">CNY (元)</option>
36
+ <option value="RUB">RUB (₽)</option>
37
+ <option value="KRW">KRW (₩)</option>
38
+ <option value="TRY">TRY (₺)</option>
39
+ <option value="PLN">PLN (zł)</option>
40
+ <option value="SEK">SEK (kr)</option>
41
+ <option value="IDR">IDR (Rp)</option>
42
+ </select>
43
+ </div>
44
+ <input type="number" id="prof-initial" value="10000" class="prof-input-field" />
45
+ </div>
46
+
47
+ <div class="prof-input-group">
48
+ <label class="prof-label">{t.labelFinalValue}</label>
49
+ <input type="number" id="prof-final" value="15000" class="prof-input-field" />
50
+ </div>
51
+
52
+ <div class="prof-input-group">
53
+ <label class="prof-label">{t.labelTimeSelection}</label>
54
+ <div class="prof-time-row">
55
+ <input type="number" id="prof-time-value" value="3" class="prof-input-field" style="flex: 2;" />
56
+ <select id="prof-time-unit" class="prof-unit-select" style="flex: 1;">
57
+ <option value="years">{t.labelYears}</option>
58
+ <option value="months">{t.labelMonths}</option>
59
+ <option value="days">{t.labelDays}</option>
60
+ </select>
61
+ </div>
62
+ </div>
63
+ </div>
64
+
65
+ <div class="prof-results">
66
+ <div class="prof-main-metric">
67
+ <div id="prof-status" class="prof-status-badge positive">{t.labelPositiveResult}</div>
68
+ <div id="prof-roi" class="prof-metric-val">0%</div>
69
+ <div class="prof-label">{t.labelROI}</div>
70
+ </div>
71
+
72
+ <div class="prof-submetrics">
73
+ <div class="prof-submetric-card">
74
+ <span class="prof-label">{t.labelCAGR}</span>
75
+ <span id="prof-cagr" class="prof-submetric-val">0%</span>
76
+ </div>
77
+ <div class="prof-submetric-card">
78
+ <span class="prof-label">{t.labelNetProfit}</span>
79
+ <span id="prof-net" class="prof-submetric-val">0</span>
80
+ </div>
81
+ </div>
82
+
83
+ <button id="prof-copy" class="prof-copy-btn">
84
+ <svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect><path d="M5 15H4a2 2 0 0 1-2-2V4a2 2 0 0 1 2-2h9a2 2 0 0 1 2 2v1"></path></svg>
85
+ <span>{t.labelCopyResult}</span>
86
+ </button>
87
+ </div>
88
+ </div>
89
+
90
+ <div class="prof-chart-wrap">
91
+ <canvas id="prof-chart"></canvas>
92
+ </div>
93
+ </div>
94
+ </div>
95
+
96
+ <script>
97
+ import { ProfitabilityCalculator } from './logic';
98
+ import type { ProfitabilityResult } from './logic';
99
+ import Chart from 'chart.js/auto';
100
+
101
+ const root = document.querySelector('.prof-root') as HTMLElement;
102
+ const initialIn = document.getElementById('prof-initial') as HTMLInputElement;
103
+ const finalIn = document.getElementById('prof-final') as HTMLInputElement;
104
+ const timeIn = document.getElementById('prof-time-value') as HTMLInputElement;
105
+ const unitIn = document.getElementById('prof-time-unit') as HTMLSelectElement;
106
+ const copyBtn = document.getElementById('prof-copy') as HTMLButtonElement;
107
+ const card = document.getElementById('prof-card');
108
+ const statusOut = document.getElementById('prof-status');
109
+ const roiOut = document.getElementById('prof-roi');
110
+ const cagrOut = document.getElementById('prof-cagr');
111
+ const netOut = document.getElementById('prof-net');
112
+ const currencySelect = document.getElementById('prof-currency-select') as HTMLSelectElement;
113
+ const ctx = document.getElementById('prof-chart') as HTMLCanvasElement;
114
+
115
+ const labelPositive = root.dataset.labelPositive || '';
116
+ const labelNegative = root.dataset.labelNegative || '';
117
+ const labelLinear = root.dataset.labelLinear || '';
118
+ const labelExponential = root.dataset.labelExponential || '';
119
+ const labelCopied = root.dataset.labelCopied || '';
120
+ const labelCopy = root.dataset.labelCopy || '';
121
+
122
+ let chart: Chart | null = null;
123
+
124
+ const updateTextValues = (result: ProfitabilityResult) => {
125
+ const currencyCode = currencySelect.value;
126
+ const locale = root.dataset.locale || 'en';
127
+ const formatter = new Intl.NumberFormat(locale, {
128
+ style: 'currency',
129
+ currency: currencyCode,
130
+ maximumFractionDigits: 0
131
+ });
132
+
133
+ if (roiOut) roiOut.innerText = `${result.roi > 0 ? '+' : ''}${result.roi}%`;
134
+ if (cagrOut) cagrOut.innerText = `${result.cagr > 0 ? '+' : ''}${result.cagr}%`;
135
+ if (netOut) netOut.innerText = formatter.format(result.netProfit);
136
+ };
137
+
138
+ const updateStatusUI = (result: ProfitabilityResult) => {
139
+ const statusClass = result.isPositive ? 'positive' : 'negative';
140
+ if (card) card.className = `prof-card ${statusClass}`;
141
+ if (statusOut) {
142
+ statusOut.className = `prof-status-badge ${statusClass}`;
143
+ statusOut.innerText = result.isPositive ? labelPositive : labelNegative;
144
+ }
145
+ };
146
+
147
+ const updateUI = (result: ProfitabilityResult) => {
148
+ updateTextValues(result);
149
+ updateStatusUI(result);
150
+ };
151
+
152
+ const getChartDatasets = (linearData: number[], exponentialData: number[]) => [
153
+ {
154
+ label: labelLinear,
155
+ data: linearData,
156
+ borderColor: '#94a3b8',
157
+ borderDash: [5, 5],
158
+ tension: 0,
159
+ pointRadius: 0
160
+ },
161
+ {
162
+ label: labelExponential,
163
+ data: exponentialData,
164
+ borderColor: '#10b981',
165
+ backgroundColor: 'rgba(16, 185, 129, 0.1)',
166
+ fill: true,
167
+ tension: 0.4,
168
+ pointRadius: 0
169
+ }
170
+ ];
171
+
172
+ const getChartOptions = () => ({
173
+ responsive: true,
174
+ maintainAspectRatio: false,
175
+ plugins: { legend: { position: 'bottom' as const, labels: { font: { family: 'Outfit', weight: 'bold' } } } },
176
+ scales: {
177
+ y: { grid: { color: 'rgba(0,0,0,0.05)' } },
178
+ x: { grid: { display: false }, title: { display: true, text: 'Years', font: { weight: 'bold' } } }
179
+ }
180
+ });
181
+
182
+ const updateChart = (initial: number, final: number, years: number, cagr: number) => {
183
+ const steps = 12;
184
+ const labels = Array.from({ length: steps + 1 }, (_, i) => (years * i / steps).toFixed(1));
185
+ const linearData = labels.map((_, i) => initial + (final - initial) * i / steps);
186
+ const exponentialData = labels.map((_, i) => initial * Math.pow(1 + cagr / 100, years * i / steps));
187
+
188
+ if (chart) {
189
+ chart.data.labels = labels;
190
+ chart.data.datasets[0].data = linearData;
191
+ chart.data.datasets[1].data = exponentialData;
192
+ chart.update();
193
+ } else {
194
+ chart = new Chart(ctx, {
195
+ type: 'line',
196
+ data: { labels, datasets: getChartDatasets(linearData, exponentialData) },
197
+ options: getChartOptions() as Parameters<typeof Chart>[1]['options'],
198
+ });
199
+ }
200
+ };
201
+
202
+ const update = () => {
203
+ const initial = parseFloat(initialIn.value) || 0;
204
+ const final = parseFloat(finalIn.value) || 0;
205
+ const time = parseFloat(timeIn.value) || 0;
206
+ const unit = unitIn.value as 'years' | 'months' | 'days';
207
+
208
+ const result = ProfitabilityCalculator.calculate({
209
+ initialInvestment: initial,
210
+ finalValue: final,
211
+ timeValue: time,
212
+ timeUnit: unit
213
+ });
214
+
215
+ updateUI(result);
216
+ updateChart(initial, final, result.years, result.cagr);
217
+ };
218
+
219
+ [initialIn, finalIn, timeIn, unitIn, currencySelect].forEach(el => el.addEventListener('input', update));
220
+
221
+ copyBtn.addEventListener('click', () => {
222
+ const text = `Investment Performance: ROI ${roiOut?.innerText}, CAGR ${cagrOut?.innerText} over ${timeIn.value} ${unitIn.value}. Total net: ${netOut?.innerText}`;
223
+ navigator.clipboard.writeText(text).then(() => {
224
+ const span = copyBtn.querySelector('span');
225
+ if (span) {
226
+ span.innerText = labelCopied;
227
+ setTimeout(() => { span.innerText = labelCopy; }, 2000);
228
+ }
229
+ });
230
+ });
231
+
232
+ const preselectCurrency = () => {
233
+ const locale = root.dataset.locale || 'en';
234
+ const mapping: Record<string, string> = {
235
+ es: 'EUR', de: 'EUR', fr: 'EUR', it: 'EUR', pt: 'EUR', nl: 'EUR',
236
+ en: 'USD',
237
+ tr: 'TRY', pl: 'PLN', sv: 'SEK', id: 'IDR',
238
+ ru: 'RUB', ja: 'JPY', zh: 'CNY', ko: 'KRW'
239
+ };
240
+ if (mapping[locale]) currencySelect.value = mapping[locale];
241
+ };
242
+
243
+ preselectCurrency();
244
+ update();
245
+ </script>
246
+
247
+ <style>
248
+ @import './profitability-calculator.css';
249
+ </style>
@@ -0,0 +1,27 @@
1
+ import type { FinanceToolEntry } from '../../types';
2
+ import type { ProfitabilityUI } from './ui';
3
+
4
+ export const profitability: FinanceToolEntry<ProfitabilityUI> = {
5
+ id: 'profitability-calculator-roi-cagr',
6
+ icons: {
7
+ bg: 'mdi:trending-up',
8
+ fg: 'mdi:chart-line',
9
+ },
10
+ i18n: {
11
+ en: () => import('./i18n/en').then((m) => m.content),
12
+ es: () => import('./i18n/es').then((m) => m.content),
13
+ fr: () => import('./i18n/fr').then((m) => m.content),
14
+ de: () => import('./i18n/de').then((m) => m.content),
15
+ it: () => import('./i18n/it').then((m) => m.content),
16
+ pt: () => import('./i18n/pt').then((m) => m.content),
17
+ nl: () => import('./i18n/nl').then((m) => m.content),
18
+ id: () => import('./i18n/id').then((m) => m.content),
19
+ pl: () => import('./i18n/pl').then((m) => m.content),
20
+ tr: () => import('./i18n/tr').then((m) => m.content),
21
+ ru: () => import('./i18n/ru').then((m) => m.content),
22
+ sv: () => import('./i18n/sv').then((m) => m.content),
23
+ ja: () => import('./i18n/ja').then((m) => m.content),
24
+ ko: () => import('./i18n/ko').then((m) => m.content),
25
+ zh: () => import('./i18n/zh').then((m) => m.content),
26
+ },
27
+ };
@@ -0,0 +1,116 @@
1
+ import type { ProfitabilityUI } from '../ui';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+
4
+ export const ui: ProfitabilityUI = {
5
+ labelInitialInvestment: 'Anfangsinvestition',
6
+ labelFinalValue: 'Endwert / Aktueller Kontostand',
7
+ labelTimeSelection: 'Investitionsdauer',
8
+ labelYears: 'Jahre',
9
+ labelMonths: 'Monate',
10
+ labelDays: 'Tage',
11
+ labelROI: 'Rentabilität (ROI)',
12
+ labelCAGR: 'Jährliche Wachstumsrate (CAGR)',
13
+ labelNetProfit: 'Nettogewinn',
14
+ labelLinearGrowth: 'Lineares Wachstum (Geschätzt)',
15
+ labelExponentialGrowth: 'Zinseszins-Wachstum (CAGR)',
16
+ labelPositiveResult: 'Rentable Investition',
17
+ labelNegativeResult: 'Verlustposition',
18
+ labelCopyResult: 'Ergebnisse kopieren',
19
+ labelCopied: 'Kopiert!',
20
+ };
21
+
22
+ const slug = 'rentabilitatsrechner-investition-roi-cagr';
23
+ const title = 'Rentabilitätsrechner: ROI & CAGR';
24
+ const description = 'Analysieren Sie Ihre Investitionsleistung. Berechnen Sie ROI und CAGR, um Ihre realen Gewinne zu verstehen.';
25
+
26
+ const faq = [
27
+ {
28
+ question: 'Was ist eine gute CAGR?',
29
+ answer: 'Historisch gesehen liegt der S&P 500 bei etwa 7-10% pro Jahr. Hochrisikoinvestitionen können 15-20%+ anstreben.',
30
+ },
31
+ {
32
+ question: 'Warum unterscheidet sich mein CAGR von meinem Gesamt-ROI?',
33
+ answer: 'Der ROI ist die Gesamtrendite unabhängig von der Zeit. Die CAGR ist die jährliche Rate, die erforderlich ist, um diese Gesamtrendite zu erreichen.',
34
+ },
35
+ {
36
+ question: 'Kann die CAGR negativ sein?',
37
+ answer: 'Ja. Wenn Ihr Endwert geringer ist als Ihre Anfangsinvestition, ist die CAGR negativ.',
38
+ },
39
+ ];
40
+
41
+ const howTo = [
42
+ {
43
+ name: 'Anfangskapital eingeben',
44
+ text: 'Geben Sie den ursprünglich investierten Betrag ein.',
45
+ },
46
+ {
47
+ name: 'Endwert eingeben',
48
+ text: 'Geben Sie den aktuellen Marktwert oder den Verkaufspreis ein.',
49
+ },
50
+ {
51
+ name: 'Zeitdauer festlegen',
52
+ text: 'Geben Sie an, wie lange Sie die Investition gehalten haben.',
53
+ },
54
+ ];
55
+
56
+ export const content: ToolLocaleContent<ProfitabilityUI> = {
57
+ slug,
58
+ title,
59
+ description,
60
+ ui,
61
+ seo: [
62
+ {
63
+ type: 'title',
64
+ text: 'ROI vs. CAGR: Welche Kennzahl ist besser?',
65
+ level: 2,
66
+ },
67
+ {
68
+ type: 'paragraph',
69
+ html: 'Der <strong>ROI</strong> zeigt den prozentualen Gesamtgewinn, ignoriert aber die Zeit. Die <strong>CAGR</strong> ist besser für langfristige Analysen.',
70
+ },
71
+ ],
72
+ faq,
73
+ bibliography: [
74
+ {
75
+ name: 'ROI Definition - Investopedia',
76
+ url: 'https://www.investopedia.com/terms/r/returnoninvestment.asp',
77
+ },
78
+ ],
79
+ howTo,
80
+ schemas: [
81
+ {
82
+ '@context': 'https://schema.org',
83
+ '@type': 'FinancialProduct',
84
+ name: title,
85
+ description,
86
+ },
87
+ {
88
+ '@context': 'https://schema.org',
89
+ '@type': 'FAQPage',
90
+ mainEntity: faq.map((f) => ({
91
+ '@type': 'Question',
92
+ name: f.question,
93
+ acceptedAnswer: { '@type': 'Answer', text: f.answer },
94
+ })),
95
+ },
96
+ {
97
+ '@context': 'https://schema.org',
98
+ '@type': 'HowTo',
99
+ name: title,
100
+ step: howTo.map((h, i) => ({
101
+ '@type': 'HowToStep',
102
+ position: i + 1,
103
+ name: h.name,
104
+ text: h.text,
105
+ })),
106
+ },
107
+ {
108
+ '@context': 'https://schema.org',
109
+ '@type': 'SoftwareApplication',
110
+ name: title,
111
+ applicationCategory: 'FinanceApplication',
112
+ operatingSystem: 'All',
113
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
114
+ },
115
+ ],
116
+ };
@@ -0,0 +1,165 @@
1
+ import type { ProfitabilityUI } from '../ui';
2
+ import type { ToolLocaleContent } from '../../../types';
3
+
4
+ export const ui: ProfitabilityUI = {
5
+ labelInitialInvestment: 'Initial Investment',
6
+ labelFinalValue: 'Final Value / Current Balance',
7
+ labelTimeSelection: 'Investment Duration',
8
+ labelYears: 'Years',
9
+ labelMonths: 'Months',
10
+ labelDays: 'Days',
11
+ labelROI: 'Return on Investment (ROI)',
12
+ labelCAGR: 'Annualized Growth (CAGR)',
13
+ labelNetProfit: 'Net Profit',
14
+ labelLinearGrowth: 'Linear Growth (Estimated)',
15
+ labelExponentialGrowth: 'Compound Growth (CAGR)',
16
+ labelPositiveResult: 'Profitable Investment',
17
+ labelNegativeResult: 'Loss Position',
18
+ labelCopyResult: 'Copy Results',
19
+ labelCopied: 'Copied!',
20
+ };
21
+
22
+ const slug = 'profitability-calculator-roi-cagr';
23
+ const title = 'Investment Profitability Calculator: ROI & CAGR';
24
+ const description = 'Analyze your investment performance with precision. Calculate total Return on Investment (ROI) and Compound Annual Growth Rate (CAGR) to understand your true annualized gains.';
25
+
26
+ const faq = [
27
+ {
28
+ question: 'What is a good CAGR?',
29
+ answer: 'A "good" CAGR depends on the asset class. Historically, the S&P 500 has returned around 7-10% annually. High-risk investments might target 15-20%+, while savings accounts usually offer much less.',
30
+ },
31
+ {
32
+ question: 'Why is my CAGR different from my total ROI?',
33
+ answer: 'ROI is the total return regardless of time. CAGR is the annual rate required to reach that total return. If your investment lasted more than a year, the CAGR will usually be a smaller number than the ROI.',
34
+ },
35
+ {
36
+ question: 'Can CAGR be negative?',
37
+ answer: 'Yes. If your final value is less than your initial investment, the CAGR will be negative, representing the annualized rate of loss.',
38
+ },
39
+ ];
40
+
41
+ const howTo = [
42
+ {
43
+ name: 'Enter your initial capital',
44
+ text: 'Input the amount of money you originally invested.',
45
+ },
46
+ {
47
+ name: 'Enter the final or current value',
48
+ text: 'Input the current market value of your investment or the price at which you sold it.',
49
+ },
50
+ {
51
+ name: 'Set the time duration',
52
+ text: 'Specify how long you held the investment to calculate the annualized return (CAGR).',
53
+ },
54
+ ];
55
+
56
+ export const content: ToolLocaleContent<ProfitabilityUI> = {
57
+ slug,
58
+ title,
59
+ description,
60
+ ui,
61
+ seo: [
62
+ {
63
+ type: 'title',
64
+ text: 'ROI vs. CAGR: Which Metric is Better?',
65
+ level: 2,
66
+ },
67
+ {
68
+ type: 'paragraph',
69
+ html: 'When evaluating an investment, <strong>ROI (Return on Investment)</strong> tells you the total percentage gain or loss from start to finish. However, it ignores the element of time. <strong>CAGR (Compound Annual Growth Rate)</strong> is superior for long-term analysis because it "annualizes" your returns, allowing you to compare a 5-year stock investment against a 1-year crypto trade or a savings account on equal terms.',
70
+ },
71
+ {
72
+ type: 'title',
73
+ text: 'How to Use the Profitability Calculator',
74
+ level: 3,
75
+ },
76
+ {
77
+ type: 'paragraph',
78
+ html: 'To get accurate results, enter your initial capital and the current value (or final sale price) of your asset. Select the duration of the investment in days, months, or years. Our tool automatically calculates the absolute profit, the total ROI, and the geometric mean of your annual growth (CAGR).',
79
+ },
80
+ {
81
+ type: 'comparative',
82
+ columns: 2,
83
+ items: [
84
+ {
85
+ title: 'Total ROI',
86
+ description: 'Measure of absolute return.',
87
+ points: [
88
+ 'Ignores duration',
89
+ 'Simple calculation',
90
+ 'Best for quick trades',
91
+ 'Shows total gain/loss',
92
+ ],
93
+ },
94
+ {
95
+ title: 'Annualized CAGR',
96
+ description: 'Measure of annual performance.',
97
+ highlight: true,
98
+ points: [
99
+ 'Includes time factor',
100
+ 'Standardizes results',
101
+ 'Allows comparisons',
102
+ 'Shows geometric growth',
103
+ ],
104
+ },
105
+ ],
106
+ },
107
+ {
108
+ type: 'title',
109
+ text: 'The Power of Compound Growth Visualization',
110
+ level: 3,
111
+ },
112
+ {
113
+ type: 'paragraph',
114
+ html: 'Our interactive chart compares linear growth (where you assume the gain is spread evenly) against exponential growth (CAGR). This visualization is crucial for understanding how compound interest works over time. Real investments rarely grow in a straight line; understanding the CAGR curve helps you set realistic expectations for future wealth building.',
115
+ },
116
+ ],
117
+ faq,
118
+ bibliography: [
119
+ {
120
+ name: 'Investopedia: ROI Definition',
121
+ url: 'https://www.investopedia.com/terms/r/returnoninvestment.asp',
122
+ },
123
+ {
124
+ name: 'Investopedia: CAGR Explained',
125
+ url: 'https://www.investopedia.com/terms/c/cagr.asp',
126
+ },
127
+ ],
128
+ howTo,
129
+ schemas: [
130
+ {
131
+ '@context': 'https://schema.org',
132
+ '@type': 'FinancialProduct',
133
+ name: title,
134
+ description,
135
+ },
136
+ {
137
+ '@context': 'https://schema.org',
138
+ '@type': 'FAQPage',
139
+ mainEntity: faq.map((f) => ({
140
+ '@type': 'Question',
141
+ name: f.question,
142
+ acceptedAnswer: { '@type': 'Answer', text: f.answer },
143
+ })),
144
+ },
145
+ {
146
+ '@context': 'https://schema.org',
147
+ '@type': 'HowTo',
148
+ name: title,
149
+ step: howTo.map((h, i) => ({
150
+ '@type': 'HowToStep',
151
+ position: i + 1,
152
+ name: h.name,
153
+ text: h.text,
154
+ })),
155
+ },
156
+ {
157
+ '@context': 'https://schema.org',
158
+ '@type': 'SoftwareApplication',
159
+ name: title,
160
+ applicationCategory: 'FinanceApplication',
161
+ operatingSystem: 'All',
162
+ offers: { '@type': 'Offer', price: '0', priceCurrency: 'USD' },
163
+ },
164
+ ],
165
+ };