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 1/6] 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 2/6] 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 3/6] 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 4/6] 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 5/6] 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 6/6] 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) ||