From 72dbe00091ae1afb995b78eaffca832fd778ecc4 Mon Sep 17 00:00:00 2001 From: Valentin Zickner Date: Sat, 31 Jul 2021 23:19:57 +0200 Subject: [PATCH] change rule service interface --- .../src/models/interfaces/rule.interface.ts | 10 +---- apps/api/src/models/portfolio.ts | 37 ++++++++++++------- apps/api/src/models/rule.ts | 10 +---- .../current-investment.ts | 13 +++---- .../initial-investment.ts | 13 +++---- .../account-cluster-risk/single-account.ts | 9 +++-- .../base-currency-current-investment.ts | 13 +++---- .../base-currency-initial-investment.ts | 13 +++---- .../current-investment.ts | 13 +++---- .../initial-investment.ts | 13 +++---- .../fees/fee-ratio-initial-investment.ts | 16 ++++---- apps/api/src/services/rules.service.ts | 9 +---- 12 files changed, 77 insertions(+), 92 deletions(-) diff --git a/apps/api/src/models/interfaces/rule.interface.ts b/apps/api/src/models/interfaces/rule.interface.ts index 1de2e66a6..894751b32 100644 --- a/apps/api/src/models/interfaces/rule.interface.ts +++ b/apps/api/src/models/interfaces/rule.interface.ts @@ -1,17 +1,9 @@ -import { PortfolioPosition } from '@ghostfolio/common/interfaces'; - import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.interface'; import { EvaluationResult } from './evaluation-result.interface'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export interface RuleInterface { - evaluate( - aPortfolioPositionMap: { - [symbol: string]: PortfolioPosition; - }, - aFees: number, - aRuleSettings: T - ): EvaluationResult; + evaluate(aRuleSettings: T): EvaluationResult; getSettings(aUserSettings: UserSettings): T; } diff --git a/apps/api/src/models/portfolio.ts b/apps/api/src/models/portfolio.ts index 9e58b3abf..a948dcbb0 100644 --- a/apps/api/src/models/portfolio.ts +++ b/apps/api/src/models/portfolio.ts @@ -450,42 +450,51 @@ export class Portfolio implements PortfolioInterface { return { rules: { accountClusterRisk: await this.rulesService.evaluate( - details, - fees, [ new AccountClusterRiskInitialInvestment( - this.exchangeRateDataService + this.exchangeRateDataService, + details ), new AccountClusterRiskCurrentInvestment( - this.exchangeRateDataService + this.exchangeRateDataService, + details ), - new AccountClusterRiskSingleAccount(this.exchangeRateDataService) + new AccountClusterRiskSingleAccount( + this.exchangeRateDataService, + details + ) ], { baseCurrency: this.user.Settings.currency } ), currencyClusterRisk: await this.rulesService.evaluate( - details, - fees, [ new CurrencyClusterRiskBaseCurrencyInitialInvestment( - this.exchangeRateDataService + this.exchangeRateDataService, + details ), new CurrencyClusterRiskBaseCurrencyCurrentInvestment( - this.exchangeRateDataService + this.exchangeRateDataService, + details ), new CurrencyClusterRiskInitialInvestment( - this.exchangeRateDataService + this.exchangeRateDataService, + details ), new CurrencyClusterRiskCurrentInvestment( - this.exchangeRateDataService + this.exchangeRateDataService, + details ) ], { baseCurrency: this.user.Settings.currency } ), fees: await this.rulesService.evaluate( - details, - fees, - [new FeeRatioInitialInvestment(this.exchangeRateDataService)], + [ + new FeeRatioInitialInvestment( + this.exchangeRateDataService, + details, + fees + ) + ], { baseCurrency: this.user.Settings.currency } ) } diff --git a/apps/api/src/models/rule.ts b/apps/api/src/models/rule.ts index d5a4d3621..48d9d0711 100644 --- a/apps/api/src/models/rule.ts +++ b/apps/api/src/models/rule.ts @@ -12,7 +12,7 @@ export abstract class Rule implements RuleInterface { private name: string; public constructor( - public exchangeRateDataService: ExchangeRateDataService, + protected exchangeRateDataService: ExchangeRateDataService, { name }: { @@ -22,13 +22,7 @@ export abstract class Rule implements RuleInterface { this.name = name; } - public abstract evaluate( - aPortfolioPositionMap: { - [symbol: string]: PortfolioPosition; - }, - aFees: number, - aRuleSettings: T - ): EvaluationResult; + public abstract evaluate(aRuleSettings: T): EvaluationResult; public abstract getSettings(aUserSettings: UserSettings): T; diff --git a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts index b6dbe86e0..d76130614 100644 --- a/apps/api/src/models/rules/account-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/current-investment.ts @@ -6,24 +6,23 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class AccountClusterRiskCurrentInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Current Investment' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings?: Settings - ) { + public evaluate(ruleSettings: Settings) { const accounts: { [symbol: string]: Pick & { investment: number; }; } = {}; - Object.values(aPositions).forEach((position) => { + Object.values(this.positions).forEach((position) => { for (const [account, { current }] of Object.entries(position.accounts)) { if (accounts[account]?.investment) { accounts[account].investment += current; diff --git a/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts b/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts index 2bf8da1f8..51ca6bb3e 100644 --- a/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts +++ b/apps/api/src/models/rules/account-cluster-risk/initial-investment.ts @@ -6,24 +6,23 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class AccountClusterRiskInitialInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Initial Investment' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings?: Settings - ) { + public evaluate(ruleSettings?: Settings) { const platforms: { [symbol: string]: Pick & { investment: number; }; } = {}; - Object.values(aPositions).forEach((position) => { + Object.values(this.positions).forEach((position) => { for (const [account, { original }] of Object.entries(position.accounts)) { if (platforms[account]?.investment) { platforms[account].investment += original; diff --git a/apps/api/src/models/rules/account-cluster-risk/single-account.ts b/apps/api/src/models/rules/account-cluster-risk/single-account.ts index 86093de2e..ba7e2bb73 100644 --- a/apps/api/src/models/rules/account-cluster-risk/single-account.ts +++ b/apps/api/src/models/rules/account-cluster-risk/single-account.ts @@ -6,16 +6,19 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class AccountClusterRiskSingleAccount extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Single Account' }); } - public evaluate(positions: { [symbol: string]: PortfolioPosition }) { + public evaluate() { const accounts: string[] = []; - Object.values(positions).forEach((position) => { + Object.values(this.positions).forEach((position) => { for (const [account] of Object.entries(position.accounts)) { if (!accounts.includes(account)) { accounts.push(account); diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts index 826bb1b55..66c2e6ebc 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-current-investment.ts @@ -7,19 +7,18 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class CurrencyClusterRiskBaseCurrencyCurrentInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Current Investment: Base Currency' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings: Settings - ) { + public evaluate(ruleSettings: Settings) { const positionsGroupedByCurrency = this.groupPositionsByAttribute( - aPositions, + this.positions, 'currency', ruleSettings.baseCurrency ); diff --git a/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts index f019aa38c..0a197bc31 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/base-currency-initial-investment.ts @@ -7,19 +7,18 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class CurrencyClusterRiskBaseCurrencyInitialInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Initial Investment: Base Currency' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings: Settings - ) { + public evaluate(ruleSettings: Settings) { const positionsGroupedByCurrency = this.groupPositionsByAttribute( - aPositions, + this.positions, 'currency', ruleSettings.baseCurrency ); diff --git a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts index 330d3ee31..41794b8b2 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/current-investment.ts @@ -7,19 +7,18 @@ import { Currency } from '@prisma/client'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class CurrencyClusterRiskCurrentInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + public exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Current Investment' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings: Settings - ) { + public evaluate(ruleSettings: Settings) { const positionsGroupedByCurrency = this.groupPositionsByAttribute( - aPositions, + this.positions, 'currency', ruleSettings.baseCurrency ); diff --git a/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts b/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts index a86ead3e5..2e38b351e 100644 --- a/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts +++ b/apps/api/src/models/rules/currency-cluster-risk/initial-investment.ts @@ -7,19 +7,18 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class CurrencyClusterRiskInitialInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition } + ) { super(exchangeRateDataService, { name: 'Initial Investment' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings: Settings - ) { + public evaluate(ruleSettings: Settings) { const positionsGroupedByCurrency = this.groupPositionsByAttribute( - aPositions, + this.positions, 'currency', ruleSettings.baseCurrency ); diff --git a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts index e5e9a91ee..8faff972b 100644 --- a/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts +++ b/apps/api/src/models/rules/fees/fee-ratio-initial-investment.ts @@ -7,19 +7,19 @@ import { UserSettings } from '@ghostfolio/api/models/interfaces/user-settings.in import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; export class FeeRatioInitialInvestment extends Rule { - public constructor(public exchangeRateDataService: ExchangeRateDataService) { + public constructor( + protected exchangeRateDataService: ExchangeRateDataService, + private positions: { [symbol: string]: PortfolioPosition }, + private fees: number + ) { super(exchangeRateDataService, { name: 'Initial Investment' }); } - public evaluate( - aPositions: { [symbol: string]: PortfolioPosition }, - aFees: number, - ruleSettings: Settings - ) { + public evaluate(ruleSettings: Settings) { const positionsGroupedByCurrency = this.groupPositionsByAttribute( - aPositions, + this.positions, 'currency', ruleSettings.baseCurrency ); @@ -31,7 +31,7 @@ export class FeeRatioInitialInvestment extends Rule { totalInvestment += groupItem.investment; }); - const feeRatio = aFees / totalInvestment; + const feeRatio = this.fees / totalInvestment; if (feeRatio > ruleSettings.threshold) { return { diff --git a/apps/api/src/services/rules.service.ts b/apps/api/src/services/rules.service.ts index 655c172a3..f3de455ac 100644 --- a/apps/api/src/services/rules.service.ts +++ b/apps/api/src/services/rules.service.ts @@ -1,6 +1,5 @@ import { Injectable } from '@nestjs/common'; import { Rule } from '../models/rule'; -import { PortfolioPosition } from '@ghostfolio/common/interfaces'; import { Currency } from '@prisma/client'; import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; @@ -9,8 +8,6 @@ export class RulesService { public constructor() {} public async evaluate( - details: { [p: string]: PortfolioPosition }, - fees: number, aRules: Rule[], aUserSettings: { baseCurrency: Currency } ) { @@ -19,11 +16,7 @@ export class RulesService { return rule.getSettings(aUserSettings)?.isActive; }) .map((rule) => { - const evaluationResult = rule.evaluate( - details, - fees, - rule.getSettings(aUserSettings) - ); + const evaluationResult = rule.evaluate(rule.getSettings(aUserSettings)); return { ...evaluationResult, name: rule.getName() }; }); }