Browse Source

dd new static portfolio analysis rule: Emergency fund setup

pull/2400/head
Thomas 2 years ago
parent
commit
9b024aa513
  1. 5
      apps/api/src/app/portfolio/portfolio.service.ts
  2. 9
      apps/api/src/models/rules/account-cluster-risk/current-investment.ts
  3. 9
      apps/api/src/models/rules/account-cluster-risk/single-account.ts
  4. 9
      apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts
  5. 9
      apps/api/src/models/rules/currency-cluster-risk/current-investment.ts
  6. 41
      apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts
  7. 15
      apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts
  8. 3
      apps/client/src/app/pages/portfolio/fire/fire-page.component.ts
  9. 27
      apps/client/src/app/pages/portfolio/fire/fire-page.html

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

@ -10,6 +10,7 @@ import { AccountClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rule
import { AccountClusterRiskSingleAccount } from '@ghostfolio/api/models/rules/account-cluster-risk/single-account';
import { CurrencyClusterRiskBaseCurrencyCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/base-currency-current-investment';
import { CurrencyClusterRiskCurrentInvestment } from '@ghostfolio/api/models/rules/currency-cluster-risk/current-investment';
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 { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
@ -1277,6 +1278,10 @@ export class PortfolioService {
],
<UserSettings>this.request.user.Settings.settings
),
emergencyFund: await this.rulesService.evaluate(
[new EmergencyFundSetup(this.exchangeRateDataService)],
<UserSettings>this.request.user.Settings.settings
),
fees: await this.rulesService.evaluate(
[
new FeeRatioInitialInvestment(

9
apps/api/src/models/rules/account-cluster-risk/current-investment.ts

@ -1,4 +1,5 @@
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 {
PortfolioDetails,
@ -6,16 +7,18 @@ import {
UserSettings
} from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class AccountClusterRiskCurrentInvestment extends Rule<Settings> {
private accounts: PortfolioDetails['accounts'];
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private accounts: PortfolioDetails['accounts']
accounts: PortfolioDetails['accounts']
) {
super(exchangeRateDataService, {
name: 'Investment'
});
this.accounts = accounts;
}
public evaluate(ruleSettings: Settings) {

9
apps/api/src/models/rules/account-cluster-risk/single-account.ts

@ -1,17 +1,20 @@
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 { PortfolioDetails, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class AccountClusterRiskSingleAccount extends Rule<RuleSettings> {
private accounts: PortfolioDetails['accounts'];
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private accounts: PortfolioDetails['accounts']
accounts: PortfolioDetails['accounts']
) {
super(exchangeRateDataService, {
name: 'Single Account'
});
this.accounts = accounts;
}
public evaluate() {

9
apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts

@ -1,17 +1,20 @@
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 { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule<Settings> {
private positions: TimelinePosition[];
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private positions: TimelinePosition[]
positions: TimelinePosition[]
) {
super(exchangeRateDataService, {
name: 'Investment: Base Currency'
});
this.positions = positions;
}
public evaluate(ruleSettings: Settings) {

9
apps/api/src/models/rules/currency-cluster-risk/current-investment.ts

@ -1,17 +1,20 @@
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 { TimelinePosition, UserSettings } from '@ghostfolio/common/interfaces';
import { Rule } from '../../rule';
export class CurrencyClusterRiskCurrentInvestment extends Rule<Settings> {
private positions: TimelinePosition[];
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private positions: TimelinePosition[]
positions: TimelinePosition[]
) {
super(exchangeRateDataService, {
name: 'Investment'
});
this.positions = positions;
}
public evaluate(ruleSettings: Settings) {

41
apps/api/src/models/rules/emergency-fund/emergency-fund-setup.ts

@ -0,0 +1,41 @@
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';
export class EmergencyFundSetup extends Rule<Settings> {
public constructor(
protected exchangeRateDataService: ExchangeRateDataService
) {
super(exchangeRateDataService, {
name: 'Emergency Fund: Set up'
});
}
public evaluate(ruleSettings: Settings) {
if (ruleSettings.threshold > 0) {
return {
evaluation: `You have set up an emergency fund`,
value: true
};
}
return {
evaluation: `You have not set up an emergency fund yet`,
value: false
};
}
public getSettings(aUserSettings: UserSettings): Settings {
return {
baseCurrency: aUserSettings.baseCurrency,
isActive: true,
threshold: aUserSettings.emergencyFund
};
}
}
interface Settings extends RuleSettings {
baseCurrency: string;
threshold: number;
}

15
apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts

@ -1,18 +1,23 @@
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 { Rule } from '../../rule';
export class FeeRatioInitialInvestment extends Rule<Settings> {
private fees: number;
private totalInvestment: number;
public constructor(
protected exchangeRateDataService: ExchangeRateDataService,
private totalInvestment: number,
private fees: number
totalInvestment: number,
fees: number
) {
super(exchangeRateDataService, {
name: 'Investment'
name: 'Fee Ratio'
});
this.fees = fees;
this.totalInvestment = totalInvestment;
}
public evaluate(ruleSettings: Settings) {

3
apps/client/src/app/pages/portfolio/fire/fire-page.component.ts

@ -18,6 +18,7 @@ export class FirePageComponent implements OnDestroy, OnInit {
public accountClusterRiskRules: PortfolioReportRule[];
public currencyClusterRiskRules: PortfolioReportRule[];
public deviceType: string;
public emergencyFundRules: PortfolioReportRule[];
public feeRules: PortfolioReportRule[];
public fireWealth: Big;
public hasImpersonationId: boolean;
@ -67,6 +68,8 @@ export class FirePageComponent implements OnDestroy, OnInit {
portfolioReport.rules['accountClusterRisk'] || null;
this.currencyClusterRiskRules =
portfolioReport.rules['currencyClusterRisk'] || null;
this.emergencyFundRules =
portfolioReport.rules['emergencyFund'] || null;
this.feeRules = portfolioReport.rules['fees'] || null;
this.changeDetectorRef.markForCheck();

27
apps/client/src/app/pages/portfolio/fire/fire-page.html

@ -96,8 +96,10 @@
<div class="col">
<h2 class="h3 mb-3 text-center">X-ray</h2>
<p class="mb-4">
Ghostfolio X-ray uses static analysis to identify potential issues and
risks in your portfolio.
<span i18n
>Ghostfolio X-ray uses static analysis to identify potential issues
and risks in your portfolio.</span
>
<span class="d-none"
>It will be highly configurable in the future: activate / deactivate
rules and customize the thresholds to match your personal investment
@ -106,7 +108,7 @@
</p>
<div class="mb-4">
<h4 class="align-items-center d-flex m-0">
<span>Currency Cluster Risks</span
<span i18n>Currency Cluster Risks</span
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
@ -119,7 +121,7 @@
</div>
<div class="mb-4">
<h4 class="align-items-center d-flex m-0">
<span>Account Cluster Risks</span
<span i18n>Account Cluster Risks</span
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
@ -130,9 +132,9 @@
[rules]="accountClusterRiskRules"
></gf-rules>
</div>
<div>
<div class="mb-4">
<h4 class="align-items-center d-flex m-0">
<span>Fees</span
<span i18n>Fees</span
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
@ -143,6 +145,19 @@
[rules]="feeRules"
></gf-rules>
</div>
<div>
<h4 class="align-items-center d-flex m-0">
<span i18n>Emergency Fund</span
><gf-premium-indicator
*ngIf="user?.subscription?.type === 'Basic'"
class="ml-1"
></gf-premium-indicator>
</h4>
<gf-rules
[hasPermissionToCreateOrder]="hasPermissionToCreateOrder"
[rules]="emergencyFundRules"
></gf-rules>
</div>
</div>
</div>
</div>

Loading…
Cancel
Save