Browse Source

Merge branch 'ghostfolio:main' into feature/upgrade-nestjs-version11

pull/4270/head
Haruka Kishida 3 months ago
committed by GitHub
parent
commit
5fa0e48683
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 4
      CHANGELOG.md
  2. 13
      apps/api/src/app/order/order.service.ts
  3. 6
      apps/api/src/app/portfolio/portfolio.service.ts
  4. 6
      apps/api/src/app/user/user.service.ts
  5. 77
      apps/api/src/models/rules/regional-market-cluster-risk/europe.ts
  6. 7
      apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts
  7. 9
      apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts
  8. 2
      apps/client/src/app/components/world-map-chart/world-map-chart.component.html
  9. 33
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  10. 20
      apps/client/src/locales/messages.ca.xlf
  11. 20
      apps/client/src/locales/messages.de.xlf
  12. 20
      apps/client/src/locales/messages.es.xlf
  13. 20
      apps/client/src/locales/messages.fr.xlf
  14. 20
      apps/client/src/locales/messages.it.xlf
  15. 20
      apps/client/src/locales/messages.nl.xlf
  16. 20
      apps/client/src/locales/messages.pl.xlf
  17. 20
      apps/client/src/locales/messages.pt.xlf
  18. 20
      apps/client/src/locales/messages.tr.xlf
  19. 20
      apps/client/src/locales/messages.uk.xlf
  20. 19
      apps/client/src/locales/messages.xlf
  21. 20
      apps/client/src/locales/messages.zh.xlf
  22. 1
      libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts
  23. 10
      package-lock.json
  24. 2
      package.json

4
CHANGELOG.md

@ -9,11 +9,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Added
- Added a new static portfolio analysis rule: _Regional Market Cluster Risk_ (Europe)
- Added a link to _Duck.ai_ to the _Copy AI prompt to clipboard_ action on the analysis page (experimental)
- Extracted the tags selector to a reusable component used in the create or update activity dialog and holding detail dialog
### Changed
- Improved the caching of the portfolio snapshot in the portfolio calculator by expiring cache entries when a user changes tags in the holding detail dialog
- Improved the language localization for German (`de`)
- Upgraded `svgmap` from version `2.6.0` to `2.12.2`
## 2.137.1 - 2025-02-01

13
apps/api/src/app/order/order.service.ts

