From afc8bc311d8b65511bb53e0b0ec6f4a427281988 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Wed, 23 Sep 2026 17:29:23 +0200 Subject: [PATCH 01/19] Task/use import type for types in decorated signatures (#7936) Refactor imports --- apps/api/src/app/auth-device/auth-device.controller.ts | 2 +- .../app/endpoints/asset-profiles/asset-profiles.controller.ts | 2 +- .../data-providers/ghostfolio/ghostfolio.controller.ts | 2 +- .../api/src/app/endpoints/market-data/market-data.controller.ts | 2 +- apps/api/src/app/endpoints/tags/tags.controller.ts | 2 +- apps/api/src/app/endpoints/watchlist/watchlist.controller.ts | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/apps/api/src/app/auth-device/auth-device.controller.ts b/apps/api/src/app/auth-device/auth-device.controller.ts index 45f7925ad6..509746ca97 100644 --- a/apps/api/src/app/auth-device/auth-device.controller.ts +++ b/apps/api/src/app/auth-device/auth-device.controller.ts @@ -3,7 +3,7 @@ import { AllowDuringImpersonation } from '@ghostfolio/api/decorators/allow-durin import { HasPermission } from '@ghostfolio/api/decorators/has-permission.decorator'; import { HasPermissionGuard } from '@ghostfolio/api/guards/has-permission.guard'; import { permissions } from '@ghostfolio/common/permissions'; -import { RequestWithUser } from '@ghostfolio/common/types'; +import type { RequestWithUser } from '@ghostfolio/common/types'; import { Controller, diff --git a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts index 1db09f95e0..58f19800e8 100644 --- a/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts +++ b/apps/api/src/app/endpoints/asset-profiles/asset-profiles.controller.ts @@ -17,7 +17,7 @@ import { } from '@ghostfolio/common/interfaces'; import { hasPermission } from '@ghostfolio/common/permissions'; import { permissions } from '@ghostfolio/common/permissions'; -import { RequestWithUser } from '@ghostfolio/common/types'; +import type { RequestWithUser } from '@ghostfolio/common/types'; import { Body, diff --git a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts index cd330f6911..b1b7f24e79 100644 --- a/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts +++ b/apps/api/src/app/endpoints/data-providers/ghostfolio/ghostfolio.controller.ts @@ -12,7 +12,7 @@ import { QuotesResponse } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; -import { RequestWithUser } from '@ghostfolio/common/types'; +import type { RequestWithUser } from '@ghostfolio/common/types'; import { Controller, diff --git a/apps/api/src/app/endpoints/market-data/market-data.controller.ts b/apps/api/src/app/endpoints/market-data/market-data.controller.ts index 6f7583acf3..73c8ad4451 100644 --- a/apps/api/src/app/endpoints/market-data/market-data.controller.ts +++ b/apps/api/src/app/endpoints/market-data/market-data.controller.ts @@ -8,7 +8,7 @@ import { UpdateBulkMarketDataDto } from '@ghostfolio/common/dtos'; import { getCurrencyFromSymbol, isCurrency } from '@ghostfolio/common/helper'; import { MarketDataOfMarketsResponse } from '@ghostfolio/common/interfaces'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { RequestWithUser } from '@ghostfolio/common/types'; +import type { RequestWithUser } from '@ghostfolio/common/types'; import { Body, diff --git a/apps/api/src/app/endpoints/tags/tags.controller.ts b/apps/api/src/app/endpoints/tags/tags.controller.ts index a61e1188c8..d464b7bb65 100644 --- a/apps/api/src/app/endpoints/tags/tags.controller.ts +++ b/apps/api/src/app/endpoints/tags/tags.controller.ts @@ -5,7 +5,7 @@ import { TagService } from '@ghostfolio/api/services/tag/tag.service'; import { CreateTagDto, UpdateTagDto } from '@ghostfolio/common/dtos'; import { isSystemTag } from '@ghostfolio/common/helper'; import { hasPermission, permissions } from '@ghostfolio/common/permissions'; -import { RequestWithUser } from '@ghostfolio/common/types'; +import type { RequestWithUser } from '@ghostfolio/common/types'; import { Body, diff --git a/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts b/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts index b9250833ec..790f0b550e 100644 --- a/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts +++ b/apps/api/src/app/endpoints/watchlist/watchlist.controller.ts @@ -7,7 +7,7 @@ import { CreateWatchlistItemDto } from '@ghostfolio/common/dtos'; import { WatchlistResponse } from '@ghostfolio/common/interfaces'; import { permissions } from '@ghostfolio/common/permissions'; import { scopes } from '@ghostfolio/common/scopes'; -import { ImpersonationContext } from '@ghostfolio/common/types'; +import type { ImpersonationContext } from '@ghostfolio/common/types'; import { Body, From 3c9cc2e5311ba02b26a130656efdfcb079b51015 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 24 Sep 2026 08:01:15 +0200 Subject: [PATCH 02/19] Task/extend personal finance tools (20260923) (#7940) Extend personal finance tools --- .../src/lib/interfaces/product.interface.ts | 1 + libs/common/src/lib/personal-finance-tools.ts | 845 ++++++++++++++++++ 2 files changed, 846 insertions(+) diff --git a/libs/common/src/lib/interfaces/product.interface.ts b/libs/common/src/lib/interfaces/product.interface.ts index b11c7ecada..11d5e35b05 100644 --- a/libs/common/src/lib/interfaces/product.interface.ts +++ b/libs/common/src/lib/interfaces/product.interface.ts @@ -17,6 +17,7 @@ export interface Product { pricingPerYear?: string; regions?: string[]; slogan?: string; + updatedAt?: string; url?: string; useAnonymously?: boolean; } diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index e6c6ce5d34..31e43bf21b 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -2,6 +2,24 @@ import { Product } from '@ghostfolio/common/interfaces'; export const personalFinanceTools: Product[] = ( [ + { + categories: [ + 'FAMILY_OFFICE', + 'FINANCIAL_PLANNING', + 'NET_WORTH_TRACKING', + 'WEALTH_MANAGEMENT' + ], + hasSelfHostingAbility: false, + key: 'abbove', + languages: ['English', 'Français', 'Nederlands'], + name: 'Abbove', + note: 'Originally named as PaxFamilia', + origin: 'BE', + platforms: ['WEB'], + slogan: 'Where every wealth planning journey begins', + updatedAt: '2026-09-23', + url: 'https://www.abbove.com' + }, { categories: ['BUDGETING'], hasFreePlan: true, @@ -72,6 +90,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Manage your entire Swiss wealth in one place', url: 'https://alpgain.ch' }, + { + categories: ['WEALTH_MANAGEMENT'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'alphaquark', + languages: ['English'], + name: 'AlphaQuark', + origin: 'IN', + platforms: ['WEB'], + regions: ['IN'], + slogan: + 'Best Wealth Management Platform in India for RAs, RIAs & Sub-Brokers', + updatedAt: '2026-09-23', + url: 'https://alphaquark.in' + }, { categories: ['STOCK_TRACKING'], founded: 2016, @@ -143,6 +176,31 @@ export const personalFinanceTools: Product[] = ( slogan: 'Analyze and track your portfolio.', url: 'https://anlage.app' }, + { + categories: ['FAMILY_OFFICE', 'WEALTH_MANAGEMENT'], + founded: 2002, + key: 'archway', + languages: ['English'], + name: 'Archway', + origin: 'US', + platforms: ['WEB'], + slogan: 'The foundation for every transaction', + updatedAt: '2026-09-23', + url: 'https://www.archwaygroup.com' + }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'asignal', + languages: ['English'], + name: 'ASignal', + platforms: ['WEB'], + pricingPerYear: '$180', + slogan: 'Every signal comes with the research attached.', + updatedAt: '2026-09-23', + url: 'https://asignal.io' + }, { categories: ['FAMILY_OFFICE'], founded: 2022, @@ -246,6 +304,20 @@ export const personalFinanceTools: Product[] = ( slogan: 'Stock Portfolio Tracker for Smart Investors', url: 'https://beanvest.com' }, + { + categories: ['INVESTMENT_RESEARCH'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'benzinga-pro', + languages: ['English'], + name: 'Benzinga Pro', + origin: 'US', + platforms: ['WEB'], + slogan: + 'The Best Investment Research Software & Breaking Stock Market News', + updatedAt: '2026-09-23', + url: 'https://www.benzinga.com/pro' + }, { categories: ['BUDGETING'], founded: 2022, @@ -297,6 +369,26 @@ export const personalFinanceTools: Product[] = ( slogan: 'Take control with retirement planning tools that begin with you', url: 'https://www.boldin.com' }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'FINANCIAL_PLANNING', + 'STOCK_TRACKING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'borderfolio', + languages: ['English'], + name: 'BorderFolio', + origin: 'GE', + platforms: ['WEB'], + pricingPerYear: '$149', + slogan: + 'Your broker shows what your portfolio is worth. BorderFolio shows how you built it.', + updatedAt: '2026-09-23', + url: 'https://borderfolio.app' + }, { categories: [ 'BUDGETING', @@ -430,6 +522,16 @@ export const personalFinanceTools: Product[] = ( slogan: 'The leading Crypto Portfolio Tracker & Tax Calculator', url: 'https://cointracking.info' }, + { + categories: ['WEALTH_MANAGEMENT'], + hasSelfHostingAbility: true, + key: 'comarch-wealth-management', + name: 'Comarch Wealth Management', + origin: 'PL', + slogan: 'Empower RMs. Engage customers. Enhance business growth.', + updatedAt: '2026-09-23', + url: 'https://www.comarch.com/finance/banking/comarch-wealth-management' + }, { categories: ['WEALTH_MANAGEMENT'], founded: 2019, @@ -465,6 +567,36 @@ export const personalFinanceTools: Product[] = ( slogan: 'Customizable and Secure Personal Finance App', url: 'https://countabout.com' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + founded: 2025, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'coveredge', + languages: ['English'], + name: 'CoverEdge', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$239.88', + slogan: 'Know what your options income is really earning.', + updatedAt: '2026-09-23', + url: 'https://coveredge.io' + }, + { + categories: ['CRYPTOCURRENCY'], + founded: 2021, + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'crypto-excel', + languages: ['English', 'Français'], + name: 'Crypto Excel', + origin: 'FR', + platforms: ['WEB'], + pricingPerYear: '€70.80', + slogan: 'Excel in your investments.', + updatedAt: '2026-09-23', + url: 'https://www.cryptoexcel.io' + }, { categories: ['INVESTMENT_RESEARCH'], hasFreePlan: true, @@ -555,6 +687,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Dividend Portfolio Tracker', url: 'https://www.digrin.com' }, + { + categories: ['INVESTMENT_RESEARCH'], + founded: 2020, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'diversiview', + languages: ['English'], + name: 'Diversiview', + origin: 'AU', + platforms: ['WEB'], + pricingPerYear: 'AUD 490', + slogan: 'Portfolio Analysis & Portfolio Optimization', + updatedAt: '2026-09-23', + url: 'https://diversiview.online' + }, { categories: ['DIVIDEND_TRACKING'], hasFreePlan: true, @@ -572,6 +719,26 @@ export const personalFinanceTools: Product[] = ( slogan: 'Track Your Dividends Like a Pro', url: 'https://dividend-wealth.com' }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'dividendatlas', + languages: ['English', 'Nederlands'], + name: 'DividendAtlas', + origin: 'NL', + platforms: ['WEB'], + pricingPerYear: '€79.90', + slogan: + 'Research every dividend stock that pays. Then track what you own.', + updatedAt: '2026-09-23', + url: 'https://dividendatlas.com' + }, { categories: ['DIVIDEND_TRACKING'], key: 'divtracker', @@ -650,6 +817,14 @@ export const personalFinanceTools: Product[] = ( slogan: 'Everybody Deserves Financial Wellness', url: 'https://www.envestnet.com' }, + { + categories: ['WEALTH_MANAGEMENT'], + key: 'envestnet-tamarac', + name: 'Envestnet Tamarac', + slogan: 'Envestnet Tamarac. Built for the way RIAs work.', + updatedAt: '2026-09-23', + url: 'https://www.envestnet.com/tamarac' + }, { categories: ['INVESTMENT_RESEARCH'], hasFreePlan: true, @@ -660,6 +835,24 @@ export const personalFinanceTools: Product[] = ( slogan: 'Stock Selection Analytics for Investors', url: 'https://epsmomentum.com' }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'NET_WORTH_TRACKING', + 'STOCK_TRACKING', + 'TAX_REPORTING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'equitystat', + languages: ['English'], + name: 'EquityStat', + platforms: ['WEB'], + slogan: 'Track All Your Stocks In One Place', + updatedAt: '2026-09-23', + url: 'https://equitystat.com' + }, { categories: ['ETF_TRACKING', 'INVESTMENT_RESEARCH'], key: 'etf-action', @@ -682,6 +875,17 @@ export const personalFinanceTools: Product[] = ( slogan: 'A Smarter Approach to Exchange Traded Funds', url: 'https://www.etfrc.com' }, + { + categories: ['WEALTH_MANAGEMENT'], + hasSelfHostingAbility: false, + key: 'etna-financial-advisor-software', + name: 'ETNA Financial Advisor Software', + origin: 'US', + platforms: ['WEB'], + slogan: 'Transform wealth management with our turnkey SaaS solution', + updatedAt: '2026-09-23', + url: 'https://www.etnasoft.com/financial-advisor-software' + }, { categories: ['WEALTH_MANAGEMENT'], founded: 2010, @@ -705,6 +909,25 @@ export const personalFinanceTools: Product[] = ( slogan: 'Plan, track, find more margin', url: 'https://www.ramseysolutions.com/money/everydollar' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'excel-price-feed', + languages: ['English'], + name: 'Excel Price Feed', + origin: 'GB', + platforms: ['WINDOWS'], + pricingPerYear: '$165', + slogan: 'Live financial markets data in your Excel spreadsheet.', + updatedAt: '2026-09-23', + url: 'https://www.excelpricefeed.com' + }, { categories: ['NET_WORTH_TRACKING'], founded: 2020, @@ -783,6 +1006,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Flexible Financial Management', url: 'https://www.fina.money' }, + { + categories: ['CRYPTOCURRENCY', 'STOCK_TRACKING'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'financial-tech-wiz-trading-journal', + languages: ['English'], + name: 'Financial Tech Wiz Trading Journal', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$119', + slogan: + 'The Trading Journal Built to Track, Analyze, and Improve Your Performance', + updatedAt: '2026-09-23', + url: 'https://journal.financialtechwiz.com' + }, { categories: ['NET_WORTH_TRACKING'], founded: 2023, @@ -854,6 +1092,17 @@ export const personalFinanceTools: Product[] = ( slogan: 'Wealth Management Software', url: 'https://fincite.de' }, + { + categories: ['WEALTH_MANAGEMENT'], + hasSelfHostingAbility: true, + key: 'finfolio', + name: 'FinFolio', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + slogan: 'Wealth management simplified.', + updatedAt: '2026-09-23', + url: 'https://www.finfolio.com' + }, { categories: ['BUDGETING'], hasSelfHostingAbility: false, @@ -873,6 +1122,19 @@ export const personalFinanceTools: Product[] = ( slogan: 'Essential Tools for Investors and Traders', url: 'https://fintel.io' }, + { + categories: ['INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT'], + hasSelfHostingAbility: false, + key: 'fintellion', + name: 'Fintellion', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$1188', + slogan: + 'Research Companies. Track Market Events. Connect the Intelligence to Client Holdings.', + updatedAt: '2026-09-23', + url: 'https://www.fintellion.ai' + }, { categories: ['ETF_TRACKING', 'STOCK_TRACKING'], founded: 2021, @@ -951,6 +1213,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Take control over your investments', url: 'https://www.folishare.com' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'foremetrics', + languages: ['English'], + name: 'Foremetrics', + origin: 'NL', + platforms: ['WEB'], + pricingPerYear: '€89', + slogan: + 'Stock research, portfolio tracking, and valuation tools in one clear workspace', + updatedAt: '2026-09-23', + url: 'https://foremetrics.ai' + }, { categories: ['BUDGETING', 'NET_WORTH_TRACKING'], hasFreePlan: true, @@ -997,6 +1274,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Take control of your finances from WhatsApp', url: 'https://gasti.pro' }, + { + categories: ['DIVIDEND_TRACKING', 'STOCK_TRACKING', 'TAX_REPORTING'], + founded: 2026, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'geckopro', + languages: ['English'], + name: 'GeckoPro', + origin: 'NZ', + platforms: ['ANDROID', 'WEB'], + pricingPerYear: 'NZD 79.90', + slogan: 'Portfolio intelligence, without the noise.', + updatedAt: '2026-09-23', + url: 'https://geckopro.app' + }, { categories: ['NET_WORTH_TRACKING', 'STOCK_TRACKING'], founded: 2020, @@ -1060,6 +1352,25 @@ export const personalFinanceTools: Product[] = ( slogan: 'Follow Hedge Funds & Insiders using 13F filings', url: 'https://hedgefollow.com' }, + { + categories: [ + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'NET_WORTH_TRACKING', + 'STOCK_TRACKING' + ], + founded: 2025, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'helm-terminal', + languages: ['English'], + name: 'Helm Terminal', + platforms: ['WEB'], + pricingPerYear: '$149', + slogan: 'Your portfolio. A clearer picture.', + updatedAt: '2026-09-23', + url: 'https://helmterminal.dev' + }, { categories: ['DIVIDEND_TRACKING', 'ETF_TRACKING', 'STOCK_TRACKING'], hasFreePlan: true, @@ -1150,6 +1461,56 @@ export const personalFinanceTools: Product[] = ( slogan: 'Advanced portfolio tracking and stock market information', url: 'https://www.investify.pk' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'investingpro', + name: 'InvestingPro', + origin: 'CY', + platforms: ['ANDROID', 'IOS', 'WEB'], + slogan: 'Make your next trade LEGENDARY', + updatedAt: '2026-09-23', + url: 'https://www.investing.com/pro' + }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'STOCK_TRACKING', + 'TAX_REPORTING' + ], + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'investment-account-manager', + languages: ['English'], + name: 'Investment Account Manager', + origin: 'US', + platforms: ['WINDOWS'], + pricingPerYear: '$159', + slogan: 'The Software Solution for Investing', + updatedAt: '2026-09-23', + url: 'https://www.investmentaccountmanager.com' + }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'FINANCIAL_PLANNING', + 'STOCK_TRACKING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'investor-pilot', + languages: ['English'], + name: 'Investor Pilot', + origin: 'AU', + platforms: ['WEB'], + pricingPerYear: '$144', + slogan: 'Take control of your investing journey', + updatedAt: '2026-09-23', + url: 'https://investorpilot.co' + }, { categories: ['NET_WORTH_TRACKING'], founded: 2021, @@ -1177,6 +1538,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Inwestujesz? Śledź swój majątek w jednym miejscu', url: 'https://inwestuje.app' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + founded: 2024, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'istfin', + languages: ['Türkçe'], + name: 'İstfin', + origin: 'TR', + platforms: ['WEB'], + pricingPerYear: '₺1188', + slogan: 'Veriyi Stratejiye Dönüştürün', + updatedAt: '2026-09-23', + url: 'https://istfin.com' + }, { categories: ['ETF_TRACKING'], founded: 2011, @@ -1290,6 +1666,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'AI Investing Assistant', url: 'https://magnifi.com' }, + { + categories: ['CRYPTOCURRENCY'], + founded: 2023, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'mantapex', + languages: ['Deutsch', 'English', 'Español', 'Français', '中文'], + name: 'Mantapex', + origin: 'NO', + platforms: ['ANDROID', 'WEB'], + pricingPerYear: '$29', + slogan: 'Track Your Crypto Portfolio Across 50+ Chains', + updatedAt: '2026-09-23', + url: 'https://mantapex.com' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'marketinout', @@ -1633,6 +2024,24 @@ export const personalFinanceTools: Product[] = ( slogan: 'Your Finances. Finally Clear.', url: 'https://nexafin.com' }, + { + categories: [ + 'FINANCIAL_PLANNING', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'nitrogen', + name: 'Nitrogen', + note: 'Originally named as Riskalyze', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$1188', + slogan: 'Showcase the value of advice in every client moment.', + updatedAt: '2026-09-23', + url: 'https://nitrogenwealth.com' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'okama', @@ -1652,6 +2061,34 @@ export const personalFinanceTools: Product[] = ( slogan: 'Dividend Day Should Feel Like Payday', url: 'https://onlydividends.app' }, + { + categories: ['INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'orion-risk-intelligence', + name: 'Orion Risk Intelligence', + note: 'Originally named as HiddenLevers', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$2970', + slogan: 'Risk analytics. Built on BeFi.', + updatedAt: '2026-09-23', + url: 'https://orion.com/advisor-tech/risk-intelligence' + }, + { + categories: ['INVESTMENT_RESEARCH'], + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'panda-trading-solutions', + languages: ['English', 'Español', 'Português'], + name: 'Panda Trading Solutions', + origin: 'BR', + platforms: ['WINDOWS'], + pricingPerYear: '$899', + slogan: 'One click on the board. Everything follows.', + updatedAt: '2026-09-23', + url: 'https://tspanda.com' + }, { categories: ['NET_WORTH_TRACKING'], founded: 2020, @@ -1720,6 +2157,19 @@ export const personalFinanceTools: Product[] = ( slogan: 'Your money. Made simple.', url: 'https://www.getpennies.com' }, + { + categories: ['FAMILY_OFFICE'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'pinion', + languages: ['English'], + name: 'Pinion', + platforms: ['WEB'], + pricingPerYear: '$50', + slogan: 'Track your angel portfolio.', + updatedAt: '2026-09-23', + url: 'https://pinion.vc' + }, { categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], founded: 2022, @@ -1785,6 +2235,19 @@ export const personalFinanceTools: Product[] = ( slogan: 'Know where your money is going', url: 'https://www.pocketsmith.com' }, + { + categories: ['FINANCIAL_PLANNING', 'WEALTH_MANAGEMENT'], + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'portax', + name: 'PORTAX', + origin: 'US', + platforms: ['WINDOWS'], + pricingPerYear: '$899', + slogan: 'After-Tax Portfolio Analysis', + updatedAt: '2026-09-23', + url: 'https://www.portaxsoftware.com' + }, { categories: ['BUDGETING', 'NET_WORTH_TRACKING', 'STOCK_TRACKING'], hasFreePlan: false, @@ -1867,6 +2330,43 @@ export const personalFinanceTools: Product[] = ( slogan: 'One look. Clear picture of your portfolio.', url: 'https://www.portfolioglance.com' }, + { + categories: ['INVESTMENT_RESEARCH'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'portfoliometrics', + languages: [ + 'Čeština', + 'Deutsch', + 'English', + 'Español', + 'Français', + 'Italiano', + '日本語', + '简体中文', + '繁體中文' + ], + name: 'PortfolioMetrics', + origin: 'CZ', + platforms: ['WEB'], + pricingPerYear: '$139', + slogan: 'What do you want to backtest today?', + updatedAt: '2026-09-23', + url: 'https://portfoliometrics.net', + useAnonymously: true + }, + { + categories: ['FAMILY_OFFICE', 'TAX_REPORTING', 'WEALTH_MANAGEMENT'], + founded: 1999, + hasSelfHostingAbility: false, + key: 'portfolioshop', + name: 'PortfolioShop', + origin: 'US', + platforms: ['WEB'], + slogan: 'Precision in Every Position', + updatedAt: '2026-09-23', + url: 'https://www.portfolioshop.com' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'portfolioslab', @@ -1874,6 +2374,27 @@ export const personalFinanceTools: Product[] = ( slogan: 'Financial tools for smart investors', url: 'https://portfolioslab.com' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + founded: 2025, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'portfoliotrackr', + languages: ['English'], + name: 'PortfolioTrackr', + origin: 'AE', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$99.99', + slogan: 'Every position. One dashboard.', + updatedAt: '2026-09-23', + url: 'https://portfoliotrackr.com' + }, { categories: ['STOCK_TRACKING'], hasFreePlan: true, @@ -1923,6 +2444,18 @@ export const personalFinanceTools: Product[] = ( slogan: 'The stock portfolio tracker built for long-term investors', url: 'https://prostocktracker.com' }, + { + categories: ['WEALTH_MANAGEMENT'], + founded: 2007, + key: 'pulse-by-assetbook', + languages: ['English'], + name: 'Pulse by AssetBook', + origin: 'US', + platforms: ['WEB'], + slogan: 'Portfolio Management and Reporting Software', + updatedAt: '2026-09-23', + url: 'https://www.assetbook.com' + }, { categories: ['NET_WORTH_TRACKING'], hasSelfHostingAbility: false, @@ -1932,6 +2465,25 @@ export const personalFinanceTools: Product[] = ( slogan: 'See your financial life clearly', url: 'https://usequantive.app' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'quotrend', + languages: ['English'], + name: 'QuoTrend', + origin: 'CY', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$154.80', + slogan: 'Know what to trade in your own words.', + updatedAt: '2026-09-23', + url: 'https://quotrend.com' + }, { categories: ['INVESTMENT_RESEARCH', 'NET_WORTH_TRACKING'], hasFreePlan: true, @@ -1949,6 +2501,7 @@ export const personalFinanceTools: Product[] = ( categories: ['INVESTMENT_RESEARCH'], key: 'reflexivity', name: 'Reflexivity', + note: 'Originally named as Toggle AI', slogan: 'Faster Insights. Better Analysis. Greater Confidence.', url: 'https://reflexivity.com' }, @@ -1976,6 +2529,20 @@ export const personalFinanceTools: Product[] = ( slogan: 'Track your net worth', url: 'https://www.rocketmoney.com' }, + { + categories: ['DIVIDEND_TRACKING', 'ETF_TRACKING', 'STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'safe-dividend-tracker', + languages: ['English'], + name: 'Safe Dividend Tracker', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$95.88', + slogan: 'The Smarter Way to Build Dividend Income', + updatedAt: '2026-09-23', + url: 'https://safedividendtracker.com' + }, { categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], founded: 2019, @@ -2086,6 +2653,27 @@ export const personalFinanceTools: Product[] = ( slogan: 'Smart portfolio tracker for informed investors', url: 'https://simplywall.st' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + founded: 2024, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'sirius-investors', + languages: ['English'], + name: 'Sirius Investors', + origin: 'NL', + platforms: ['WEB'], + pricingPerYear: '$190', + slogan: + 'Professional-Grade Investment Research with Automated Portfolio Management', + updatedAt: '2026-09-23', + url: 'https://www.siriusinvestors.com' + }, { categories: ['BUDGETING'], hasFreePlan: true, @@ -2145,6 +2733,22 @@ export const personalFinanceTools: Product[] = ( slogan: 'Take control of your investments', url: 'https://statfolio.net' }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + founded: 2010, + key: 'statmetrics', + name: 'Statmetrics', + origin: 'DE', + platforms: ['ANDROID'], + slogan: 'Mobile App Solution for investment analysis and management', + updatedAt: '2026-09-23', + url: 'https://statmetrics.org' + }, { categories: ['INVESTMENT_RESEARCH'], hasFreePlan: true, @@ -2165,6 +2769,35 @@ export const personalFinanceTools: Product[] = ( slogan: 'Track all your Investments', url: 'https://stockevents.app' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + founded: 2025, + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'stock-expert-ai', + name: 'Stock Expert AI', + origin: 'US', + platforms: ['WEB'], + slogan: 'Research US stocks with AI.', + updatedAt: '2026-09-23', + url: 'https://www.stockexpertai.com' + }, + { + categories: ['DIVIDEND_TRACKING', 'ETF_TRACKING', 'STOCK_TRACKING'], + founded: 2010, + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'stock-portfolio-organizer', + languages: ['English'], + name: 'Stock Portfolio Organizer', + note: 'License is a perpetual license', + origin: 'AU', + platforms: ['WINDOWS'], + pricingPerYear: '$99', + slogan: 'The Ultimate Stock Portfolio Management Software', + updatedAt: '2026-09-23', + url: 'https://www.stockportfolioorganizer.com' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'stockcharts', @@ -2182,6 +2815,25 @@ export const personalFinanceTools: Product[] = ( slogan: 'Supercharge your investments tracking experience', url: 'https://stockle.app' }, + { + categories: [ + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'STOCK_TRACKING', + 'TAX_REPORTING' + ], + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'stockmarket-plus', + languages: ['English'], + name: 'StockMarket Plus', + origin: 'AU', + platforms: ['WINDOWS'], + pricingPerYear: 'AUD 288', + slogan: 'Share Portfolio Management Software Australia', + updatedAt: '2026-09-23', + url: 'https://stockmarketplus.com.au' + }, { categories: ['STOCK_TRACKING'], founded: 2008, @@ -2192,6 +2844,20 @@ export const personalFinanceTools: Product[] = ( note: 'StockMarketEye was discontinued in 2023', slogan: 'A Powerful Portfolio & Investment Tracking App' }, + { + categories: ['DIVIDEND_TRACKING', 'STOCK_TRACKING', 'TAX_REPORTING'], + hasFreePlan: true, + hasSelfHostingAbility: true, + key: 'stockmaster', + languages: ['English'], + name: 'StockMaster', + origin: 'AU', + platforms: ['WINDOWS'], + pricingPerYear: '$275', + slogan: 'Australia Leading Portfolio Management Software', + updatedAt: '2026-09-23', + url: 'https://supertech.com.au/stockmaster.html' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'stockopedia', @@ -2221,6 +2887,20 @@ export const personalFinanceTools: Product[] = ( slogan: 'Unique Stock Insights & Portfolio Tracking', url: 'https://stockunlock.com' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: true, + key: 'stockwarepro', + languages: ['English'], + name: 'StockwarePro', + origin: 'IN', + platforms: ['WINDOWS'], + pricingPerYear: '$70', + slogan: 'Signals are often lagging, AI gives us the leading edge!', + updatedAt: '2026-09-23', + url: 'https://www.stockwarepro.com' + }, { categories: ['STOCK_TRACKING'], hasFreePlan: true, @@ -2330,6 +3010,25 @@ export const personalFinanceTools: Product[] = ( slogan: 'Make your money go further with daily budgets', url: 'https://www.todays-budget.com' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'DIVIDEND_TRACKING', + 'ETF_TRACKING', + 'STOCK_TRACKING', + 'TAX_REPORTING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'track-my-shares', + languages: ['English'], + name: 'Track My Shares', + platforms: ['WEB'], + pricingPerYear: '$49.99', + slogan: 'The portfolio tracker that handles your tax time too.', + updatedAt: '2026-09-23', + url: 'https://trackmyshares.com' + }, { categories: ['ETF_TRACKING'], founded: 2016, @@ -2364,6 +3063,22 @@ export const personalFinanceTools: Product[] = ( 'Follow the Performance, Payments, and Diversification of Your Dividend Portfolio', url: 'https://www.trackyourdividends.com' }, + { + categories: ['CRYPTOCURRENCY', 'STOCK_TRACKING'], + founded: 2026, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'trade-journal-ai', + languages: ['English'], + name: 'Trade Journal AI', + origin: 'US', + platforms: ['IOS', 'WEB'], + pricingPerYear: '$195', + slogan: + 'The AI trading journal that reads every entry — not just every trade', + updatedAt: '2026-09-23', + url: 'https://tradejournal.ai' + }, { key: 'tradebb', name: 'TradeBB', @@ -2380,6 +3095,34 @@ export const personalFinanceTools: Product[] = ( slogan: 'Take Control Of Trader Taxes', url: 'https://tradelog.com' }, + { + categories: ['CRYPTOCURRENCY', 'ETF_TRACKING', 'STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'tradersforge-journal', + languages: ['English', 'Español', 'Português'], + name: 'TradersForge Journal', + origin: 'US', + platforms: ['IOS', 'WEB'], + pricingPerYear: '$100', + slogan: 'Your Trading Journal — now with Forge.', + updatedAt: '2026-09-23', + url: 'https://app.tradersforge.net' + }, + { + categories: ['CRYPTOCURRENCY', 'STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'traderswatcher', + languages: ['English'], + name: 'TradersWatcher', + origin: 'CA', + platforms: ['WEB'], + pricingPerYear: '$290', + slogan: 'The journal that watches you trade.', + updatedAt: '2026-09-23', + url: 'https://traderswatcher.com' + }, { founded: 2011, hasFreePlan: false, @@ -2449,6 +3192,20 @@ export const personalFinanceTools: Product[] = ( slogan: 'The Stock Market Platform to Stay Ahead', url: 'https://trendlyne.com' }, + { + categories: ['CRYPTOCURRENCY', 'INVESTMENT_RESEARCH'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'trendspider', + languages: ['English'], + name: 'TrendSpider', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$708', + slogan: 'Welcome to the AI-Powered Super Platform for Active Investors', + updatedAt: '2026-09-23', + url: 'https://trendspider.com' + }, { categories: ['NET_WORTH_TRACKING'], founded: 2020, @@ -2482,6 +3239,37 @@ export const personalFinanceTools: Product[] = ( slogan: 'Analyzing stocks has never been easier', url: 'https://www.tweenvest.com' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'ETF_TRACKING', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'tykr', + languages: ['English'], + name: 'Tykr', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$99.99', + slogan: 'Clear Confident Investing', + updatedAt: '2026-09-23', + url: 'https://tykr.com' + }, + { + categories: ['CRYPTOCURRENCY', 'STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'ultratrader', + name: 'UltraTrader', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$108', + slogan: 'The Best Trading Journal for Web & Mobile', + updatedAt: '2026-09-23', + url: 'https://ultratrader.app' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'uncle-stock', @@ -2490,6 +3278,19 @@ export const personalFinanceTools: Product[] = ( slogan: 'Fundamental Stock Screener', url: 'https://www.unclestock.com' }, + { + categories: ['STOCK_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'upogee', + languages: ['English', 'Español'], + name: 'Upogee', + origin: 'ES', + platforms: ['WEB'], + slogan: 'See whether what you’re doing with your investments is working.', + updatedAt: '2026-09-23', + url: 'https://upogee.com' + }, { categories: ['STOCK_TRACKING'], hasFreePlan: true, @@ -2523,6 +3324,35 @@ export const personalFinanceTools: Product[] = ( slogan: 'Track your real portfolio. Not a watchlist.', url: 'https://valuedge.app' }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'valuescreener', + languages: ['English'], + name: 'ValueScreener', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$228', + slogan: + 'We draft the numbers. You write the reason. We tell you the day one breaks.', + updatedAt: '2026-09-23', + url: 'https://valuescreener.ai' + }, + { + categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], + hasFreePlan: false, + hasSelfHostingAbility: true, + key: 'vectorvest', + languages: ['English'], + name: 'VectorVest', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB', 'WINDOWS'], + pricingPerYear: '$499', + slogan: 'Protect & grow your stock portfolio in only 10 minutes a day', + updatedAt: '2026-09-23', + url: 'https://www.vectorvest.com' + }, { categories: ['FAMILY_OFFICE', 'WEALTH_MANAGEMENT'], founded: 2020, @@ -2572,6 +3402,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Stock market analysis for the serious part-time investor', url: 'https://www.wallstreetzen.com' }, + { + categories: ['FAMILY_OFFICE', 'TAX_REPORTING'], + founded: 2001, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'wealth-write-up', + languages: ['English', 'Français'], + name: 'Wealth Write.Up', + origin: 'CA', + platforms: ['WEB'], + pricingPerYear: 'CAD 899', + slogan: 'The Competitive Edge in Investment Accounting', + updatedAt: '2026-09-23', + url: 'https://wealthwriteup.com' + }, { categories: ['FAMILY_OFFICE', 'WEALTH_MANAGEMENT'], founded: 2015, From af3d72f94c61d0d0380798f21567de70e4d4adc6 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Thu, 24 Sep 2026 08:01:51 +0200 Subject: [PATCH 03/19] Task/refresh cryptocurrencies list (20260923) (#7943) * Update cryptocurrencies.json * Update changelog --- CHANGELOG.md | 1 + .../cryptocurrencies/cryptocurrencies.json | 38 ++++++++++--------- 2 files changed, 21 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index b7acd3e068..0fa122381c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Refreshed the cryptocurrencies list - Upgraded `bull-board` from version `9.9.0` to `9.10.1` - Upgraded `zod` from version `4.5.4` to `4.6.5` diff --git a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json index 69d4552648..7e9558bbbd 100644 --- a/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json +++ b/apps/api/src/assets/cryptocurrencies/cryptocurrencies.json @@ -459,7 +459,7 @@ "AHARWBTC": "Aave Harmony WBTC", "AHOO": "Ahoolee", "AHT": "AhaToken", - "AI": "Flourishing AI", + "AI": "Gensyn", "AI16Z": "ai16z", "AI21X": "ai21x", "AI23T": "23 Turtles", @@ -467,7 +467,7 @@ "AI3": "Autonomys Network", "AI4": "AI⁴", "AI69SAKURA": "Sakura", - "AIA": "AIA Chain", + "AIA": "DeAgentAI", "AIACHAIN": "AIA Chain", "AIAF": "AI Agent Factory", "AIAGENT": "AI Agents", @@ -1338,7 +1338,6 @@ "AUX": "Auxilium", "AV": "AvatarCoin", "AVA": "AVA", - "AVA34326": "AVA Chiang Mai Night Safari", "AVAAI": "Ava AI", "AVACN": "AVACOIN", "AVAI": "Orca AVAI", @@ -2066,7 +2065,7 @@ "BHIGH": "Backed HIGH € High Yield Corp Bond", "BHIRE": "BitHIRE", "BHIVE": "Hive", - "BHO": "Bholdus", + "BHO": "Bholdus Token", "BHP": "Blockchain of Hash Power", "BHPC": "BHPCash", "BIAFRA": "Biafra Coin", @@ -3064,6 +3063,7 @@ "BTU": "BTU Protocol", "BTV": "Bitvote", "BTW": "BitWhite", + "BTW39158": "Bitway", "BTX": "BitCore", "BTXC": "Bettex coin", "BTXEX": "BTXEX", @@ -4055,7 +4055,6 @@ "COMAI": "Commune AI", "COMB": "Combine.finance", "COMBO": "COMBO", - "COMBO8259": "Furucombo", "COMBOX": "ComBox", "COMC": "ComCrica Token", "COME": "Community of Meme", @@ -4096,7 +4095,7 @@ "COOHA": "CoolHash", "COOK": "Cook Finance", "COOK33720": "mETH Protocol", - "COOKIE": "CookieSale", + "COOKIE": "Cookie DAO", "COOKTOKEN": "Cook", "COOL": "CoolCoin", "COOP": "Coop Network", @@ -8898,6 +8897,7 @@ "IMS": "Independent Money System", "IMST": "Imsmart", "IMT": "Moneytoken", + "IMU": "Immunefi", "IMUSIFY": "imusify", "IMVR": "ImmVRse", "IMX": "Immutable", @@ -9654,6 +9654,7 @@ "KINECOSYSTEM": "Kin", "KINET": "KinetixFi", "KING": "King Swap", + "KING33695": "King Protocol", "KING93": "King93", "KINGB": "King Bean", "KINGBONK": "King Bonk", @@ -9981,7 +9982,6 @@ "LAELAPS": "Laelaps", "LAFFIN": "Laffin Kamala", "LAI": "LayerAI", - "LAI23846": "LayerAI", "LAIKA": "LAIKA", "LAIKAPROTOCOL": "Laika Protocol", "LAINESOL": "Laine Staked SOL", @@ -11576,7 +11576,8 @@ "MOMO": "Momo", "MOMO2": "MOMO 2.0", "MOMO2025": "momo", - "MON": "PocMon", + "MON": "Monad", + "MON22337": "PocMon", "MON30495": "Monad", "MON30950": "MON", "MONA": "MonaCoin", @@ -11645,7 +11646,6 @@ "MOOMEME": "MOO MOO", "MOOMOO": "MOOMOO THE BULL", "MOON": "MoonSwap", - "MOON7396": "r/CryptoCurrency Moons", "MOONARCH": "Moonarch.app", "MOONB": "Moon Base", "MOONBEANS": "Moonbeans", @@ -13604,7 +13604,8 @@ "PHV": "PATHHIVE", "PHX": "Phoenix Global [old]", "PHY": "DePHY", - "PI": "Plian", + "PI": "Pi Network", + "PI2620": "Plian", "PI35697": "Pi", "PIA": "Olympia AI", "PIAI": "Pi Network AI", @@ -13830,7 +13831,7 @@ "PNDC": "Pond Coin", "PNDN": "Pandana", "PNDO": "Pondo", - "PNDR": "Pandora Protocol", + "PNDR": "Pandora Finance", "PNFT": "Pawn My NFT", "PNG": "Pangolin", "PNGDA": "Pengda Yellow Panda", @@ -14001,7 +14002,7 @@ "POWERMARKET": "POWER MARKET", "POWR": "Powerledger", "POWSCHE": "Powsche", - "POX": "Pollux Coin", + "POX": "Monkey Pox", "POZO": "Pozo Coin", "PP": "Phoenix Protocol Dao", "PPAD": "PlayPad", @@ -14508,6 +14509,7 @@ "RAIL": "Railgun", "RAILS": "Rails Token", "RAIN": "Rainmaker Games", + "RAIN38341": "Rain", "RAINBOW": "Rainbow Token", "RAINBOWTOKEN": "Rainbow Token", "RAINC": "RainCheck", @@ -15930,7 +15932,8 @@ "SKULL": "Skull Order", "SKUY": "SEKUYA", "SKX": "SKPANAX", - "SKY": "Skycoin", + "SKY": "Sky", + "SKY1619": "Skycoin", "SKY33038": "Sky", "SKYA": "Sekuya Multiverse", "SKYAI": "SKYAI", @@ -18274,7 +18277,8 @@ "USDQ": "Quantoz USDQ", "USDQSTABLE": "USDQ", "USDR": "Wrapped USDR", - "USDS": "Stably Classic", + "USDS": "USDS", + "USDS20039": "USDS", "USDS33039": "USDS", "USDSB": "USDSB", "USDSTABLY": "StableUSD", @@ -18698,7 +18702,7 @@ "VPAY": "VPay by Virtuals", "VPK": "Vulture Peak", "VPND": "VaporNodes", - "VPP": "Virtue Poker", + "VPP": "Virtue Poker Points", "VPR": "VaporWallet", "VPRC": "VapersCoin", "VPS": "VPS AI", @@ -18948,7 +18952,7 @@ "WDOT": "WDOT", "WDR": "Wider Coin", "WDX": "WeiDex", - "WE": "Wanda Exchange", + "WE": "WeBuy", "WEALTH": "WealthCoin", "WEAPON": "MEGAWEAPON", "WEAR": "MetaWear", @@ -19116,7 +19120,6 @@ "WINB": "WINBIT CASINO", "WINE": "Wine Shares", "WING": "Wing Finance", - "WING7048": "Wing Finance", "WINGS": "Wings", "WINK": "Wink", "WINN": "Winnerz", @@ -19687,7 +19690,6 @@ "XPLA": "XPLA", "XPLL": "ParallelChain", "XPM": "Primecoin", - "XPM20261": "XPMarket", "XPN": "PANTHEON X", "XPND": "Time Raiders", "XPNET": "XP NETWORK", From c8a7e31f2bb3be15b73086bf6d7701e4894c8560 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 26 Sep 2026 09:12:46 +0200 Subject: [PATCH 04/19] Task/extend personal finance tools (20260923) part II (#7941) Extend personal finance tools --- libs/common/src/lib/personal-finance-tools.ts | 258 +++++++++++++++++- .../src/lib/types/product-category.type.ts | 1 + libs/ui/src/lib/i18n.ts | 1 + 3 files changed, 247 insertions(+), 13 deletions(-) diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index 31e43bf21b..fcc4901de1 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -5,6 +5,7 @@ export const personalFinanceTools: Product[] = ( { categories: [ 'FAMILY_OFFICE', + 'FINANCIAL_ADVISOR', 'FINANCIAL_PLANNING', 'NET_WORTH_TRACKING', 'WEALTH_MANAGEMENT' @@ -40,6 +41,32 @@ export const personalFinanceTools: Product[] = ( slogan: 'Transform your business with Addepar', url: 'https://addepar.com' }, + { + alias: 'APX', + categories: ['FAMILY_OFFICE', 'FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], + hasSelfHostingAbility: true, + key: 'advent-portfolio-exchange', + name: 'Advent Portfolio Exchange', + origin: 'US', + platforms: ['WEB'], + slogan: 'Simplify portfolio accounting and reporting', + updatedAt: '2026-09-23', + url: 'https://www.advent.com/solutions/advent-portfolio-exchange' + }, + { + categories: [ + 'FINANCIAL_ADVISOR', + 'FINANCIAL_PLANNING', + 'NET_WORTH_TRACKING', + 'WEALTH_MANAGEMENT' + ], + key: 'advisorengine', + name: 'AdvisorEngine', + origin: 'US', + slogan: 'Your complete wealth management platform', + updatedAt: '2026-09-23', + url: 'https://www.advisorengine.com' + }, { categories: ['WEALTH_MANAGEMENT'], key: 'akkuro', @@ -91,7 +118,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://alpgain.ch' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], hasFreePlan: false, hasSelfHostingAbility: false, key: 'alphaquark', @@ -127,7 +154,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://altoo.io' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], founded: 2018, hasFreePlan: false, hasSelfHostingAbility: false, @@ -318,6 +345,18 @@ export const personalFinanceTools: Product[] = ( updatedAt: '2026-09-23', url: 'https://www.benzinga.com/pro' }, + { + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], + founded: 2014, + hasSelfHostingAbility: false, + key: 'betterment-advisor-solutions', + name: 'Betterment Advisor Solutions', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + slogan: 'The independent custodian built for independent advisors', + updatedAt: '2026-09-23', + url: 'https://www.betterment.com/advisors' + }, { categories: ['BUDGETING'], founded: 2022, @@ -523,7 +562,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://cointracking.info' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], hasSelfHostingAbility: true, key: 'comarch-wealth-management', name: 'Comarch Wealth Management', @@ -582,6 +621,19 @@ export const personalFinanceTools: Product[] = ( updatedAt: '2026-09-23', url: 'https://coveredge.io' }, + { + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], + founded: 1987, + hasSelfHostingAbility: false, + key: 'croesus-advisor', + languages: ['English', 'Français'], + name: 'Croesus Advisor', + origin: 'CA', + slogan: + 'A trusted, all-in-one, customizable portfolio management system that empowers top-performing advisors and firms.', + updatedAt: '2026-09-23', + url: 'https://www.croesus.com/solutions/portfolio-management' + }, { categories: ['CRYPTOCURRENCY'], founded: 2021, @@ -626,7 +678,11 @@ export const personalFinanceTools: Product[] = ( url: 'https://de.fi' }, { - categories: ['INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT'], + categories: [ + 'FINANCIAL_ADVISOR', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], key: 'deepvest', name: 'DeepVest', slogan: @@ -774,6 +830,17 @@ export const personalFinanceTools: Product[] = ( slogan: 'The Portfolio Tracker that replaces your spreadsheets', url: 'https://www.donkycapital.com' }, + { + categories: ['BUDGETING', 'FINANCIAL_ADVISOR', 'FINANCIAL_PLANNING'], + hasSelfHostingAbility: false, + key: 'emoney', + name: 'eMoney', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + slogan: 'Everything you need. Every stage of advice.', + updatedAt: '2026-09-23', + url: 'https://emoneyadvisor.com' + }, { categories: ['FINANCIAL_PLANNING', 'NET_WORTH_TRACKING'], founded: 2009, @@ -818,7 +885,26 @@ export const personalFinanceTools: Product[] = ( url: 'https://www.envestnet.com' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: [ + 'BUDGETING', + 'FINANCIAL_ADVISOR', + 'FINANCIAL_PLANNING', + 'NET_WORTH_TRACKING' + ], + founded: 1985, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'envestnet-moneyguide', + name: 'Envestnet MoneyGuide', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$2000', + slogan: 'A Comprehensive Planning Platform', + updatedAt: '2026-09-23', + url: 'https://www.moneyguidepro.com' + }, + { + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], key: 'envestnet-tamarac', name: 'Envestnet Tamarac', slogan: 'Envestnet Tamarac. Built for the way RIAs work.', @@ -876,7 +962,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://www.etfrc.com' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], hasSelfHostingAbility: false, key: 'etna-financial-advisor-software', name: 'ETNA Financial Advisor Software', @@ -994,6 +1080,19 @@ export const personalFinanceTools: Product[] = ( slogan: 'Make better investments.', url: 'https://fey.com' }, + { + categories: ['FINANCIAL_ADVISOR', 'INVESTMENT_RESEARCH'], + founded: 1999, + hasSelfHostingAbility: false, + key: 'fiduciary-focus-toolkit', + name: 'Fiduciary Focus Toolkit', + note: 'Originally named as Fi360 Toolkit', + origin: 'US', + platforms: ['WEB'], + slogan: 'Your all-in-one solution', + updatedAt: '2026-09-23', + url: 'https://www.broadridge.com/hub/fiduciary-governance-solutions/investment-and-account-evaluation-tools' + }, { founded: 2023, hasFreePlan: true, @@ -1093,7 +1192,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://fincite.de' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], hasSelfHostingAbility: true, key: 'finfolio', name: 'FinFolio', @@ -1123,7 +1222,11 @@ export const personalFinanceTools: Product[] = ( url: 'https://fintel.io' }, { - categories: ['INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT'], + categories: [ + 'FINANCIAL_ADVISOR', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], hasSelfHostingAbility: false, key: 'fintellion', name: 'Fintellion', @@ -1603,6 +1706,26 @@ export const personalFinanceTools: Product[] = ( slogan: 'The Time Machine for your Net Worth', url: 'https://www.kubera.com' }, + { + categories: [ + 'FINANCIAL_ADVISOR', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], + founded: 2008, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'kwanti', + languages: ['English'], + name: 'Kwanti', + note: 'Originally named as Portfolio Lab', + origin: 'US', + platforms: ['WEB'], + pricingPerYear: '$2628', + slogan: 'Smart Analytics for Data-Driven Advisors', + updatedAt: '2026-09-23', + url: 'https://kwanti.com' + }, { categories: [ 'CRYPTOCURRENCY', @@ -1619,7 +1742,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://my.kyro.app' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], founded: 2021, hasFreePlan: false, key: 'leafs', @@ -1865,6 +1988,20 @@ export const personalFinanceTools: Product[] = ( slogan: 'Personal Budgeting Software for Mac and iOS', url: 'https://moneywell.app' }, + { + categories: ['BUDGETING', 'FINANCIAL_PLANNING', 'NET_WORTH_TRACKING'], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'moneywellth', + languages: ['English'], + name: 'MoneyWellth', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$84.99', + slogan: 'Make Money Simple with MoneyWellth', + updatedAt: '2026-09-23', + url: 'https://www.moneywellth.com' + }, { categories: ['BUDGETING'], key: 'moneywiz', @@ -1901,6 +2038,21 @@ export const personalFinanceTools: Product[] = ( slogan: 'Smart, simple, stress-free money tracking.', url: 'https://www.monsy.app' }, + { + categories: [ + 'FINANCIAL_ADVISOR', + 'FINANCIAL_PLANNING', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], + key: 'morningstar-direct-advisory-suite', + name: 'Morningstar Direct Advisory Suite', + note: 'Originally named as Advisor Workstation', + origin: 'US', + slogan: 'Build trust. Showcase value. Deliver elevated advice at scale.', + updatedAt: '2026-09-23', + url: 'https://www.morningstar.com/business/products/direct-advisory-suite' + }, { categories: ['INVESTMENT_RESEARCH', 'STOCK_TRACKING'], hasFreePlan: true, @@ -2026,6 +2178,7 @@ export const personalFinanceTools: Product[] = ( }, { categories: [ + 'FINANCIAL_ADVISOR', 'FINANCIAL_PLANNING', 'INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT' @@ -2062,7 +2215,28 @@ export const personalFinanceTools: Product[] = ( url: 'https://onlydividends.app' }, { - categories: ['INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT'], + categories: [ + 'FAMILY_OFFICE', + 'FINANCIAL_ADVISOR', + 'FINANCIAL_PLANNING', + 'WEALTH_MANAGEMENT' + ], + founded: 1999, + hasSelfHostingAbility: false, + key: 'orion-advisor-technology', + name: 'Orion Advisor Technology', + origin: 'US', + platforms: ['WEB'], + slogan: 'Run a firm where every advisor can thrive.', + updatedAt: '2026-09-23', + url: 'https://orion.com/advisor-tech' + }, + { + categories: [ + 'FINANCIAL_ADVISOR', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], hasFreePlan: false, hasSelfHostingAbility: false, key: 'orion-risk-intelligence', @@ -2075,6 +2249,25 @@ export const personalFinanceTools: Product[] = ( updatedAt: '2026-09-23', url: 'https://orion.com/advisor-tech/risk-intelligence' }, + { + categories: [ + 'CRYPTOCURRENCY', + 'ETF_TRACKING', + 'FAMILY_OFFICE', + 'INVESTMENT_RESEARCH', + 'STOCK_TRACKING' + ], + hasFreePlan: true, + hasSelfHostingAbility: false, + key: 'palance', + languages: ['English', '日本語', '中文'], + name: 'Palance', + platforms: ['WEB'], + pricingPerYear: '$1200', + slogan: 'Markets, in clarity.', + updatedAt: '2026-09-23', + url: 'https://palance.co' + }, { categories: ['INVESTMENT_RESEARCH'], hasFreePlan: false, @@ -2445,7 +2638,7 @@ export const personalFinanceTools: Product[] = ( url: 'https://prostocktracker.com' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], founded: 2007, key: 'pulse-by-assetbook', languages: ['English'], @@ -2518,6 +2711,25 @@ export const personalFinanceTools: Product[] = ( slogan: 'Das kostenfreie Tool für Ihren Finanzerfolg', url: 'https://www.rentablo.de' }, + { + categories: [ + 'BUDGETING', + 'FINANCIAL_ADVISOR', + 'FINANCIAL_PLANNING', + 'NET_WORTH_TRACKING' + ], + founded: 2015, + hasFreePlan: false, + hasSelfHostingAbility: false, + key: 'rightcapital', + name: 'RightCapital', + origin: 'US', + platforms: ['ANDROID', 'IOS', 'WEB'], + pricingPerYear: '$1799.40', + slogan: 'Financial planning software done right', + updatedAt: '2026-09-23', + url: 'https://www.rightcapital.com' + }, { categories: ['BUDGETING', 'NET_WORTH_TRACKING'], founded: 2015, @@ -2720,7 +2932,7 @@ export const personalFinanceTools: Product[] = ( slogan: 'Manage your money anytime, anywhere.' }, { - categories: ['WEALTH_MANAGEMENT'], + categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], key: 'ssc-black-diamond', name: 'SS&C Black Diamond Wealth Solutions', slogan: 'The Cornerstone of a Successful Business', @@ -2914,6 +3126,22 @@ export const personalFinanceTools: Product[] = ( slogan: 'Visualize all of your portfolios', url: 'https://stonksfolio.com' }, + { + categories: [ + 'FINANCIAL_ADVISOR', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], + hasFreePlan: false, + key: 'stratifi', + name: 'StratiFi', + platforms: ['WEB'], + pricingPerYear: '$5995', + slogan: + 'Use AI trained by top independent wealth firms, engineered with sophisticated quant finance & grounded in proven behavioral finance.', + updatedAt: '2026-09-23', + url: 'https://www.stratifi.com' + }, { categories: ['INVESTMENT_RESEARCH'], key: 'streamxls', @@ -3507,7 +3735,11 @@ export const personalFinanceTools: Product[] = ( url: 'https://www.wisesheets.io' }, { - categories: ['INVESTMENT_RESEARCH', 'WEALTH_MANAGEMENT'], + categories: [ + 'FINANCIAL_ADVISOR', + 'INVESTMENT_RESEARCH', + 'WEALTH_MANAGEMENT' + ], key: 'ycharts', name: 'YCharts', slogan: 'Financial Research and Proposal Platform', diff --git a/libs/common/src/lib/types/product-category.type.ts b/libs/common/src/lib/types/product-category.type.ts index 7fae17a72f..12976f0323 100644 --- a/libs/common/src/lib/types/product-category.type.ts +++ b/libs/common/src/lib/types/product-category.type.ts @@ -4,6 +4,7 @@ export type ProductCategory = | 'DIVIDEND_TRACKING' | 'ETF_TRACKING' | 'FAMILY_OFFICE' + | 'FINANCIAL_ADVISOR' | 'FINANCIAL_PLANNING' | 'INVESTMENT_RESEARCH' | 'NET_WORTH_TRACKING' diff --git a/libs/ui/src/lib/i18n.ts b/libs/ui/src/lib/i18n.ts index 5051c9aa5a..4040b45c57 100644 --- a/libs/ui/src/lib/i18n.ts +++ b/libs/ui/src/lib/i18n.ts @@ -107,6 +107,7 @@ const locales = { DIVIDEND_TRACKING: $localize`Dividend Tracking`, ETF_TRACKING: $localize`ETF Tracking`, FAMILY_OFFICE: $localize`Family Office`, + FINANCIAL_ADVISOR: $localize`Financial Advisor`, FINANCIAL_PLANNING: $localize`Financial Planning`, INVESTMENT_RESEARCH: $localize`Investment Research`, NET_WORTH_TRACKING: $localize`Net Worth Tracking`, From 8f2d42640f91b1fba1134ec9768e22a91f803f59 Mon Sep 17 00:00:00 2001 From: Dani Date: Sat, 26 Sep 2026 00:13:31 -0700 Subject: [PATCH 05/19] Task/improve Catalan localization (#7947) * Update translations * Update changelog --- CHANGELOG.md | 1 + apps/client/src/locales/messages.ca.xlf | 20 ++++++++++---------- 2 files changed, 11 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0fa122381c..c0b7e512a0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Refreshed the cryptocurrencies list +- Improved the language localization for Catalan (`ca`) - Upgraded `bull-board` from version `9.9.0` to `9.10.1` - Upgraded `zod` from version `4.5.4` to `4.6.5` diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 525d25fb23..610cca4ca3 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -3,7 +3,7 @@ Invalid API key - Invalid API key + Clau API no vàlida apps/client/src/app/components/admin-settings/admin-settings.component.html 115 @@ -516,7 +516,7 @@ Copy - Copy + Copia libs/ui/src/lib/notifications/alert-dialog/alert-dialog.html 20 @@ -788,7 +788,7 @@ Unknown - Unknown + Desconegut libs/ui/src/lib/i18n.ts 89 @@ -904,7 +904,7 @@ Find an account... - Find an account... + Cerca un compte... libs/ui/src/lib/assistant/assistant.component.ts 450 @@ -984,7 +984,7 @@ Category - Category + Categoria apps/client/src/app/pages/resources/personal-finance-tools/product-page.html 76 @@ -1644,7 +1644,7 @@ Current year - Current year + Any actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts 267 @@ -2080,7 +2080,7 @@ Last Used - Last Used + Últim ús apps/client/src/app/components/access-table/access-table.component.html 31 @@ -2184,7 +2184,7 @@ Current week - Current week + Setmana actual apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts 259 @@ -2992,7 +2992,7 @@ Next - Next + Següent apps/client/src/app/pages/resources/personal-finance-tools/product-page.html 406 @@ -3148,7 +3148,7 @@ Daily - Daily + Diàriament apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts 247 From 363ae34bded8883a912644b755108c6ebd1c957c Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 26 Sep 2026 09:41:41 +0200 Subject: [PATCH 06/19] Bugfix/value of holdings excluded from analysis in portfolio summary (#7945) * Fix value of holdings excluded from analysis in portfolio summary * Update changelog --- CHANGELOG.md | 4 + .../app/portfolio/portfolio.service.spec.ts | 198 +++++++++++++++++- .../src/app/portfolio/portfolio.service.ts | 127 +++++++++-- 3 files changed, 307 insertions(+), 22 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c0b7e512a0..d69d280038 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -14,6 +14,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Upgraded `bull-board` from version `9.9.0` to `9.10.1` - Upgraded `zod` from version `4.5.4` to `4.6.5` +### Fixed + +- Fixed the value of the holdings excluded from analysis in the portfolio summary + ## 3.72.0 - 2026-09-20 ### Added diff --git a/apps/api/src/app/portfolio/portfolio.service.spec.ts b/apps/api/src/app/portfolio/portfolio.service.spec.ts index 59addfb44e..223a8964c1 100644 --- a/apps/api/src/app/portfolio/portfolio.service.spec.ts +++ b/apps/api/src/app/portfolio/portfolio.service.spec.ts @@ -773,6 +773,27 @@ describe('PortfolioService', () => { ).getSummary(args); }; + function createExcludedActivity({ + currency = 'CHF', + quantity, + symbol, + type, + unitPrice + }: Pick & { + currency?: string; + symbol: string; + }) { + return { + currency, + quantity, + type, + unitPrice, + account: { tags: [{ id: TAG_ID_EXCLUDE_FROM_ANALYSIS }] }, + assetProfile: { currency, symbol, dataSource: DataSource.YAHOO }, + tags: [] + } as unknown as Activity; + } + function createPortfolioCalculator() { return { getDividendInBaseCurrency: jest.fn().mockResolvedValue(new Big(0)), @@ -791,9 +812,13 @@ describe('PortfolioService', () => { beforeEach(() => { jest - .spyOn(activitiesService, 'getActivities') + .spyOn(activitiesService, 'getActivitiesForPortfolioCalculator') .mockResolvedValue({ activities: [], count: 0 }); + jest + .spyOn(exchangeRateDataService, 'toCurrency') + .mockImplementation((aValue) => aValue); + jest.spyOn(portfolioService, 'getPerformance').mockResolvedValue({ performance: { currentValueInBaseCurrency: 3000, @@ -837,6 +862,177 @@ describe('PortfolioService', () => { expect(summary.totalAssetsInBaseCurrency).toBe(3000); expect(summary.totalValueInBaseCurrency).toBe(3000); }); + + it('should value the open holdings of excluded accounts at the current market price', async () => { + jest.spyOn(accountService, 'getCashDetails').mockResolvedValue({ + accounts: [], + balanceInBaseCurrency: 1500 + }); + + jest + .spyOn(activitiesService, 'getActivitiesForPortfolioCalculator') + .mockResolvedValue({ + activities: [ + createExcludedActivity({ + quantity: 10, + symbol: 'AAPL', + type: 'BUY', + unitPrice: 100 + }), + createExcludedActivity({ + quantity: 4, + symbol: 'AAPL', + type: 'SELL', + unitPrice: 150 + }), + createExcludedActivity({ + quantity: 5, + symbol: 'MSFT', + type: 'BUY', + unitPrice: 100 + }), + createExcludedActivity({ + quantity: 5, + symbol: 'MSFT', + type: 'SELL', + unitPrice: 120 + }) + ], + count: 4 + }); + + const getQuotes = jest + .spyOn(dataProviderService, 'getQuotes') + .mockResolvedValue({ + 'YAHOO-AAPL': { + currency: 'CHF', + dataSource: DataSource.YAHOO, + marketPrice: 200, + marketState: 'open' + } + }); + + const summary = await getSummary({ + balanceInBaseCurrency: 1000, + emergencyFundHoldingsValueInBaseCurrency: 0, + filteredValueInBaseCurrency: new Big(3000), + portfolioCalculator: createPortfolioCalculator(), + userCurrency: 'CHF', + userId: userDummyData.id + }); + + // The closed holding (MSFT) does not need a quote + expect(getQuotes).toHaveBeenCalledWith( + expect.objectContaining({ + items: [{ dataSource: DataSource.YAHOO, symbol: 'AAPL' }] + }) + ); + + // 500 (balance of excluded accounts) + 6 * 200 (AAPL) + 0 (MSFT) + expect(summary.excludedAccountsAndActivities).toBe(1700); + expect(summary.totalValueInBaseCurrency).toBe(4700); + }); + + it('should convert the market value of an excluded holding from the currency of the asset profile to the user currency', async () => { + jest.spyOn(accountService, 'getCashDetails').mockResolvedValue({ + accounts: [], + balanceInBaseCurrency: 1000 + }); + + jest + .spyOn(activitiesService, 'getActivitiesForPortfolioCalculator') + .mockResolvedValue({ + activities: [ + createExcludedActivity({ + currency: 'USD', + quantity: 10, + symbol: 'AAPL', + type: 'BUY', + unitPrice: 100 + }), + createExcludedActivity({ + currency: 'USD', + quantity: 4, + symbol: 'AAPL', + type: 'SELL', + unitPrice: 150 + }) + ], + count: 2 + }); + + jest.spyOn(dataProviderService, 'getQuotes').mockResolvedValue({ + 'YAHOO-AAPL': { + currency: 'USD', + dataSource: DataSource.YAHOO, + marketPrice: 200, + marketState: 'open' + } + }); + + jest + .spyOn(exchangeRateDataService, 'toCurrency') + .mockImplementation((aValue, aFromCurrency, aToCurrency) => { + return aFromCurrency === 'USD' && aToCurrency === 'CHF' + ? aValue * 0.8 + : aValue; + }); + + const summary = await getSummary({ + balanceInBaseCurrency: 1000, + emergencyFundHoldingsValueInBaseCurrency: 0, + filteredValueInBaseCurrency: new Big(3000), + portfolioCalculator: createPortfolioCalculator(), + userCurrency: 'CHF', + userId: userDummyData.id + }); + + // 6 * 200 USD (AAPL) * 0.8 (USDCHF) + expect(summary.excludedAccountsAndActivities).toBe(960); + expect(summary.totalValueInBaseCurrency).toBe(3960); + }); + + it('should fall back to the unit price of the latest activity of an excluded holding without a market price', async () => { + jest.spyOn(accountService, 'getCashDetails').mockResolvedValue({ + accounts: [], + balanceInBaseCurrency: 1000 + }); + + jest + .spyOn(activitiesService, 'getActivitiesForPortfolioCalculator') + .mockResolvedValue({ + activities: [ + createExcludedActivity({ + quantity: 10, + symbol: 'AAPL', + type: 'BUY', + unitPrice: 100 + }), + createExcludedActivity({ + quantity: 4, + symbol: 'AAPL', + type: 'SELL', + unitPrice: 150 + }) + ], + count: 2 + }); + + jest.spyOn(dataProviderService, 'getQuotes').mockResolvedValue({}); + + const summary = await getSummary({ + balanceInBaseCurrency: 1000, + emergencyFundHoldingsValueInBaseCurrency: 0, + filteredValueInBaseCurrency: new Big(3000), + portfolioCalculator: createPortfolioCalculator(), + userCurrency: 'CHF', + userId: userDummyData.id + }); + + // 6 * 150 (unit price of the latest activity) + expect(summary.excludedAccountsAndActivities).toBe(900); + expect(summary.totalValueInBaseCurrency).toBe(3900); + }); }); describe('getValueOfAccountsAndPlatforms', () => { diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 1476db4ae0..90de5ddc38 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -39,6 +39,7 @@ import { TAG_ID_EXCLUDE_FROM_ANALYSIS, UNKNOWN_KEY } from '@ghostfolio/common/config'; +import { SubscriptionType } from '@ghostfolio/common/enums'; import { DATE_FORMAT, getAssetProfileIdentifier, @@ -2093,11 +2094,12 @@ export class PortfolioService { }): Promise { const user = await this.userService.user({ id: userId }); - const { activities } = await this.activitiesService.getActivities({ - userCurrency, - userId, - withExcludedAccountsAndActivities: true - }); + const { activities } = + await this.activitiesService.getActivitiesForPortfolioCalculator({ + userCurrency, + userId, + withExcludedAccountsAndActivities: true + }); const excludedActivities: Activity[] = []; const nonExcludedActivities: Activity[] = []; @@ -2164,31 +2166,28 @@ export class PortfolioService { .plus(emergencyFundHoldingsValueInBaseCurrency) .toNumber(); - const totalOfExcludedActivities = this.getSumOfActivityType({ - userCurrency, - activities: excludedActivities, - activityType: 'BUY' - }).minus( - this.getSumOfActivityType({ - userCurrency, - activities: excludedActivities, - activityType: 'SELL' - }) - ); - - const cashDetailsWithExcludedAccounts = - await this.accountService.getCashDetails({ + const [ + cashDetailsWithExcludedAccounts, + valueOfExcludedActivitiesInBaseCurrency + ] = await Promise.all([ + this.accountService.getCashDetails({ userId, currency: userCurrency, withExcludedAccounts: true - }); + }), + this.getValueOfExcludedActivitiesInBaseCurrency({ + userCurrency, + activities: excludedActivities, + subscriptionType: user.subscription?.type + }) + ]); const excludedBalanceInBaseCurrency = new Big( cashDetailsWithExcludedAccounts.balanceInBaseCurrency ).minus(balanceInBaseCurrency); const excludedAccountsAndActivities = excludedBalanceInBaseCurrency - .plus(totalOfExcludedActivities) + .plus(valueOfExcludedActivitiesInBaseCurrency) .toNumber(); // Exclude emergency fund from the financial independence calculation @@ -2491,6 +2490,92 @@ export class PortfolioService { return { accounts, platforms }; } + private async getValueOfExcludedActivitiesInBaseCurrency({ + activities, + subscriptionType, + userCurrency + }: { + activities: Activity[]; + subscriptionType?: SubscriptionType; + userCurrency: string; + }) { + const holdings: { + [assetProfileIdentifier: string]: { + latestActivity: Activity; + quantity: Big; + }; + } = {}; + + // The activities are sorted by date in ascending order + for (const activity of activities) { + const factor = getFactor(activity.type); + + if (factor === 0 || isDraftActivity(activity)) { + continue; + } + + const assetProfileIdentifier = getAssetProfileIdentifier( + activity.assetProfile + ); + + const quantity = holdings[assetProfileIdentifier]?.quantity ?? new Big(0); + + holdings[assetProfileIdentifier] = { + latestActivity: activity, + quantity: quantity.plus(new Big(activity.quantity).mul(factor)) + }; + } + + const openHoldings = Object.values(holdings).filter(({ quantity }) => { + return !quantity.eq(0); + }); + + const quotes = + openHoldings.length > 0 + ? await this.dataProviderService.getQuotes({ + subscriptionType, + items: openHoldings.map( + ({ + latestActivity: { + assetProfile: { dataSource, symbol } + } + }) => { + return { dataSource, symbol }; + } + ) + }) + : {}; + + return getSum( + openHoldings.map(({ latestActivity, quantity }) => { + const { assetProfile, currency, unitPrice } = latestActivity; + + const marketPrice = + quotes[getAssetProfileIdentifier(assetProfile)]?.marketPrice; + + if (!marketPrice) { + // Fall back to the unit price of the latest activity without a + // market price + return new Big( + this.exchangeRateDataService.toCurrency( + quantity.mul(unitPrice).toNumber(), + currency ?? assetProfile.currency, + userCurrency + ) + ); + } + + return new Big( + this.exchangeRateDataService.toCurrency( + quantity.mul(marketPrice).toNumber(), + assetProfile.currency, + userCurrency + ) + ); + }) + ); + } + private isExcludedFromAnalysis(activity: Activity) { return ( isAccountExcluded(activity.account) || From 0fc152cc5a49834a725b660c82258d4b0658d9d1 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 26 Sep 2026 10:13:29 +0200 Subject: [PATCH 07/19] Task/filter MCP tools by scopes of access (#7935) * Update @rekog/mcp-nest to version 2.0.7 * Filter MCP tools by scopes of access * Update changelog --- CHANGELOG.md | 2 + .../app/endpoints/mcp/mcp.controller.spec.ts | 105 +++++++++++++++++- .../src/app/endpoints/mcp/mcp.controller.ts | 8 +- apps/api/src/app/endpoints/mcp/mcp.module.ts | 4 +- .../requires-scope-of-access.decorator.ts | 11 +- apps/api/src/guards/access.guard.ts | 8 +- .../src/helper/bearer-token.helper.spec.ts | 31 ++++++ apps/api/src/helper/bearer-token.helper.ts | 29 +++++ package-lock.json | 80 ++++++++++--- package.json | 2 +- 10 files changed, 252 insertions(+), 28 deletions(-) create mode 100644 apps/api/src/helper/bearer-token.helper.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index d69d280038..f4efde2ebb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,8 +9,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Improved the server of the Model Context Protocol (MCP) to list only the tools covered by the scopes of the access (experimental) - Refreshed the cryptocurrencies list - Improved the language localization for Catalan (`ca`) +- Upgraded `@rekog/mcp-nest` from version `2.0.2` to `2.0.7` - Upgraded `bull-board` from version `9.9.0` to `9.10.1` - Upgraded `zod` from version `4.5.4` to `4.6.5` diff --git a/apps/api/src/app/endpoints/mcp/mcp.controller.spec.ts b/apps/api/src/app/endpoints/mcp/mcp.controller.spec.ts index f6e1d04383..4fcb92a9be 100644 --- a/apps/api/src/app/endpoints/mcp/mcp.controller.spec.ts +++ b/apps/api/src/app/endpoints/mcp/mcp.controller.spec.ts @@ -1,13 +1,26 @@ import { REQUIRES_SCOPE_KEY } from '@ghostfolio/api/decorators/requires-scope.decorator'; import { McpToolExceptionFilter } from '@ghostfolio/api/filters/mcp-tool-exception.filter'; import { AccessGuard } from '@ghostfolio/api/guards/access.guard'; -import { Scope, scopes } from '@ghostfolio/common/scopes'; +import { getMcpUserOfBearerToken } from '@ghostfolio/api/helper/bearer-token.helper'; +import { + getScopesOfAccess, + getScopesOfAccessLevel, + Scope, + scopes +} from '@ghostfolio/common/scopes'; import { EXCEPTION_FILTERS_METADATA, GUARDS_METADATA } from '@nestjs/common/constants'; -import { MCP_TOOL_METADATA_KEY, ToolMetadata } from '@rekog/mcp-nest'; +import { + AccessMatchMode, + MCP_SCOPES_MATCH_METADATA_KEY, + MCP_SCOPES_METADATA_KEY, + MCP_TOOL_METADATA_KEY, + ToolAuthorizationService, + ToolMetadata +} from '@rekog/mcp-nest'; import { GhostfolioMcpController } from './mcp.controller'; @@ -35,6 +48,41 @@ function getToolMethodNames() { ); } +/** + * Gives the names of the tools which the transport lists for the request. The + * metadata of each tool is read as the transport reads it. + */ +function getNamesOfListedTools(request: unknown) { + const toolAuthorizationService = new ToolAuthorizationService(); + const user = getMcpUserOfBearerToken(request); + + return getToolMethodNames() + .map((methodName) => { + return { + metadata: { + ...getMetadataOfMethod( + MCP_TOOL_METADATA_KEY, + methodName + ), + requiredScopes: getMetadataOfMethod( + MCP_SCOPES_METADATA_KEY, + methodName + ), + requiredScopesMatch: getMetadataOfMethod( + MCP_SCOPES_MATCH_METADATA_KEY, + methodName + ) + } + }; + }) + .filter((tool) => { + return toolAuthorizationService.canAccessTool(user, tool); + }) + .map(({ metadata: { name } }) => { + return name; + }); +} + describe('GhostfolioMcpController', () => { // A tool without the decorator of the scope would be open to every access, // hence a new tool has to declare its scope @@ -71,6 +119,59 @@ describe('GhostfolioMcpController', () => { expect(toolMethodNamesWithoutGuardOfAccess).toEqual([]); }); + it('Lists only the tools to read for an access with the permission "Restricted view"', () => { + expect( + getNamesOfListedTools({ + impersonationOfBearerToken: { + isActive: true, + scopes: getScopesOfAccess({ + scopes: getScopesOfAccessLevel('READ_RESTRICTED'), + type: 'MCP' + }) + } + }) + ).toEqual([ + 'get-accounts', + 'get-activities', + 'get-portfolio', + 'get-watchlist' + ]); + }); + + it('Lists every tool for an access with the permission "Restricted view and manage"', () => { + expect( + getNamesOfListedTools({ + impersonationOfBearerToken: { + isActive: true, + scopes: getScopesOfAccess({ + scopes: getScopesOfAccessLevel( + 'CREATE_READ_RESTRICTED_UPDATE_DELETE' + ), + type: 'MCP' + }) + } + }) + ).toEqual([ + 'get-accounts', + 'get-activities', + 'get-portfolio', + 'get-watchlist', + 'import-activities', + 'search-asset-profiles' + ]); + }); + + it('Lists no tool for an inactive access', () => { + expect( + getNamesOfListedTools({ + impersonationOfBearerToken: { + isActive: false, + scopes: getScopesOfAccessLevel('CREATE_READ_RESTRICTED_UPDATE_DELETE') + } + }) + ).toEqual([]); + }); + it('Requires the scope to create an activity for the tool to import activities', () => { expect( getMetadataOfMethod(REQUIRES_SCOPE_KEY, 'importActivities') diff --git a/apps/api/src/app/endpoints/mcp/mcp.controller.ts b/apps/api/src/app/endpoints/mcp/mcp.controller.ts index dee145015f..802567ad35 100644 --- a/apps/api/src/app/endpoints/mcp/mcp.controller.ts +++ b/apps/api/src/app/endpoints/mcp/mcp.controller.ts @@ -101,12 +101,6 @@ export class GhostfolioMcpController { return this.mcpService.getWatchlist({ userId }); } - /** - * The transport gives the tool to every client, because it filters the list - * of the tools by the scopes of request.user, which a request of an access - * never has. The guard refuses the call itself, hence the description names - * the permission which the access needs. - */ @RequiresScopeOfAccess(scopes.activityCreate) @Tool({ annotations: { @@ -115,7 +109,7 @@ export class GhostfolioMcpController { readOnlyHint: false, title: 'Import activities' }, - description: `Imports activities into the portfolio and gives the number of the imported activities and the number of the skipped activities. Use search-asset-profiles first unless the exact symbol and data source are already known. An activity is skipped if an equal activity is in the portfolio already, hence send each activity one time only: two equal activities of the same call are both imported. The access needs the permission "Restricted view and manage". At most ${MCP_MAX_ACTIVITIES} activities are imported per call, while the instance can have a lower limit, which an error names. An error does not remove the activities of the same call which are imported already, hence get the activities after an error before you import them again.`, + description: `Imports activities into the portfolio and gives the number of the imported activities and the number of the skipped activities. Use search-asset-profiles first unless the exact symbol and data source are already known. An activity is skipped if an equal activity is in the portfolio already, hence send each activity one time only: two equal activities of the same call are both imported. At most ${MCP_MAX_ACTIVITIES} activities are imported per call, while the instance can have a lower limit, which an error names. An error does not remove the activities of the same call which are imported already, hence get the activities after an error before you import them again.`, name: 'import-activities', parameters: IMPORT_ACTIVITIES_PARAMETERS }) diff --git a/apps/api/src/app/endpoints/mcp/mcp.module.ts b/apps/api/src/app/endpoints/mcp/mcp.module.ts index be81137f54..1da7a06823 100644 --- a/apps/api/src/app/endpoints/mcp/mcp.module.ts +++ b/apps/api/src/app/endpoints/mcp/mcp.module.ts @@ -2,6 +2,7 @@ import { ImportModule } from '@ghostfolio/api/app/import/import.module'; import { SymbolModule } from '@ghostfolio/api/app/symbol/symbol.module'; import { UserModule } from '@ghostfolio/api/app/user/user.module'; import { environment } from '@ghostfolio/api/environments/environment'; +import { getMcpUserOfBearerToken } from '@ghostfolio/api/helper/bearer-token.helper'; import { ApiModule } from '@ghostfolio/api/services/api/api.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; @@ -38,8 +39,9 @@ import { McpService } from './mcp.service'; return new McpStrategy({ instructions: - 'Ghostfolio is a wealth management application. The tools read the portfolio and the watchlist of the user who granted the access and import activities into the portfolio. They give no quantity and no monetary value (except the unit price of an activity).', + 'Ghostfolio is a wealth management application. The tools read the portfolio and the watchlist of the user who granted the access and import activities into the portfolio. They give no quantity and no monetary value (except the unit price of an activity). Only the tools which the permission of the access covers are listed. To import activities, the access needs the permission "Restricted view and manage".', name: 'ghostfolio', + resolveUser: getMcpUserOfBearerToken, title: 'Ghostfolio', transports: [ new StreamableHttpTransport({ diff --git a/apps/api/src/decorators/requires-scope-of-access.decorator.ts b/apps/api/src/decorators/requires-scope-of-access.decorator.ts index b76f1441c1..f0d35effcb 100644 --- a/apps/api/src/decorators/requires-scope-of-access.decorator.ts +++ b/apps/api/src/decorators/requires-scope-of-access.decorator.ts @@ -4,15 +4,24 @@ import { ScopeGuard } from '@ghostfolio/api/guards/scope.guard'; import { Scope } from '@ghostfolio/common/scopes'; import { applyDecorators, SetMetadata, UseGuards } from '@nestjs/common'; +import { ToolScopes } from '@rekog/mcp-nest'; /** * Marks a handler which requires the given scopes of an access, but no * authenticated user. The access itself is the credential, hence a client of * the model context protocol can use it. + * + * The same scopes are declared to the transport of the model context + * protocol, which lists a tool only for an access whose scopes cover it. The + * transport refuses the call of a tool which it does not list with a protocol + * error before the guards and the filter of the exceptions run. */ -export function RequiresScopeOfAccess(...requiredScopes: Scope[]) { +export function RequiresScopeOfAccess(scope: Scope, ...otherScopes: Scope[]) { + const requiredScopes = [scope, ...otherScopes]; + return applyDecorators( SetMetadata(REQUIRES_SCOPE_KEY, requiredScopes), + ToolScopes(requiredScopes), UseGuards(AccessGuard, ScopeGuard) ); } diff --git a/apps/api/src/guards/access.guard.ts b/apps/api/src/guards/access.guard.ts index 87a1f24692..f57c5a5b85 100644 --- a/apps/api/src/guards/access.guard.ts +++ b/apps/api/src/guards/access.guard.ts @@ -1,3 +1,4 @@ +import { getActiveImpersonationOfBearerToken } from '@ghostfolio/api/helper/bearer-token.helper'; import { getRequest } from '@ghostfolio/api/helper/execution-context.helper'; import type { RequestWithUser } from '@ghostfolio/common/types'; @@ -28,14 +29,17 @@ export class AccessGuard implements CanActivate { public canActivate(context: ExecutionContext) { const request = getRequest(context); - if (!request?.impersonationOfBearerToken?.isActive) { + const impersonationOfBearerToken = + getActiveImpersonationOfBearerToken(request); + + if (!impersonationOfBearerToken) { throw new HttpException( getReasonPhrase(StatusCodes.FORBIDDEN), StatusCodes.FORBIDDEN ); } - request.impersonation = request.impersonationOfBearerToken; + request.impersonation = impersonationOfBearerToken; return true; } diff --git a/apps/api/src/helper/bearer-token.helper.spec.ts b/apps/api/src/helper/bearer-token.helper.spec.ts new file mode 100644 index 0000000000..e2f48ff5bb --- /dev/null +++ b/apps/api/src/helper/bearer-token.helper.spec.ts @@ -0,0 +1,31 @@ +import { scopes } from '@ghostfolio/common/scopes'; + +import { getMcpUserOfBearerToken } from './bearer-token.helper'; + +describe('getMcpUserOfBearerToken', () => { + it('should give the scopes of an active access', () => { + expect( + getMcpUserOfBearerToken({ + impersonationOfBearerToken: { + isActive: true, + scopes: [scopes.portfolioRead] + } + }) + ).toEqual({ scopes: [scopes.portfolioRead] }); + }); + + it('should give no user for an inactive access', () => { + expect( + getMcpUserOfBearerToken({ + impersonationOfBearerToken: { + isActive: false, + scopes: [scopes.portfolioRead] + } + }) + ).toBeUndefined(); + }); + + it('should give no user without an access', () => { + expect(getMcpUserOfBearerToken({})).toBeUndefined(); + }); +}); diff --git a/apps/api/src/helper/bearer-token.helper.ts b/apps/api/src/helper/bearer-token.helper.ts index 5641016f5b..47be1e69b6 100644 --- a/apps/api/src/helper/bearer-token.helper.ts +++ b/apps/api/src/helper/bearer-token.helper.ts @@ -1,3 +1,5 @@ +import type { RequestWithUser } from '@ghostfolio/common/types'; + const PREFIX_OF_BEARER_TOKEN = 'bearer '; /** @@ -16,3 +18,30 @@ export function getAccessIdOfBearerToken(authorization?: string) { ? value.slice(PREFIX_OF_BEARER_TOKEN.length).trim() || undefined : undefined; } + +/** + * Gives the context of the access which the authorization middleware of the + * model context protocol resolved from the bearer token, but only while the + * access is active + */ +export function getActiveImpersonationOfBearerToken( + request?: Pick +) { + return request?.impersonationOfBearerToken?.isActive + ? request.impersonationOfBearerToken + : undefined; +} + +/** + * Gives the user which the transport of the model context protocol evaluates + * to list and to call the tools. It carries the scopes of the active access, + * hence the transport lists only the tools which the access covers. + */ +export function getMcpUserOfBearerToken(request: unknown) { + const impersonationOfBearerToken = + getActiveImpersonationOfBearerToken(request); + + return impersonationOfBearerToken + ? { scopes: impersonationOfBearerToken.scopes } + : undefined; +} diff --git a/package-lock.json b/package-lock.json index 9ed3b35966..9469e56421 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "@openrouter/ai-sdk-provider": "3.0.0", "@prisma/adapter-pg": "7.10.0", "@prisma/client": "7.10.0", - "@rekog/mcp-nest": "2.0.2", + "@rekog/mcp-nest": "2.0.7", "@simplewebauthn/browser": "13.3.0", "@simplewebauthn/server": "13.3.1", "ai": "7.0.37", @@ -13614,14 +13614,13 @@ } }, "node_modules/@rekog/mcp-nest": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@rekog/mcp-nest/-/mcp-nest-2.0.2.tgz", - "integrity": "sha512-kuye6wmRk5Gw4KZSCSXd83cWznRw4eFbvNUXsd8+1dYcS4uWKVVbRvxQIKNCyxc2UcljpsmLpnksr1NCRn3YAQ==", + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@rekog/mcp-nest/-/mcp-nest-2.0.7.tgz", + "integrity": "sha512-8DWrSapEA9Z/YJL9dFmj7sSbemmeQmf0VkGkW6Sn1itwKFf0n9hzTiwWt8XBtZvV5JVDNCtvRZKYYKgNjDcYPg==", "license": "MIT", "dependencies": { - "multer": "^2.2.0", - "path-to-regexp": "^8.4.2", - "rxjs": "^7.8.2" + "multer": "^2.3.0", + "path-to-regexp": "^8.4.2" }, "peerDependencies": { "@modelcontextprotocol/core": "^2.0.0-beta.5", @@ -13630,9 +13629,10 @@ "@nestjs/common": ">=9.0.0", "@nestjs/core": ">=9.0.0", "@nestjs/microservices": ">=9.0.0", - "@nestjs/platform-fastify": "^11.1.5", + "@nestjs/platform-fastify": "^11.1.5 || ^12.0.0", "express": ">=4.0.0", "reflect-metadata": "^0.2.2", + "rxjs": "^7.1.0", "zod": "^4.3.5" }, "peerDependenciesMeta": { @@ -13641,13 +13641,65 @@ } } }, - "node_modules/@rekog/mcp-nest/node_modules/rxjs": { - "version": "7.8.2", - "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.2.tgz", - "integrity": "sha512-dhKf903U/PQZY6boNNtAGdWbG85WAbjT/1xYoZIC7FAY0yWapOBQVsVrDl58W86//e1VpMNBtRV4MaXfdMySFA==", - "license": "Apache-2.0", + "node_modules/@rekog/mcp-nest/node_modules/media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@rekog/mcp-nest/node_modules/mime-db": { + "version": "1.52.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", + "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@rekog/mcp-nest/node_modules/mime-types": { + "version": "2.1.35", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", + "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", + "license": "MIT", "dependencies": { - "tslib": "^2.1.0" + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/@rekog/mcp-nest/node_modules/multer": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/multer/-/multer-2.4.0.tgz", + "integrity": "sha512-7dqa0ZcFfzbefdTuIkzOSMvZWC0J7FLqBOjJUZvDCXShIURWKxAyTT1wHhnE5q19c7jOJf43IYYKjBmZVZmvhg==", + "license": "MIT", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.6.0", + "type-is": "^1.6.18" + }, + "engines": { + "node": ">= 10.16.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/@rekog/mcp-nest/node_modules/type-is": { + "version": "1.6.18", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz", + "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==", + "license": "MIT", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" } }, "node_modules/@rolldown/binding-android-arm64": { diff --git a/package.json b/package.json index 83aff10108..638fd1ed10 100644 --- a/package.json +++ b/package.json @@ -93,7 +93,7 @@ "@openrouter/ai-sdk-provider": "3.0.0", "@prisma/adapter-pg": "7.10.0", "@prisma/client": "7.10.0", - "@rekog/mcp-nest": "2.0.2", + "@rekog/mcp-nest": "2.0.7", "@simplewebauthn/browser": "13.3.0", "@simplewebauthn/server": "13.3.1", "ai": "7.0.37", From 3cd7c1d093689d22026f1d33fa4fdf2e9ca27ab2 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 26 Sep 2026 10:14:36 +0200 Subject: [PATCH 08/19] Task/extend personal finance tools with last update date (#7942) Extend with last update date --- libs/common/src/lib/personal-finance-tools.ts | 274 +++++++++++++++++- 1 file changed, 258 insertions(+), 16 deletions(-) diff --git a/libs/common/src/lib/personal-finance-tools.ts b/libs/common/src/lib/personal-finance-tools.ts index fcc4901de1..f713871dc8 100644 --- a/libs/common/src/lib/personal-finance-tools.ts +++ b/libs/common/src/lib/personal-finance-tools.ts @@ -32,6 +32,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['MACOS', 'WINDOWS'], pricingPerYear: '$44.95', slogan: 'Lifetime Personal Finance Control, One Single Payment.', + updatedAt: '2026-07-05', url: 'https://www.mechcad.net' }, { @@ -39,6 +40,7 @@ export const personalFinanceTools: Product[] = ( key: 'addepar', name: 'Addepar', slogan: 'Transform your business with Addepar', + updatedAt: '2026-08-28', url: 'https://addepar.com' }, { @@ -72,6 +74,7 @@ export const personalFinanceTools: Product[] = ( key: 'akkuro', name: 'Akkuro', slogan: 'Composable Banking', + updatedAt: '2026-07-09', url: 'https://akkuro.com' }, { @@ -83,6 +86,7 @@ export const personalFinanceTools: Product[] = ( name: 'AllInvestView', platforms: ['WEB'], slogan: 'All your Investments in One View', + updatedAt: '2026-07-05', url: 'https://www.allinvestview.com' }, { @@ -94,6 +98,7 @@ export const personalFinanceTools: Product[] = ( name: 'Allvue Systems', origin: 'US', slogan: 'Investment Software Suite', + updatedAt: '2026-07-05', url: 'https://www.allvuesystems.com' }, { @@ -115,6 +120,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: 'CHF 99', slogan: 'Manage your entire Swiss wealth in one place', + updatedAt: '2026-08-27', url: 'https://alpgain.ch' }, { @@ -140,6 +146,7 @@ export const personalFinanceTools: Product[] = ( name: 'AlphaTrackr', platforms: ['WEB'], slogan: 'Investment Portfolio Tracking Tool', + updatedAt: '2026-07-05', url: 'https://www.alphatrackr.com' }, { @@ -151,6 +158,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CH', platforms: ['WEB'], slogan: 'Simplicity for Complex Wealth', + updatedAt: '2026-07-05', url: 'https://altoo.io' }, { @@ -163,6 +171,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['WEB'], slogan: 'The wealth platform built for independent advisors', + updatedAt: '2026-07-05', url: 'https://altruist.com' }, { @@ -175,6 +184,7 @@ export const personalFinanceTools: Product[] = ( origin: 'SG', pricingPerYear: '$228', slogan: 'Portfolio Visualizer', + updatedAt: '2026-07-05', url: 'https://amsflow.com' }, { @@ -187,6 +197,7 @@ export const personalFinanceTools: Product[] = ( origin: 'FR', platforms: ['WEB'], slogan: 'The investment copilot with no conflict of interest', + updatedAt: '2026-08-16', url: 'https://anantys.com' }, { @@ -201,6 +212,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$120', slogan: 'Analyze and track your portfolio.', + updatedAt: '2026-07-05', url: 'https://anlage.app' }, { @@ -238,6 +250,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['WEB'], slogan: 'The Intelligent Family Office Suite', + updatedAt: '2026-07-05', url: 'https://www.asseta.ai' }, { @@ -247,6 +260,7 @@ export const personalFinanceTools: Product[] = ( name: 'Atominvest', origin: 'GB', slogan: 'Portfolio Management', + updatedAt: '2026-07-05', url: 'https://www.atominvest.co' }, { @@ -260,6 +274,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$47.99', slogan: 'The Smarter Way to Track Your Finances', + updatedAt: '2026-07-05', url: 'https://www.balancepro.app' }, { @@ -273,6 +288,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€39.99', slogan: 'L’app tout-en-1 pour mieux gérer son argent', + updatedAt: '2026-08-17', url: 'https://www.bankin.com' }, { @@ -285,6 +301,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS', 'MACOS'], pricingPerYear: '$59.99', slogan: 'Proactive money management app for macOS & iOS', + updatedAt: '2026-07-05', url: 'https://www.banktivity.com' }, { @@ -292,6 +309,7 @@ export const personalFinanceTools: Product[] = ( key: 'basil-wealth', name: 'Basil', platforms: ['WEB'], + updatedAt: '2026-07-05', url: 'https://basilwealth.com' }, { @@ -303,6 +321,7 @@ export const personalFinanceTools: Product[] = ( name: 'Basil Finance', slogan: 'The ultimate solution for tracking and managing your investments', + updatedAt: '2026-07-05', url: 'https://basil.fi' }, { @@ -316,6 +335,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], pricingPerYear: '$49.99', slogan: 'Stop guessing your net worth', + updatedAt: '2026-08-27', url: 'https://www.get-beam.app' }, { @@ -329,6 +349,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$100', slogan: 'Stock Portfolio Tracker for Smart Investors', + updatedAt: '2026-07-05', url: 'https://beanvest.com' }, { @@ -368,6 +389,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CA', platforms: ['ANDROID', 'IOS'], slogan: 'Be Money Mindful', + updatedAt: '2026-08-17', url: 'https://billi.webflow.io' }, { @@ -380,6 +402,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CA', platforms: ['ANDROID', 'IOS'], slogan: 'Real Portfolios, Trades & Market Insights', + updatedAt: '2026-08-16', url: 'https://blossomsocial.com' }, { @@ -392,6 +415,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CH', platforms: ['ANDROID', 'IOS'], slogan: 'Schweizer Budget App für einfache & smarte Budgetplanung', + updatedAt: '2026-07-05', url: 'https://www.bluebudget.ch' }, { @@ -406,6 +430,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$144', slogan: 'Take control with retirement planning tools that begin with you', + updatedAt: '2026-07-05', url: 'https://www.boldin.com' }, { @@ -453,6 +478,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CZ', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Your Finances in One Place', + updatedAt: '2026-08-18', url: 'https://budgetbakers.com' }, { @@ -462,6 +488,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['WEB'], slogan: 'Giving life to your finance!', + updatedAt: '2026-07-05', url: 'https://www.budgetpulse.com' }, { @@ -476,6 +503,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$96', regions: ['Global'], slogan: 'Take control of your financial future', + updatedAt: '2026-07-09', url: 'https://www.buxfer.com' }, { @@ -488,6 +516,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€80', slogan: 'Optimize your investments performance', + updatedAt: '2026-07-05', url: 'https://www.mycapitally.com' }, { @@ -499,13 +528,15 @@ export const personalFinanceTools: Product[] = ( note: 'CapMon.org was discontinued in 2023', origin: 'DE', platforms: ['WEB'], - slogan: 'Next Generation Assets Tracking' + slogan: 'Next Generation Assets Tracking', + updatedAt: '2026-07-05' }, { categories: ['INVESTMENT_RESEARCH'], key: 'cbonds', name: 'Cbonds', slogan: 'Financial Market Data Hub', + updatedAt: '2026-08-28', url: 'https://cbonds.com' }, { @@ -513,6 +544,7 @@ export const personalFinanceTools: Product[] = ( key: 'chaikin-analytics', name: 'Chaikin Analytics', slogan: 'Investing tools and research from Marc Chaikin & Team', + updatedAt: '2026-08-28', url: 'https://chaikinanalytics.com' }, { @@ -522,7 +554,8 @@ export const personalFinanceTools: Product[] = ( key: 'cleverbilling', languages: ['Español'], name: 'CleverBilling', - slogan: 'Toma el control total de tus finanzas.' + slogan: 'Toma el control total de tus finanzas.', + updatedAt: '2025-07-27' }, { categories: ['WEALTH_MANAGEMENT'], @@ -532,6 +565,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['WEB'], slogan: 'Next-Level Portfolio Monitoring', + updatedAt: '2026-07-05', url: 'https://www.cobalt.pe' }, { @@ -545,6 +579,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$168', slogan: 'Manage All Your Wallets & Exchanges From One Place', + updatedAt: '2026-07-05', url: 'https://coinstats.app' }, { @@ -559,6 +594,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$120', slogan: 'The leading Crypto Portfolio Tracker & Tax Calculator', + updatedAt: '2026-07-05', url: 'https://cointracking.info' }, { @@ -579,6 +615,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['IOS', 'WEB'], slogan: 'Modern Wealth & Investment Management', + updatedAt: '2026-07-05', url: 'https://compoundplanning.com' }, { @@ -592,6 +629,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS', 'MACOS', 'WEB'], pricingPerYear: '$95', slogan: 'Do money better with Copilot', + updatedAt: '2026-07-05', url: 'https://www.copilot.money' }, { @@ -604,6 +642,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$9.99', slogan: 'Customizable and Secure Personal Finance App', + updatedAt: '2026-07-05', url: 'https://countabout.com' }, { @@ -656,6 +695,7 @@ export const personalFinanceTools: Product[] = ( name: 'Danelfin', pricingPerYear: '$264', slogan: 'AI-Powered Stock Picking', + updatedAt: '2026-08-28', url: 'https://danelfin.com' }, { @@ -666,6 +706,7 @@ export const personalFinanceTools: Product[] = ( name: 'Danti', origin: 'GB', slogan: 'Digitising Generational Wealth', + updatedAt: '2026-07-05', url: 'https://danti.io' }, { @@ -675,6 +716,7 @@ export const personalFinanceTools: Product[] = ( languages: ['English'], name: 'De.Fi', slogan: 'DeFi Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://de.fi' }, { @@ -687,6 +729,7 @@ export const personalFinanceTools: Product[] = ( name: 'DeepVest', slogan: 'The AI-Powered Research Platform for Financial Advisors and Investment Managers', + updatedAt: '2026-08-28', url: 'https://www.deepvest.ai' }, { @@ -701,6 +744,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$99', slogan: 'DeFi Portfolio Tracker for All Chains', + updatedAt: '2026-07-05', url: 'https://zerion.io/defi-portfolio-tracker' }, { @@ -715,6 +759,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€24', slogan: 'Democratizing Data Analytics', + updatedAt: '2026-07-05', url: 'https://capitalyse.app/app/degiro' }, { @@ -729,6 +774,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'MACOS', 'WEB', 'WINDOWS'], pricingPerYear: '$150', slogan: 'The app to track all your investments. Make smart moves only.', + updatedAt: '2026-07-05', url: 'https://delta.app' }, { @@ -741,6 +787,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$49.90', slogan: 'Dividend Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://www.digrin.com' }, { @@ -765,6 +812,7 @@ export const personalFinanceTools: Product[] = ( name: 'Dividend Watch', pricingPerYear: '$72', slogan: 'The Essential Dividend and Portfolio Tracker', + updatedAt: '2026-08-28', url: 'https://dividend.watch' }, { @@ -773,6 +821,7 @@ export const personalFinanceTools: Product[] = ( name: 'Dividend Wealth', pricingPerYear: '$99.99', slogan: 'Track Your Dividends Like a Pro', + updatedAt: '2026-08-28', url: 'https://dividend-wealth.com' }, { @@ -801,6 +850,7 @@ export const personalFinanceTools: Product[] = ( name: 'DivTracker', pricingPerYear: '$29.99', slogan: 'Your Ultimate Dividend Tracker', + updatedAt: '2026-08-28', url: 'https://divtracker.app' }, { @@ -815,6 +865,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€65', slogan: 'Your personal Dividend Calendar', + updatedAt: '2026-07-05', url: 'https://divvydiary.com' }, { @@ -828,6 +879,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'WEB'], pricingPerYear: '€57.48', slogan: 'The Portfolio Tracker that replaces your spreadsheets', + updatedAt: '2026-08-16', url: 'https://www.donkycapital.com' }, { @@ -851,6 +903,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['WEB'], slogan: 'Get answers to your money questions', + updatedAt: '2026-07-05', url: 'https://www.empower.com' }, { @@ -862,6 +915,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Portfolio Tracker Designed by Professional Investors', + updatedAt: '2026-07-05', url: 'https://8figures.com' }, { @@ -875,6 +929,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '£41.99', slogan: 'Take control of your money', + updatedAt: '2026-08-17', url: 'https://emma-app.com' }, { @@ -882,6 +937,7 @@ export const personalFinanceTools: Product[] = ( key: 'envestnet', name: 'Envestnet', slogan: 'Everybody Deserves Financial Wellness', + updatedAt: '2026-08-28', url: 'https://www.envestnet.com' }, { @@ -919,6 +975,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', pricingPerYear: '$83.88', slogan: 'Stock Selection Analytics for Investors', + updatedAt: '2026-08-28', url: 'https://epsmomentum.com' }, { @@ -944,6 +1001,7 @@ export const personalFinanceTools: Product[] = ( key: 'etf-action', name: 'ETF Action', slogan: 'Markets through the lens of ETFs', + updatedAt: '2026-08-28', url: 'https://www.etfaction.com' }, { @@ -951,6 +1009,7 @@ export const personalFinanceTools: Product[] = ( key: 'etf-insider', name: 'ETF Insider', slogan: 'Precision asset allocation', + updatedAt: '2026-08-28', url: 'https://etfinsider.co' }, { @@ -959,6 +1018,7 @@ export const personalFinanceTools: Product[] = ( key: 'etf-research-center', name: 'ETF Research Center', slogan: 'A Smarter Approach to Exchange Traded Funds', + updatedAt: '2026-08-28', url: 'https://www.etfrc.com' }, { @@ -981,6 +1041,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CH', platforms: ['WEB'], slogan: 'Your financial superpower', + updatedAt: '2026-07-05', url: 'https://www.etops.com' }, { @@ -993,6 +1054,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Plan, track, find more margin', + updatedAt: '2026-07-05', url: 'https://www.ramseysolutions.com/money/everydollar' }, { @@ -1025,6 +1087,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$100', slogan: 'All your wealth, in one place.', + updatedAt: '2026-07-05', url: 'https://www.exirio.com' }, { @@ -1035,6 +1098,7 @@ export const personalFinanceTools: Product[] = ( name: 'Expersoft', origin: 'CH', slogan: 'Investment Management Platforms', + updatedAt: '2026-07-05', url: 'https://www.expersoft.com' }, { @@ -1049,6 +1113,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€89.99', slogan: 'Die besten ETFs finden, vergleichen und beobachten', + updatedAt: '2026-08-16', url: 'https://extraetf.com' }, { @@ -1056,6 +1121,7 @@ export const personalFinanceTools: Product[] = ( key: 'factorstoday', name: 'FactorsToday', slogan: 'Modern Quantitative Analysis', + updatedAt: '2026-08-28', url: 'https://www.factorstoday.com' }, { @@ -1064,6 +1130,7 @@ export const personalFinanceTools: Product[] = ( name: 'FAST Graphs', pricingPerYear: '$191.40', slogan: 'Invest Intelligently with the Most Powerful Stock Analysis Tool', + updatedAt: '2026-08-28', url: 'https://www.fastgraphs.com' }, { @@ -1078,6 +1145,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CA', pricingPerYear: '$300', slogan: 'Make better investments.', + updatedAt: '2026-07-05', url: 'https://fey.com' }, { @@ -1103,6 +1171,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', pricingPerYear: '$115', slogan: 'Flexible Financial Management', + updatedAt: '2026-06-04', url: 'https://www.fina.money' }, { @@ -1131,6 +1200,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€69.99', slogan: 'Portfolio Tracker für dein Vermögen', + updatedAt: '2026-07-05', url: 'https://www.finanzfluss.de/copilot' }, { @@ -1144,6 +1214,7 @@ export const personalFinanceTools: Product[] = ( origin: 'DE', platforms: ['ANDROID', 'IOS', 'MACOS'], slogan: 'Finanzen. Magisch. Einfach.', + updatedAt: '2026-07-05', url: 'https://www.finanzguru.de' }, { @@ -1155,6 +1226,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Real-Time Portfolio Tracker & Stock Tracker', + updatedAt: '2026-07-05', url: 'https://finary.com' }, { @@ -1169,6 +1241,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], slogan: 'The most convenient mobile application for personal finance accounting', + updatedAt: '2026-07-05', url: 'https://finateka.com' }, { @@ -1178,6 +1251,7 @@ export const personalFinanceTools: Product[] = ( name: 'Fincake', origin: 'VG', slogan: 'Easy-to-use Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://fincake.io' }, { @@ -1189,6 +1263,7 @@ export const personalFinanceTools: Product[] = ( origin: 'DE', platforms: ['WEB'], slogan: 'Wealth Management Software', + updatedAt: '2026-07-05', url: 'https://fincite.de' }, { @@ -1212,6 +1287,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$84.00', slogan: 'Sync your bank to spreadsheets', + updatedAt: '2026-08-17', url: 'https://fintable.io' }, { @@ -1219,6 +1295,7 @@ export const personalFinanceTools: Product[] = ( key: 'fintel', name: 'Fintel', slogan: 'Essential Tools for Investors and Traders', + updatedAt: '2026-08-28', url: 'https://fintel.io' }, { @@ -1247,6 +1324,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Grow your wealth in a stress-free way', + updatedAt: '2026-07-05', url: 'https://www.getfinvest.com' }, { @@ -1257,6 +1335,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$299.50', slogan: 'Stock screener for investors and traders, financial visualizations', + updatedAt: '2026-08-28', url: 'https://finviz.com' }, { @@ -1269,6 +1348,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€69.99', slogan: 'Personal finances, simplified', + updatedAt: '2026-07-05', url: 'https://finwiseapp.io' }, { @@ -1282,6 +1362,7 @@ export const personalFinanceTools: Product[] = ( origin: 'UA', pricingPerYear: '$40', slogan: 'A simple solution to track your wealth online', + updatedAt: '2026-07-05', url: 'https://firekit.space' }, { @@ -1289,6 +1370,7 @@ export const personalFinanceTools: Product[] = ( key: 'fiscal.ai', name: 'Fiscal.ai', slogan: 'The Modern Financial Data Platform', + updatedAt: '2026-08-28', url: 'https://fiscal.ai' }, { @@ -1302,6 +1384,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], pricingPerYear: '€23.88', slogan: 'Your money on autopilot', + updatedAt: '2026-08-17', url: 'https://flowyour.money' }, { @@ -1314,6 +1397,7 @@ export const personalFinanceTools: Product[] = ( origin: 'AT', pricingPerYear: '$65', slogan: 'Take control over your investments', + updatedAt: '2026-07-05', url: 'https://www.folishare.com' }, { @@ -1341,6 +1425,7 @@ export const personalFinanceTools: Product[] = ( origin: 'AU', platforms: ['ANDROID', 'IOS'], slogan: 'Feel good about money', + updatedAt: '2026-08-17', url: 'https://www.frollo.com.au' }, { @@ -1354,6 +1439,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WINDOWS'], pricingPerYear: '$99', slogan: 'Powerful portfolio management software', + updatedAt: '2026-07-05', url: 'https://www.fundmanagersoftware.com' }, { @@ -1375,6 +1461,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$60', regions: ['Global'], slogan: 'Take control of your finances from WhatsApp', + updatedAt: '2026-07-05', url: 'https://gasti.pro' }, { @@ -1404,6 +1491,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€48', slogan: 'Portfolio Tracker, Analysis & Community', + updatedAt: '2026-07-05', url: 'https://www.getquin.com' }, { @@ -1415,6 +1503,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Budget with a why', + updatedAt: '2026-07-05', url: 'https://goodbudget.com' }, { @@ -1425,13 +1514,15 @@ export const personalFinanceTools: Product[] = ( name: 'goSPATZ', note: 'Renamed to Money Peak', origin: 'DE', - slogan: 'Volle Kontrolle über deine Investitionen' + slogan: 'Volle Kontrolle über deine Investitionen', + updatedAt: '2025-04-17' }, { categories: ['INVESTMENT_RESEARCH'], key: 'gurufocus', name: 'GuruFocus', slogan: 'Stock Market Research, Data and Tools', + updatedAt: '2026-08-28', url: 'https://www.gurufocus.com' }, { @@ -1446,6 +1537,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€59.99', slogan: 'Prenez enfin le contrôle de votre argent', + updatedAt: '2026-07-05', url: 'https://get-gustav.com' }, { @@ -1453,6 +1545,7 @@ export const personalFinanceTools: Product[] = ( key: 'hedgefollow', name: 'HedgeFollow', slogan: 'Follow Hedge Funds & Insiders using 13F filings', + updatedAt: '2026-08-28', url: 'https://hedgefollow.com' }, { @@ -1484,6 +1577,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CH', platforms: ['IOS', 'WEB'], slogan: 'Dein Vermögen im Überblick', + updatedAt: '2026-08-18', url: 'https://www.helvestor.ch' }, { @@ -1496,6 +1590,7 @@ export const personalFinanceTools: Product[] = ( origin: 'DE', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Die All-in-One Lösung für dein Vermögen.', + updatedAt: '2026-07-05', url: 'https://holistic.capital', useAnonymously: true }, @@ -1508,6 +1603,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS'], slogan: 'Finance App for Couples', + updatedAt: '2026-07-05', url: 'https://www.honeydue.com' }, { @@ -1517,7 +1613,8 @@ export const personalFinanceTools: Product[] = ( key: 'ibank', name: 'iBank', note: 'Renamed to Banktivity', - origin: 'US' + origin: 'US', + updatedAt: '2026-06-23' }, { founded: 2022, @@ -1526,13 +1623,15 @@ export const personalFinanceTools: Product[] = ( name: 'Income Reign', note: 'Income Reign was discontinued in 2025', origin: 'US', - pricingPerYear: '$120' + pricingPerYear: '$120', + updatedAt: '2025-08-27' }, { categories: ['INVESTMENT_RESEARCH'], hasFreePlan: true, key: 'insidearbitrage', name: 'InsideArbitrage', + updatedAt: '2026-08-28', url: 'https://www.insidearbitrage.com' }, { @@ -1544,13 +1643,15 @@ export const personalFinanceTools: Product[] = ( note: 'Intuit Mint was discontinued in 2023', origin: 'US', pricingPerYear: '$60', - slogan: 'Managing money, made simple' + slogan: 'Managing money, made simple', + updatedAt: '2024-10-19' }, { categories: ['INVESTMENT_RESEARCH'], key: 'invesst', name: 'Invesst', slogan: 'Power Your Portfolio with AI', + updatedAt: '2026-08-28', url: 'https://invesst.ai' }, { @@ -1562,6 +1663,7 @@ export const personalFinanceTools: Product[] = ( origin: 'PK', platforms: ['ANDROID', 'IOS'], slogan: 'Advanced portfolio tracking and stock market information', + updatedAt: '2026-07-05', url: 'https://www.investify.pk' }, { @@ -1626,6 +1728,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['MACOS'], pricingPerYear: '$156', slogan: 'Track all your assets, investments and portfolios in one place', + updatedAt: '2026-07-05', url: 'https://invmon.com', useAnonymously: true }, @@ -1639,6 +1742,7 @@ export const personalFinanceTools: Product[] = ( origin: 'PL', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Inwestujesz? Śledź swój majątek w jednym miejscu', + updatedAt: '2026-08-16', url: 'https://inwestuje.app' }, { @@ -1667,6 +1771,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '€119', slogan: 'ETF portfolios made simple', + updatedAt: '2026-07-05', url: 'https://www.justetf.com' }, { @@ -1678,6 +1783,7 @@ export const personalFinanceTools: Product[] = ( name: 'Koinly', origin: 'SG', slogan: 'Track all your crypto wallets in one place', + updatedAt: '2026-07-05', url: 'https://koinly.io' }, { @@ -1691,6 +1797,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$468', slogan: 'Comprehensive financial data analysis', + updatedAt: '2026-07-05', url: 'https://www.koyfin.com' }, { @@ -1704,6 +1811,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$249', slogan: 'The Time Machine for your Net Worth', + updatedAt: '2026-07-05', url: 'https://www.kubera.com' }, { @@ -1739,6 +1847,7 @@ export const personalFinanceTools: Product[] = ( languages: ['English'], name: 'Kyro', platforms: ['WEB'], + updatedAt: '2026-08-27', url: 'https://my.kyro.app' }, { @@ -1750,6 +1859,7 @@ export const personalFinanceTools: Product[] = ( name: 'Leafs', origin: 'CH', slogan: 'Sustainability insights for wealth managers', + updatedAt: '2026-07-05', url: 'https://leafs.ch' }, { @@ -1763,6 +1873,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], pricingPerYear: '£26.99', slogan: 'Couples finances, made easy', + updatedAt: '2026-08-17', url: 'https://www.lumio-app.com' }, { @@ -1774,6 +1885,7 @@ export const personalFinanceTools: Product[] = ( name: 'Lunch Money', origin: 'CA', slogan: 'Delightfully simple personal finance and budgeting', + updatedAt: '2026-07-05', url: 'https://lunchmoney.app' }, { @@ -1787,6 +1899,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$132', slogan: 'AI Investing Assistant', + updatedAt: '2026-07-05', url: 'https://magnifi.com' }, { @@ -1809,6 +1922,7 @@ export const personalFinanceTools: Product[] = ( key: 'marketinout', name: 'MarketInOut', slogan: 'Stock Screener with Backtesting & Advanced Filters', + updatedAt: '2026-08-28', url: 'https://www.marketinout.com' }, { @@ -1816,6 +1930,7 @@ export const personalFinanceTools: Product[] = ( key: 'marketlog', name: 'Marketlog', slogan: 'Stock Portfolio and Investments Tracker', + updatedAt: '2026-08-28', url: 'https://www.marketlog.com' }, { @@ -1831,6 +1946,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '€168', regions: ['Global'], slogan: 'Financial Intelligence Platform', + updatedAt: '2026-07-05', url: 'https://markets.sh' }, { @@ -1838,6 +1954,7 @@ export const personalFinanceTools: Product[] = ( key: 'marketscreener', name: 'MarketScreener', slogan: 'Financial News & Stock Market Quotes', + updatedAt: '2026-08-28', url: 'https://www.marketscreener.com' }, { @@ -1846,6 +1963,7 @@ export const personalFinanceTools: Product[] = ( name: 'MarketXLS', pricingPerYear: '$850', slogan: 'Real-Time Stock Data & Analysis in Excel', + updatedAt: '2026-08-28', url: 'https://marketxls.com' }, { @@ -1855,6 +1973,7 @@ export const personalFinanceTools: Product[] = ( name: 'Masttro', origin: 'US', slogan: 'Your platform for wealth in full view', + updatedAt: '2026-07-05', url: 'https://masttro.com' }, { @@ -1871,6 +1990,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$145', regions: ['US'], slogan: 'Your financial future, in your control', + updatedAt: '2026-06-04', url: 'https://github.com/maybe-finance/maybe' }, { @@ -1885,6 +2005,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$204', regions: ['CA', 'US'], slogan: 'The smartest way to track your crypto', + updatedAt: '2026-07-05', url: 'https://www.merlincrypto.com' }, { @@ -1897,6 +2018,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS', 'WEB'], pricingPerYear: '$48', slogan: 'Self-manage your wealth. Get fiduciary advice.', + updatedAt: '2026-07-05', url: 'https://www.mezzi.com' }, { @@ -1906,13 +2028,15 @@ export const personalFinanceTools: Product[] = ( key: 'microsoft-money', name: 'Microsoft Money', note: 'Microsoft Money was discontinued in 2010', - origin: 'US' + origin: 'US', + updatedAt: '2024-10-19' }, { categories: ['INVESTMENT_RESEARCH'], key: 'moatmap', name: 'MoatMap', slogan: 'AI Stock Screening & Equity Research', + updatedAt: '2026-08-28', url: 'https://moatmap.ai' }, { @@ -1926,6 +2050,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$99.99', slogan: 'The modern way to manage your money', + updatedAt: '2026-07-05', url: 'https://www.monarch.com' }, { @@ -1939,6 +2064,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'LINUX', 'MACOS', 'WINDOWS'], pricingPerYear: '$100', slogan: 'Personal Finance Manager for Mac, Windows, and Linux', + updatedAt: '2026-07-05', url: 'https://moneydance.com' }, { @@ -1951,6 +2077,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', pricingPerYear: '$29.99', slogan: 'Personal Accounting Made Easy, Accurate, Comprehensive', + updatedAt: '2026-07-05', url: 'https://www.moneypatrol.com' }, { @@ -1963,6 +2090,7 @@ export const personalFinanceTools: Product[] = ( origin: 'DE', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Dein smarter Finance Assistant', + updatedAt: '2026-07-05', url: 'https://moneypeak.ai' }, { @@ -1975,6 +2103,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['LINUX', 'MACOS', 'WINDOWS'], pricingPerYear: '$59.99', slogan: 'Have total control of your financial life', + updatedAt: '2026-07-05', url: 'https://www.moneyspire.com' }, { @@ -1986,6 +2115,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['IOS', 'MACOS'], slogan: 'Personal Budgeting Software for Mac and iOS', + updatedAt: '2026-07-05', url: 'https://moneywell.app' }, { @@ -2010,6 +2140,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS', 'MACOS'], pricingPerYear: '$29.99', slogan: 'Get money management superpowers', + updatedAt: '2026-07-05', url: 'https://www.wiz.money' }, { @@ -2022,6 +2153,7 @@ export const personalFinanceTools: Product[] = ( note: 'Renamed to Nexafin', pricingPerYear: '$60', slogan: 'Gain financial control and keep your data private.', + updatedAt: '2026-07-05', url: 'https://monse.app' }, { @@ -2036,6 +2168,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$20', slogan: 'Smart, simple, stress-free money tracking.', + updatedAt: '2026-07-05', url: 'https://www.monsy.app' }, { @@ -2064,6 +2197,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], slogan: 'Track your equity, fund, investment trust, ETF and pension investments in one place.', + updatedAt: '2026-07-05', url: 'https://www.morningstar.com/mm' }, { @@ -2083,6 +2217,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$49.99', slogan: 'Keep track of and visualize your investments throughout your day', + updatedAt: '2026-08-16', url: 'https://peeksoft.co' }, { @@ -2095,6 +2230,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$36', slogan: 'Your Personal Finance Command Center', + updatedAt: '2026-07-05', url: 'https://myfinancetools.io' }, { @@ -2108,6 +2244,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: 'PLN 36.10', slogan: 'Manage all your assets and accounts in one place', + updatedAt: '2026-08-16', url: 'https://myfund.pl' }, { @@ -2121,6 +2258,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$1188', slogan: 'Your Complete Crypto Portfolio, Reimagined', + updatedAt: '2026-07-05', url: 'https://www.nansen.ai/crypto-portfolio-tracker' }, { @@ -2134,6 +2272,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$90', slogan: 'The Intelligent Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://www.navexa.com' }, { @@ -2155,6 +2294,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$75', slogan: 'Everything you own. Everything you owe. Everything in one place.', + updatedAt: '2026-09-02', url: 'https://neontra.com' }, { @@ -2166,6 +2306,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€49.99', slogan: 'Your Personal Financial Analyst, powered by AI.', + updatedAt: '2026-07-05', url: 'https://networthy.pro' }, { @@ -2174,6 +2315,7 @@ export const personalFinanceTools: Product[] = ( name: 'Nexafin', platforms: ['WEB'], slogan: 'Your Finances. Finally Clear.', + updatedAt: '2026-07-05', url: 'https://nexafin.com' }, { @@ -2200,6 +2342,7 @@ export const personalFinanceTools: Product[] = ( key: 'okama', name: 'okama', slogan: 'Efficient Frontier for the investment portfolios', + updatedAt: '2026-08-28', url: 'https://okama.io' }, { @@ -2212,6 +2355,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], pricingPerYear: '€49.99', slogan: 'Dividend Day Should Feel Like Payday', + updatedAt: '2026-08-28', url: 'https://onlydividends.app' }, { @@ -2295,6 +2439,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '€99.99', regions: ['AT', 'CH', 'DE'], slogan: 'Dein Vermögen immer im Blick', + updatedAt: '2026-07-05', url: 'https://www.parqet.com' }, { @@ -2309,6 +2454,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$99', slogan: 'Autopilot for your Portfolio', + updatedAt: '2026-08-16', url: 'https://passiv.com' }, { @@ -2328,6 +2474,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€49', slogan: 'Votre patrimoine, enfin clair', + updatedAt: '2026-07-05', url: 'https://mypatrice.com' }, { @@ -2338,6 +2485,7 @@ export const personalFinanceTools: Product[] = ( origin: 'SG', platforms: ['IOS'], slogan: 'Feel in control of your money without spreadsheets or shame', + updatedAt: '2026-07-05', url: 'https://peek.money' }, { @@ -2348,6 +2496,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS'], pricingPerYear: '$39.99', slogan: 'Your money. Made simple.', + updatedAt: '2026-07-05', url: 'https://www.getpennies.com' }, { @@ -2374,6 +2523,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€50', slogan: 'Invest smarter, not harder', + updatedAt: '2026-07-05', url: 'https://pinklion.xyz' }, { @@ -2387,6 +2537,7 @@ export const personalFinanceTools: Product[] = ( origin: 'PL', pricingPerYear: '$74', slogan: 'Free dividend tracker for your portfolio', + updatedAt: '2026-07-05', url: 'https://plainzer.com' }, { @@ -2398,6 +2549,7 @@ export const personalFinanceTools: Product[] = ( origin: 'IT', platforms: ['WEB'], slogan: 'Your Personal Finance Hub', + updatedAt: '2026-07-05', url: 'https://www.plannix.co' }, { @@ -2411,6 +2563,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$74.99', slogan: 'Budgeting App & Finance Planner', + updatedAt: '2026-07-05', url: 'https://pocketguard.com' }, { @@ -2426,6 +2579,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$120', regions: ['Global'], slogan: 'Know where your money is going', + updatedAt: '2026-07-05', url: 'https://www.pocketsmith.com' }, { @@ -2452,6 +2606,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: 'PLN 168', slogan: 'Wszystkie Twoje inwestycje w jednym miejscu', + updatedAt: '2026-08-16', url: 'https://www.portfeo.pl' }, { @@ -2465,6 +2620,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '£120', slogan: 'Know your wealth. Ask it anything.', + updatedAt: '2026-08-13', url: 'https://portfoliocoach.co.uk' }, { @@ -2478,6 +2634,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€60', slogan: 'Manage all your portfolios', + updatedAt: '2026-07-05', url: 'https://portfoliodividendtracker.com' }, { @@ -2491,6 +2648,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS'], slogan: 'Professional stock portfolio tracking for iPhone, iPad and Apple Watch', + updatedAt: '2026-08-16', url: 'https://www.iportfoliotrader.com' }, { @@ -2502,6 +2660,7 @@ export const personalFinanceTools: Product[] = ( name: 'Portfolio Visualizer', pricingPerYear: '$360', slogan: 'Tools for Better Investors', + updatedAt: '2026-07-05', url: 'https://www.portfoliovisualizer.com' }, { @@ -2509,6 +2668,7 @@ export const personalFinanceTools: Product[] = ( key: 'portfolio123', name: 'Portfolio123', slogan: 'Power Your Portfolio with Backtested Stock Strategies', + updatedAt: '2026-08-28', url: 'https://www.portfolio123.com' }, { @@ -2521,6 +2681,7 @@ export const personalFinanceTools: Product[] = ( origin: 'PL', platforms: ['WEB'], slogan: 'One look. Clear picture of your portfolio.', + updatedAt: '2026-08-13', url: 'https://www.portfolioglance.com' }, { @@ -2565,6 +2726,7 @@ export const personalFinanceTools: Product[] = ( key: 'portfolioslab', name: 'PortfoliosLab', slogan: 'Financial tools for smart investors', + updatedAt: '2026-08-28', url: 'https://portfolioslab.com' }, { @@ -2596,7 +2758,8 @@ export const personalFinanceTools: Product[] = ( name: 'Portfoloo', note: 'Portfoloo was discontinued', slogan: - 'Free Stock Portfolio Tracker with unlimited portfolio and stocks for DIY investors' + 'Free Stock Portfolio Tracker with unlimited portfolio and stocks for DIY investors', + updatedAt: '2026-07-05' }, { categories: ['DIVIDEND_TRACKING', 'STOCK_TRACKING'], @@ -2609,6 +2772,7 @@ export const personalFinanceTools: Product[] = ( origin: 'TH', pricingPerYear: '$96', slogan: 'Portfolio Performance and Dividend Tracker', + updatedAt: '2026-07-05', url: 'https://www.portseido.com' }, { @@ -2622,6 +2786,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$108', slogan: 'Build Financial Plans You Love.', + updatedAt: '2026-07-05', url: 'https://projectionlab.com' }, { @@ -2635,6 +2800,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$60', slogan: 'The stock portfolio tracker built for long-term investors', + updatedAt: '2026-07-05', url: 'https://prostocktracker.com' }, { @@ -2656,6 +2822,7 @@ export const personalFinanceTools: Product[] = ( name: 'Quantive', platforms: ['WEB'], slogan: 'See your financial life clearly', + updatedAt: '2026-07-05', url: 'https://usequantive.app' }, { @@ -2688,6 +2855,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$99.99', slogan: 'Your entire financial life in one app, monitored continuously by agents', + updatedAt: '2026-07-05', url: 'https://rallies.ai' }, { @@ -2696,6 +2864,7 @@ export const personalFinanceTools: Product[] = ( name: 'Reflexivity', note: 'Originally named as Toggle AI', slogan: 'Faster Insights. Better Analysis. Greater Confidence.', + updatedAt: '2026-09-23', url: 'https://reflexivity.com' }, { @@ -2709,6 +2878,7 @@ export const personalFinanceTools: Product[] = ( origin: 'DE', platforms: ['WEB'], slogan: 'Das kostenfreie Tool für Ihren Finanzerfolg', + updatedAt: '2026-08-16', url: 'https://www.rentablo.de' }, { @@ -2739,6 +2909,7 @@ export const personalFinanceTools: Product[] = ( origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Track your net worth', + updatedAt: '2026-07-05', url: 'https://www.rocketmoney.com' }, { @@ -2764,7 +2935,8 @@ export const personalFinanceTools: Product[] = ( name: 'Sarmaaya.pk Portfolio Tracking', note: 'Sarmaaya.pk Portfolio Tracking was discontinued in 2024', origin: 'PK', - slogan: 'Unified platform for financial research and portfolio tracking' + slogan: 'Unified platform for financial research and portfolio tracking', + updatedAt: '2026-07-05' }, { categories: ['INVESTMENT_RESEARCH'], @@ -2777,6 +2949,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$239', slogan: 'Stock Market Analysis & Tools for Investors', + updatedAt: '2026-07-05', url: 'https://seekingalpha.com' }, { @@ -2787,6 +2960,7 @@ export const personalFinanceTools: Product[] = ( origin: 'RO', platforms: ['WEB'], slogan: 'Track your net worth. Project every possible future.', + updatedAt: '2026-07-05', url: 'https://www.segmio.com' }, { @@ -2796,6 +2970,7 @@ export const personalFinanceTools: Product[] = ( origin: 'GB', slogan: 'Award-winning investment, trading and portfolio management tools', + updatedAt: '2026-08-28', url: 'https://www.sharescope.co.uk' }, { @@ -2810,6 +2985,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$135', regions: ['Global'], slogan: 'Stock Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://www.sharesight.com' }, { @@ -2819,7 +2995,8 @@ export const personalFinanceTools: Product[] = ( key: 'sharesmaster', name: 'SharesMaster', note: 'SharesMaster was discontinued', - slogan: 'Free Stock Portfolio Tracker' + slogan: 'Free Stock Portfolio Tracker', + updatedAt: '2026-07-05' }, { categories: ['STOCK_TRACKING'], @@ -2831,6 +3008,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€80', slogan: 'Stock Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://simpleportfolio.app' }, { @@ -2842,6 +3020,7 @@ export const personalFinanceTools: Product[] = ( name: 'Simplifi by Quicken', origin: 'US', platforms: ['ANDROID', 'IOS', 'WEB'], + updatedAt: '2026-07-05', url: 'https://www.quicken.com/products/simplifi' }, { @@ -2850,6 +3029,7 @@ export const personalFinanceTools: Product[] = ( name: 'Simply Safe Dividends', pricingPerYear: '$468', slogan: 'Proven dividend research and tracking tools', + updatedAt: '2026-08-28', url: 'https://www.simplysafedividends.com' }, { @@ -2863,6 +3043,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$120', slogan: 'Smart portfolio tracker for informed investors', + updatedAt: '2026-07-05', url: 'https://simplywall.st' }, { @@ -2897,6 +3078,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], pricingPerYear: '£47.99', slogan: 'Cut the cost of living and build your savings', + updatedAt: '2026-08-17', url: 'https://snoop.app' }, { @@ -2910,6 +3092,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$80', slogan: 'Simple and powerful portfolio tracker', + updatedAt: '2026-07-05', url: 'https://snowball-analytics.com' }, { @@ -2923,19 +3106,22 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$14.99', slogan: 'The only app that gets your money into shape', + updatedAt: '2026-08-17', url: 'https://www.spendee.com' }, { key: 'splashmoney', name: 'SplashMoney', origin: 'US', - slogan: 'Manage your money anytime, anywhere.' + slogan: 'Manage your money anytime, anywhere.', + updatedAt: '2025-09-14' }, { categories: ['FINANCIAL_ADVISOR', 'WEALTH_MANAGEMENT'], key: 'ssc-black-diamond', name: 'SS&C Black Diamond Wealth Solutions', slogan: 'The Cornerstone of a Successful Business', + updatedAt: '2026-08-28', url: 'https://www.sscblackdiamond.com' }, { @@ -2943,6 +3129,7 @@ export const personalFinanceTools: Product[] = ( key: 'statfolio', name: 'Statfolio', slogan: 'Take control of your investments', + updatedAt: '2026-08-28', url: 'https://statfolio.net' }, { @@ -2968,6 +3155,7 @@ export const personalFinanceTools: Product[] = ( name: 'Stock Analysis', pricingPerYear: '$79', slogan: 'Free Online Stock Information for Investors', + updatedAt: '2026-08-28', url: 'https://stockanalysis.com' }, { @@ -2979,6 +3167,7 @@ export const personalFinanceTools: Product[] = ( origin: 'DE', platforms: ['ANDROID', 'IOS', 'WEB'], slogan: 'Track all your Investments', + updatedAt: '2026-07-05', url: 'https://stockevents.app' }, { @@ -3016,6 +3205,7 @@ export const personalFinanceTools: Product[] = ( name: 'StockCharts', pricingPerYear: '$239.40', slogan: 'Advanced Charting, Screening & Financial Analysis Tools', + updatedAt: '2026-08-28', url: 'https://stockcharts.com' }, { @@ -3025,6 +3215,7 @@ export const personalFinanceTools: Product[] = ( origin: 'FI', platforms: ['WEB'], slogan: 'Supercharge your investments tracking experience', + updatedAt: '2026-07-05', url: 'https://stockle.app' }, { @@ -3054,7 +3245,8 @@ export const personalFinanceTools: Product[] = ( name: 'StockMarketEye', origin: 'FR', note: 'StockMarketEye was discontinued in 2023', - slogan: 'A Powerful Portfolio & Investment Tracking App' + slogan: 'A Powerful Portfolio & Investment Tracking App', + updatedAt: '2026-07-05' }, { categories: ['DIVIDEND_TRACKING', 'STOCK_TRACKING', 'TAX_REPORTING'], @@ -3076,6 +3268,7 @@ export const personalFinanceTools: Product[] = ( name: 'Stockopedia', pricingPerYear: '€550', slogan: 'Data-Driven Stock Research for Active Investors', + updatedAt: '2026-08-28', url: 'https://www.stockopedia.com' }, { @@ -3089,6 +3282,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$79.99', slogan: 'Investment Research and Portfolio Management', + updatedAt: '2026-07-05', url: 'https://www.stockrover.com' }, { @@ -3097,6 +3291,7 @@ export const personalFinanceTools: Product[] = ( name: 'Stock Unlock', pricingPerYear: '$90', slogan: 'Unique Stock Insights & Portfolio Tracking', + updatedAt: '2026-08-28', url: 'https://stockunlock.com' }, { @@ -3124,6 +3319,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€49.90', slogan: 'Visualize all of your portfolios', + updatedAt: '2026-07-05', url: 'https://stonksfolio.com' }, { @@ -3148,6 +3344,7 @@ export const personalFinanceTools: Product[] = ( name: 'StreamXLS', pricingPerYear: '$590', slogan: 'Excel bridge to IBKR TWS', + updatedAt: '2026-08-28', url: 'https://streamxls.com' }, { @@ -3160,6 +3357,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS'], pricingPerYear: '$20', slogan: 'AI-Powered Portfolio & Net Worth Tracker', + updatedAt: '2026-07-05', url: 'https://www.sumio.app' }, { @@ -3167,6 +3365,7 @@ export const personalFinanceTools: Product[] = ( key: 'tc2000', name: 'TC2000', slogan: 'Helping traders think for themselves for over 30 years', + updatedAt: '2026-08-28', url: 'https://www.tc2000.com' }, { @@ -3174,6 +3373,7 @@ export const personalFinanceTools: Product[] = ( key: 'tickeron', name: 'Tickeron', slogan: 'AI Trading Agents, Tools and News', + updatedAt: '2026-08-28', url: 'https://tickeron.com' }, { @@ -3182,6 +3382,7 @@ export const personalFinanceTools: Product[] = ( name: 'Tickertape', pricingPerYear: '₹2999', slogan: 'Financial freedom begins here', + updatedAt: '2026-08-28', url: 'https://www.tickertape.in' }, { @@ -3190,6 +3391,7 @@ export const personalFinanceTools: Product[] = ( key: 'tikr', name: 'TIKR', slogan: 'Invest like Wall Street with TIKR Terminal', + updatedAt: '2026-08-28', url: 'https://www.tikr.com' }, { @@ -3203,6 +3405,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$79', slogan: 'Your financial life in a spreadsheet, automatically updated each day', + updatedAt: '2026-07-05', url: 'https://tiller.com' }, { @@ -3216,6 +3419,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€35', slogan: 'Your key to empowered wealth management', + updatedAt: '2026-08-13', url: 'https://www.tinywallet.de' }, { @@ -3223,6 +3427,7 @@ export const personalFinanceTools: Product[] = ( key: 'tipranks', name: 'TipRanks', slogan: 'Make Smarter, Data-Driven Investment Decisions', + updatedAt: '2026-08-28', url: 'https://www.tipranks.com' }, { @@ -3236,6 +3441,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['IOS'], pricingPerYear: '$24.99', slogan: 'Make your money go further with daily budgets', + updatedAt: '2026-08-18', url: 'https://www.todays-budget.com' }, { @@ -3263,6 +3469,7 @@ export const personalFinanceTools: Product[] = ( key: 'trackinsight', name: 'Trackinsight', slogan: 'Empowering ETF Investors', + updatedAt: '2026-08-28', url: 'https://www.trackinsight.com' }, { @@ -3275,6 +3482,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€40', slogan: 'See your real investment performance — across every broker', + updatedAt: '2026-08-16', url: 'https://trackinv.com' }, { @@ -3289,6 +3497,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$99.99', slogan: 'Follow the Performance, Payments, and Diversification of Your Dividend Portfolio', + updatedAt: '2026-08-16', url: 'https://www.trackyourdividends.com' }, { @@ -3312,6 +3521,7 @@ export const personalFinanceTools: Product[] = ( name: 'TradeBB', slogan: 'Trading journal for tracking, reviewing, and improving your trades', + updatedAt: '2026-08-28', url: 'https://www.tradebb.ai' }, { @@ -3321,6 +3531,7 @@ export const personalFinanceTools: Product[] = ( pricingPerYear: '$219', regions: ['US'], slogan: 'Take Control Of Trader Taxes', + updatedAt: '2026-08-28', url: 'https://tradelog.com' }, { @@ -3361,6 +3572,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$360', slogan: 'The Trading Journal to Improve Your Trading Performance', + updatedAt: '2026-07-05', url: 'https://www.tradervue.com' }, { @@ -3368,6 +3580,7 @@ export const personalFinanceTools: Product[] = ( name: 'TradeZella', pricingPerYear: '$315', slogan: 'Meet Your AI Trading Partner', + updatedAt: '2026-08-28', url: 'https://www.tradezella.com' }, { @@ -3376,6 +3589,7 @@ export const personalFinanceTools: Product[] = ( key: 'tradingview', name: 'TradingView', slogan: 'Track All Markets', + updatedAt: '2026-08-28', url: 'https://www.tradingview.com' }, { @@ -3389,6 +3603,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€80.04', slogan: 'Investing that never bores you', + updatedAt: '2026-08-16', url: 'https://www.treestep.fr' }, { @@ -3410,6 +3625,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€60', slogan: 'The Extra Leaf for Your Portfolio', + updatedAt: '2026-07-05', url: 'https://trefolio.com' }, { @@ -3418,6 +3634,7 @@ export const personalFinanceTools: Product[] = ( name: 'Trendlyne', pricingPerYear: '₹2190', slogan: 'The Stock Market Platform to Stay Ahead', + updatedAt: '2026-08-28', url: 'https://trendlyne.com' }, { @@ -3445,7 +3662,8 @@ export const personalFinanceTools: Product[] = ( note: 'Renamed to Parqet', origin: 'DE', regions: ['AT', 'CH', 'DE'], - slogan: 'Dein Vermögen immer im Blick' + slogan: 'Dein Vermögen immer im Blick', + updatedAt: '2026-07-05' }, { categories: ['NET_WORTH_TRACKING', 'STOCK_TRACKING'], @@ -3458,6 +3676,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€35.90', slogan: 'Your complete portfolio and expense tracker. Actually private.', + updatedAt: '2026-09-09', url: 'https://www.turbobulls.com' }, { @@ -3465,6 +3684,7 @@ export const personalFinanceTools: Product[] = ( key: 'tweenvest', name: 'Tweenvest', slogan: 'Analyzing stocks has never been easier', + updatedAt: '2026-08-28', url: 'https://www.tweenvest.com' }, { @@ -3504,6 +3724,7 @@ export const personalFinanceTools: Product[] = ( name: 'Uncle Stock', pricingPerYear: '$130', slogan: 'Fundamental Stock Screener', + updatedAt: '2026-08-28', url: 'https://www.unclestock.com' }, { @@ -3530,6 +3751,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$300', slogan: 'Your Portfolio. Revealed.', + updatedAt: '2026-07-05', url: 'https://www.utluna.com', useAnonymously: true }, @@ -3539,6 +3761,7 @@ export const personalFinanceTools: Product[] = ( name: 'Validea', slogan: 'Factor-Based Portfolios and Investment Research Utilizing Proven Long-Term Strategies', + updatedAt: '2026-08-28', url: 'https://www.validea.com' }, { @@ -3550,6 +3773,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€78', slogan: 'Track your real portfolio. Not a watchlist.', + updatedAt: '2026-07-05', url: 'https://valuedge.app' }, { @@ -3591,6 +3815,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$348', slogan: 'Virtual Family Office for Smart Wealth Management', + updatedAt: '2026-07-05', url: 'https://vyzer.co' }, { @@ -3604,6 +3829,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '€90', slogan: 'Personal finance reimagined with AI', + updatedAt: '2026-07-05', url: 'https://walletguide.com' }, { @@ -3615,7 +3841,8 @@ export const personalFinanceTools: Product[] = ( note: 'wallmine was discontinued in 2024', origin: 'CZ', pricingPerYear: '$600', - slogan: 'Make Smarter Investments' + slogan: 'Make Smarter Investments', + updatedAt: '2025-12-13' }, { categories: ['INVESTMENT_RESEARCH'], @@ -3628,6 +3855,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$234', slogan: 'Stock market analysis for the serious part-time investor', + updatedAt: '2026-07-05', url: 'https://www.wallstreetzen.com' }, { @@ -3654,6 +3882,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CH', platforms: ['WEB'], slogan: 'Manage wealth data more efficiently', + updatedAt: '2026-07-05', url: 'https://www.wealtharc.com' }, { @@ -3666,6 +3895,7 @@ export const personalFinanceTools: Product[] = ( origin: 'AE', platforms: ['WEB'], slogan: 'Portfolio Management System', + updatedAt: '2026-07-05', url: 'https://wealthbrain.com' }, { @@ -3680,6 +3910,7 @@ export const personalFinanceTools: Product[] = ( origin: 'CA', platforms: ['IOS', 'LINUX', 'MACOS', 'WEB', 'WINDOWS'], slogan: 'Open-Source, Offline & Private Portfolio Tracker', + updatedAt: '2026-07-05', url: 'https://wealthfolio.app' }, { @@ -3694,6 +3925,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$50', slogan: 'See all your investments in one place', + updatedAt: '2026-07-05', url: 'https://wealthica.com' }, { @@ -3705,6 +3937,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$60', slogan: 'Personal Finance & Budgeting App', + updatedAt: '2026-07-05', url: 'https://www.wealthposition.com' }, { @@ -3717,6 +3950,7 @@ export const personalFinanceTools: Product[] = ( origin: 'IN', platforms: ['WEB'], slogan: 'One app to manage all your investments', + updatedAt: '2026-07-05', url: 'https://www.wealthy.in/tracker' }, { @@ -3724,7 +3958,8 @@ export const personalFinanceTools: Product[] = ( key: 'whal', name: 'Whal', origin: 'US', - slogan: 'Manage your investments in one place' + slogan: 'Manage your investments in one place', + updatedAt: '2026-07-05' }, { categories: ['INVESTMENT_RESEARCH'], @@ -3732,6 +3967,7 @@ export const personalFinanceTools: Product[] = ( name: 'Wisesheets', pricingPerYear: '$60', slogan: 'The Ultimate Spreadsheet Add-On for Stock Investors', + updatedAt: '2026-08-28', url: 'https://www.wisesheets.io' }, { @@ -3743,6 +3979,7 @@ export const personalFinanceTools: Product[] = ( key: 'ycharts', name: 'YCharts', slogan: 'Financial Research and Proposal Platform', + updatedAt: '2026-08-28', url: 'https://ycharts.com' }, { @@ -3757,7 +3994,8 @@ export const personalFinanceTools: Product[] = ( note: 'yeekatee was discontinued in 2024', origin: 'CH', regions: ['Global'], - slogan: 'Connect. Share. Invest.' + slogan: 'Connect. Share. Invest.', + updatedAt: '2026-07-05' }, { categories: ['BUDGETING'], @@ -3770,6 +4008,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['ANDROID', 'IOS', 'WEB'], pricingPerYear: '$109', slogan: 'Change Your Relationship With Money', + updatedAt: '2026-07-05', url: 'https://www.ynab.com' }, { @@ -3778,6 +4017,7 @@ export const personalFinanceTools: Product[] = ( key: 'zacks', name: 'Zacks', slogan: 'Stock Research, Analysis, & Recommendations', + updatedAt: '2026-08-28', url: 'https://www.zacks.com' }, { @@ -3785,6 +4025,7 @@ export const personalFinanceTools: Product[] = ( key: 'zenvesto', name: 'Zenvesto', slogan: 'Smart Investment Portfolio Tracker', + updatedAt: '2026-08-28', url: 'https://zenvesto.com' }, { @@ -3798,6 +4039,7 @@ export const personalFinanceTools: Product[] = ( platforms: ['WEB'], pricingPerYear: '$84', slogan: 'Your solution for investing success', + updatedAt: '2026-07-05', url: 'https://ziggma.com' } ] satisfies Product[] From 6282e39b6bbe9849ba83a0403d2dbf1f5e97b17b Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sat, 26 Sep 2026 10:17:14 +0200 Subject: [PATCH 09/19] Release 3.73.0 (#7949) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f4efde2ebb..fe31b7a9b8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 3.73.0 - 2026-09-26 ### Changed diff --git a/package-lock.json b/package-lock.json index 9469e56421..b3eae247c2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "3.72.0", + "version": "3.73.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "3.72.0", + "version": "3.73.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 638fd1ed10..5648ac6693 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "3.72.0", + "version": "3.73.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio", From f6b25eec05312a3cda466e00323b94f39c8f5a5f Mon Sep 17 00:00:00 2001 From: Ahson Shaikh <59800198+Ahson-Shaikh@users.noreply.github.com> Date: Sat, 26 Sep 2026 16:19:03 +0500 Subject: [PATCH 10/19] Task/add Easypanel to home server systems list (#7939) Add Easypanel --- README.md | 2 +- .../src/app/pages/faq/self-hosting/self-hosting-page.html | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index c98c163c40..b9352e3bd3 100644 --- a/README.md +++ b/README.md @@ -173,7 +173,7 @@ docker compose -f docker/docker-compose.build.yml up -d ### Home Server Systems (Community) -Ghostfolio is available for various home server systems, including [CasaOS](https://github.com/bigbeartechworld/big-bear-casaos), [Home Assistant](https://github.com/lildude/ha-addon-ghostfolio), [Runtipi](https://www.runtipi.io/docs/apps-available), [TrueCharts](https://truecharts.org/charts/stable/ghostfolio), [Umbrel](https://apps.umbrel.com/app/ghostfolio), and [Unraid](https://unraid.net/community/apps?q=ghostfolio). +Ghostfolio is available for various home server systems, including [CasaOS](https://github.com/bigbeartechworld/big-bear-casaos), [Easypanel](https://easypanel.io/templates/ghostfolio), [Home Assistant](https://github.com/lildude/ha-addon-ghostfolio), [Runtipi](https://www.runtipi.io/docs/apps-available), [TrueCharts](https://truecharts.org/charts/stable/ghostfolio), [Umbrel](https://apps.umbrel.com/app/ghostfolio), and [Unraid](https://unraid.net/community/apps?q=ghostfolio). ## Development diff --git a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html index 59478d3cfa..7d5776d0ca 100644 --- a/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html +++ b/apps/client/src/app/pages/faq/self-hosting/self-hosting-page.html @@ -30,7 +30,7 @@ systems, including CasaOS, + >, Easypanel, Home Assistant, Runtipi, From 08e923ca105a6a8582f32971b3d3bd0cf50eba52 Mon Sep 17 00:00:00 2001 From: Neo RS Date: Sun, 27 Sep 2026 06:56:09 -0700 Subject: [PATCH 11/19] Task/improve Catalan localization (#7950) * Update translations * Update changelog --- CHANGELOG.md | 6 ++++ apps/client/src/locales/messages.ca.xlf | 40 ++++++++++++------------- 2 files changed, 26 insertions(+), 20 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index fe31b7a9b8..28710d17e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,12 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## Unreleased + +### Changed + +- Improved the language localization for Catalan (`ca`) + ## 3.73.0 - 2026-09-26 ### Changed diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 610cca4ca3..1d502bb80b 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -324,7 +324,7 @@ Date must be in the future. - Date must be in the future. + La data ha de ser futura. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html 70 @@ -332,7 +332,7 @@ Fetch market price - Fetch market price + Recupera el preu de mercat libs/ui/src/lib/historical-market-data-editor/historical-market-data-editor-dialog/historical-market-data-editor-dialog.html 40 @@ -372,7 +372,7 @@ Any person who has the link can view the data. - Any person who has the link can view the data. + Qualsevol persona que tingui l’enllaç pot veure les dades. apps/client/src/app/components/user-account-access/create-or-update-access-dialog/create-or-update-access-dialog.html 42 @@ -696,7 +696,7 @@ Paid - Paid + De pagament apps/client/src/app/components/user-detail-dialog/user-detail-dialog.component.ts 136 @@ -804,7 +804,7 @@ View and manage - View and manage + Veure i gestionar libs/ui/src/lib/access-level-icon/access-level-icon.component.html 9 @@ -1052,7 +1052,7 @@ Data Gathering Frequency - Data Gathering Frequency + Freqüència de recollida de dades apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.html 477 @@ -1088,7 +1088,7 @@ Apply current market price - Apply current market price + Aplica el preu de mercat actual apps/client/src/app/pages/portfolio/activities/create-or-update-activity-dialog/create-or-update-activity-dialog.html 221 @@ -1096,7 +1096,7 @@ Subscription History - Subscription History + Historial de subscripcions apps/client/src/app/components/user-detail-dialog/user-detail-dialog.html 156 @@ -1144,7 +1144,7 @@ Healthcare - Healthcare + Salut libs/ui/src/lib/i18n.ts 98 @@ -1276,7 +1276,7 @@ Technology - Technology + Tecnologia libs/ui/src/lib/i18n.ts 102 @@ -1344,7 +1344,7 @@ Asset profile has been saved - Asset profile has been saved + El perfil de l’actiu s’ha desat apps/client/src/app/components/admin-market-data/asset-profile-dialog/asset-profile-dialog.component.ts 754 @@ -1512,7 +1512,7 @@ Update Account - Update Account + Actualitza el compte libs/common/src/lib/routes/routes.ts 120 @@ -1660,7 +1660,7 @@ Cache has been flushed. - Cache has been flushed. + La memòria cau s’ha buidat. apps/client/src/app/components/admin-overview/admin-overview.component.ts 281 @@ -2212,7 +2212,7 @@ Code - Code + Codi apps/client/src/app/components/admin-overview/admin-overview.html 165 @@ -2312,7 +2312,7 @@ Energy - Energy + Energia libs/ui/src/lib/i18n.ts 96 @@ -2676,7 +2676,7 @@ The value has been copied to the clipboard - The value has been copied to the clipboard + El valor s’ha copiat al porta-retalls libs/ui/src/lib/notifications/alert-dialog/alert-dialog.component.ts 46 @@ -2752,7 +2752,7 @@ Add Account - Add Account + Afegeix un compte libs/common/src/lib/routes/routes.ts 101 @@ -2848,7 +2848,7 @@ Clone Activity - Clone Activity + Clona l’activitat libs/common/src/lib/routes/routes.ts 190 @@ -3849,7 +3849,7 @@ Creation - Creation + Creació apps/client/src/app/components/admin-overview/admin-overview.html 191 @@ -6758,7 +6758,7 @@ View Details - View Details + Veure els detalls apps/client/src/app/components/admin-users/admin-users.html 220 From 98cea58da80bc99c88d7770238f3ad1da7fde04f Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 16:12:46 +0200 Subject: [PATCH 12/19] Bugfix/wrapping of name column in accounts table (#7951) * Fix wrapping of name column * Update changelog --- CHANGELOG.md | 4 ++++ .../accounts-table/accounts-table.component.html | 16 +++++++++------- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 28710d17e3..f99c393b0a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Improved the language localization for Catalan (`ca`) +### Fixed + +- Fixed the wrapping of the name column in the accounts table component on mobile + ## 3.73.0 - 2026-09-26 ### Changed diff --git a/libs/ui/src/lib/accounts-table/accounts-table.component.html b/libs/ui/src/lib/accounts-table/accounts-table.component.html index a01abff1a8..60be93ad8a 100644 --- a/libs/ui/src/lib/accounts-table/accounts-table.component.html +++ b/libs/ui/src/lib/accounts-table/accounts-table.component.html @@ -50,13 +50,15 @@ Name - - {{ element.name }} +
+ + {{ element.name }} +
Total From 67957f3c3e8ff14c13db9ac3eb85000629baa99d Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 16:21:11 +0200 Subject: [PATCH 13/19] Task/hide currency in portfolio summary on mobile (#7952) * Hide currency on mobile * Update changelog --- CHANGELOG.md | 1 + .../portfolio-summary.component.html | 38 +++++++++---------- .../portfolio-summary.component.ts | 4 ++ 3 files changed, 24 insertions(+), 19 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f99c393b0a..a5e7a65c69 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed +- Simplified the portfolio summary by hiding the currency on mobile - Improved the language localization for Catalan (`ca`) ### Fixed diff --git a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html index ea408c17d8..8846c14a7c 100644 --- a/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html +++ b/apps/client/src/app/components/portfolio-summary/portfolio-summary.component.html @@ -48,7 +48,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.totalBuy" /> @@ -62,7 +62,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.totalSell" /> @@ -79,7 +79,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.totalInvestmentValueWithCurrencyEffect" /> @@ -93,7 +93,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.grossPerformanceWithCurrencyEffect" /> @@ -110,7 +110,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.fees" /> @@ -127,7 +127,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.netPerformanceWithCurrencyEffect" /> @@ -171,7 +171,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.totalAssetsInBaseCurrency" /> @@ -217,7 +217,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="holdingsInBaseCurrency" /> @@ -233,7 +233,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="investmentsInBaseCurrency" /> @@ -248,7 +248,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.emergencyFund?.assets" /> @@ -295,7 +295,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.totalCashInBaseCurrency" /> @@ -311,7 +311,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.cash" /> @@ -326,7 +326,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.emergencyFund?.cash" /> @@ -356,7 +356,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.excludedAccountsAndActivities" /> @@ -379,7 +379,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.liabilitiesInBaseCurrency" /> @@ -396,7 +396,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.totalValueInBaseCurrency" /> @@ -469,7 +469,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.emergencyFund?.total" /> @@ -483,7 +483,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.interestInBaseCurrency" /> @@ -497,7 +497,7 @@ [isLoading]="isLoading" [locale]="locale" [precision]="precision" - [unit]="baseCurrency" + [unit]="displayedCurrency" [value]="summary?.dividendInBaseCurrency" /> 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 ea68713189..dec65ddad9 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 @@ -79,6 +79,10 @@ export class GfPortfolioSummaryComponent implements OnChanges { : 0; } + protected get displayedCurrency() { + return this.deviceType === 'mobile' ? undefined : this.baseCurrency; + } + protected get emergencyFundPercentage() { return this.summary?.totalValueInBaseCurrency ? (this.summary.emergencyFund?.total || 0) / From 920eb697f4ef9714aeb447debf94f55a19c84cf4 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:20:37 +0200 Subject: [PATCH 14/19] Bugfix/fix watchlist sorting for asset profiles without name (#7921) * Fix sorting of watchlist items without a name * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/endpoints/watchlist/watchlist.service.ts | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a5e7a65c69..ad28005494 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 ### Fixed - Fixed the wrapping of the name column in the accounts table component on mobile +- Fixed the sorting of the watchlist for asset profiles without a name ## 3.73.0 - 2026-09-26 diff --git a/apps/api/src/app/endpoints/watchlist/watchlist.service.ts b/apps/api/src/app/endpoints/watchlist/watchlist.service.ts index ccdd04e27c..c69a31df82 100644 --- a/apps/api/src/app/endpoints/watchlist/watchlist.service.ts +++ b/apps/api/src/app/endpoints/watchlist/watchlist.service.ts @@ -151,7 +151,7 @@ export class WatchlistService { ); return watchlist.sort((a, b) => { - return a.name.localeCompare(b.name); + return (a.name ?? '').localeCompare(b.name ?? ''); }); } From ed7138cf5f9c4a7e891f2f4afdbc7084fdee6aec Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:25:27 +0200 Subject: [PATCH 15/19] Task/enable browser cache for logo endpoints (#7956) * Enable browser cache * Update changelog --- CHANGELOG.md | 1 + apps/api/src/app/logo/logo.controller.ts | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ad28005494..f5431bf8ca 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Changed - Simplified the portfolio summary by hiding the currency on mobile +- Improved the performance of the logo endpoints by enabling the browser cache - Improved the language localization for Catalan (`ca`) ### Fixed diff --git a/apps/api/src/app/logo/logo.controller.ts b/apps/api/src/app/logo/logo.controller.ts index 47bd1fc750..30c85e585e 100644 --- a/apps/api/src/app/logo/logo.controller.ts +++ b/apps/api/src/app/logo/logo.controller.ts @@ -11,12 +11,15 @@ import { } from '@nestjs/common'; import { DataSource } from '@prisma/client'; import { Response } from 'express'; +import ms from 'ms'; import { GetLogoDto } from './get-logo.dto'; import { LogoService } from './logo.service'; @Controller('logo') export class LogoController { + private static readonly CACHE_MAX_AGE_IN_SECONDS = ms('7 days') / 1000; + public constructor(private readonly logoService: LogoService) {} @Get(':dataSource/:symbol') @@ -34,6 +37,12 @@ export class LogoController { }); response.contentType(type); + + response.setHeader( + 'Cache-Control', + `public, max-age=${LogoController.CACHE_MAX_AGE_IN_SECONDS}` + ); + response.send(buffer); } catch { response.status(HttpStatus.NOT_FOUND).send(); @@ -49,6 +58,12 @@ export class LogoController { const { buffer, type } = await this.logoService.getLogoByUrl(url); response.contentType(type); + + response.setHeader( + 'Cache-Control', + `public, max-age=${LogoController.CACHE_MAX_AGE_IN_SECONDS}` + ); + response.send(buffer); } catch { response.status(HttpStatus.NOT_FOUND).send(); From 30208907a6899e7f62a4b0fea1a3c9013970c663 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:42:08 +0200 Subject: [PATCH 16/19] Feature/add dividend performance to analysis page (#7924) * Add dividend performance * Update changelog --- CHANGELOG.md | 4 + .../calculator/portfolio-calculator.ts | 125 +++++- .../roai/portfolio-calculator-btceur.spec.ts | 6 + .../roai/portfolio-calculator-btcusd.spec.ts | 6 + .../roai/portfolio-calculator-cash.spec.ts | 6 + ...-calculator-googl-fee-and-dividend.spec.ts | 362 ++++++++++++++++++ ...-calculator-msft-buy-with-dividend.spec.ts | 6 + ...folio-calculator-novn-buy-and-sell.spec.ts | 6 + .../calculator/roai/portfolio-calculator.ts | 50 ++- .../accumulated-values.interface.ts | 1 + .../src/app/portfolio/portfolio.controller.ts | 9 +- .../src/app/portfolio/portfolio.service.ts | 9 + .../types/performance-percentages.type.ts | 1 + .../portfolio/analysis/analysis-page.html | 40 ++ .../historical-data-item.interface.ts | 2 + .../portfolio-performance.interface.ts | 2 + .../interfaces/portfolio-summary.interface.ts | 1 - 17 files changed, 617 insertions(+), 19 deletions(-) create mode 100644 apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-fee-and-dividend.spec.ts diff --git a/CHANGELOG.md b/CHANGELOG.md index f5431bf8ca..c199d06c0d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## Unreleased +### Added + +- Added the dividend performance to the analysis page (experimental) + ### Changed - Simplified the portfolio summary by hiding the currency on mobile diff --git a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts index d9efa9f86c..d868b65b3f 100644 --- a/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/portfolio-calculator.ts @@ -223,15 +223,19 @@ export abstract class PortfolioCalculator { ): PortfolioSnapshot; protected abstract calculatePerformancePercentages({ - accumulatedValuesByDate + accumulatedValuesByDate, + holdings }: { accumulatedValuesByDate: { [date: string]: AccumulatedValues }; + holdings: PortfolioSnapshotHolding[]; }): { [date: string]: PerformancePercentages }; protected abstract calculatePerformancePercentagesForDateRange({ - historicalDataItems + historicalDataItems, + holdings }: { historicalDataItems: HistoricalDataItem[]; + holdings: PortfolioSnapshotHolding[]; }): { [date: string]: PerformancePercentages }; @LogPerformance @@ -544,6 +548,13 @@ export abstract class PortfolioCalculator { } } + const totalDividendValueWithCurrencyEffectByDate = + this.getTotalDividendValueWithCurrencyEffectByDate({ + chartDates, + exchangeRatesByCurrency, + holdings: positions + }); + const assetProfileIdentifiers = Object.keys(valuesByAssetProfileIdentifier); for (const dateString of chartDates) { @@ -620,6 +631,8 @@ export abstract class PortfolioCalculator { accumulatedValuesByDate[dateString] ?.totalCurrentValueWithCurrencyEffect ?? new Big(0) ).add(currentValueWithCurrencyEffect), + totalDividendValueWithCurrencyEffect: + totalDividendValueWithCurrencyEffectByDate[dateString], totalInvestmentValue: ( accumulatedValuesByDate[dateString]?.totalInvestmentValue ?? new Big(0) @@ -644,8 +657,18 @@ export abstract class PortfolioCalculator { } } + const positionsIncludedInHoldings = positions + .filter(({ includeInHoldings }) => { + return includeInHoldings; + }) + // eslint-disable-next-line @typescript-eslint/no-unused-vars + .map(({ includeInHoldings, includeInPerformance, ...rest }) => { + return rest; + }); + const performancePercentagesByDate = this.calculatePerformancePercentages({ - accumulatedValuesByDate + accumulatedValuesByDate, + holdings: positionsIncludedInHoldings }); const historicalData: HistoricalDataItem[] = Object.entries( @@ -656,6 +679,7 @@ export abstract class PortfolioCalculator { totalCashValueWithCurrencyEffect, totalCurrentValue, totalCurrentValueWithCurrencyEffect, + totalDividendValueWithCurrencyEffect, totalInvestmentValue, totalInvestmentValueWithCurrencyEffect, totalNetPerformanceValue, @@ -666,6 +690,7 @@ export abstract class PortfolioCalculator { return { ...performancePercentagesByDate[date], date, + dividendInBaseCurrency: totalDividendValueWithCurrencyEffect.toNumber(), investmentValueWithCurrencyEffect: investmentValueWithCurrencyEffect.toNumber(), netPerformance: totalNetPerformanceValue.toNumber(), @@ -683,15 +708,6 @@ export abstract class PortfolioCalculator { const overall = this.calculateOverallPerformance(positions); - const positionsIncludedInHoldings = positions - .filter(({ includeInHoldings }) => { - return includeInHoldings; - }) - // eslint-disable-next-line @typescript-eslint/no-unused-vars - .map(({ includeInHoldings, includeInPerformance, ...rest }) => { - return rest; - }); - return { ...overall, errors, @@ -1343,6 +1359,7 @@ export abstract class PortfolioCalculator { const historicalDataItemsOfDateRange: HistoricalDataItem[] = []; + let dividendInBaseCurrencyAtStartDate: number; let netPerformanceAtStartDate: number; let netPerformanceWithCurrencyEffectAtStartDate: number; @@ -1353,6 +1370,11 @@ export abstract class PortfolioCalculator { // Take the values at the start date from the first day of the date // range if (historicalDataItemsOfDateRange.length === 0) { + // TODO: Remove the fallback to 0 with the next release, when each + // cached portfolio snapshot contains the dividend + dividendInBaseCurrencyAtStartDate = + historicalDataItem.dividendInBaseCurrency ?? 0; + netPerformanceAtStartDate = historicalDataItem.netPerformance; netPerformanceWithCurrencyEffectAtStartDate = @@ -1361,6 +1383,11 @@ export abstract class PortfolioCalculator { historicalDataItemsOfDateRange.push({ ...historicalDataItem, + // TODO: Remove the fallback to 0 with the next release, when each + // cached portfolio snapshot contains the dividend + dividendInBaseCurrency: + (historicalDataItem.dividendInBaseCurrency ?? 0) - + dividendInBaseCurrencyAtStartDate, netPerformance: historicalDataItem.netPerformance - netPerformanceAtStartDate, netPerformanceWithCurrencyEffect: @@ -1372,7 +1399,8 @@ export abstract class PortfolioCalculator { const performancePercentagesByDate = this.calculatePerformancePercentagesForDateRange({ - historicalDataItems: historicalDataItemsOfDateRange + historicalDataItems: historicalDataItemsOfDateRange, + holdings: this.snapshot.positions }); const chart = historicalDataItemsOfDateRange.map((historicalDataItem) => { @@ -1734,6 +1762,77 @@ export abstract class PortfolioCalculator { return chartDateMap; } + private getTotalDividendValueWithCurrencyEffectByDate({ + chartDates, + exchangeRatesByCurrency, + holdings + }: { + chartDates: string[]; + exchangeRatesByCurrency: { + [currencyPair: string]: { [dateString: string]: number }; + }; + holdings: PortfolioCalculatorHolding[]; + }): { [date: string]: Big } { + // Take the dividend from the same holdings as the portfolio summary, so + // that the response shows one dividend only + const assetProfileIdentifiersIncludedInHoldings = new Set( + holdings + .filter(({ includeInHoldings }) => { + return includeInHoldings; + }) + .map(({ dataSource, symbol }) => { + return getAssetProfileIdentifier({ dataSource, symbol }); + }) + ); + + const dividendActivities = this.activities.filter( + ({ assetProfile, type }) => { + return ( + type === 'DIVIDEND' && + assetProfileIdentifiersIncludedInHoldings.has( + getAssetProfileIdentifier(assetProfile) + ) + ); + } + ); + + const totalDividendValueWithCurrencyEffectByDate: { [date: string]: Big } = + {}; + + let index = 0; + let totalDividendValueWithCurrencyEffect = new Big(0); + + // The activities and the chart dates are sorted by date, so one pass over + // both gives the dividends received up to each chart date + for (const chartDate of chartDates) { + while ( + index < dividendActivities.length && + dividendActivities[index].date <= chartDate + ) { + const { assetProfile, date, quantity, unitPrice } = + dividendActivities[index]; + + totalDividendValueWithCurrencyEffect = + totalDividendValueWithCurrencyEffect.plus( + quantity + .mul(unitPrice) + .mul( + exchangeRatesByCurrency[ + `${assetProfile.currency}${this.currency}` + ]?.[date] ?? 1 + ) + ); + + index++; + } + + totalDividendValueWithCurrencyEffectByDate[chartDate] = + totalDividendValueWithCurrencyEffect; + } + + return totalDividendValueWithCurrencyEffectByDate; + } + @LogPerformance private async initialize(attempt = 1) { const startTimeTotal = performance.now(); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts index aadf2e23a0..ed8841b167 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btceur.spec.ts @@ -142,6 +142,8 @@ describe('PortfolioCalculator', () => { expect(portfolioSnapshot.historicalData[0]).toEqual({ date: '2021-12-11', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, @@ -160,6 +162,8 @@ describe('PortfolioCalculator', () => { */ expect(portfolioSnapshot.historicalData[1]).toEqual({ date: '2021-12-12', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 44558.42, netPerformance: 5535.42, // 1 * (50098.3 - 44558.42) - 4.46 = 5535.42 netPerformanceInPercentage: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 @@ -179,6 +183,8 @@ describe('PortfolioCalculator', () => { ] ).toEqual({ date: '2022-01-14', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: -1463.18, netPerformanceInPercentage: -0.032837340282712, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts index fe86d9d457..e0cfeb8227 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-btcusd.spec.ts @@ -142,6 +142,8 @@ describe('PortfolioCalculator', () => { expect(portfolioSnapshot.historicalData[0]).toEqual({ date: '2021-12-11', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, @@ -160,6 +162,8 @@ describe('PortfolioCalculator', () => { */ expect(portfolioSnapshot.historicalData[1]).toEqual({ date: '2021-12-12', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 44558.42, netPerformance: 5535.42, // 1 * (50098.3 - 44558.42) - 4.46 = 5535.42 netPerformanceInPercentage: 0.12422837255001412, // 5535.42 ÷ 44558.42 = 0.12422837255001412 @@ -179,6 +183,8 @@ describe('PortfolioCalculator', () => { ] ).toEqual({ date: '2022-01-14', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: -1463.18, netPerformanceInPercentage: -0.032837340282712, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts index 23c806483c..b98aa9e5f2 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-cash.spec.ts @@ -321,6 +321,8 @@ describe('PortfolioCalculator', () => { */ expect(portfolioSnapshot.historicalData.at(-1)).toEqual({ date: '2025-01-01', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, @@ -459,6 +461,8 @@ describe('PortfolioCalculator', () => { */ expect(portfolioSnapshot.historicalData.at(-1)).toEqual({ date: '2025-01-01', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, @@ -601,6 +605,8 @@ describe('PortfolioCalculator', () => { */ expect(portfolioSnapshot.historicalData.at(-1)).toEqual({ date: '2025-01-01', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-fee-and-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-fee-and-dividend.spec.ts new file mode 100644 index 0000000000..ab9c24b4fb --- /dev/null +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-googl-fee-and-dividend.spec.ts @@ -0,0 +1,362 @@ +import { + activityDummyData, + assetProfileDummyData, + getPerformanceByDateRange, + userDummyData +} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils'; +import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory'; +import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service'; +import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock'; +import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service'; +import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; +import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; +import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service'; +import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service'; +import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock'; +import { parseDate } from '@ghostfolio/common/helper'; +import { Activity } from '@ghostfolio/common/interfaces'; +import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; + +import { Big } from 'big.js'; + +jest.mock('@ghostfolio/api/app/portfolio/current-rate.service', () => { + return { + CurrentRateService: jest.fn().mockImplementation(() => { + return CurrentRateServiceMock; + }) + }; +}); + +jest.mock( + '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service', + () => { + return { + PortfolioSnapshotService: jest.fn().mockImplementation(() => { + return PortfolioSnapshotServiceMock; + }) + }; + } +); + +jest.mock('@ghostfolio/api/app/redis-cache/redis-cache.service', () => { + return { + RedisCacheService: jest.fn().mockImplementation(() => { + return RedisCacheServiceMock; + }) + }; +}); + +describe('PortfolioCalculator', () => { + let configurationService: ConfigurationService; + let currentRateService: CurrentRateService; + let exchangeRateDataService: ExchangeRateDataService; + let portfolioCalculatorFactory: PortfolioCalculatorFactory; + let portfolioSnapshotService: PortfolioSnapshotService; + let redisCacheService: RedisCacheService; + + beforeEach(() => { + PortfolioSnapshotServiceMock.reset(); + RedisCacheServiceMock.reset(); + + configurationService = new ConfigurationService(); + + currentRateService = new CurrentRateService(null, null, null); + + exchangeRateDataService = new ExchangeRateDataService( + null, + null, + null, + null + ); + + portfolioSnapshotService = new PortfolioSnapshotService(null, null); + + redisCacheService = new RedisCacheService(null, null); + + portfolioCalculatorFactory = new PortfolioCalculatorFactory( + configurationService, + currentRateService, + exchangeRateDataService, + portfolioSnapshotService, + redisCacheService + ); + }); + + describe('get current positions', () => { + it('with GOOGL fee and dividend', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2023-07-10').getTime()); + + const activities: Activity[] = [ + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2021-09-16'), + feeInAssetProfileCurrency: 19, + feeInBaseCurrency: 19, + quantity: 1, + type: 'BUY', + unitPriceInAssetProfileCurrency: 298.58 + }, + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2021-11-16'), + feeInAssetProfileCurrency: 0, + feeInBaseCurrency: 0, + quantity: 1, + type: 'DIVIDEND', + unitPriceInAssetProfileCurrency: 0.62 + }, + { + // The first activity of this asset profile is a fee, which is not an + // investment activity. Thus the holding is not included in the + // holdings of the portfolio summary, and its dividend must not be + // included in the chart + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Alphabet Inc.', + symbol: 'GOOGL' + }, + date: new Date('2023-01-03'), + feeInAssetProfileCurrency: 1, + feeInBaseCurrency: 1, + quantity: 0, + type: 'FEE', + unitPriceInAssetProfileCurrency: 0 + }, + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Alphabet Inc.', + symbol: 'GOOGL' + }, + date: new Date('2023-07-10'), + feeInAssetProfileCurrency: 0, + feeInBaseCurrency: 0, + quantity: 1, + type: 'DIVIDEND', + unitPriceInAssetProfileCurrency: 5 + } + ]; + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'USD', + usePortfolioSnapshotCache: false, + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + + const dividendInBaseCurrency = + await portfolioCalculator.getDividendInBaseCurrency(); + + expect( + portfolioSnapshot.positions.map(({ symbol }) => { + return symbol; + }) + ).toEqual(['MSFT']); + + // The chart and the portfolio summary must show the same dividend + expect(dividendInBaseCurrency).toEqual(new Big('0.62')); + + expect( + portfolioSnapshot.historicalData.at(-1).dividendInBaseCurrency + ).toEqual(0.62); + }); + + it('with GOOGL dividend without investment', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2023-07-10').getTime()); + + const activities: Activity[] = [ + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2021-09-16'), + feeInAssetProfileCurrency: 19, + feeInBaseCurrency: 19, + quantity: 1, + type: 'BUY', + unitPriceInAssetProfileCurrency: 298.58 + }, + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2021-11-16'), + feeInAssetProfileCurrency: 0, + feeInBaseCurrency: 0, + quantity: 1, + type: 'DIVIDEND', + unitPriceInAssetProfileCurrency: 0.62 + }, + { + // The holding has a dividend, but no average investment. Thus the + // dividend percentage stays 0, like the dividend yield + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Alphabet Inc.', + symbol: 'GOOGL' + }, + date: new Date('2023-07-10'), + feeInAssetProfileCurrency: 0, + feeInBaseCurrency: 0, + quantity: 1, + type: 'DIVIDEND', + unitPriceInAssetProfileCurrency: 5 + } + ]; + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'USD', + usePortfolioSnapshotCache: false, + userId: userDummyData.id + }); + + const portfolioSnapshot = await portfolioCalculator.computeSnapshot(); + + const performanceByDateRange = await getPerformanceByDateRange({ + portfolioCalculator, + dateRanges: ['max'] + }); + + expect(portfolioSnapshot).toMatchObject({ + dividendYieldPercentWithCurrencyEffect: new Big(0) + }); + + expect(portfolioSnapshot.historicalData.at(-1)).toMatchObject({ + dividendInBaseCurrency: 5.62, + dividendInPercentageWithCurrencyEffect: 0 + }); + + expect(performanceByDateRange).toMatchObject({ + max: { + dividendInBaseCurrency: 5.62, + dividendInPercentageWithCurrencyEffect: 0 + } + }); + }); + + it('with MSFT dividend before and in the date range', async () => { + jest.useFakeTimers().setSystemTime(parseDate('2023-07-10').getTime()); + + const activities: Activity[] = [ + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2021-09-16'), + feeInAssetProfileCurrency: 19, + feeInBaseCurrency: 19, + quantity: 1, + type: 'BUY', + unitPriceInAssetProfileCurrency: 298.58 + }, + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2021-11-16'), + feeInAssetProfileCurrency: 0, + feeInBaseCurrency: 0, + quantity: 1, + type: 'DIVIDEND', + unitPriceInAssetProfileCurrency: 0.62 + }, + { + ...activityDummyData, + assetProfile: { + ...assetProfileDummyData, + currency: 'USD', + dataSource: 'YAHOO', + name: 'Microsoft Inc.', + symbol: 'MSFT' + }, + date: new Date('2023-07-10'), + feeInAssetProfileCurrency: 0, + feeInBaseCurrency: 0, + quantity: 1, + type: 'DIVIDEND', + unitPriceInAssetProfileCurrency: 0.68 + } + ]; + + const portfolioCalculator = portfolioCalculatorFactory.createCalculator({ + activities, + calculationType: PerformanceCalculationType.ROAI, + currency: 'USD', + usePortfolioSnapshotCache: false, + userId: userDummyData.id + }); + + await portfolioCalculator.computeSnapshot(); + + const performanceByDateRange = await getPerformanceByDateRange({ + portfolioCalculator, + dateRanges: ['1d', 'max', 'ytd'] + }); + + // The dividend before the date range is subtracted, so that the date + // range shows the dividend in the date range only + expect(performanceByDateRange).toMatchObject({ + '1d': { + dividendInBaseCurrency: 0.68, + dividendInPercentageWithCurrencyEffect: 0.002016487752802325 + }, + max: { + dividendInBaseCurrency: 1.3, + dividendInPercentageWithCurrencyEffect: 0.004353941992095899 + }, + ytd: { + dividendInBaseCurrency: 0.68, + dividendInPercentageWithCurrencyEffect: 0.002002886512915673 + } + }); + }); + }); +}); diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts index 18dc5ab246..2c6ff79b6d 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-msft-buy-with-dividend.spec.ts @@ -198,6 +198,8 @@ describe('PortfolioCalculator', () => { expect(performanceByDateRange).toMatchObject({ '1d': { date: '2023-07-10', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, netPerformance: -5.390000000000001, netPerformanceInPercentage: -0.015983630864124312, netPerformanceInPercentageWithCurrencyEffect: -0.015983630864124312, @@ -207,6 +209,8 @@ describe('PortfolioCalculator', () => { }, max: { date: '2023-07-10', + dividendInBaseCurrency: 0.62, + dividendInPercentageWithCurrencyEffect: 0.002076495411614967, netPerformance: 14.25, netPerformanceInPercentage: 0.04772590260566659, netPerformanceInPercentageWithCurrencyEffect: 0.04772590260566659, @@ -216,6 +220,8 @@ describe('PortfolioCalculator', () => { }, ytd: { date: '2023-07-10', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, netPerformance: -7.68, netPerformanceInPercentage: -0.022620835910577012, netPerformanceInPercentageWithCurrencyEffect: -0.022620835910577012, diff --git a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts index feb9a3c20e..46e1b14aa4 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator-novn-buy-and-sell.spec.ts @@ -139,6 +139,8 @@ describe('PortfolioCalculator', () => { expect(portfolioSnapshot.historicalData[0]).toEqual({ date: '2022-03-06', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, @@ -158,6 +160,8 @@ describe('PortfolioCalculator', () => { */ expect(portfolioSnapshot.historicalData[1]).toEqual({ date: '2022-03-07', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 151.6, netPerformance: 0, // 2 * (75.8 - 75.8) = 0 netPerformanceInPercentage: 0, // 0 ÷ 151.6 = 0 @@ -177,6 +181,8 @@ describe('PortfolioCalculator', () => { ] ).toEqual({ date: '2022-04-11', + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, investmentValueWithCurrencyEffect: 0, netPerformance: 19.86, netPerformanceInPercentage: 0.13100263852242744, 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 39a1b4188b..2b7b4e6dce 100644 --- a/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts +++ b/apps/api/src/app/portfolio/calculator/roai/portfolio-calculator.ts @@ -17,7 +17,10 @@ import { AssetProfileIdentifier, HistoricalDataItem } from '@ghostfolio/common/interfaces'; -import { PortfolioSnapshot } from '@ghostfolio/common/models'; +import { + PortfolioSnapshot, + PortfolioSnapshotHolding +} from '@ghostfolio/common/models'; import { DateRange } from '@ghostfolio/common/types'; import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type'; @@ -165,10 +168,15 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { } protected calculatePerformancePercentages({ - accumulatedValuesByDate + accumulatedValuesByDate, + holdings }: { accumulatedValuesByDate: { [date: string]: AccumulatedValues }; + holdings: PortfolioSnapshotHolding[]; }): { [date: string]: PerformancePercentages } { + const hasDividendWithoutAverageInvestment = + this.hasDividendWithoutAverageInvestment(holdings); + const performancePercentagesByDate: { [date: string]: PerformancePercentages; } = {}; @@ -178,11 +186,19 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { { totalAverageInvestmentValue, totalAverageInvestmentValueWithCurrencyEffect, + totalDividendValueWithCurrencyEffect, totalNetPerformanceValue, totalNetPerformanceValueWithCurrencyEffect } ] of Object.entries(accumulatedValuesByDate)) { performancePercentagesByDate[date] = { + dividendInPercentageWithCurrencyEffect: + hasDividendWithoutAverageInvestment || + totalAverageInvestmentValueWithCurrencyEffect.eq(0) + ? 0 + : totalDividendValueWithCurrencyEffect + .div(totalAverageInvestmentValueWithCurrencyEffect) + .toNumber(), netPerformanceInPercentage: totalAverageInvestmentValue.eq(0) ? 0 : totalNetPerformanceValue @@ -201,10 +217,15 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { } protected calculatePerformancePercentagesForDateRange({ - historicalDataItems + historicalDataItems, + holdings }: { historicalDataItems: HistoricalDataItem[]; + holdings: PortfolioSnapshotHolding[]; }): { [date: string]: PerformancePercentages } { + const hasDividendWithoutAverageInvestment = + this.hasDividendWithoutAverageInvestment(holdings); + const averageInvestmentValues: number[] = []; const averageInvestmentValuesWithCurrencyEffect: number[] = []; let grossPerformanceAtStartDate: number; @@ -254,6 +275,12 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { : 0; performancePercentagesByDate[historicalDataItem.date] = { + dividendInPercentageWithCurrencyEffect: + !hasDividendWithoutAverageInvestment && + averageInvestmentValueWithCurrencyEffect > 0 + ? historicalDataItem.dividendInBaseCurrency / + averageInvestmentValueWithCurrencyEffect + : 0, netPerformanceInPercentage: averageInvestmentValue > 0 ? historicalDataItem.netPerformance / averageInvestmentValue @@ -741,4 +768,21 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator { protected getPerformanceCalculationType() { return PerformanceCalculationType.ROAI; } + + private hasDividendWithoutAverageInvestment( + holdings: PortfolioSnapshotHolding[] + ) { + // A holding with a dividend only (without a buy activity), and a holding + // without a market price, gives a dividend but no average investment. + // Such a holding makes the dividend percentage too high. Therefore the + // dividend percentage stays 0 in this case, like the dividend yield. + return holdings.some( + ({ averageInvestmentWithCurrencyEffect, dividendInBaseCurrency }) => { + return ( + !dividendInBaseCurrency.eq(0) && + averageInvestmentWithCurrencyEffect.eq(0) + ); + } + ); + } } diff --git a/apps/api/src/app/portfolio/interfaces/accumulated-values.interface.ts b/apps/api/src/app/portfolio/interfaces/accumulated-values.interface.ts index 919dccc227..3810cbdeca 100644 --- a/apps/api/src/app/portfolio/interfaces/accumulated-values.interface.ts +++ b/apps/api/src/app/portfolio/interfaces/accumulated-values.interface.ts @@ -7,6 +7,7 @@ export interface AccumulatedValues { totalCashValueWithCurrencyEffect: Big; totalCurrentValue: Big; totalCurrentValueWithCurrencyEffect: Big; + totalDividendValueWithCurrencyEffect: Big; totalInvestmentValue: Big; totalInvestmentValueWithCurrencyEffect: Big; totalNetPerformanceValue: Big; diff --git a/apps/api/src/app/portfolio/portfolio.controller.ts b/apps/api/src/app/portfolio/portfolio.controller.ts index a65186100a..45b7477e8b 100644 --- a/apps/api/src/app/portfolio/portfolio.controller.ts +++ b/apps/api/src/app/portfolio/portfolio.controller.ts @@ -565,6 +565,7 @@ export class PortfolioController { [ 'currentNetWorth', 'currentValueInBaseCurrency', + 'dividendInBaseCurrency', 'grossPerformance', 'grossPerformanceWithCurrencyEffect', 'netPerformance', @@ -580,12 +581,16 @@ export class PortfolioController { ) { performanceInformation.chart = performanceInformation.chart.map( (item) => { - return nullifyValuesInObject(item, ['totalInvestment', 'value']); + return nullifyValuesInObject(item, [ + 'dividendInBaseCurrency', + 'totalInvestment', + 'value' + ]); } ); performanceInformation.performance = nullifyValuesInObject( performanceInformation.performance, - ['netPerformance'] + ['dividendInBaseCurrency', 'netPerformance'] ); } diff --git a/apps/api/src/app/portfolio/portfolio.service.ts b/apps/api/src/app/portfolio/portfolio.service.ts index 90de5ddc38..e5866ca3b2 100644 --- a/apps/api/src/app/portfolio/portfolio.service.ts +++ b/apps/api/src/app/portfolio/portfolio.service.ts @@ -1221,6 +1221,8 @@ export class PortfolioService { performance: { currentNetWorth: 0, currentValueInBaseCurrency: 0, + dividendInBaseCurrency: 0, + dividendPercentageWithCurrencyEffect: 0, netPerformance: 0, netPerformancePercentage: 0, netPerformancePercentageWithCurrencyEffect: 0, @@ -1252,6 +1254,8 @@ export class PortfolioService { }); const { + dividendInBaseCurrency, + dividendInPercentageWithCurrencyEffect, netPerformance, netPerformanceInPercentage, netPerformanceInPercentageWithCurrencyEffect, @@ -1261,6 +1265,8 @@ export class PortfolioService { totalInvestmentValueWithCurrencyEffect, valueWithCurrencyEffect } = chart?.at(-1) ?? { + dividendInBaseCurrency: 0, + dividendInPercentageWithCurrencyEffect: 0, netPerformance: 0, netPerformanceInPercentage: 0, netPerformanceInPercentageWithCurrencyEffect: 0, @@ -1276,12 +1282,15 @@ export class PortfolioService { hasErrors, dateOfFirstActivity: parseDate(historicalData[0]?.date), performance: { + dividendInBaseCurrency, netPerformance, netPerformanceWithCurrencyEffect, totalInvestment, totalInvestmentValueWithCurrencyEffect, currentNetWorth: netWorth, currentValueInBaseCurrency: valueWithCurrencyEffect, + dividendPercentageWithCurrencyEffect: + dividendInPercentageWithCurrencyEffect, netPerformancePercentage: netPerformanceInPercentage, netPerformancePercentageWithCurrencyEffect: netPerformanceInPercentageWithCurrencyEffect diff --git a/apps/api/src/app/portfolio/types/performance-percentages.type.ts b/apps/api/src/app/portfolio/types/performance-percentages.type.ts index 99521e516e..590e25895a 100644 --- a/apps/api/src/app/portfolio/types/performance-percentages.type.ts +++ b/apps/api/src/app/portfolio/types/performance-percentages.type.ts @@ -3,6 +3,7 @@ import { HistoricalDataItem } from '@ghostfolio/common/interfaces'; export type PerformancePercentages = Required< Pick< HistoricalDataItem, + | 'dividendInPercentageWithCurrencyEffect' | 'netPerformanceInPercentage' | 'netPerformanceInPercentageWithCurrencyEffect' > 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 abf2de00ee..94a0328755 100644 --- a/apps/client/src/app/pages/portfolio/analysis/analysis-page.html +++ b/apps/client/src/app/pages/portfolio/analysis/analysis-page.html @@ -279,6 +279,46 @@ /> + @if (user?.settings?.isExperimentalFeatures) { +

+
+
+ Absolute Dividend Performance + @if (user?.subscription?.type === 'Basic') { + + } +
+
+ +
+
+
+
+ Dividend Performance +
+
+ +
+
+ } diff --git a/libs/common/src/lib/interfaces/historical-data-item.interface.ts b/libs/common/src/lib/interfaces/historical-data-item.interface.ts index adb5b7e655..a733837d52 100644 --- a/libs/common/src/lib/interfaces/historical-data-item.interface.ts +++ b/libs/common/src/lib/interfaces/historical-data-item.interface.ts @@ -1,6 +1,8 @@ export interface HistoricalDataItem { averagePrice?: number; date: string; + dividendInBaseCurrency?: number; + dividendInPercentageWithCurrencyEffect?: number; grossPerformancePercent?: number; investmentValueWithCurrencyEffect?: number; marketPrice?: number; diff --git a/libs/common/src/lib/interfaces/portfolio-performance.interface.ts b/libs/common/src/lib/interfaces/portfolio-performance.interface.ts index 0698004d53..da0bb04f40 100644 --- a/libs/common/src/lib/interfaces/portfolio-performance.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-performance.interface.ts @@ -2,6 +2,8 @@ export interface PortfolioPerformance { annualizedPerformancePercent?: number; currentNetWorth?: number; currentValueInBaseCurrency: number; + dividendInBaseCurrency: number; + dividendPercentageWithCurrencyEffect?: number; netPerformance: number; netPerformancePercentage: number; netPerformancePercentageWithCurrencyEffect: number; diff --git a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts index 4e6402d162..d9bd435b1b 100644 --- a/libs/common/src/lib/interfaces/portfolio-summary.interface.ts +++ b/libs/common/src/lib/interfaces/portfolio-summary.interface.ts @@ -7,7 +7,6 @@ export interface PortfolioSummary extends PortfolioPerformance { annualizedPerformancePercentWithCurrencyEffect: number; cash: number; dateOfFirstActivity?: Date; - dividendInBaseCurrency: number; dividendYieldPercent: number; dividendYieldPercentWithCurrencyEffect: number; emergencyFund: { From cb3094491e6098536240cec19da46d44e78caaea Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:45:40 +0200 Subject: [PATCH 17/19] Task/update locales (#7904) Co-authored-by: github-actions[bot] --- apps/client/src/locales/messages.ca.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.de.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.es.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.fr.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.it.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.ja.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.ko.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.nl.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.pl.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.pt.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.tr.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.uk.xlf | 102 +++++++++++++++--------- apps/client/src/locales/messages.xlf | 99 ++++++++++++++--------- apps/client/src/locales/messages.zh.xlf | 102 +++++++++++++++--------- 14 files changed, 879 insertions(+), 546 deletions(-) diff --git a/apps/client/src/locales/messages.ca.xlf b/apps/client/src/locales/messages.ca.xlf index 1d502bb80b..409ba1247c 100644 --- a/apps/client/src/locales/messages.ca.xlf +++ b/apps/client/src/locales/messages.ca.xlf @@ -399,7 +399,7 @@
libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163
@@ -415,7 +415,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -495,7 +495,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -511,7 +511,7 @@ Total libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -547,7 +547,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -579,11 +579,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -595,7 +595,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -627,7 +627,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -675,7 +675,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1039,7 +1039,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1298,6 +1298,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Configuració del Proveïdor de Dades @@ -1367,7 +1375,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1955,7 +1963,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1963,7 +1971,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2447,7 +2455,7 @@ Definiu l’import del vostre fons d’emergència. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -3347,7 +3355,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -4664,7 +4672,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -4847,6 +4855,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here Trieu o deixeu anar un fitxer aquí @@ -5248,7 +5264,7 @@ A dalt apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -5256,7 +5272,7 @@ A baix apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -5264,7 +5280,7 @@ Evolució de la cartera apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -5272,7 +5288,7 @@ Cronologia de la inversió apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -5280,7 +5296,7 @@ Ratxa actual apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -5288,7 +5304,7 @@ Ratxa més llarga apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -5296,7 +5312,7 @@ Cronologia de dividends apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -5921,7 +5937,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -5945,7 +5961,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -6413,15 +6429,15 @@ Assignació libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -6441,7 +6457,7 @@ Mostra-ho tot libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -6765,7 +6781,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -6880,6 +6896,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Àfrica @@ -7241,7 +7265,7 @@ Wealth Management libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7445,7 +7469,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7749,7 +7773,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7975,7 +7999,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8031,7 +8055,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8159,7 +8183,7 @@ Change libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 54369efe59..333d817656 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -166,7 +166,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -182,7 +182,7 @@ Gesamt libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -210,11 +210,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -226,7 +226,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -258,7 +258,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -306,7 +306,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -566,7 +566,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1098,7 +1098,7 @@ Bitte setze den Betrag deines Notfallfonds. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1166,15 +1166,15 @@ Allokation libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -1194,7 +1194,7 @@ Alle anzeigen libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -1638,7 +1638,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1658,7 +1658,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -1674,7 +1674,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -1690,7 +1690,7 @@ Finanzplanung libs/ui/src/lib/i18n.ts - 110 + 111 @@ -2082,7 +2082,7 @@ Zeitstrahl der Investitionen apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -2090,7 +2090,7 @@ Gewinner apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -2098,7 +2098,7 @@ Verlierer apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -2242,7 +2242,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2250,7 +2250,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2282,7 +2282,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2338,7 +2338,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -3066,7 +3066,7 @@ Portfolio Wertentwicklung apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -3293,6 +3293,14 @@ 79 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Afrika @@ -3454,7 +3462,7 @@ Zeitstrahl der Dividenden apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -3637,6 +3645,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Yearly Jährlich @@ -4454,7 +4470,7 @@ Aktueller Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4462,7 +4478,7 @@ Längster Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4506,7 +4522,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -4697,6 +4713,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Scraper Konfiguration @@ -4902,7 +4926,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5864,7 +5888,7 @@ Aktien-Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -7265,7 +7289,7 @@ Vermögensverwaltung libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7469,7 +7493,7 @@ Steuerreporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7773,7 +7797,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7999,7 +8023,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8055,7 +8079,7 @@ Vermögens-Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8183,7 +8207,7 @@ Änderung libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8219,11 +8243,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.es.xlf b/apps/client/src/locales/messages.es.xlf index 2d48ddf15d..858a5309bb 100644 --- a/apps/client/src/locales/messages.es.xlf +++ b/apps/client/src/locales/messages.es.xlf @@ -167,7 +167,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -183,7 +183,7 @@ Total libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -211,11 +211,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -227,7 +227,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -259,7 +259,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -307,7 +307,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -567,7 +567,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1083,7 +1083,7 @@ Por favor, ingresa la cantidad de tu fondo de emergencia. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1151,15 +1151,15 @@ Distribución libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -1179,7 +1179,7 @@ Mostrar todos libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -1623,7 +1623,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1643,7 +1643,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -1659,7 +1659,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -1675,7 +1675,7 @@ Planificación financiera libs/ui/src/lib/i18n.ts - 110 + 111 @@ -2067,7 +2067,7 @@ Cronología de la inversión apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -2075,7 +2075,7 @@ Mejores apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -2083,7 +2083,7 @@ Peores apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -2227,7 +2227,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2235,7 +2235,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2267,7 +2267,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2323,7 +2323,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -3051,7 +3051,7 @@ Evolución de la cartera apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -3278,6 +3278,14 @@ 79 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa África @@ -3487,7 +3495,7 @@ Calendario de dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -3622,6 +3630,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Yearly Anual @@ -4431,7 +4447,7 @@ Racha actual apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4439,7 +4455,7 @@ Racha más larga apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4483,7 +4499,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -4674,6 +4690,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Configuración del scraper @@ -4879,7 +4903,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5841,7 +5865,7 @@ Seguimiento de acciones libs/ui/src/lib/i18n.ts - 113 + 114 @@ -7242,7 +7266,7 @@ Gestión de patrimonios libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7446,7 +7470,7 @@ Informes fiscales libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7750,7 +7774,7 @@ Investigación de inversiones libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7976,7 +8000,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8032,7 +8056,7 @@ Seguimiento del patrimonio neto libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8160,7 +8184,7 @@ Cambio libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8196,11 +8220,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.fr.xlf b/apps/client/src/locales/messages.fr.xlf index 6a329a5421..130ede7174 100644 --- a/apps/client/src/locales/messages.fr.xlf +++ b/apps/client/src/locales/messages.fr.xlf @@ -118,7 +118,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -174,7 +174,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -190,7 +190,7 @@ Total libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -226,7 +226,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -246,7 +246,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -274,11 +274,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -290,7 +290,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -322,7 +322,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -370,7 +370,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -638,7 +638,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -830,7 +830,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1418,7 +1418,7 @@ Veuillez entrer le montant de votre fonds d’urgence : apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1450,7 +1450,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1458,7 +1458,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2006,7 +2006,7 @@ Planification Financière libs/ui/src/lib/i18n.ts - 110 + 111 @@ -2386,7 +2386,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -2794,7 +2794,7 @@ Haut apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -2802,7 +2802,7 @@ Bas apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -2810,7 +2810,7 @@ Évolution du Portefeuille apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -2818,7 +2818,7 @@ Historique des Investissements apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -2826,7 +2826,7 @@ Historique des Dividendes apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -3254,15 +3254,15 @@ Part libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -3282,7 +3282,7 @@ Montrer tout libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -3485,6 +3485,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Afrique @@ -3621,6 +3629,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Yearly Annuel @@ -4430,7 +4446,7 @@ Série en cours apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4438,7 +4454,7 @@ Série la plus longue apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4482,7 +4498,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -4673,6 +4689,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Configuration du Scraper @@ -4878,7 +4902,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5840,7 +5864,7 @@ Suivi des Actions libs/ui/src/lib/i18n.ts - 113 + 114 @@ -7241,7 +7265,7 @@ Gestion de Patrimoine libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7445,7 +7469,7 @@ Déclaration Fiscale libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7749,7 +7773,7 @@ Recherche d’Investissement libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7975,7 +7999,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8031,7 +8055,7 @@ Suivi du Patrimoine Net libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8159,7 +8183,7 @@ Variation libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.it.xlf b/apps/client/src/locales/messages.it.xlf index 13d58ae069..496900f288 100644 --- a/apps/client/src/locales/messages.it.xlf +++ b/apps/client/src/locales/messages.it.xlf @@ -167,7 +167,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -183,7 +183,7 @@ Totale libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -211,11 +211,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -227,7 +227,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -259,7 +259,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -307,7 +307,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -567,7 +567,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1083,7 +1083,7 @@ Inserisci l’importo del tuo fondo di emergenza: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1151,15 +1151,15 @@ Allocazione libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -1179,7 +1179,7 @@ Mostra tutti libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -1623,7 +1623,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1643,7 +1643,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -1659,7 +1659,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -1675,7 +1675,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -2067,7 +2067,7 @@ Cronologia degli investimenti apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -2075,7 +2075,7 @@ In alto apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -2083,7 +2083,7 @@ In basso apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -2227,7 +2227,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2235,7 +2235,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2267,7 +2267,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2323,7 +2323,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -3051,7 +3051,7 @@ Evoluzione del portafoglio apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -3278,6 +3278,14 @@ 79 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Africa @@ -3487,7 +3495,7 @@ Cronologia dei dividendi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -3622,6 +3630,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Yearly Annuale @@ -4431,7 +4447,7 @@ Serie attuale apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4439,7 +4455,7 @@ Serie più lunga apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4483,7 +4499,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -4674,6 +4690,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Configurazione dello scraper @@ -4879,7 +4903,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5841,7 +5865,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -7242,7 +7266,7 @@ Gestione Patrimoniale libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7446,7 +7470,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7750,7 +7774,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7976,7 +8000,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8032,7 +8056,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8160,7 +8184,7 @@ Cambia libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8196,11 +8220,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.ja.xlf b/apps/client/src/locales/messages.ja.xlf index e64d0ce7b4..7cc567ca40 100644 --- a/apps/client/src/locales/messages.ja.xlf +++ b/apps/client/src/locales/messages.ja.xlf @@ -328,7 +328,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -344,7 +344,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -424,7 +424,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -440,7 +440,7 @@ 合計 libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -476,7 +476,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -508,11 +508,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -524,7 +524,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -556,7 +556,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -604,7 +604,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -928,7 +928,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1191,6 +1191,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration スクレイパーの設定 @@ -1216,7 +1224,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2164,7 +2172,7 @@ 緊急用資金の金額を設定してください。 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -2196,7 +2204,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2204,7 +2212,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -3028,7 +3036,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -4308,7 +4316,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -4491,6 +4499,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here ここでファイルを選択またはドロップ @@ -4824,7 +4840,7 @@ トップ apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -4832,7 +4848,7 @@ ボトム apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -4840,7 +4856,7 @@ ポートフォリオ進化 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -4848,7 +4864,7 @@ 投資タイムライン apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -4856,7 +4872,7 @@ 現在のストリーク apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4864,7 +4880,7 @@ 最長のストリーク apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4872,7 +4888,7 @@ 配当金タイムライン apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -5485,7 +5501,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -5509,7 +5525,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5869,15 +5885,15 @@ 配分 libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5897,7 +5913,7 @@ すべて表示 libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -6205,7 +6221,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -6320,6 +6336,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa アフリカ @@ -7194,7 +7218,7 @@ Wealth Management libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7526,7 +7550,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7774,7 +7798,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -8000,7 +8024,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8056,7 +8080,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8184,7 +8208,7 @@ Change libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8220,11 +8244,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.ko.xlf b/apps/client/src/locales/messages.ko.xlf index 99649ef133..49d9aff787 100644 --- a/apps/client/src/locales/messages.ko.xlf +++ b/apps/client/src/locales/messages.ko.xlf @@ -328,7 +328,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -344,7 +344,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -424,7 +424,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -440,7 +440,7 @@ 합계 libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -476,7 +476,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -508,11 +508,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -524,7 +524,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -556,7 +556,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -604,7 +604,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -928,7 +928,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1191,6 +1191,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration 스크래퍼 설정 @@ -1216,7 +1224,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2164,7 +2172,7 @@ 비상금 금액을 설정해 주세요. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -2196,7 +2204,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2204,7 +2212,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -3028,7 +3036,7 @@ 재무 설계 libs/ui/src/lib/i18n.ts - 110 + 111 @@ -4300,7 +4308,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -4483,6 +4491,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here 여기에 파일을 선택하거나 드롭하세요. @@ -4816,7 +4832,7 @@ 상위 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -4824,7 +4840,7 @@ 하위 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -4832,7 +4848,7 @@ 포트폴리오 진화 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -4840,7 +4856,7 @@ 투자 일정 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -4848,7 +4864,7 @@ 현재 연속 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4856,7 +4872,7 @@ 최장 연속 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4864,7 +4880,7 @@ 배당 일정 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -5477,7 +5493,7 @@ 주식 추적 libs/ui/src/lib/i18n.ts - 113 + 114 @@ -5501,7 +5517,7 @@ 웹 libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5861,15 +5877,15 @@ 자산 배분 libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5889,7 +5905,7 @@ 모두 표시 libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -6205,7 +6221,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -6320,6 +6336,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa 아프리카 @@ -7194,7 +7218,7 @@ 자산관리 libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7526,7 +7550,7 @@ 세금 보고 libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7774,7 +7798,7 @@ 투자 리서치 libs/ui/src/lib/i18n.ts - 111 + 112 @@ -8000,7 +8024,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8056,7 +8080,7 @@ 순자산 추적 libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8184,7 +8208,7 @@ 변동 libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8220,11 +8244,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.nl.xlf b/apps/client/src/locales/messages.nl.xlf index b9fb3ecbcb..431207b54d 100644 --- a/apps/client/src/locales/messages.nl.xlf +++ b/apps/client/src/locales/messages.nl.xlf @@ -166,7 +166,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -182,7 +182,7 @@ Totaal libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -210,11 +210,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -226,7 +226,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -258,7 +258,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -306,7 +306,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -566,7 +566,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1082,7 +1082,7 @@ Voer het bedrag van je noodfonds in: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1150,15 +1150,15 @@ Allocatie libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -1178,7 +1178,7 @@ Toon alle libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -1622,7 +1622,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1642,7 +1642,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -1658,7 +1658,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -1674,7 +1674,7 @@ Financiële planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -2066,7 +2066,7 @@ Tijdlijn investeringen apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -2074,7 +2074,7 @@ Winnaars apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -2082,7 +2082,7 @@ Verliezers apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -2226,7 +2226,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2234,7 +2234,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2266,7 +2266,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2322,7 +2322,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -3050,7 +3050,7 @@ Waardeontwikkeling van portefeuille apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -3277,6 +3277,14 @@ 79 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Afrika @@ -3486,7 +3494,7 @@ Tijdlijn dividend apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -3621,6 +3629,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Yearly Jaarlijks @@ -4430,7 +4446,7 @@ Huidige reeks apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4438,7 +4454,7 @@ Langste reeks apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4482,7 +4498,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -4673,6 +4689,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Scraper instellingen @@ -4878,7 +4902,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5840,7 +5864,7 @@ Aandelen volgen libs/ui/src/lib/i18n.ts - 113 + 114 @@ -7241,7 +7265,7 @@ Vermogensbeheer libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7445,7 +7469,7 @@ Belastingrapportage libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7749,7 +7773,7 @@ Beleggingsonderzoek libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7975,7 +7999,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8031,7 +8055,7 @@ Netto waarde volgen libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8159,7 +8183,7 @@ Aanpassen libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.pl.xlf b/apps/client/src/locales/messages.pl.xlf index 9a2921ec5e..cb7519a70e 100644 --- a/apps/client/src/locales/messages.pl.xlf +++ b/apps/client/src/locales/messages.pl.xlf @@ -327,7 +327,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -343,7 +343,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -415,7 +415,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -431,7 +431,7 @@ Suma libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -467,7 +467,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -499,11 +499,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -515,7 +515,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -547,7 +547,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -595,7 +595,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -919,7 +919,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1158,6 +1158,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Konfiguracja Scrapera @@ -1183,7 +1191,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2131,7 +2139,7 @@ Wprowadź wysokość funduszu rezerwowego: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -2163,7 +2171,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2171,7 +2179,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2995,7 +3003,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -4267,7 +4275,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -4450,6 +4458,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here Wybierz lub przeciągnij plik tutaj @@ -4783,7 +4799,7 @@ Największe wzrosty apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -4791,7 +4807,7 @@ Największy spadek apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -4799,7 +4815,7 @@ Rozwój portfela apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -4807,7 +4823,7 @@ Oś czasu inwestycji apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -4815,7 +4831,7 @@ Obecna passa apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4823,7 +4839,7 @@ Najdłuższa passa apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4831,7 +4847,7 @@ Oś czasu dywidend apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -5432,7 +5448,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -5456,7 +5472,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5784,15 +5800,15 @@ Podział libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5812,7 +5828,7 @@ Pokaż wszystko libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -6128,7 +6144,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -6243,6 +6259,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Afryka @@ -7241,7 +7265,7 @@ Zarządzanie Majątkiem libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7445,7 +7469,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7749,7 +7773,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7975,7 +7999,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8031,7 +8055,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8159,7 +8183,7 @@ Zmiana libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.pt.xlf b/apps/client/src/locales/messages.pt.xlf index 3960bda31b..d89c725518 100644 --- a/apps/client/src/locales/messages.pt.xlf +++ b/apps/client/src/locales/messages.pt.xlf @@ -118,7 +118,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -174,7 +174,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -190,7 +190,7 @@ Total libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -226,7 +226,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -246,7 +246,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -274,11 +274,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -290,7 +290,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -322,7 +322,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -370,7 +370,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -638,7 +638,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1262,7 +1262,7 @@ Por favor, insira o valor do seu fundo de emergência: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1294,7 +1294,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1302,7 +1302,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -1410,15 +1410,15 @@ Alocação libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -1438,7 +1438,7 @@ Mostrar tudo libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -1990,7 +1990,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -2322,7 +2322,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -2430,7 +2430,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2674,7 +2674,7 @@ Topo apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -2682,7 +2682,7 @@ Fundo apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -2690,7 +2690,7 @@ Evolução do Portefólio apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -2698,7 +2698,7 @@ Cronograma de Investimento apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -3289,6 +3289,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa África @@ -3570,7 +3578,7 @@ Cronograma de Dividendos apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -3621,6 +3629,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Yearly Anualmente @@ -4430,7 +4446,7 @@ Série Atual apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4438,7 +4454,7 @@ Série mais Longa apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4482,7 +4498,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -4673,6 +4689,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Configuração do raspador @@ -4878,7 +4902,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5840,7 +5864,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -7241,7 +7265,7 @@ Gestão de patrimônio libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7445,7 +7469,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7749,7 +7773,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7975,7 +7999,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8031,7 +8055,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8159,7 +8183,7 @@ Mudar libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.tr.xlf b/apps/client/src/locales/messages.tr.xlf index d5308a8cf0..27af34b080 100644 --- a/apps/client/src/locales/messages.tr.xlf +++ b/apps/client/src/locales/messages.tr.xlf @@ -299,7 +299,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -315,7 +315,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -371,7 +371,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -387,7 +387,7 @@ Toplam libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -423,7 +423,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -455,11 +455,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -471,7 +471,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -503,7 +503,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -551,7 +551,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -863,7 +863,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1070,6 +1070,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Veri Toplayıcı Yapılandırması @@ -1095,7 +1103,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1959,7 +1967,7 @@ Lütfen acil durum yedeği meblağını giriniz: apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -1991,7 +1999,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1999,7 +2007,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2491,7 +2499,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -3523,7 +3531,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -3682,6 +3690,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + The following file formats are supported: Aşağıdaki dosya formatları desteklenmektedir: @@ -4023,7 +4039,7 @@ Üst apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -4031,7 +4047,7 @@ Alt apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -4039,7 +4055,7 @@ Portföyün Gelişimi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -4047,7 +4063,7 @@ Yatırım Zaman Çizelgesi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -4055,7 +4071,7 @@ Güncel Seri apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4063,7 +4079,7 @@ En Uzun Seri apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4071,7 +4087,7 @@ Temettü Zaman Çizelgesi apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -4684,7 +4700,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -4708,7 +4724,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5320,15 +5336,15 @@ Dağılım libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5348,7 +5364,7 @@ Tümünü göster libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -5664,7 +5680,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -5763,6 +5779,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Afrika @@ -7241,7 +7265,7 @@ Zenginlik Yönetimi libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7445,7 +7469,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7749,7 +7773,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7975,7 +7999,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8031,7 +8055,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8159,7 +8183,7 @@ Değişim libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.uk.xlf b/apps/client/src/locales/messages.uk.xlf index ea186767f2..6943517691 100644 --- a/apps/client/src/locales/messages.uk.xlf +++ b/apps/client/src/locales/messages.uk.xlf @@ -367,7 +367,7 @@ Податкова звітність libs/ui/src/lib/i18n.ts - 114 + 115 @@ -423,7 +423,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -439,7 +439,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -519,7 +519,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -535,7 +535,7 @@ Загалом libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -571,7 +571,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -603,11 +603,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -619,7 +619,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -651,7 +651,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -699,7 +699,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1027,7 +1027,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1278,6 +1278,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration Конфігурація скребка @@ -1347,7 +1355,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1743,7 +1751,7 @@ Відстеження чистого капіталу libs/ui/src/lib/i18n.ts - 112 + 113 @@ -2103,7 +2111,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2111,7 +2119,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2567,7 +2575,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -2595,7 +2603,7 @@ Будь ласка, встановіть суму вашого резервного фонду. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -2807,7 +2815,7 @@ Інвестиційні дослідження libs/ui/src/lib/i18n.ts - 111 + 112 @@ -3643,7 +3651,7 @@ Фінансове планування libs/ui/src/lib/i18n.ts - 110 + 111 @@ -4968,7 +4976,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -5187,6 +5195,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here Виберіть або перетягніть файл сюди @@ -5604,7 +5620,7 @@ Топ apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -5612,7 +5628,7 @@ Низ apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -5620,7 +5636,7 @@ Еволюція портфеля apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -5628,7 +5644,7 @@ Інвестиційний графік apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -5636,7 +5652,7 @@ Поточна серія apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -5644,7 +5660,7 @@ Найдовша серія apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -5652,7 +5668,7 @@ Графік дивідендів apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -6371,7 +6387,7 @@ Управління багатством libs/ui/src/lib/i18n.ts - 115 + 116 @@ -6755,7 +6771,7 @@ Відстеження акцій libs/ui/src/lib/i18n.ts - 113 + 114 @@ -6779,7 +6795,7 @@ Веб libs/ui/src/lib/i18n.ts - 122 + 123 @@ -7271,15 +7287,15 @@ Розподіл libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -7299,7 +7315,7 @@ Показати все libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -7739,7 +7755,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -7870,6 +7886,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa Африка @@ -8159,7 +8183,7 @@ Змінити libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8195,11 +8219,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.xlf b/apps/client/src/locales/messages.xlf index 726b23d4b5..bf03ea0e6c 100644 --- a/apps/client/src/locales/messages.xlf +++ b/apps/client/src/locales/messages.xlf @@ -305,7 +305,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -320,7 +320,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -397,7 +397,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -412,7 +412,7 @@ Total libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -446,7 +446,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -477,11 +477,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -493,7 +493,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -524,7 +524,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -571,7 +571,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -865,7 +865,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1102,6 +1102,13 @@ 175 + + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration @@ -1125,7 +1132,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -1978,7 +1985,7 @@ Please set the amount of your emergency fund. apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -2007,7 +2014,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2015,7 +2022,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -2765,7 +2772,7 @@ Financial Planning libs/ui/src/lib/i18n.ts - 110 + 111 @@ -3928,7 +3935,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -4092,6 +4099,13 @@ 71 + + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here @@ -4390,49 +4404,49 @@ Top apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 Bottom apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 Portfolio Evolution apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 Investment Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 Current Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 Longest Streak apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 Dividend Timeline apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -4986,7 +5000,7 @@ Stock Tracking libs/ui/src/lib/i18n.ts - 113 + 114 @@ -5007,7 +5021,7 @@ Web libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5330,15 +5344,15 @@ Allocation libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5357,7 +5371,7 @@ Show all libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -5640,7 +5654,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -5743,6 +5757,13 @@ 74 + + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa @@ -6525,7 +6546,7 @@ Wealth Management libs/ui/src/lib/i18n.ts - 115 + 116 @@ -6829,7 +6850,7 @@ Tax Reporting libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7051,7 +7072,7 @@ Investment Research libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7255,7 +7276,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -7307,7 +7328,7 @@ Net Worth Tracking libs/ui/src/lib/i18n.ts - 112 + 113 @@ -7419,7 +7440,7 @@ Change libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -7452,11 +7473,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts diff --git a/apps/client/src/locales/messages.zh.xlf b/apps/client/src/locales/messages.zh.xlf index 853f9dcc1f..8c43c4a725 100644 --- a/apps/client/src/locales/messages.zh.xlf +++ b/apps/client/src/locales/messages.zh.xlf @@ -328,7 +328,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 161 + 163 @@ -344,7 +344,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 92 + 94 @@ -424,7 +424,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 34 + 35 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -440,7 +440,7 @@ 总计 libs/ui/src/lib/accounts-table/accounts-table.component.html - 61 + 63 @@ -476,7 +476,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 71 + 73 libs/ui/src/lib/activities-table/activities-table.component.html @@ -508,11 +508,11 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 196 + 198 libs/ui/src/lib/accounts-table/accounts-table.component.html - 231 + 233 libs/ui/src/lib/activities-table/activities-table.component.html @@ -524,7 +524,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 112 + 113 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -556,7 +556,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 348 + 350 libs/ui/src/lib/activities-table/activities-table.component.html @@ -604,7 +604,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 361 + 363 libs/ui/src/lib/activities-table/activities-table.component.html @@ -928,7 +928,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 63 + 64 @@ -1167,6 +1167,14 @@ 175 + + Financial Advisor + Financial Advisor + + libs/ui/src/lib/i18n.ts + 110 + + Scraper Configuration 刮削配置 @@ -1192,7 +1200,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 305 + 307 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2140,7 +2148,7 @@ 请输入您的应急基金金额。 apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 169 + 173 @@ -2172,7 +2180,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 141 + 143 libs/ui/src/lib/activities-table/activities-table.component.html @@ -2180,7 +2188,7 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 87 + 88 @@ -3004,7 +3012,7 @@ 财务规划 libs/ui/src/lib/i18n.ts - 110 + 111 @@ -4284,7 +4292,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 124 + 126 @@ -4467,6 +4475,14 @@ 71 + + Dividend Performance + Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 307 + + Choose or drop a file here 在此处选择或放置文件 @@ -4800,7 +4816,7 @@ 顶部 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 292 + 332 @@ -4808,7 +4824,7 @@ 底部 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 343 + 383 @@ -4816,7 +4832,7 @@ 投资组合演变 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 398 + 438 @@ -4824,7 +4840,7 @@ 投资时间表 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 425 + 465 @@ -4832,7 +4848,7 @@ 当前连胜 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 446 + 486 @@ -4840,7 +4856,7 @@ 最长连续纪录 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 455 + 495 @@ -4848,7 +4864,7 @@ 股息时间表 apps/client/src/app/pages/portfolio/analysis/analysis-page.html - 482 + 522 @@ -5461,7 +5477,7 @@ 股票追踪 libs/ui/src/lib/i18n.ts - 113 + 114 @@ -5485,7 +5501,7 @@ 网页 libs/ui/src/lib/i18n.ts - 122 + 123 @@ -5845,15 +5861,15 @@ 分配 libs/ui/src/lib/accounts-table/accounts-table.component.html - 266 + 268 libs/ui/src/lib/holdings-table/holdings-table.component.html - 137 + 138 libs/ui/src/lib/holdings-table/holdings-table.component.html - 138 + 139 libs/ui/src/lib/top-holdings/top-holdings.component.html @@ -5873,7 +5889,7 @@ 显示所有 libs/ui/src/lib/holdings-table/holdings-table.component.html - 242 + 243 @@ -6181,7 +6197,7 @@ libs/ui/src/lib/accounts-table/accounts-table.component.html - 337 + 339 @@ -6296,6 +6312,14 @@ 74 + + Absolute Dividend Performance + Absolute Dividend Performance + + apps/client/src/app/pages/portfolio/analysis/analysis-page.html + 288 + + Africa 非洲 @@ -7242,7 +7266,7 @@ 财富管理 libs/ui/src/lib/i18n.ts - 115 + 116 @@ -7446,7 +7470,7 @@ 税务报告 libs/ui/src/lib/i18n.ts - 114 + 115 @@ -7750,7 +7774,7 @@ 投资研究 libs/ui/src/lib/i18n.ts - 111 + 112 @@ -7976,7 +8000,7 @@ apps/client/src/app/components/portfolio-summary/portfolio-summary.component.ts - 167 + 171 apps/client/src/app/components/rule/rule-settings-dialog/rule-settings-dialog.html @@ -8032,7 +8056,7 @@ 净资产追踪 libs/ui/src/lib/i18n.ts - 112 + 113 @@ -8160,7 +8184,7 @@ 涨跌 libs/ui/src/lib/holdings-table/holdings-table.component.html - 159 + 160 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts @@ -8196,11 +8220,11 @@ libs/ui/src/lib/holdings-table/holdings-table.component.html - 184 + 185 libs/ui/src/lib/holdings-table/holdings-table.component.html - 185 + 186 libs/ui/src/lib/treemap-chart/treemap-chart.component.ts From 37f1e61c537a8f2fd0e1980c4eaf30f1aa0b9c2a Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:48:32 +0200 Subject: [PATCH 18/19] Task/improve language localization for DE (20260927) (#7957) * Update translations * Update changelog --- CHANGELOG.md | 1 + apps/client/src/locales/messages.de.xlf | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index c199d06c0d..dcf03ee1a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Simplified the portfolio summary by hiding the currency on mobile - Improved the performance of the logo endpoints by enabling the browser cache - Improved the language localization for Catalan (`ca`) +- Improved the language localization for German (`de`) ### Fixed diff --git a/apps/client/src/locales/messages.de.xlf b/apps/client/src/locales/messages.de.xlf index 333d817656..58da7dc525 100644 --- a/apps/client/src/locales/messages.de.xlf +++ b/apps/client/src/locales/messages.de.xlf @@ -3295,7 +3295,7 @@ Absolute Dividend Performance - Absolute Dividend Performance + Absolute Dividendenperformance apps/client/src/app/pages/portfolio/analysis/analysis-page.html 288 @@ -3647,7 +3647,7 @@ Dividend Performance - Dividend Performance + Dividendenperformance apps/client/src/app/pages/portfolio/analysis/analysis-page.html 307 @@ -4715,7 +4715,7 @@ Financial Advisor - Financial Advisor + Finanzberatung libs/ui/src/lib/i18n.ts 110 From 82cee20f2d4f7a653c088afbc1fd315adf25e9f6 Mon Sep 17 00:00:00 2001 From: Thomas Kaul <4159106+dtslvr@users.noreply.github.com> Date: Sun, 27 Sep 2026 17:50:19 +0200 Subject: [PATCH 19/19] Release 3.74.0 (#7958) --- CHANGELOG.md | 2 +- package-lock.json | 4 ++-- package.json | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index dcf03ee1a6..6e705c788e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,7 +5,7 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## Unreleased +## 3.74.0 - 2026-09-27 ### Added diff --git a/package-lock.json b/package-lock.json index b3eae247c2..62a865e1b3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "ghostfolio", - "version": "3.73.0", + "version": "3.74.0", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ghostfolio", - "version": "3.73.0", + "version": "3.74.0", "hasInstallScript": true, "license": "AGPL-3.0", "dependencies": { diff --git a/package.json b/package.json index 5648ac6693..91907a9f18 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghostfolio", - "version": "3.73.0", + "version": "3.74.0", "homepage": "https://ghostfol.io", "license": "AGPL-3.0", "repository": "https://github.com/ghostfolio/ghostfolio",