mirror of https://github.com/ghostfolio/ghostfolio
				
				
			
							committed by
							
								
								Thomas
							
						
					
				
				 14 changed files with 169 additions and 119 deletions
			
			
		@ -0,0 +1,3 @@ | 
				
			|||
export interface RuleSettings { | 
				
			|||
  isActive: boolean; | 
				
			|||
} | 
				
			|||
@ -1,15 +1,17 @@ | 
				
			|||
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 { | 
				
			|||
export interface RuleInterface<T extends RuleSettings> { | 
				
			|||
  evaluate( | 
				
			|||
    aPortfolioPositionMap: { | 
				
			|||
      [symbol: string]: PortfolioPosition; | 
				
			|||
    }, | 
				
			|||
    aFees: number, | 
				
			|||
    aRuleSettingsMap: { | 
				
			|||
      [key: string]: any; | 
				
			|||
    } | 
				
			|||
    aRuleSettings: T | 
				
			|||
  ): EvaluationResult; | 
				
			|||
 | 
				
			|||
  getSettings(aUserSettings: UserSettings): T; | 
				
			|||
} | 
				
			|||
 | 
				
			|||
@ -0,0 +1,5 @@ | 
				
			|||
import { Currency } from '@prisma/client'; | 
				
			|||
 | 
				
			|||
export interface UserSettings { | 
				
			|||
  baseCurrency: Currency; | 
				
			|||
} | 
				
			|||
@ -1,78 +1,30 @@ | 
				
			|||
import { Injectable } from '@nestjs/common'; | 
				
			|||
 | 
				
			|||
import { Portfolio } from '../models/portfolio'; | 
				
			|||
import { Rule } from '../models/rule'; | 
				
			|||
import { AccountClusterRiskCurrentInvestment } from '../models/rules/account-cluster-risk/current-investment'; | 
				
			|||
import { AccountClusterRiskInitialInvestment } from '../models/rules/account-cluster-risk/initial-investment'; | 
				
			|||
import { AccountClusterRiskSingleAccount } from '../models/rules/account-cluster-risk/single-account'; | 
				
			|||
import { CurrencyClusterRiskBaseCurrencyCurrentInvestment } from '../models/rules/currency-cluster-risk/base-currency-current-investment'; | 
				
			|||
import { CurrencyClusterRiskBaseCurrencyInitialInvestment } from '../models/rules/currency-cluster-risk/base-currency-initial-investment'; | 
				
			|||
import { CurrencyClusterRiskCurrentInvestment } from '../models/rules/currency-cluster-risk/current-investment'; | 
				
			|||
import { CurrencyClusterRiskInitialInvestment } from '../models/rules/currency-cluster-risk/initial-investment'; | 
				
			|||
import { FeeRatioInitialInvestment } from '../models/rules/fees/fee-ratio-initial-investment'; | 
				
			|||
import { PortfolioPosition } from '@ghostfolio/common/interfaces'; | 
				
			|||
import { Currency } from '@prisma/client'; | 
				
			|||
import { RuleSettings } from '@ghostfolio/api/models/interfaces/rule-settings.interface'; | 
				
			|||
 | 
				
			|||
@Injectable() | 
				
			|||
export class RulesService { | 
				
			|||
  public constructor() {} | 
				
			|||
 | 
				
			|||
  public async evaluate( | 
				
			|||
    aPortfolio: Portfolio, | 
				
			|||
    aRules: Rule[], | 
				
			|||
    aUserSettings: { baseCurrency: string } | 
				
			|||
  public async evaluate<T extends RuleSettings>( | 
				
			|||
    details: { [p: string]: PortfolioPosition }, | 
				
			|||
    fees: number, | 
				
			|||
    aRules: Rule<T>[], | 
				
			|||
    aUserSettings: { baseCurrency: Currency } | 
				
			|||
  ) { | 
				
			|||
    const defaultSettings = this.getDefaultRuleSettings(aUserSettings); | 
				
			|||
    const details = await aPortfolio.getDetails(); | 
				
			|||
 | 
				
			|||
    return aRules | 
				
			|||
      .filter((rule) => { | 
				
			|||
        return defaultSettings[rule.constructor.name]?.isActive; | 
				
			|||
        return rule.getSettings(aUserSettings)?.isActive; | 
				
			|||
      }) | 
				
			|||
      .map((rule) => { | 
				
			|||
        const evaluationResult = rule.evaluate( | 
				
			|||
          details, | 
				
			|||
          aPortfolio.getFees(), | 
				
			|||
          defaultSettings | 
				
			|||
          fees, | 
				
			|||
          rule.getSettings(aUserSettings) | 
				
			|||
        ); | 
				
			|||
        return { ...evaluationResult, name: rule.getName() }; | 
				
			|||
      }); | 
				
			|||
  } | 
				
			|||
 | 
				
			|||
  private getDefaultRuleSettings(aUserSettings: { baseCurrency: string }) { | 
				
			|||
    return { | 
				
			|||
      [AccountClusterRiskCurrentInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true, | 
				
			|||
        threshold: 0.5 | 
				
			|||
      }, | 
				
			|||
      [AccountClusterRiskInitialInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true, | 
				
			|||
        threshold: 0.5 | 
				
			|||
      }, | 
				
			|||
      [AccountClusterRiskSingleAccount.name]: { isActive: true }, | 
				
			|||
      [CurrencyClusterRiskBaseCurrencyInitialInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true | 
				
			|||
      }, | 
				
			|||
      [CurrencyClusterRiskBaseCurrencyCurrentInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true | 
				
			|||
      }, | 
				
			|||
      [CurrencyClusterRiskCurrentInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true, | 
				
			|||
        threshold: 0.5 | 
				
			|||
      }, | 
				
			|||
      [CurrencyClusterRiskInitialInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true, | 
				
			|||
        threshold: 0.5 | 
				
			|||
      }, | 
				
			|||
      [FeeRatioInitialInvestment.name]: { | 
				
			|||
        baseCurrency: aUserSettings.baseCurrency, | 
				
			|||
        isActive: true, | 
				
			|||
        threshold: 0.01 | 
				
			|||
      } | 
				
			|||
    }; | 
				
			|||
  } | 
				
			|||
} | 
				
			|||
 | 
				
			|||
					Loading…
					
					
				
		Reference in new issue