@ -63,14 +63,14 @@ export class OrderService {
}
});
return Promise.all(
await Promise.all(
orders.map(({ id }) =>
this.prismaService.order.update({
data: {
tags: {
// The set operation replaces all existing connections with the provided ones
set: tags.map(({ id }) => {
return { id };
set: tags.map((tag) => {
return { id: tag.id };
})
}
},
@ -78,6 +78,13 @@ export class OrderService {
})
)
);
this.eventEmitter.emit(
PortfolioChangedEvent.getName(),
new PortfolioChangedEvent({
userId
})
);
}
public async createOrder(

6
apps/api/src/app/portfolio/portfolio.service.ts

@ -15,6 +15,7 @@ import { EconomicMarketClusterRiskDevelopedMarkets } from '@ghostfolio/api/model
import { EconomicMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/economic-market-cluster-risk/emerging-markets';
import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup';
import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment';
import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe';
import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
@ -1278,6 +1279,11 @@ export class PortfolioService {
summary.ordersCount > 0
? await this.rulesService.evaluate(
[
new RegionalMarketClusterRiskEurope(
this.exchangeRateDataService,
marketsAdvancedTotalInBaseCurrency,
marketsAdvanced.europe.valueInBaseCurrency
),
new RegionalMarketClusterRiskNorthAmerica(
this.exchangeRateDataService,
marketsAdvancedTotalInBaseCurrency,

6
apps/api/src/app/user/user.service.ts

@ -13,6 +13,7 @@ import { EconomicMarketClusterRiskDevelopedMarkets } from '@ghostfolio/api/model
import { EconomicMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models/rules/economic-market-cluster-risk/emerging-markets';
import { EmergencyFundSetup } from '@ghostfolio/api/models/rules/emergency-fund/emergency-fund-setup';
import { FeeRatioInitialInvestment } from '@ghostfolio/api/models/rules/fees/fee-ratio-initial-investment';
import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe';
import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
import { I18nService } from '@ghostfolio/api/services/i18n/i18n.service';
@ -270,6 +271,11 @@ export class UserService {
undefined,
undefined
).getSettings(user.Settings.settings),
RegionalMarketClusterRiskEurope: new RegionalMarketClusterRiskEurope(
undefined,
undefined,
undefined
).getSettings(user.Settings.settings),
RegionalMarketClusterRiskNorthAmerica:
new RegionalMarketClusterRiskNorthAmerica(
undefined,

77
apps/api/src/models/rules/regional-market-cluster-risk/europe.ts

@ -0,0 +1,77 @@
import { Rule } from '@ghostfolio/api/models/rule';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { UserSettings } from '@ghostfolio/common/interfaces';
import { Settings } from './interfaces/rule-settings.interface';
export class RegionalMarketClusterRiskEurope extends Rule<Settings> {
private currentValueInBaseCurrency: number;
private europeValueInBaseCurrency: number;
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
currentValueInBaseCurrency: number,
europeValueInBaseCurrency: number
) {
super(exchangeRateDataService, {
key: RegionalMarketClusterRiskEurope.name,
name: 'Europe'
});
this.currentValueInBaseCurrency = currentValueInBaseCurrency;
this.europeValueInBaseCurrency = europeValueInBaseCurrency;
}
public evaluate(ruleSettings: Settings) {
const europeMarketValueRatio = this.currentValueInBaseCurrency
? this.europeValueInBaseCurrency / this.currentValueInBaseCurrency
: 0;
if (europeMarketValueRatio > ruleSettings.thresholdMax) {
return {
evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) exceeds ${(
ruleSettings.thresholdMax * 100
).toPrecision(3)}%`,
value: false
};
} else if (europeMarketValueRatio < ruleSettings.thresholdMin) {
return {
evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) is below ${(
ruleSettings.thresholdMin * 100
).toPrecision(3)}%`,
value: false
};
}
return {
evaluation: `The Europe market contribution of your current investment (${(europeMarketValueRatio * 100).toPrecision(3)}%) is within the range of ${(
ruleSettings.thresholdMin * 100
).toPrecision(
3
)}% and ${(ruleSettings.thresholdMax * 100).toPrecision(3)}%`,
value: true
};
}
public getConfiguration() {
return {
threshold: {
max: 1,
min: 0,
step: 0.01,
unit: '%'
},
thresholdMax: true,
thresholdMin: true
};
}
public getSettings({ baseCurrency, xRayRules }: UserSettings): Settings {
return {
baseCurrency,
isActive: xRayRules?.[this.getKey()]?.isActive ?? true,
thresholdMax: xRayRules?.[this.getKey()]?.thresholdMax ?? 0.15,
thresholdMin: xRayRules?.[this.getKey()]?.thresholdMin ?? 0.11
};
}
}

7
apps/api/src/models/rules/regional-market-cluster-risk/interfaces/rule-settings.interface.ts

@ -0,0 +1,7 @@
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
export interface Settings extends RuleSettings {
baseCurrency: string;
thresholdMin: number;
thresholdMax: number;
}

9
apps/api/src/models/rules/regional-market-cluster-risk/north-america.ts

@ -1,8 +1,9 @@
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface';
import { Rule } from '@ghostfolio/api/models/rule';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
import { UserSettings } from '@ghostfolio/common/interfaces';
import { Settings } from './interfaces/rule-settings.interface';
export class RegionalMarketClusterRiskNorthAmerica extends Rule<Settings> {
private currentValueInBaseCurrency: number;
private northAmericaValueInBaseCurrency: number;
@ -74,9 +75,3 @@ export class RegionalMarketClusterRiskNorthAmerica extends Rule<Settings> {
};
}
}
interface Settings extends RuleSettings {
baseCurrency: string;
thresholdMin: number;
thresholdMax: number;
}

2
apps/client/src/app/components/world-map-chart/world-map-chart.component.html

@ -8,4 +8,4 @@
/>
}
<div class="align-items-center d-flex h-100 w-100" id="svgMap"></div>
<div class="h-100 w-100" id="svgMap"></div>

33
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -20,6 +20,7 @@ import { ChangeDetectorRef, Component, OnDestroy, OnInit } from '@angular/core';
import { MatSnackBar } from '@angular/material/snack-bar';
import { SymbolProfile } from '@prisma/client';
import { isNumber, sortBy } from 'lodash';
import ms from 'ms';
import { DeviceDetectorService } from 'ngx-device-detector';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -142,17 +143,27 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
}
public onCopyPromptToClipboard() {
this.dataService.fetchPrompt().subscribe(({ prompt }) => {
this.clipboard.copy(prompt);
this.snackBar.open(
'✅ ' + $localize`AI prompt has been copied to the clipboard`,
undefined,
{
duration: 3000
}
);
});
this.dataService
.fetchPrompt()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ prompt }) => {
this.clipboard.copy(prompt);
const snackBarRef = this.snackBar.open(
'✅ ' + $localize`AI prompt has been copied to the clipboard`,
$localize`Open Duck.ai` + ' →',
{
duration: ms('7 seconds')
}
);
snackBarRef
.onAction()
.pipe(takeUntil(this.unsubscribeSubject))
.subscribe(() => {
window.open('https://duck.ai', '_blank');
});
});
}
public ngOnDestroy() {

20
apps/client/src/locales/messages.ca.xlf

@ -5075,7 +5075,7 @@
<target state="new">Dividend</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -5087,11 +5087,11 @@
<target state="new">Investment</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -5103,7 +5103,7 @@
<target state="new">Monthly</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
@ -5111,7 +5111,7 @@
<target state="new">Yearly</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -7641,7 +7641,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.de.xlf

@ -2806,7 +2806,7 @@
<target state="translated">Monatlich</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="5213771062241898526" datatype="html">
@ -3326,7 +3326,7 @@
<target state="translated">Dividenden</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -3434,7 +3434,7 @@
<target state="translated">Jährlich</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="72640258012696878" datatype="html">
@ -6319,11 +6319,11 @@
<target state="translated">Einlage</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7641,7 +7641,7 @@
<target state="translated">KI-Anweisung wurde in die Zwischenablage kopiert</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="translated">Öffne Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.es.xlf

@ -2835,7 +2835,7 @@
<target state="translated">Mensual</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8511b16abcf065252b350d64e337ba2447db3ffb" datatype="html">
@ -3319,7 +3319,7 @@
<target state="translated">Dividendo</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -3435,7 +3435,7 @@
<target state="translated">Anual</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="72640258012696878" datatype="html">
@ -6320,11 +6320,11 @@
<target state="translated">Inversión</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7642,7 +7642,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7741,6 +7741,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.fr.xlf

@ -2750,7 +2750,7 @@
<target state="translated">Dividende</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -2770,7 +2770,7 @@
<target state="translated">Mensuel</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -3434,7 +3434,7 @@
<target state="translated">Annuel</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="72640258012696878" datatype="html">
@ -6319,11 +6319,11 @@
<target state="translated">Investissement</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7641,7 +7641,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.it.xlf

@ -2835,7 +2835,7 @@
<target state="translated">Mensile</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8511b16abcf065252b350d64e337ba2447db3ffb" datatype="html">
@ -3319,7 +3319,7 @@
<target state="translated">Dividendi</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -3435,7 +3435,7 @@
<target state="translated">Annuale</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="72640258012696878" datatype="html">
@ -6320,11 +6320,11 @@
<target state="translated">Investimento</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7642,7 +7642,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7741,6 +7741,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.nl.xlf

@ -2834,7 +2834,7 @@
<target state="translated">Maandelijks</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8511b16abcf065252b350d64e337ba2447db3ffb" datatype="html">
@ -3318,7 +3318,7 @@
<target state="translated">Dividend</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -3434,7 +3434,7 @@
<target state="translated">Jaarlijks</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="72640258012696878" datatype="html">
@ -6319,11 +6319,11 @@
<target state="new">Investment</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7641,7 +7641,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.pl.xlf

@ -4667,7 +4667,7 @@
<target state="translated">Dywidenda</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -4687,7 +4687,7 @@
<target state="translated">Miesięcznie</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
@ -4695,7 +4695,7 @@
<target state="translated">Rocznie</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -6319,11 +6319,11 @@
<target state="translated">Inwestycje</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7641,7 +7641,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.pt.xlf

@ -2654,7 +2654,7 @@
<target state="translated">Mensalmente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -3386,7 +3386,7 @@
<target state="translated">Dividendos</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -3434,7 +3434,7 @@
<target state="translated">Anualmente</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="72640258012696878" datatype="html">
@ -6319,11 +6319,11 @@
<target state="new">Investment</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7641,7 +7641,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.tr.xlf

@ -4151,7 +4151,7 @@
<target state="translated">Temettü</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -4171,7 +4171,7 @@
<target state="translated">Aylık</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
@ -4179,7 +4179,7 @@
<target state="translated">Yıllık</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -6319,11 +6319,11 @@
<target state="new">Investment</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7641,7 +7641,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.uk.xlf

@ -5351,7 +5351,7 @@
<target state="translated">Дивіденди</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -5363,11 +5363,11 @@
<target state="translated">Інвестиції</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -5379,7 +5379,7 @@
<target state="translated">Щомісячно</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
@ -5387,7 +5387,7 @@
<target state="translated">Щорічно</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -7649,7 +7649,7 @@
<target state="translated">Запит AI скопійовано в буфер обміну</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7740,6 +7740,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

19
apps/client/src/locales/messages.xlf

@ -4294,7 +4294,7 @@
<source>Dividend</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -4312,14 +4312,14 @@
<source>Monthly</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
<source>Yearly</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -5772,11 +5772,11 @@
<source>Investment</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -6920,7 +6920,7 @@
<source>AI prompt has been copied to the clipboard</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="1616747898909934803" datatype="html">
@ -7000,6 +7000,13 @@
<context context-type="linenumber">93</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

20
apps/client/src/locales/messages.zh.xlf

@ -4684,7 +4684,7 @@
<target state="translated">股息</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">41</context>
<context context-type="linenumber">42</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">libs/ui/src/lib/i18n.ts</context>
@ -4704,7 +4704,7 @@
<target state="translated">每月</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">54</context>
<context context-type="linenumber">55</context>
</context-group>
</trans-unit>
<trans-unit id="8036977202721714375" datatype="html">
@ -4712,7 +4712,7 @@
<target state="translated">每年</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">55</context>
<context context-type="linenumber">56</context>
</context-group>
</trans-unit>
<trans-unit id="f6413089f93ac0756a20f8e74ef1ab78c81ef13c" datatype="html">
@ -6344,11 +6344,11 @@
<target state="translated">投资</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">46</context>
<context context-type="linenumber">47</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">60</context>
<context context-type="linenumber">61</context>
</context-group>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/resources/personal-finance-tools/product-page.component.ts</context>
@ -7642,7 +7642,7 @@
<target state="new">AI prompt has been copied to the clipboard</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">149</context>
<context context-type="linenumber">153</context>
</context-group>
</trans-unit>
<trans-unit id="4eecb3acb016e7d86740405b21599cdad8e0dd9f" datatype="html">
@ -7741,6 +7741,14 @@
<context context-type="linenumber">97</context>
</context-group>
</trans-unit>
<trans-unit id="7109040016560023658" datatype="html">
<source>Open Duck.ai</source>
<target state="new">Open Duck.ai</target>
<context-group purpose="location">
<context context-type="sourcefile">apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts</context>
<context context-type="linenumber">154</context>
</context-group>
</trans-unit>
</body>
</file>
</xliff>

1
libs/common/src/lib/interfaces/x-ray-rules-settings.interface.ts

@ -9,6 +9,7 @@ export interface XRayRulesSettings {
EconomicMarketClusterRiskEmergingMarkets?: RuleSettings;
EmergencyFundSetup?: RuleSettings;
FeeRatioInitialInvestment?: RuleSettings;
RegionalMarketClusterRiskEurope?: RuleSettings;
RegionalMarketClusterRiskNorthAmerica?: RuleSettings;
}

10
package-lock.json

@ -86,7 +86,7 @@
"reflect-metadata": "0.2.2",
"rxjs": "7.8.1",
"stripe": "17.3.0",
"svgmap": "2.6.0",
"svgmap": "2.12.2",
"twitter-api-v2": "1.14.2",
"uuid": "11.0.5",
"yahoo-finance2": "2.11.3",
@ -30272,12 +30272,12 @@
"license": "BSD-2-Clause"
},
"node_modules/svgmap": {
"version": "2.6.0",
"resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.6.0.tgz",
"integrity": "sha512-MePkVjgYlHwEfCSuGt+wB6WX6Z2fTD6yDtqZO5syzKYH7gamt1Hp9f/Bw5R49OvBtbsF7WCaGR0/GhewZGGA+w==",
"version": "2.12.2",
"resolved": "https://registry.npmjs.org/svgmap/-/svgmap-2.12.2.tgz",
"integrity": "sha512-SCX1Oys3v1dz3mTEbQha+6lrHGyu3LwXBhcgW0HlTh7waQDMFqNUKD8hADvDaPkPapRvNCLMnXaVD1Pbxbnhow==",
"license": "MIT",
"dependencies": {
"svg-pan-zoom": "^3.6.1"
"svg-pan-zoom": "^3.6.2"
}
},
"node_modules/svgo": {

2
package.json

@ -132,7 +132,7 @@
"reflect-metadata": "0.2.2",
"rxjs": "7.8.1",
"stripe": "17.3.0",
"svgmap": "2.6.0",
"svgmap": "2.12.2",
"twitter-api-v2": "1.14.2",
"uuid": "11.0.5",
"yahoo-finance2": "2.11.3",

Loading…
Cancel
Save