From 2db2a471147598b1e583264284e04268530a3fc9 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Tue, 29 Sep 2026 20:51:37 +0200
Subject: [PATCH 1/3] Bugfix/color scheme of investment chart (#7972)
* Fix color scheme of investment chart component
* Update changelog
---
CHANGELOG.md | 1 +
.../account-detail-dialog.html | 1 +
.../investment-chart.component.ts | 24 ++++++++++++-------
.../portfolio/analysis/analysis-page.html | 3 +++
4 files changed, 20 insertions(+), 9 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 998d9fe239..7c55df458c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed
+- Fixed the colors of the investment chart component (dark mode)
- Fixed the value column of the top holdings on the allocations page in the _Presenter View_
- Fixed the projected sustainable retirement income on the _FIRE_ page for a projected total amount of zero (experimental)
- Fixed the emergency fund in the portfolio summary for redacted values
diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html
index a87179ecb9..5a86e4aa9b 100644
--- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html
+++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.html
@@ -23,6 +23,7 @@
(
this.chartCanvas().nativeElement,
{
data: chartData,
options: {
animation: false,
- elements: getChartElementsOptions(this.colorScheme),
+ elements: getChartElementsOptions(colorScheme),
interaction: { intersect: false, mode: 'index' },
maintainAspectRatio: true,
plugins: {
@@ -204,7 +210,7 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
value: this.savingsRate
}
: undefined,
- yAxis: getZeroLineAnnotation(this.colorScheme)
+ yAxis: getZeroLineAnnotation(colorScheme)
}
},
legend: {
@@ -212,18 +218,18 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
},
tooltip: this.getTooltipPluginConfiguration(),
verticalHoverLine: {
- color: getChartBorderColor(this.colorScheme)
+ color: getChartBorderColor(colorScheme)
}
},
responsive: true,
scales: {
x: getTimeAxisOptions({
+ colorScheme,
borderWidth: this.groupBy ? 0 : 1,
- colorScheme: this.colorScheme,
locale: this.locale
}),
y: getValueAxisOptions({
- colorScheme: this.colorScheme,
+ colorScheme,
display: !this.isInPercentage,
tickCallback: (tickValue) => {
return transformTickToAbbreviation(Number(tickValue));
@@ -232,7 +238,7 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
}
},
plugins: [
- getVerticalHoverLinePlugin(this.chartCanvas(), this.colorScheme)
+ getVerticalHoverLinePlugin(this.chartCanvas(), colorScheme)
],
type: this.groupBy ? 'bar' : 'line'
}
@@ -245,7 +251,7 @@ export class GfInvestmentChartComponent implements OnChanges, OnDestroy {
TooltipOptions<'bar' | 'line'>
> {
return getTimeSeriesTooltipOptions<'bar' | 'line'>({
- colorScheme: this.colorScheme,
+ colorScheme: this.colorScheme ?? DEFAULT_COLOR_SCHEME,
currency: this.isInPercentage ? undefined : this.currency,
groupBy: this.groupBy,
locale: this.isInPercentage ? undefined : this.locale,
diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html
index 47cee7af6e..2756076b7a 100644
--- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html
+++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html
@@ -443,6 +443,7 @@
class="h-100"
[benchmarkDataItems]="investments"
[benchmarkDataLabel]="portfolioEvolutionDataLabel"
+ [colorScheme]="user?.settings?.colorScheme"
[currency]="user?.settings?.baseCurrency"
[historicalDataItems]="performanceDataItems"
[isInPercentage]="showValuesInPercentage()"
@@ -499,6 +500,7 @@
class="h-100"
[benchmarkDataItems]="investmentsByGroup"
[benchmarkDataLabel]="investmentTimelineDataLabel"
+ [colorScheme]="user?.settings?.colorScheme"
[currency]="user?.settings?.baseCurrency"
[groupBy]="mode()"
[isInPercentage]="showValuesInPercentage()"
@@ -534,6 +536,7 @@
class="h-100"
[benchmarkDataItems]="dividendsByGroup"
[benchmarkDataLabel]="dividendTimelineDataLabel"
+ [colorScheme]="user?.settings?.colorScheme"
[currency]="user?.settings?.baseCurrency"
[groupBy]="mode()"
[isInPercentage]="showValuesInPercentage()"
From c13a0c18fb9c221adc4fed02d3ba32b274c8dc80 Mon Sep 17 00:00:00 2001
From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
Date: Tue, 29 Sep 2026 21:53:38 +0200
Subject: [PATCH 2/3] Bugfix/redaction of values of ETF holdings (#7973)
* Fix redaction of values of ETF holdings
* Update changelog
---
CHANGELOG.md | 1 +
apps/api/src/helper/object.helper.spec.ts | 1050 ++++++++++++---------
libs/common/src/lib/config.ts | 2 +-
3 files changed, 582 insertions(+), 471 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 7c55df458c..4bbf0a08dd 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -22,6 +22,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Fixed the value column of the top holdings on the allocations page in the _Presenter View_
- Fixed the projected sustainable retirement income on the _FIRE_ page for a projected total amount of zero (experimental)
- Fixed the emergency fund in the portfolio summary for redacted values
+- Fixed the redaction of `valueInBaseCurrency` in the holdings of ETFs in a restricted view
## 3.75.0 - 2026-09-28
diff --git a/apps/api/src/helper/object.helper.spec.ts b/apps/api/src/helper/object.helper.spec.ts
index 415851a6c6..ca487ed8f7 100644
--- a/apps/api/src/helper/object.helper.spec.ts
+++ b/apps/api/src/helper/object.helper.spec.ts
@@ -1,4 +1,5 @@
import { DEFAULT_REDACTED_PATHS } from '@ghostfolio/common/config';
+import { PortfolioDetails } from '@ghostfolio/common/interfaces';
import { query, redactPaths } from './object.helper';
@@ -133,6 +134,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.044900865255793135,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -149,7 +151,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3183066634822068,
grossPerformancePercentWithCurrencyEffect: 0.3183066634822068,
grossPerformanceWithCurrencyEffect: 2665.5,
- holdings: [],
investment: 0.060265768702233234,
name: 'Apple Inc',
netPerformance: 2664.5,
@@ -185,6 +186,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.026912563036519527,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{ code: 'DE', weight: 1, continent: 'Europe', name: 'Germany' }
@@ -196,7 +198,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3719230057375532,
grossPerformancePercentWithCurrencyEffect: 0.2650716044872953,
grossPerformanceWithCurrencyEffect: 1386.429698978564,
- holdings: [],
investment: 0.03471025137190358,
name: 'Allianz SE',
netPerformance: 1789.1095737558583,
@@ -232,6 +233,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.07646101417126275,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -248,7 +250,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.8594552890963852,
grossPerformancePercentWithCurrencyEffect: 0.8594552890963852,
grossPerformanceWithCurrencyEffect: 8689.05,
- holdings: [],
investment: 0.07275900505029173,
name: 'Amazon.com, Inc.',
netPerformance: 8608.26,
@@ -290,6 +291,7 @@ describe('redactAttributes', () => {
],
allocationInPercentage: 0.15042891393226654,
assetClass: 'LIQUIDITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'CRYPTOCURRENCY',
countries: [],
dataSource: 'COINGECKO',
@@ -299,7 +301,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 17.4925166352,
grossPerformancePercentWithCurrencyEffect: 17.4925166352,
grossPerformanceWithCurrencyEffect: 34985.0332704,
- holdings: [],
investment: 0.014393543993846005,
name: 'Bitcoin',
netPerformance: 34955.1332704,
@@ -341,6 +342,7 @@ describe('redactAttributes', () => {
],
allocationInPercentage: 0.009076749759365777,
assetClass: 'FIXED_INCOME',
+ assetProfile: { holdings: [] },
assetSubClass: 'BOND',
countries: [],
dataSource: 'MANUAL',
@@ -350,7 +352,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0,
grossPerformancePercentWithCurrencyEffect: -0.06153834320225245,
grossPerformanceWithCurrencyEffect: -125.68932723700505,
- holdings: [],
investment: 0.016060638243523776,
name: 'Bondora Go & Grow',
netPerformance: 0,
@@ -392,6 +393,7 @@ describe('redactAttributes', () => {
],
allocationInPercentage: 0.09095764645669335,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'ETF',
countries: [
{
@@ -474,7 +476,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.27579517683678895,
grossPerformancePercentWithCurrencyEffect: 0.458553421589667,
grossPerformanceWithCurrencyEffect: 5322.44900391902,
- holdings: [],
investment: 0.13551383737034509,
name: 'frankly Extreme 95 Index',
netPerformance: 3533.389614611676,
@@ -510,6 +511,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.05222646409742627,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -526,7 +528,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.7865431171216295,
grossPerformancePercentWithCurrencyEffect: 0.7865431171216295,
grossPerformanceWithCurrencyEffect: 5653.2,
- holdings: [],
investment: 0.051726079050684395,
name: 'Microsoft Corporation',
netPerformance: 5653.2,
@@ -562,6 +563,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.1589050142378352,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -578,7 +580,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 17.184314638161936,
grossPerformancePercentWithCurrencyEffect: 17.184314638161936,
grossPerformanceWithCurrencyEffect: 36920.500000005,
- holdings: [],
investment: 0.01546226463535309,
name: 'Tesla, Inc.',
netPerformance: 36890.500000005,
@@ -614,6 +615,85 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.057358979326040366,
assetClass: 'EQUITY',
+ assetProfile: {
+ holdings: [
+ {
+ allocationInPercentage: 0.06099941636982121,
+ name: 'APPLE INC',
+ valueInBaseCurrency: 860.2442693554036
+ },
+ {
+ allocationInPercentage: 0.05862464529372787,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: 826.7540602547973
+ },
+ {
+ allocationInPercentage: 0.05156070760128074,
+ name: 'NVIDIA CORP',
+ valueInBaseCurrency: 727.1348789470617
+ },
+ {
+ allocationInPercentage: 0.03301535551128066,
+ name: 'AMAZON COM INC',
+ valueInBaseCurrency: 465.5990510978355
+ },
+ {
+ allocationInPercentage: 0.01962204914568647,
+ name: 'FACEBOOK CLASS A INC',
+ valueInBaseCurrency: 276.71994807704345
+ },
+ {
+ allocationInPercentage: 0.01902835637666313,
+ name: 'ALPHABET INC CLASS A',
+ valueInBaseCurrency: 268.34739580189176
+ },
+ {
+ allocationInPercentage: 0.01555676306627245,
+ name: 'ALPHABET INC CLASS C',
+ valueInBaseCurrency: 219.3892511421072
+ },
+ {
+ allocationInPercentage: 0.01463100485016827,
+ name: 'BERKSHIRE HATHAWAY INC CLASS B',
+ valueInBaseCurrency: 206.33374589949804
+ },
+ {
+ allocationInPercentage: 0.01403731208114493,
+ name: 'BROADCOM INC',
+ valueInBaseCurrency: 197.96119362434638
+ },
+ {
+ allocationInPercentage: 0.01297067761476403,
+ name: 'ELI LILLY',
+ valueInBaseCurrency: 182.91898106220972
+ },
+ {
+ allocationInPercentage: 0.0118637927911612,
+ name: 'TESLA INC',
+ valueInBaseCurrency: 167.30913783735082
+ },
+ {
+ allocationInPercentage: 0.01152166475477487,
+ name: 'JPMORGAN CHASE & CO',
+ valueInBaseCurrency: 162.48427720421262
+ },
+ {
+ allocationInPercentage: 0.0100324015375638,
+ name: 'EXXON MOBIL CORP',
+ valueInBaseCurrency: 141.4819426834935
+ },
+ {
+ allocationInPercentage: 0.01000221376964736,
+ name: 'UNITEDHEALTH GROUP INC',
+ valueInBaseCurrency: 141.0562196864519
+ },
+ {
+ allocationInPercentage: 0.007818631890358146,
+ name: 'VISA INC CLASS A',
+ valueInBaseCurrency: 110.26225623377576
+ }
+ ]
+ },
assetSubClass: 'ETF',
countries: [
{
@@ -660,83 +740,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.8832083851170418,
grossPerformancePercentWithCurrencyEffect: 0.8832083851170418,
grossPerformanceWithCurrencyEffect: 5856.3,
- holdings: [
- {
- allocationInPercentage: 0.06099941636982121,
- name: 'APPLE INC',
- valueInBaseCurrency: 860.2442693554036
- },
- {
- allocationInPercentage: 0.05862464529372787,
- name: 'MICROSOFT CORP',
- valueInBaseCurrency: 826.7540602547973
- },
- {
- allocationInPercentage: 0.05156070760128074,
- name: 'NVIDIA CORP',
- valueInBaseCurrency: 727.1348789470617
- },
- {
- allocationInPercentage: 0.03301535551128066,
- name: 'AMAZON COM INC',
- valueInBaseCurrency: 465.5990510978355
- },
- {
- allocationInPercentage: 0.01962204914568647,
- name: 'FACEBOOK CLASS A INC',
- valueInBaseCurrency: 276.71994807704345
- },
- {
- allocationInPercentage: 0.01902835637666313,
- name: 'ALPHABET INC CLASS A',
- valueInBaseCurrency: 268.34739580189176
- },
- {
- allocationInPercentage: 0.01555676306627245,
- name: 'ALPHABET INC CLASS C',
- valueInBaseCurrency: 219.3892511421072
- },
- {
- allocationInPercentage: 0.01463100485016827,
- name: 'BERKSHIRE HATHAWAY INC CLASS B',
- valueInBaseCurrency: 206.33374589949804
- },
- {
- allocationInPercentage: 0.01403731208114493,
- name: 'BROADCOM INC',
- valueInBaseCurrency: 197.96119362434638
- },
- {
- allocationInPercentage: 0.01297067761476403,
- name: 'ELI LILLY',
- valueInBaseCurrency: 182.91898106220972
- },
- {
- allocationInPercentage: 0.0118637927911612,
- name: 'TESLA INC',
- valueInBaseCurrency: 167.30913783735082
- },
- {
- allocationInPercentage: 0.01152166475477487,
- name: 'JPMORGAN CHASE & CO',
- valueInBaseCurrency: 162.48427720421262
- },
- {
- allocationInPercentage: 0.0100324015375638,
- name: 'EXXON MOBIL CORP',
- valueInBaseCurrency: 141.4819426834935
- },
- {
- allocationInPercentage: 0.01000221376964736,
- name: 'UNITEDHEALTH GROUP INC',
- valueInBaseCurrency: 141.0562196864519
- },
- {
- allocationInPercentage: 0.007818631890358146,
- name: 'VISA INC CLASS A',
- valueInBaseCurrency: 110.26225623377576
- }
- ],
investment: 0.05934602124102648,
name: 'Vanguard Total Stock Market Index Fund ETF Shares',
netPerformance: 5756.8,
@@ -786,6 +789,85 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.09386983901959013,
assetClass: 'EQUITY',
+ assetProfile: {
+ holdings: [
+ {
+ allocationInPercentage: 0.042520261085,
+ name: 'APPLE INC',
+ valueInBaseCurrency: 981.3336460398625
+ },
+ {
+ allocationInPercentage: 0.037017038038,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: 854.3236559815404
+ },
+ {
+ allocationInPercentage: 0.018861883836,
+ name: 'AMAZON COM INC',
+ valueInBaseCurrency: 435.31720557783655
+ },
+ {
+ allocationInPercentage: 0.017806548325,
+ name: 'NVIDIA CORP',
+ valueInBaseCurrency: 410.9609053487602
+ },
+ {
+ allocationInPercentage: 0.012188534864,
+ name: 'ALPHABET INC CLASS A',
+ valueInBaseCurrency: 281.3016442693628
+ },
+ {
+ allocationInPercentage: 0.010831709166,
+ name: 'ALPHABET INC CLASS C',
+ valueInBaseCurrency: 249.98719145833246
+ },
+ {
+ allocationInPercentage: 0.010813551981,
+ name: 'TESLA INC',
+ valueInBaseCurrency: 249.56813813873381
+ },
+ {
+ allocationInPercentage: 0.009934819182,
+ name: 'FACEBOOK CLASS A INC',
+ valueInBaseCurrency: 229.28768737165962
+ },
+ {
+ allocationInPercentage: 0.007403227621000001,
+ name: 'BERKSHIRE HATHAWAY INC CLASS B',
+ valueInBaseCurrency: 170.8605772494153
+ },
+ {
+ allocationInPercentage: 0.007076883908,
+ name: 'ELI LILLY',
+ valueInBaseCurrency: 163.32882514892185
+ },
+ {
+ allocationInPercentage: 0.006844271583,
+ name: 'EXXON MOBIL CORP',
+ valueInBaseCurrency: 157.96031857861325
+ },
+ {
+ allocationInPercentage: 0.006718061670999999,
+ name: 'UNITEDHEALTH GROUP INC',
+ valueInBaseCurrency: 155.0474946695187
+ },
+ {
+ allocationInPercentage: 0.006456949621,
+ name: 'JPMORGAN CHASE & CO',
+ valueInBaseCurrency: 149.02123722158794
+ },
+ {
+ allocationInPercentage: 0.006293890054,
+ name: 'TAIWAN SEMICONDUCTOR MANUFACTURING',
+ valueInBaseCurrency: 145.25795272326576
+ },
+ {
+ allocationInPercentage: 0.00600392555,
+ name: 'VISA INC CLASS A',
+ valueInBaseCurrency: 138.56580369427397
+ }
+ ]
+ },
assetSubClass: 'ETF',
countries: [
{
@@ -1060,83 +1142,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3683200415015591,
grossPerformancePercentWithCurrencyEffect: 0.5806366182968891,
grossPerformanceWithCurrencyEffect: 6402.248165662604,
- holdings: [
- {
- allocationInPercentage: 0.042520261085,
- name: 'APPLE INC',
- valueInBaseCurrency: 981.3336460398625
- },
- {
- allocationInPercentage: 0.037017038038,
- name: 'MICROSOFT CORP',
- valueInBaseCurrency: 854.3236559815404
- },
- {
- allocationInPercentage: 0.018861883836,
- name: 'AMAZON COM INC',
- valueInBaseCurrency: 435.31720557783655
- },
- {
- allocationInPercentage: 0.017806548325,
- name: 'NVIDIA CORP',
- valueInBaseCurrency: 410.9609053487602
- },
- {
- allocationInPercentage: 0.012188534864,
- name: 'ALPHABET INC CLASS A',
- valueInBaseCurrency: 281.3016442693628
- },
- {
- allocationInPercentage: 0.010831709166,
- name: 'ALPHABET INC CLASS C',
- valueInBaseCurrency: 249.98719145833246
- },
- {
- allocationInPercentage: 0.010813551981,
- name: 'TESLA INC',
- valueInBaseCurrency: 249.56813813873381
- },
- {
- allocationInPercentage: 0.009934819182,
- name: 'FACEBOOK CLASS A INC',
- valueInBaseCurrency: 229.28768737165962
- },
- {
- allocationInPercentage: 0.007403227621000001,
- name: 'BERKSHIRE HATHAWAY INC CLASS B',
- valueInBaseCurrency: 170.8605772494153
- },
- {
- allocationInPercentage: 0.007076883908,
- name: 'ELI LILLY',
- valueInBaseCurrency: 163.32882514892185
- },
- {
- allocationInPercentage: 0.006844271583,
- name: 'EXXON MOBIL CORP',
- valueInBaseCurrency: 157.96031857861325
- },
- {
- allocationInPercentage: 0.006718061670999999,
- name: 'UNITEDHEALTH GROUP INC',
- valueInBaseCurrency: 155.0474946695187
- },
- {
- allocationInPercentage: 0.006456949621,
- name: 'JPMORGAN CHASE & CO',
- valueInBaseCurrency: 149.02123722158794
- },
- {
- allocationInPercentage: 0.006293890054,
- name: 'TAIWAN SEMICONDUCTOR MANUFACTURING',
- valueInBaseCurrency: 145.25795272326576
- },
- {
- allocationInPercentage: 0.00600392555,
- name: 'VISA INC CLASS A',
- valueInBaseCurrency: 138.56580369427397
- }
- ],
investment: 0.13346122254229614,
name: 'Vanguard FTSE All-World UCITS ETF',
netPerformance: 4438.993935069568,
@@ -1194,6 +1199,80 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.03598477442100562,
assetClass: 'EQUITY',
+ assetProfile: {
+ holdings: [
+ {
+ allocationInPercentage: 0.051778373,
+ name: 'APPLE INC',
+ valueInBaseCurrency: 458.1016731945994
+ },
+ {
+ allocationInPercentage: 0.0403267055,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: 356.78469974280296
+ },
+ {
+ allocationInPercentage: 0.0221895862,
+ name: 'AMAZON COM INC',
+ valueInBaseCurrency: 196.3191575315778
+ },
+ {
+ allocationInPercentage: 0.0208100035,
+ name: 'NVIDIA CORP',
+ valueInBaseCurrency: 184.1134989416425
+ },
+ {
+ allocationInPercentage: 0.0139820061,
+ name: 'ALPHABET INC CLASS A',
+ valueInBaseCurrency: 123.70377858390985
+ },
+ {
+ allocationInPercentage: 0.0126263246,
+ name: 'ALPHABET INC CLASS C',
+ valueInBaseCurrency: 111.70958240727516
+ },
+ {
+ allocationInPercentage: 0.0121596126,
+ name: 'TESLA INC',
+ valueInBaseCurrency: 107.58041542669048
+ },
+ {
+ allocationInPercentage: 0.0114079282,
+ name: 'FACEBOOK CLASS A INC',
+ valueInBaseCurrency: 100.92999631533141
+ },
+ {
+ allocationInPercentage: 0.0081570352,
+ name: 'BERKSHIRE HATHAWAY INC CLASS B',
+ valueInBaseCurrency: 72.16819024860523
+ },
+ {
+ allocationInPercentage: 0.0079471416,
+ name: 'EXXON MOBIL CORP',
+ valueInBaseCurrency: 70.31118695201964
+ },
+ {
+ allocationInPercentage: 0.0078190388,
+ name: 'ELI LILLY',
+ valueInBaseCurrency: 69.1778159397456
+ },
+ {
+ allocationInPercentage: 0.0077121293,
+ name: 'UNITEDHEALTH GROUP INC',
+ valueInBaseCurrency: 68.23194958681098
+ },
+ {
+ allocationInPercentage: 0.0074484861,
+ name: 'JPMORGAN CHASE & CO',
+ valueInBaseCurrency: 65.89940447098863
+ },
+ {
+ allocationInPercentage: 0.006978079,
+ name: 'VISA INC CLASS A',
+ valueInBaseCurrency: 61.73754562709217
+ }
+ ]
+ },
assetSubClass: 'ETF',
countries: [
{
@@ -1342,78 +1421,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3474381850624522,
grossPerformancePercentWithCurrencyEffect: 0.28744846894552306,
grossPerformanceWithCurrencyEffect: 1975.348026988124,
- holdings: [
- {
- allocationInPercentage: 0.051778373,
- name: 'APPLE INC',
- valueInBaseCurrency: 458.1016731945994
- },
- {
- allocationInPercentage: 0.0403267055,
- name: 'MICROSOFT CORP',
- valueInBaseCurrency: 356.78469974280296
- },
- {
- allocationInPercentage: 0.0221895862,
- name: 'AMAZON COM INC',
- valueInBaseCurrency: 196.3191575315778
- },
- {
- allocationInPercentage: 0.0208100035,
- name: 'NVIDIA CORP',
- valueInBaseCurrency: 184.1134989416425
- },
- {
- allocationInPercentage: 0.0139820061,
- name: 'ALPHABET INC CLASS A',
- valueInBaseCurrency: 123.70377858390985
- },
- {
- allocationInPercentage: 0.0126263246,
- name: 'ALPHABET INC CLASS C',
- valueInBaseCurrency: 111.70958240727516
- },
- {
- allocationInPercentage: 0.0121596126,
- name: 'TESLA INC',
- valueInBaseCurrency: 107.58041542669048
- },
- {
- allocationInPercentage: 0.0114079282,
- name: 'FACEBOOK CLASS A INC',
- valueInBaseCurrency: 100.92999631533141
- },
- {
- allocationInPercentage: 0.0081570352,
- name: 'BERKSHIRE HATHAWAY INC CLASS B',
- valueInBaseCurrency: 72.16819024860523
- },
- {
- allocationInPercentage: 0.0079471416,
- name: 'EXXON MOBIL CORP',
- valueInBaseCurrency: 70.31118695201964
- },
- {
- allocationInPercentage: 0.0078190388,
- name: 'ELI LILLY',
- valueInBaseCurrency: 69.1778159397456
- },
- {
- allocationInPercentage: 0.0077121293,
- name: 'UNITEDHEALTH GROUP INC',
- valueInBaseCurrency: 68.23194958681098
- },
- {
- allocationInPercentage: 0.0074484861,
- name: 'JPMORGAN CHASE & CO',
- valueInBaseCurrency: 65.89940447098863
- },
- {
- allocationInPercentage: 0.006978079,
- name: 'VISA INC CLASS A',
- valueInBaseCurrency: 61.73754562709217
- }
- ],
investment: 0.04725441287200783,
name: 'Xtrackers MSCI World UCITS ETF 1C',
netPerformance: 2247.935728632002,
@@ -1454,6 +1461,7 @@ describe('redactAttributes', () => {
currency: 'USD',
allocationInPercentage: 0.20291717628620132,
assetClass: 'LIQUIDITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'CASH',
countries: [],
dividend: 0,
@@ -1461,7 +1469,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0,
grossPerformancePercentWithCurrencyEffect: 0,
grossPerformanceWithCurrencyEffect: 0,
- holdings: [],
investment: 0.35904695492648864,
marketPrice: 0,
name: 'USD',
@@ -1637,6 +1644,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.044900865255793135,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -1653,7 +1661,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3183066634822068,
grossPerformancePercentWithCurrencyEffect: 0.3183066634822068,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Apple Inc',
netPerformance: null,
@@ -1689,6 +1696,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.026912563036519527,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{ code: 'DE', weight: 1, continent: 'Europe', name: 'Germany' }
@@ -1700,7 +1708,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3719230057375532,
grossPerformancePercentWithCurrencyEffect: 0.2650716044872953,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Allianz SE',
netPerformance: null,
@@ -1736,6 +1743,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.07646101417126275,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -1752,7 +1760,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.8594552890963852,
grossPerformancePercentWithCurrencyEffect: 0.8594552890963852,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Amazon.com, Inc.',
netPerformance: null,
@@ -1794,6 +1801,7 @@ describe('redactAttributes', () => {
],
allocationInPercentage: 0.15042891393226654,
assetClass: 'LIQUIDITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'CRYPTOCURRENCY',
countries: [],
dataSource: 'COINGECKO',
@@ -1803,7 +1811,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 17.4925166352,
grossPerformancePercentWithCurrencyEffect: 17.4925166352,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Bitcoin',
netPerformance: null,
@@ -1845,6 +1852,7 @@ describe('redactAttributes', () => {
],
allocationInPercentage: 0.009076749759365777,
assetClass: 'FIXED_INCOME',
+ assetProfile: { holdings: [] },
assetSubClass: 'BOND',
countries: [],
dataSource: 'MANUAL',
@@ -1854,7 +1862,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0,
grossPerformancePercentWithCurrencyEffect: -0.06153834320225245,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Bondora Go & Grow',
netPerformance: null,
@@ -1896,6 +1903,7 @@ describe('redactAttributes', () => {
],
allocationInPercentage: 0.09095764645669335,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'ETF',
countries: [
{
@@ -1958,7 +1966,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.27579517683678895,
grossPerformancePercentWithCurrencyEffect: 0.458553421589667,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'frankly Extreme 95 Index',
netPerformance: null,
@@ -1994,6 +2001,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.05222646409742627,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -2010,7 +2018,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.7865431171216295,
grossPerformancePercentWithCurrencyEffect: 0.7865431171216295,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Microsoft Corporation',
netPerformance: null,
@@ -2046,6 +2053,7 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.1589050142378352,
assetClass: 'EQUITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'STOCK',
countries: [
{
@@ -2062,7 +2070,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 17.184314638161936,
grossPerformancePercentWithCurrencyEffect: 17.184314638161936,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
name: 'Tesla, Inc.',
netPerformance: null,
@@ -2098,6 +2105,85 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.057358979326040366,
assetClass: 'EQUITY',
+ assetProfile: {
+ holdings: [
+ {
+ allocationInPercentage: 0.06099941636982121,
+ name: 'APPLE INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.05862464529372787,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.05156070760128074,
+ name: 'NVIDIA CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.03301535551128066,
+ name: 'AMAZON COM INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01962204914568647,
+ name: 'FACEBOOK CLASS A INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01902835637666313,
+ name: 'ALPHABET INC CLASS A',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01555676306627245,
+ name: 'ALPHABET INC CLASS C',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01463100485016827,
+ name: 'BERKSHIRE HATHAWAY INC CLASS B',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01403731208114493,
+ name: 'BROADCOM INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01297067761476403,
+ name: 'ELI LILLY',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0118637927911612,
+ name: 'TESLA INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01152166475477487,
+ name: 'JPMORGAN CHASE & CO',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0100324015375638,
+ name: 'EXXON MOBIL CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.01000221376964736,
+ name: 'UNITEDHEALTH GROUP INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.007818631890358146,
+ name: 'VISA INC CLASS A',
+ valueInBaseCurrency: null
+ }
+ ]
+ },
assetSubClass: 'ETF',
countries: [
{
@@ -2144,83 +2230,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.8832083851170418,
grossPerformancePercentWithCurrencyEffect: 0.8832083851170418,
grossPerformanceWithCurrencyEffect: null,
- holdings: [
- {
- allocationInPercentage: 0.06099941636982121,
- name: 'APPLE INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.05862464529372787,
- name: 'MICROSOFT CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.05156070760128074,
- name: 'NVIDIA CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.03301535551128066,
- name: 'AMAZON COM INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01962204914568647,
- name: 'FACEBOOK CLASS A INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01902835637666313,
- name: 'ALPHABET INC CLASS A',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01555676306627245,
- name: 'ALPHABET INC CLASS C',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01463100485016827,
- name: 'BERKSHIRE HATHAWAY INC CLASS B',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01403731208114493,
- name: 'BROADCOM INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01297067761476403,
- name: 'ELI LILLY',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0118637927911612,
- name: 'TESLA INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01152166475477487,
- name: 'JPMORGAN CHASE & CO',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0100324015375638,
- name: 'EXXON MOBIL CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.01000221376964736,
- name: 'UNITEDHEALTH GROUP INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.007818631890358146,
- name: 'VISA INC CLASS A',
- valueInBaseCurrency: null
- }
- ],
investment: null,
name: 'Vanguard Total Stock Market Index Fund ETF Shares',
netPerformance: null,
@@ -2270,6 +2279,85 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.09386983901959013,
assetClass: 'EQUITY',
+ assetProfile: {
+ holdings: [
+ {
+ allocationInPercentage: 0.042520261085,
+ name: 'APPLE INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.037017038038,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.018861883836,
+ name: 'AMAZON COM INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.017806548325,
+ name: 'NVIDIA CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.012188534864,
+ name: 'ALPHABET INC CLASS A',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.010831709166,
+ name: 'ALPHABET INC CLASS C',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.010813551981,
+ name: 'TESLA INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.009934819182,
+ name: 'FACEBOOK CLASS A INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.007403227621000001,
+ name: 'BERKSHIRE HATHAWAY INC CLASS B',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.007076883908,
+ name: 'ELI LILLY',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.006844271583,
+ name: 'EXXON MOBIL CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.006718061670999999,
+ name: 'UNITEDHEALTH GROUP INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.006456949621,
+ name: 'JPMORGAN CHASE & CO',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.006293890054,
+ name: 'TAIWAN SEMICONDUCTOR MANUFACTURING',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.00600392555,
+ name: 'VISA INC CLASS A',
+ valueInBaseCurrency: null
+ }
+ ]
+ },
assetSubClass: 'ETF',
countries: [
{
@@ -2539,83 +2627,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3683200415015591,
grossPerformancePercentWithCurrencyEffect: 0.5806366182968891,
grossPerformanceWithCurrencyEffect: null,
- holdings: [
- {
- allocationInPercentage: 0.042520261085,
- name: 'APPLE INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.037017038038,
- name: 'MICROSOFT CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.018861883836,
- name: 'AMAZON COM INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.017806548325,
- name: 'NVIDIA CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.012188534864,
- name: 'ALPHABET INC CLASS A',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.010831709166,
- name: 'ALPHABET INC CLASS C',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.010813551981,
- name: 'TESLA INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.009934819182,
- name: 'FACEBOOK CLASS A INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.007403227621000001,
- name: 'BERKSHIRE HATHAWAY INC CLASS B',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.007076883908,
- name: 'ELI LILLY',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.006844271583,
- name: 'EXXON MOBIL CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.006718061670999999,
- name: 'UNITEDHEALTH GROUP INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.006456949621,
- name: 'JPMORGAN CHASE & CO',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.006293890054,
- name: 'TAIWAN SEMICONDUCTOR MANUFACTURING',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.00600392555,
- name: 'VISA INC CLASS A',
- valueInBaseCurrency: null
- }
- ],
investment: null,
name: 'Vanguard FTSE All-World UCITS ETF',
netPerformance: null,
@@ -2670,6 +2681,80 @@ describe('redactAttributes', () => {
tags: [],
allocationInPercentage: 0.03598477442100562,
assetClass: 'EQUITY',
+ assetProfile: {
+ holdings: [
+ {
+ allocationInPercentage: 0.051778373,
+ name: 'APPLE INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0403267055,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0221895862,
+ name: 'AMAZON COM INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0208100035,
+ name: 'NVIDIA CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0139820061,
+ name: 'ALPHABET INC CLASS A',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0126263246,
+ name: 'ALPHABET INC CLASS C',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0121596126,
+ name: 'TESLA INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0114079282,
+ name: 'FACEBOOK CLASS A INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0081570352,
+ name: 'BERKSHIRE HATHAWAY INC CLASS B',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0079471416,
+ name: 'EXXON MOBIL CORP',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0078190388,
+ name: 'ELI LILLY',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0077121293,
+ name: 'UNITEDHEALTH GROUP INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.0074484861,
+ name: 'JPMORGAN CHASE & CO',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.006978079,
+ name: 'VISA INC CLASS A',
+ valueInBaseCurrency: null
+ }
+ ]
+ },
assetSubClass: 'ETF',
countries: [
{
@@ -2818,78 +2903,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0.3474381850624522,
grossPerformancePercentWithCurrencyEffect: 0.28744846894552306,
grossPerformanceWithCurrencyEffect: null,
- holdings: [
- {
- allocationInPercentage: 0.051778373,
- name: 'APPLE INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0403267055,
- name: 'MICROSOFT CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0221895862,
- name: 'AMAZON COM INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0208100035,
- name: 'NVIDIA CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0139820061,
- name: 'ALPHABET INC CLASS A',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0126263246,
- name: 'ALPHABET INC CLASS C',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0121596126,
- name: 'TESLA INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0114079282,
- name: 'FACEBOOK CLASS A INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0081570352,
- name: 'BERKSHIRE HATHAWAY INC CLASS B',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0079471416,
- name: 'EXXON MOBIL CORP',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0078190388,
- name: 'ELI LILLY',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0077121293,
- name: 'UNITEDHEALTH GROUP INC',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.0074484861,
- name: 'JPMORGAN CHASE & CO',
- valueInBaseCurrency: null
- },
- {
- allocationInPercentage: 0.006978079,
- name: 'VISA INC CLASS A',
- valueInBaseCurrency: null
- }
- ],
investment: null,
name: 'Xtrackers MSCI World UCITS ETF 1C',
netPerformance: null,
@@ -2930,6 +2943,7 @@ describe('redactAttributes', () => {
currency: 'USD',
allocationInPercentage: 0.20291717628620132,
assetClass: 'LIQUIDITY',
+ assetProfile: { holdings: [] },
assetSubClass: 'CASH',
countries: [],
dividend: null,
@@ -2937,7 +2951,6 @@ describe('redactAttributes', () => {
grossPerformancePercent: 0,
grossPerformancePercentWithCurrencyEffect: 0,
grossPerformanceWithCurrencyEffect: null,
- holdings: [],
investment: null,
marketPrice: 0,
name: 'USD',
@@ -3237,4 +3250,101 @@ describe('redactAttributes', () => {
]
});
});
+
+ // The type makes sure that the object keeps the shape of the response, in
+ // which the holdings of an ETF are part of its asset profile
+ it('should redact the values of the holdings of an ETF', () => {
+ expect(
+ redactPaths({
+ object: {
+ holdings: [
+ {
+ activitiesCount: 5,
+ allocationInPercentage: 0.057358979326040366,
+ assetProfile: {
+ assetClass: 'EQUITY',
+ assetSubClass: 'ETF',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ holdings: [
+ {
+ allocationInPercentage: 0.06099941636982121,
+ name: 'APPLE INC',
+ valueInBaseCurrency: 860.2442693554036
+ },
+ {
+ allocationInPercentage: 0.05862464529372787,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: 826.7540602547973
+ }
+ ],
+ name: 'Vanguard Total Stock Market Index Fund ETF Shares',
+ sectors: [],
+ symbol: 'VTI'
+ },
+ dateOfFirstActivity: new Date('2019-02-28T23:00:00.000Z'),
+ dividend: 0,
+ grossPerformance: 5856.3,
+ grossPerformancePercent: 0.8832083851170418,
+ grossPerformancePercentWithCurrencyEffect: 0.8832083851170418,
+ grossPerformanceWithCurrencyEffect: 5856.3,
+ investment: 8246.2,
+ marketPrice: 282.05,
+ netPerformance: 5756.8,
+ netPerformancePercent: 0.8682024540139314,
+ netPerformancePercentWithCurrencyEffect: 0.8328704068843998,
+ netPerformanceWithCurrencyEffect: 5756.8,
+ quantity: 50,
+ valueInBaseCurrency: 14102.5
+ }
+ ]
+ } satisfies Pick,
+ paths: DEFAULT_REDACTED_PATHS
+ })
+ ).toStrictEqual({
+ holdings: [
+ {
+ activitiesCount: 5,
+ allocationInPercentage: 0.057358979326040366,
+ assetProfile: {
+ assetClass: 'EQUITY',
+ assetSubClass: 'ETF',
+ countries: [],
+ currency: 'USD',
+ dataSource: 'YAHOO',
+ holdings: [
+ {
+ allocationInPercentage: 0.06099941636982121,
+ name: 'APPLE INC',
+ valueInBaseCurrency: null
+ },
+ {
+ allocationInPercentage: 0.05862464529372787,
+ name: 'MICROSOFT CORP',
+ valueInBaseCurrency: null
+ }
+ ],
+ name: 'Vanguard Total Stock Market Index Fund ETF Shares',
+ sectors: [],
+ symbol: 'VTI'
+ },
+ dateOfFirstActivity: '2019-02-28T23:00:00.000Z',
+ dividend: null,
+ grossPerformance: null,
+ grossPerformancePercent: 0.8832083851170418,
+ grossPerformancePercentWithCurrencyEffect: 0.8832083851170418,
+ grossPerformanceWithCurrencyEffect: null,
+ investment: null,
+ marketPrice: 282.05,
+ netPerformance: null,
+ netPerformancePercent: 0.8682024540139314,
+ netPerformancePercentWithCurrencyEffect: 0.8328704068843998,
+ netPerformanceWithCurrencyEffect: null,
+ quantity: null,
+ valueInBaseCurrency: null
+ }
+ ]
+ });
+ });
});
diff --git a/libs/common/src/lib/config.ts b/libs/common/src/lib/config.ts
index beedb741cb..03d36f577b 100644
--- a/libs/common/src/lib/config.ts
+++ b/libs/common/src/lib/config.ts
@@ -158,10 +158,10 @@ export const DEFAULT_REDACTED_PATHS = [
'grossPerformance',
'grossPerformanceWithCurrencyEffect',
'historicalData[*].quantity',
+ 'holdings[*].assetProfile.holdings[*].valueInBaseCurrency',
'holdings[*].dividend',
'holdings[*].grossPerformance',
'holdings[*].grossPerformanceWithCurrencyEffect',
- 'holdings[*].holdings[*].valueInBaseCurrency',
'holdings[*].investment',
'holdings[*].netPerformance',
'holdings[*].netPerformanceWithCurrencyEffect',
From f46f77f352d50728361d62ed73613d69acf67e80 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Szymon=20=C5=81=C4=85giewka?=
Date: Wed, 30 Sep 2026 10:15:01 +0200
Subject: [PATCH 3/3] Task/migrate from lodash to lodash-es (#7850)
* Migrate from lodash to lodash-es
* Update changelog
---
CHANGELOG.md | 1 +
.../account-balance.service.ts | 2 +-
apps/api/src/app/account/account.service.ts | 2 +-
.../app/activities/activities-filter.dto.ts | 2 +-
.../src/app/activities/activities.service.ts | 2 +-
apps/api/src/app/asset/asset.controller.ts | 2 +-
.../asset-profiles/asset-profiles.service.ts | 2 +-
.../benchmarks/benchmarks.service.ts | 2 +-
.../ghostfolio/ghostfolio.service.ts | 2 +-
apps/api/src/app/export/export.service.ts | 2 +-
apps/api/src/app/export/get-export.dto.ts | 2 +-
apps/api/src/app/import/import.service.ts | 2 +-
apps/api/src/app/info/info.service.ts | 2 +-
.../calculator/portfolio-calculator.ts | 2 +-
.../calculator/roai/portfolio-calculator.ts | 2 +-
.../src/app/portfolio/current-rate.service.ts | 2 +-
.../src/app/portfolio/portfolio.service.ts | 2 +-
apps/api/src/app/symbol/symbol.controller.ts | 2 +-
apps/api/src/app/user/user.controller.ts | 2 +-
apps/api/src/app/user/user.service.ts | 2 +-
apps/api/src/dtos/filter.dto.ts | 2 +-
apps/api/src/helper/activity.helper.ts | 2 +-
apps/api/src/helper/object.helper.ts | 2 +-
apps/api/src/models/rule.ts | 2 +-
.../services/benchmark/benchmark.service.ts | 2 +-
.../data-provider/data-provider.service.ts | 2 +-
.../eod-historical-data.service.ts | 2 +-
.../financial-modeling-prep.service.ts | 2 +-
.../yahoo-finance/yahoo-finance.service.ts | 2 +-
.../exchange-rate-data.service.ts | 2 +-
.../data-gathering/data-gathering.service.ts | 2 +-
.../twitter-bot/twitter-bot.service.ts | 2 +-
apps/client/jest.config.ts | 2 +-
.../account-detail-dialog.component.ts | 2 +-
.../admin-jobs/admin-jobs.component.ts | 2 +-
.../asset-profile-dialog.component.ts | 2 +-
.../admin-settings.component.ts | 2 +-
.../holding-detail-dialog.component.ts | 2 +-
.../portfolio-performance.component.ts | 2 +-
.../portfolio-summary.component.ts | 2 +-
.../src/app/pages/api/api-page.component.ts | 2 +-
.../import-activities-dialog.component.ts | 2 +-
.../allocations/allocations-page.component.ts | 2 +-
.../analysis/analysis-page.component.ts | 2 +-
.../portfolio/fire/fire-page.component.ts | 2 +-
.../app/services/import-activities.service.ts | 2 +-
eslint.config.cjs | 19 ++++++++++++++++++-
jest.preset.js | 5 ++++-
libs/common/src/lib/calculation-helper.ts | 2 +-
.../common/src/lib/dtos/create-account.dto.ts | 2 +-
libs/common/src/lib/dtos/create-order.dto.ts | 2 +-
.../common/src/lib/dtos/update-account.dto.ts | 2 +-
libs/common/src/lib/dtos/update-order.dto.ts | 2 +-
libs/common/src/lib/helper.ts | 2 +-
libs/ui/jest.config.ts | 2 +-
.../account-balances.component.ts | 2 +-
.../activities-filter.component.ts | 2 +-
.../src/lib/assistant/assistant.component.ts | 2 +-
.../src/lib/benchmark/benchmark.component.ts | 2 +-
.../fire-calculator.component.ts | 2 +-
...cal-market-data-editor-dialog.component.ts | 2 +-
.../lib/notifications/notification.service.ts | 2 +-
libs/ui/src/lib/services/admin.service.ts | 2 +-
libs/ui/src/lib/services/data.service.ts | 2 +-
.../symbol-autocomplete.component.ts | 2 +-
.../top-holdings/top-holdings.component.ts | 2 +-
.../treemap-chart/treemap-chart.component.ts | 2 +-
libs/ui/src/lib/value/value.component.ts | 2 +-
package-lock.json | 15 ++++++++++++---
package.json | 4 ++--
70 files changed, 102 insertions(+), 72 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 4bbf0a08dd..c9937fcb31 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Extended the emergency fund dialog in the portfolio summary to include the currency suffix
- Migrated the client to the code generated by the new `prisma-client` generator of _Prisma_
+- Migrated from `lodash` to `lodash-es`
### Fixed
diff --git a/apps/api/src/app/account-balance/account-balance.service.ts b/apps/api/src/app/account-balance/account-balance.service.ts
index 3823498df3..ad990c66bd 100644
--- a/apps/api/src/app/account-balance/account-balance.service.ts
+++ b/apps/api/src/app/account-balance/account-balance.service.ts
@@ -24,7 +24,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { AccountBalance, Prisma } from '@prisma/client';
import { Big } from 'big.js';
import { endOfToday, format, min, parseISO } from 'date-fns';
-import { groupBy } from 'lodash';
+import { groupBy } from 'lodash-es';
@Injectable()
export class AccountBalanceService {
diff --git a/apps/api/src/app/account/account.service.ts b/apps/api/src/app/account/account.service.ts
index 59315602a8..d1a895a5a3 100644
--- a/apps/api/src/app/account/account.service.ts
+++ b/apps/api/src/app/account/account.service.ts
@@ -28,7 +28,7 @@ import {
} from '@prisma/client';
import { Big } from 'big.js';
import { format } from 'date-fns';
-import { groupBy, isNil } from 'lodash';
+import { groupBy, isNil } from 'lodash-es';
import { CashDetails } from './interfaces/cash-details.interface';
diff --git a/apps/api/src/app/activities/activities-filter.dto.ts b/apps/api/src/app/activities/activities-filter.dto.ts
index 0c56aacc85..17385148cc 100644
--- a/apps/api/src/app/activities/activities-filter.dto.ts
+++ b/apps/api/src/app/activities/activities-filter.dto.ts
@@ -5,7 +5,7 @@ import { DateRange } from '@ghostfolio/common/types';
import { Type as ActivityType } from '@prisma/client';
import { Transform, TransformFnParams } from 'class-transformer';
import { IsEnum, IsOptional, Matches } from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class ActivitiesFilterDto extends FilterDto {
@IsEnum(ActivityType, { each: true })
diff --git a/apps/api/src/app/activities/activities.service.ts b/apps/api/src/app/activities/activities.service.ts
index ecc2296a90..59d1ba9c33 100644
--- a/apps/api/src/app/activities/activities.service.ts
+++ b/apps/api/src/app/activities/activities.service.ts
@@ -60,7 +60,7 @@ import {
Type as ActivityType
} from '@prisma/client';
import { Big } from 'big.js';
-import { groupBy, uniqBy } from 'lodash';
+import { groupBy, uniqBy } from 'lodash-es';
import { randomUUID } from 'node:crypto';
@Injectable()
diff --git a/apps/api/src/app/asset/asset.controller.ts b/apps/api/src/app/asset/asset.controller.ts
index 49afb43d71..352d3e18b1 100644
--- a/apps/api/src/app/asset/asset.controller.ts
+++ b/apps/api/src/app/asset/asset.controller.ts
@@ -5,7 +5,7 @@ import type { AssetResponse } from '@ghostfolio/common/interfaces';
import { Controller, Get, Param, UseInterceptors } from '@nestjs/common';
import { DataSource } from '@prisma/client';
-import { pick } from 'lodash';
+import { pick } from 'lodash-es';
@Controller('asset')
export class AssetController {
diff --git a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts
index e9aad6911f..4a2507e697 100644
--- a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts
+++ b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.service.ts
@@ -29,7 +29,7 @@ import { MarketDataPreset } from '@ghostfolio/common/types';
import { Injectable, Logger, NotFoundException } from '@nestjs/common';
import { EventEmitter2 } from '@nestjs/event-emitter';
import { AssetClass, AssetSubClass, DataSource, Prisma } from '@prisma/client';
-import { groupBy } from 'lodash';
+import { groupBy } from 'lodash-es';
@Injectable()
export class AssetProfilesService {
diff --git a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts
index beff7ffa60..908db59b7f 100644
--- a/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts
+++ b/apps/api/src/app/endpoints/benchmarks/benchmarks.service.ts
@@ -14,7 +14,7 @@ import { DateRange } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { format, isSameDay } from 'date-fns';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
@Injectable()
export class BenchmarksService {
diff --git a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts
index ec0eeeb868..4042241449 100644
--- a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts
+++ b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.service.ts
@@ -40,7 +40,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client';
import { Big } from 'big.js';
import { addMilliseconds, isBefore } from 'date-fns';
-import { isEmpty } from 'lodash';
+import { isEmpty } from 'lodash-es';
@Injectable()
export class GhostfolioService {
diff --git a/apps/api/src/app/export/export.service.ts b/apps/api/src/app/export/export.service.ts
index 35db209935..db08f62052 100644
--- a/apps/api/src/app/export/export.service.ts
+++ b/apps/api/src/app/export/export.service.ts
@@ -11,7 +11,7 @@ import {
import { Injectable } from '@nestjs/common';
import { Platform, Prisma, Type as ActivityType } from '@prisma/client';
-import { groupBy, uniqBy } from 'lodash';
+import { groupBy, uniqBy } from 'lodash-es';
@Injectable()
export class ExportService {
diff --git a/apps/api/src/app/export/get-export.dto.ts b/apps/api/src/app/export/get-export.dto.ts
index 5fc3c81baa..524c357112 100644
--- a/apps/api/src/app/export/get-export.dto.ts
+++ b/apps/api/src/app/export/get-export.dto.ts
@@ -2,7 +2,7 @@ import { ActivitiesFilterDto } from '@ghostfolio/api/app/activities/activities-f
import { Transform, TransformFnParams } from 'class-transformer';
import { IsOptional, IsUUID } from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class GetExportDto extends ActivitiesFilterDto {
@IsOptional()
diff --git a/apps/api/src/app/import/import.service.ts b/apps/api/src/app/import/import.service.ts
index 5f202f4ac4..5afa4c33dd 100644
--- a/apps/api/src/app/import/import.service.ts
+++ b/apps/api/src/app/import/import.service.ts
@@ -47,7 +47,7 @@ import { Account, DataSource, Prisma } from '@prisma/client';
import { Big } from 'big.js';
import { isISIN } from 'class-validator';
import { isSameSecond, parseISO } from 'date-fns';
-import { omit, uniqBy } from 'lodash';
+import { omit, uniqBy } from 'lodash-es';
import { randomUUID } from 'node:crypto';
import { ImportValidationError } from './errors/import-validation.error';
diff --git a/apps/api/src/app/info/info.service.ts b/apps/api/src/app/info/info.service.ts
index a0759b1698..2a7382446c 100644
--- a/apps/api/src/app/info/info.service.ts
+++ b/apps/api/src/app/info/info.service.ts
@@ -26,7 +26,7 @@ import { Injectable } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { MarketData } from '@prisma/client';
import { subDays } from 'date-fns';
-import { isNil } from 'lodash';
+import { isNil } from 'lodash-es';
@Injectable()
export class InfoService {
diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
index d868b65b3f..e03b530258 100644
--- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
+++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
@@ -72,7 +72,7 @@ import {
startOfYear,
subDays
} from 'date-fns';
-import { groupBy, sortBy, uniqBy } from 'lodash';
+import { groupBy, sortBy, uniqBy } from 'lodash-es';
export abstract class PortfolioCalculator {
protected static readonly ENABLE_LOGGING = false;
diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts
index 2b7b4e6dce..c0b7337350 100644
--- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts
+++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts
@@ -32,7 +32,7 @@ import {
isBefore,
isThisYear
} from 'date-fns';
-import { sum } from 'lodash';
+import { sum } from 'lodash-es';
export class RoaiPortfolioCalculator extends PortfolioCalculator {
protected calculateOverallPerformance(
diff --git a/apps/api/src/app/portfolio/current-rate.service.ts b/apps/api/src/app/portfolio/current-rate.service.ts
index 79363c6344..80d37259a4 100644
--- a/apps/api/src/app/portfolio/current-rate.service.ts
+++ b/apps/api/src/app/portfolio/current-rate.service.ts
@@ -14,7 +14,7 @@ import {
import { Injectable } from '@nestjs/common';
import { isBefore, isToday } from 'date-fns';
-import { isEmpty, uniqBy } from 'lodash';
+import { isEmpty, uniqBy } from 'lodash-es';
import { GetValueObject } from './interfaces/get-value-object.interface';
import { GetValuesObject } from './interfaces/get-values-object.interface';
diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts
index 7350f5fc01..72c5b5946a 100644
--- a/apps/api/src/app/portfolio/portfolio.service.ts
+++ b/apps/api/src/app/portfolio/portfolio.service.ts
@@ -104,7 +104,7 @@ import {
set,
startOfDay
} from 'date-fns';
-import { groupBy } from 'lodash';
+import { groupBy } from 'lodash-es';
import { PortfolioCalculator } from './calculator/portfolio-calculator';
import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory';
diff --git a/apps/api/src/app/symbol/symbol.controller.ts b/apps/api/src/app/symbol/symbol.controller.ts
index 9d8abb47ba..cf26d39d54 100644
--- a/apps/api/src/app/symbol/symbol.controller.ts
+++ b/apps/api/src/app/symbol/symbol.controller.ts
@@ -25,7 +25,7 @@ import { AuthGuard } from '@nestjs/passport';
import { DataSource } from '@prisma/client';
import { isValid, parseISO } from 'date-fns';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
-import { isEmpty } from 'lodash';
+import { isEmpty } from 'lodash-es';
import { GetLookupDto } from './get-lookup.dto';
import { SymbolService } from './symbol.service';
diff --git a/apps/api/src/app/user/user.controller.ts b/apps/api/src/app/user/user.controller.ts
index ae9e7d680b..32ac353351 100644
--- a/apps/api/src/app/user/user.controller.ts
+++ b/apps/api/src/app/user/user.controller.ts
@@ -53,7 +53,7 @@ import { AuthGuard } from '@nestjs/passport';
import { Throttle } from '@nestjs/throttler';
import { User as UserModel } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes';
-import { merge, size } from 'lodash';
+import { merge, size } from 'lodash-es';
import { UserService } from './user.service';
diff --git a/apps/api/src/app/user/user.service.ts b/apps/api/src/app/user/user.service.ts
index a74e32ca93..2e54a7ddc3 100644
--- a/apps/api/src/app/user/user.service.ts
+++ b/apps/api/src/app/user/user.service.ts
@@ -46,7 +46,7 @@ import { EventEmitter2 } from '@nestjs/event-emitter';
import { InjectThrottlerStorage, ThrottlerStorage } from '@nestjs/throttler';
import { Prisma, Role, User } from '@prisma/client';
import { differenceInDays, subDays } from 'date-fns';
-import { isNil, without } from 'lodash';
+import { isNil, without } from 'lodash-es';
import { createHmac } from 'node:crypto';
@Injectable()
diff --git a/apps/api/src/dtos/filter.dto.ts b/apps/api/src/dtos/filter.dto.ts
index 09206984ab..84d9ffc0d0 100644
--- a/apps/api/src/dtos/filter.dto.ts
+++ b/apps/api/src/dtos/filter.dto.ts
@@ -9,7 +9,7 @@ import {
IsUUID,
MaxLength
} from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class FilterDto {
@IsOptional()
diff --git a/apps/api/src/helper/activity.helper.ts b/apps/api/src/helper/activity.helper.ts
index b281106c77..f7cb20505e 100644
--- a/apps/api/src/helper/activity.helper.ts
+++ b/apps/api/src/helper/activity.helper.ts
@@ -5,7 +5,7 @@ import {
import { Prisma, Type as ActivityType } from '@prisma/client';
import { endOfToday, isAfter } from 'date-fns';
-import { uniqBy } from 'lodash';
+import { uniqBy } from 'lodash-es';
export const WHERE_ACTIVITY_NOT_DRAFT: Prisma.OrderWhereInput = {
tags: {
diff --git a/apps/api/src/helper/object.helper.ts b/apps/api/src/helper/object.helper.ts
index 350d5fe04a..c040c5e0fc 100644
--- a/apps/api/src/helper/object.helper.ts
+++ b/apps/api/src/helper/object.helper.ts
@@ -1,6 +1,6 @@
import fastRedact from 'fast-redact';
import jsonpath from 'jsonpath';
-import { cloneDeep, isObject } from 'lodash';
+import { cloneDeep, isObject } from 'lodash-es';
export function hasNotDefinedValuesInObject(aObject: Object): boolean {
for (const key in aObject) {
diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts
index 4985b26477..f7f6c53637 100644
--- a/apps/api/src/models/rule.ts
+++ b/apps/api/src/models/rule.ts
@@ -7,7 +7,7 @@ import {
} from '@ghostfolio/common/interfaces';
import { Big } from 'big.js';
-import { groupBy } from 'lodash';
+import { groupBy } from 'lodash-es';
import { EvaluationResult } from './interfaces/evaluation-result.interface';
import { RuleInterface } from './interfaces/rule.interface';
diff --git a/apps/api/src/services/benchmark/benchmark.service.ts b/apps/api/src/services/benchmark/benchmark.service.ts
index 953939caac..4ea27b2f2e 100644
--- a/apps/api/src/services/benchmark/benchmark.service.ts
+++ b/apps/api/src/services/benchmark/benchmark.service.ts
@@ -23,7 +23,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client';
import { Big } from 'big.js';
import { addHours, isPast, subDays } from 'date-fns';
-import { round, uniqBy } from 'lodash';
+import { round, uniqBy } from 'lodash-es';
import ms from 'ms';
import { BenchmarkValue } from './interfaces/benchmark-value.interface';
diff --git a/apps/api/src/services/data-provider/data-provider.service.ts b/apps/api/src/services/data-provider/data-provider.service.ts
index 87c1e85c61..cfacab3231 100644
--- a/apps/api/src/services/data-provider/data-provider.service.ts
+++ b/apps/api/src/services/data-provider/data-provider.service.ts
@@ -42,7 +42,7 @@ import { Inject, Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { DataSource, MarketData, Prisma, SymbolProfile } from '@prisma/client';
import { Big } from 'big.js';
import { eachDayOfInterval, format, isValid } from 'date-fns';
-import { groupBy, isEmpty, isNumber, omit, uniqWith } from 'lodash';
+import { groupBy, isEmpty, isNumber, omit, uniqWith } from 'lodash-es';
import ms from 'ms';
import { AssetProfileInvalidError } from './errors/asset-profile-invalid.error';
diff --git a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
index 6bc003fc23..7dbb3b859c 100644
--- a/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
+++ b/apps/api/src/services/data-provider/eod-historical-data/eod-historical-data.service.ts
@@ -31,7 +31,7 @@ import {
SymbolProfile
} from '@prisma/client';
import { addDays, format, isSameDay, isToday } from 'date-fns';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
@Injectable()
export class EodHistoricalDataService
diff --git a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
index 7c840b5fc6..a8f1c6287c 100644
--- a/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
+++ b/apps/api/src/services/data-provider/financial-modeling-prep/financial-modeling-prep.service.ts
@@ -47,7 +47,7 @@ import {
isSameDay,
parseISO
} from 'date-fns';
-import { isArray, uniqBy } from 'lodash';
+import { isArray, uniqBy } from 'lodash-es';
@Injectable()
export class FinancialModelingPrepService
diff --git a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
index ca6357e257..d2b741d372 100644
--- a/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
+++ b/apps/api/src/services/data-provider/yahoo-finance/yahoo-finance.service.ts
@@ -24,7 +24,7 @@ import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client';
import { addDays, format, isSameDay } from 'date-fns';
import { ReasonPhrases, StatusCodes } from 'http-status-codes';
-import { uniqBy } from 'lodash';
+import { uniqBy } from 'lodash-es';
import YahooFinance from 'yahoo-finance2';
import type { ChartResultArray } from 'yahoo-finance2/modules/chart';
import type {
diff --git a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts
index 0d7e98e2e0..824149e74f 100644
--- a/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts
+++ b/apps/api/src/services/exchange-rate-data/exchange-rate-data.service.ts
@@ -26,7 +26,7 @@ import {
isToday,
subDays
} from 'date-fns';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import ms from 'ms';
import { ExchangeRatesByCurrency } from './interfaces/exchange-rate-data.interface';
diff --git a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts
index 4cbe6969ae..3a98757591 100644
--- a/apps/api/src/services/queues/data-gathering/data-gathering.service.ts
+++ b/apps/api/src/services/queues/data-gathering/data-gathering.service.ts
@@ -33,7 +33,7 @@ import { Inject, Injectable, Logger } from '@nestjs/common';
import { Prisma } from '@prisma/client';
import { Job, JobOptions, Queue } from 'bull';
import { format, min, subDays, subMilliseconds, subYears } from 'date-fns';
-import { isEmpty } from 'lodash';
+import { isEmpty } from 'lodash-es';
import ms, { StringValue } from 'ms';
@Injectable()
diff --git a/apps/api/src/services/twitter-bot/twitter-bot.service.ts b/apps/api/src/services/twitter-bot/twitter-bot.service.ts
index 2dbed82d21..6282b4363b 100644
--- a/apps/api/src/services/twitter-bot/twitter-bot.service.ts
+++ b/apps/api/src/services/twitter-bot/twitter-bot.service.ts
@@ -10,7 +10,7 @@ import {
import { Injectable, Logger, OnModuleInit } from '@nestjs/common';
import { isWeekend } from 'date-fns';
-import { round } from 'lodash';
+import { round } from 'lodash-es';
import { TwitterApi, TwitterApiReadWrite } from 'twitter-api-v2';
@Injectable()
diff --git a/apps/client/jest.config.ts b/apps/client/jest.config.ts
index 26d772e11f..d60a24ae4f 100644
--- a/apps/client/jest.config.ts
+++ b/apps/client/jest.config.ts
@@ -18,6 +18,6 @@ export default {
}
]
},
- transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'],
+ transformIgnorePatterns: ['node_modules/(?!.*.mjs$|lodash-es/)'],
preset: '../../jest.preset.js'
};
diff --git a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts
index b8c7f16dbc..44f7280473 100644
--- a/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts
+++ b/apps/client/src/app/components/account-detail-dialog/account-detail-dialog.component.ts
@@ -55,7 +55,7 @@ import {
readerOutline,
swapVerticalOutline
} from 'ionicons/icons';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { filter, forkJoin } from 'rxjs';
diff --git a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts
index fd90bff2c1..e8e3a21255 100644
--- a/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts
+++ b/apps/client/src/app/components/admin-jobs/admin-jobs.component.ts
@@ -49,7 +49,7 @@ import {
removeCircleOutline,
timeOutline
} from 'ionicons/icons';
-import { get } from 'lodash';
+import { get } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@Component({
diff --git a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
index 154211b918..ba119b565f 100644
--- a/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
+++ b/apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts
@@ -106,7 +106,7 @@ import {
serverOutline,
trashOutline
} from 'ionicons/icons';
-import { isBoolean } from 'lodash';
+import { isBoolean } from 'lodash-es';
import ms from 'ms';
import { EMPTY } from 'rxjs';
import { catchError } from 'rxjs/operators';
diff --git a/apps/client/src/app/components/admin-settings/admin-settings.component.ts b/apps/client/src/app/components/admin-settings/admin-settings.component.ts
index b0c3dc2d22..d49f3fb0aa 100644
--- a/apps/client/src/app/components/admin-settings/admin-settings.component.ts
+++ b/apps/client/src/app/components/admin-settings/admin-settings.component.ts
@@ -42,7 +42,7 @@ import { RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { ellipsisHorizontal, trashOutline } from 'ionicons/icons';
-import { get } from 'lodash';
+import { get } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { catchError, filter, of } from 'rxjs';
diff --git a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
index 4a16c1a4e2..8c3ec2206e 100644
--- a/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
+++ b/apps/client/src/app/components/holding-detail-dialog/holding-detail-dialog.component.ts
@@ -82,7 +82,7 @@ import {
swapVerticalOutline,
walletOutline
} from 'ionicons/icons';
-import { isNumber, round, uniqBy } from 'lodash';
+import { isNumber, round, uniqBy } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { filter, switchMap } from 'rxjs/operators';
diff --git a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts
index a48d77a2dd..4f7f35dd1e 100644
--- a/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts
+++ b/apps/client/src/app/components/portfolio-performance/portfolio-performance.component.ts
@@ -23,7 +23,7 @@ import { IonIcon } from '@ionic/angular/standalone';
import { CountUp } from 'countup.js';
import { addIcons } from 'ionicons';
import { timeOutline } from 'ionicons/icons';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@Component({
diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts
index feedddacae..13686624f7 100644
--- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts
+++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts
@@ -23,7 +23,7 @@ import {
ellipsisHorizontalCircleOutline,
informationCircleOutline
} from 'ionicons/icons';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
@Component({
diff --git a/apps/client/src/app/pages/api/api-page.component.ts b/apps/client/src/app/pages/api/api-page.component.ts
index 8b80370e8d..36c780a04e 100644
--- a/apps/client/src/app/pages/api/api-page.component.ts
+++ b/apps/client/src/app/pages/api/api-page.component.ts
@@ -32,7 +32,7 @@ import {
import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { MatCardModule } from '@angular/material/card';
import { format, startOfYear } from 'date-fns';
-import { isObject } from 'lodash';
+import { isObject } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { catchError, map, Observable, of, OperatorFunction } from 'rxjs';
diff --git a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts
index 26255f2061..a1a9bddd6b 100644
--- a/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts
+++ b/apps/client/src/app/pages/portfolio/activities/import-activities-dialog/import-activities-dialog.component.ts
@@ -51,7 +51,7 @@ import { MatTableDataSource } from '@angular/material/table';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { cloudUploadOutline, warningOutline } from 'ionicons/icons';
-import { isArray, sortBy } from 'lodash';
+import { isArray, sortBy } from 'lodash-es';
import ms from 'ms';
import { ImportStep } from './enums/import-step';
diff --git a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
index 6d67b0253c..487bcf6086 100644
--- a/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
+++ b/apps/client/src/app/pages/portfolio/allocations/allocations-page.component.ts
@@ -53,7 +53,7 @@ import { MatCardModule } from '@angular/material/card';
import { MatDialog } from '@angular/material/dialog';
import { MatProgressBarModule } from '@angular/material/progress-bar';
import { ActivatedRoute, Router } from '@angular/router';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import { DeviceDetectorService } from 'ngx-device-detector';
import { filter, switchMap, tap } from 'rxjs';
diff --git a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
index 898c7f51a8..880753cce5 100644
--- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
+++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
@@ -51,7 +51,7 @@ import { RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { copyOutline, ellipsisVertical } from 'ionicons/icons';
-import { isNumber, keyBy, sortBy, union } from 'lodash';
+import { isNumber, keyBy, sortBy, union } from 'lodash-es';
import ms from 'ms';
import { DeviceDetectorService } from 'ngx-device-detector';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
diff --git a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts
index dc787ae26a..33b877d42f 100644
--- a/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts
+++ b/apps/client/src/app/pages/portfolio/fire/fire-page.component.ts
@@ -27,7 +27,7 @@ import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
import { FormsModule, ReactiveFormsModule } from '@angular/forms';
import { FormControl } from '@angular/forms';
import { Big } from 'big.js';
-import { isFinite, isNumber } from 'lodash';
+import { isFinite, isNumber } from 'lodash-es';
import { DeviceDetectorService } from 'ngx-device-detector';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
diff --git a/apps/client/src/app/services/import-activities.service.ts b/apps/client/src/app/services/import-activities.service.ts
index 599c66551a..e302f00f9b 100644
--- a/apps/client/src/app/services/import-activities.service.ts
+++ b/apps/client/src/app/services/import-activities.service.ts
@@ -16,7 +16,7 @@ import { DataSource, Type as ActivityType } from '@ghostfolio/prisma/enums';
import { HttpClient } from '@angular/common/http';
import { inject, Service } from '@angular/core';
-import { isFinite, isNumber, isString } from 'lodash';
+import { isFinite, isNumber, isString } from 'lodash-es';
import { parse as csvToJson } from 'papaparse';
import { firstValueFrom } from 'rxjs';
import { v4 as uuidv4 } from 'uuid';
diff --git a/eslint.config.cjs b/eslint.config.cjs
index ee5e0a557c..282e1b548c 100644
--- a/eslint.config.cjs
+++ b/eslint.config.cjs
@@ -116,7 +116,24 @@ module.exports = [
'no-eval': 'error',
'no-fallthrough': 'error',
'no-new-wrappers': 'error',
- 'no-restricted-imports': ['error', 'rxjs/Rx'],
+ 'no-restricted-imports': [
+ 'error',
+ {
+ paths: [
+ 'rxjs/Rx',
+ {
+ message: 'Import from lodash-es instead.',
+ name: 'lodash'
+ }
+ ],
+ patterns: [
+ {
+ group: ['lodash/*'],
+ message: 'Import from lodash-es instead.'
+ }
+ ]
+ }
+ ],
'no-undef-init': 'error',
'no-underscore-dangle': 'off',
'no-var': 'error',
diff --git a/jest.preset.js b/jest.preset.js
index f078ddcec1..3cdca44c04 100644
--- a/jest.preset.js
+++ b/jest.preset.js
@@ -1,3 +1,6 @@
const nxPreset = require('@nx/jest/preset').default;
-module.exports = { ...nxPreset };
+module.exports = {
+ ...nxPreset,
+ transformIgnorePatterns: ['node_modules/(?!lodash-es/)']
+};
diff --git a/libs/common/src/lib/calculation-helper.ts b/libs/common/src/lib/calculation-helper.ts
index d49663d6cf..2cc1fa2d1c 100644
--- a/libs/common/src/lib/calculation-helper.ts
+++ b/libs/common/src/lib/calculation-helper.ts
@@ -10,7 +10,7 @@ import {
subMilliseconds,
subYears
} from 'date-fns';
-import { isFinite, isNumber } from 'lodash';
+import { isFinite, isNumber } from 'lodash-es';
import { resetHours } from './helper';
import { DateRange } from './types';
diff --git a/libs/common/src/lib/dtos/create-account.dto.ts b/libs/common/src/lib/dtos/create-account.dto.ts
index 92879dbb2c..5c1275db76 100644
--- a/libs/common/src/lib/dtos/create-account.dto.ts
+++ b/libs/common/src/lib/dtos/create-account.dto.ts
@@ -11,7 +11,7 @@ import {
MaxLength,
ValidateIf
} from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class CreateAccountDto {
/**
diff --git a/libs/common/src/lib/dtos/create-order.dto.ts b/libs/common/src/lib/dtos/create-order.dto.ts
index fd062b610b..d473e8e7b6 100644
--- a/libs/common/src/lib/dtos/create-order.dto.ts
+++ b/libs/common/src/lib/dtos/create-order.dto.ts
@@ -25,7 +25,7 @@ import {
Min,
Validate
} from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class CreateOrderDto {
@IsOptional()
diff --git a/libs/common/src/lib/dtos/update-account.dto.ts b/libs/common/src/lib/dtos/update-account.dto.ts
index deec684aae..c5f9f34679 100644
--- a/libs/common/src/lib/dtos/update-account.dto.ts
+++ b/libs/common/src/lib/dtos/update-account.dto.ts
@@ -11,7 +11,7 @@ import {
MaxLength,
ValidateIf
} from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class UpdateAccountDto {
/**
diff --git a/libs/common/src/lib/dtos/update-order.dto.ts b/libs/common/src/lib/dtos/update-order.dto.ts
index 0e381f2069..f7dfb0df53 100644
--- a/libs/common/src/lib/dtos/update-order.dto.ts
+++ b/libs/common/src/lib/dtos/update-order.dto.ts
@@ -24,7 +24,7 @@ import {
Min,
Validate
} from 'class-validator';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
export class UpdateOrderDto {
@IsOptional()
diff --git a/libs/common/src/lib/helper.ts b/libs/common/src/lib/helper.ts
index 69764935d1..e10ca215cc 100644
--- a/libs/common/src/lib/helper.ts
+++ b/libs/common/src/lib/helper.ts
@@ -42,7 +42,7 @@ import {
uk,
zhCN
} from 'date-fns/locale';
-import { get, isNil, isString } from 'lodash';
+import { get, isNil, isString } from 'lodash-es';
import {
DEFAULT_CURRENCY,
diff --git a/libs/ui/jest.config.ts b/libs/ui/jest.config.ts
index 116fe6d54f..f9b97fe1a4 100644
--- a/libs/ui/jest.config.ts
+++ b/libs/ui/jest.config.ts
@@ -14,7 +14,7 @@ export default {
}
]
},
- transformIgnorePatterns: ['node_modules/(?!.*.mjs$)'],
+ transformIgnorePatterns: ['node_modules/(?!.*.mjs$|lodash-es/)'],
snapshotSerializers: [
'jest-preset-angular/build/serializers/no-ng-attributes',
'jest-preset-angular/build/serializers/ng-snapshot',
diff --git a/libs/ui/src/lib/account-balances/account-balances.component.ts b/libs/ui/src/lib/account-balances/account-balances.component.ts
index e27d29516c..04f13ccf10 100644
--- a/libs/ui/src/lib/account-balances/account-balances.component.ts
+++ b/libs/ui/src/lib/account-balances/account-balances.component.ts
@@ -40,7 +40,7 @@ import {
ellipsisHorizontal,
trashOutline
} from 'ionicons/icons';
-import { get, isNil } from 'lodash';
+import { get, isNil } from 'lodash-es';
import { GfValueComponent } from '../value';
diff --git a/libs/ui/src/lib/activities-filter/activities-filter.component.ts b/libs/ui/src/lib/activities-filter/activities-filter.component.ts
index 7a434d94c8..b6af11b0dc 100644
--- a/libs/ui/src/lib/activities-filter/activities-filter.component.ts
+++ b/libs/ui/src/lib/activities-filter/activities-filter.component.ts
@@ -29,7 +29,7 @@ import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { closeOutline, searchOutline } from 'ionicons/icons';
-import { groupBy } from 'lodash';
+import { groupBy } from 'lodash-es';
import { BehaviorSubject } from 'rxjs';
import { translate } from '../i18n';
diff --git a/libs/ui/src/lib/assistant/assistant.component.ts b/libs/ui/src/lib/assistant/assistant.component.ts
index 6babc10398..ef0fb554ce 100644
--- a/libs/ui/src/lib/assistant/assistant.component.ts
+++ b/libs/ui/src/lib/assistant/assistant.component.ts
@@ -39,7 +39,7 @@ import {
closeOutline,
searchOutline
} from 'ionicons/icons';
-import { isFunction, sample } from 'lodash';
+import { isFunction, sample } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { EMPTY, Observable, merge, of } from 'rxjs';
import {
diff --git a/libs/ui/src/lib/benchmark/benchmark.component.ts b/libs/ui/src/lib/benchmark/benchmark.component.ts
index 4f76978d45..bee06e3265 100644
--- a/libs/ui/src/lib/benchmark/benchmark.component.ts
+++ b/libs/ui/src/lib/benchmark/benchmark.component.ts
@@ -33,7 +33,7 @@ import { ActivatedRoute, Router, RouterModule } from '@angular/router';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { ellipsisHorizontal, trashOutline } from 'ionicons/icons';
-import { isNumber, round } from 'lodash';
+import { isNumber, round } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfEntityLogoComponent } from '../entity-logo/entity-logo.component';
diff --git a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts
index cfa2ee5cd2..959e934553 100644
--- a/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts
+++ b/libs/ui/src/lib/fire-calculator/fire-calculator.component.ts
@@ -59,7 +59,7 @@ import {
} from 'date-fns';
import { addIcons } from 'ionicons';
import { calendarClearOutline } from 'ionicons/icons';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { debounceTime } from 'rxjs';
diff --git a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts
index 17a5a5e612..4f8540974f 100644
--- a/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts
+++ b/libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.component.ts
@@ -29,7 +29,7 @@ import { MatInputModule } from '@angular/material/input';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { calendarClearOutline, refreshOutline } from 'ionicons/icons';
-import { isNil } from 'lodash';
+import { isNil } from 'lodash-es';
import { HistoricalMarketDataEditorDialogParams } from './interfaces/interfaces';
diff --git a/libs/ui/src/lib/notifications/notification.service.ts b/libs/ui/src/lib/notifications/notification.service.ts
index 4eb1cbd54d..d1c8459a6c 100644
--- a/libs/ui/src/lib/notifications/notification.service.ts
+++ b/libs/ui/src/lib/notifications/notification.service.ts
@@ -3,7 +3,7 @@ import { translate } from '@ghostfolio/ui/i18n';
import { inject, Service } from '@angular/core';
import { MatDialog } from '@angular/material/dialog';
-import { isFunction } from 'lodash';
+import { isFunction } from 'lodash-es';
import { GfAlertDialogComponent } from './alert-dialog/alert-dialog.component';
import { GfConfirmationDialogComponent } from './confirmation-dialog/confirmation-dialog.component';
diff --git a/libs/ui/src/lib/services/admin.service.ts b/libs/ui/src/lib/services/admin.service.ts
index aba02c9b3f..0307909dc1 100644
--- a/libs/ui/src/lib/services/admin.service.ts
+++ b/libs/ui/src/lib/services/admin.service.ts
@@ -31,7 +31,7 @@ import { GF_ENVIRONMENT } from '@ghostfolio/ui/environment';
import { HttpClient, HttpHeaders, HttpParams } from '@angular/common/http';
import { inject, Service } from '@angular/core';
import { JobStatus } from 'bull';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
@Service()
export class AdminService {
diff --git a/libs/ui/src/lib/services/data.service.ts b/libs/ui/src/lib/services/data.service.ts
index 9bbb0bf5fa..8545c36ba4 100644
--- a/libs/ui/src/lib/services/data.service.ts
+++ b/libs/ui/src/lib/services/data.service.ts
@@ -82,7 +82,7 @@ import { inject, Service } from '@angular/core';
import { SortDirection } from '@angular/material/sort';
import { utc } from '@date-fns/utc';
import { format, parseISO } from 'date-fns';
-import { cloneDeep, groupBy, isNumber } from 'lodash';
+import { cloneDeep, groupBy, isNumber } from 'lodash-es';
import { Observable } from 'rxjs';
import { map } from 'rxjs/operators';
diff --git a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts
index 683f7c9252..d56aa177bf 100644
--- a/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts
+++ b/libs/ui/src/lib/symbol-autocomplete/symbol-autocomplete.component.ts
@@ -36,7 +36,7 @@ import {
} from '@angular/material/form-field';
import { MatInput, MatInputModule } from '@angular/material/input';
import { MatProgressSpinnerModule } from '@angular/material/progress-spinner';
-import { isString } from 'lodash';
+import { isString } from 'lodash-es';
import { tap } from 'rxjs';
import {
debounceTime,
diff --git a/libs/ui/src/lib/top-holdings/top-holdings.component.ts b/libs/ui/src/lib/top-holdings/top-holdings.component.ts
index 03e7f6cc46..1a675a5531 100644
--- a/libs/ui/src/lib/top-holdings/top-holdings.component.ts
+++ b/libs/ui/src/lib/top-holdings/top-holdings.component.ts
@@ -18,7 +18,7 @@ import {
import { MatButtonModule } from '@angular/material/button';
import { MatPaginator, MatPaginatorModule } from '@angular/material/paginator';
import { MatTableDataSource, MatTableModule } from '@angular/material/table';
-import { capitalize } from 'lodash';
+import { capitalize } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import { GfValueComponent } from '../value/value.component';
diff --git a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
index 54c8d7f907..a35d3deef5 100644
--- a/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
+++ b/libs/ui/src/lib/treemap-chart/treemap-chart.component.ts
@@ -32,7 +32,7 @@ import { Chart, LinearScale, Tooltip } from 'chart.js';
import { TreemapController, TreemapElement } from 'chartjs-chart-treemap';
import { isUUID } from 'class-validator';
import { differenceInDays, max } from 'date-fns';
-import { orderBy, round } from 'lodash';
+import { orderBy, round } from 'lodash-es';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
import OpenColor from 'open-color';
diff --git a/libs/ui/src/lib/value/value.component.ts b/libs/ui/src/lib/value/value.component.ts
index c2c7d4621d..4101b4066f 100644
--- a/libs/ui/src/lib/value/value.component.ts
+++ b/libs/ui/src/lib/value/value.component.ts
@@ -21,7 +21,7 @@ import { MatSnackBar } from '@angular/material/snack-bar';
import { IonIcon } from '@ionic/angular/standalone';
import { addIcons } from 'ionicons';
import { checkmarkOutline, copyOutline } from 'ionicons/icons';
-import { isNumber } from 'lodash';
+import { isNumber } from 'lodash-es';
import ms from 'ms';
import { NgxSkeletonLoaderModule } from 'ngx-skeleton-loader';
diff --git a/package-lock.json b/package-lock.json
index 3f8ee0f880..c3ee51dc53 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -83,7 +83,7 @@
"ionicons": "8.0.13",
"jsonpath": "1.3.0",
"katex": "0.16.47",
- "lodash": "4.18.1",
+ "lodash-es": "4.18.1",
"marked": "18.0.12",
"marked-katex-extension": "5.1.12",
"ms": "3.0.0-canary.1",
@@ -147,7 +147,7 @@
"@types/google-spreadsheet": "3.1.5",
"@types/jest": "30.0.0",
"@types/jsonpath": "0.2.4",
- "@types/lodash": "4.17.25",
+ "@types/lodash-es": "4.17.12",
"@types/node": "22.20.1",
"@types/papaparse": "5.5.2",
"@types/passport-google-oauth20": "2.0.17",
@@ -15221,6 +15221,16 @@
"devOptional": true,
"license": "MIT"
},
+ "node_modules/@types/lodash-es": {
+ "version": "4.17.12",
+ "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz",
+ "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/lodash": "*"
+ }
+ },
"node_modules/@types/luxon": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.7.1.tgz",
@@ -27042,7 +27052,6 @@
"version": "4.18.1",
"resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
"integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
- "dev": true,
"license": "MIT"
},
"node_modules/lodash.debounce": {
diff --git a/package.json b/package.json
index a3f94b74b6..ca4f3ebcff 100644
--- a/package.json
+++ b/package.json
@@ -127,7 +127,7 @@
"ionicons": "8.0.13",
"jsonpath": "1.3.0",
"katex": "0.16.47",
- "lodash": "4.18.1",
+ "lodash-es": "4.18.1",
"marked": "18.0.12",
"marked-katex-extension": "5.1.12",
"ms": "3.0.0-canary.1",
@@ -191,7 +191,7 @@
"@types/google-spreadsheet": "3.1.5",
"@types/jest": "30.0.0",
"@types/jsonpath": "0.2.4",
- "@types/lodash": "4.17.25",
+ "@types/lodash-es": "4.17.12",
"@types/node": "22.20.1",
"@types/papaparse": "5.5.2",
"@types/passport-google-oauth20": "2.0.17",