64 lines
1.6 KiB
TypeScript
64 lines
1.6 KiB
TypeScript
|
import { Currency } from '@prisma/client';
|
||
|
import { groupBy } from 'libs/helper/src';
|
||
|
|
||
|
import { PortfolioPosition } from '../app/portfolio/interfaces/portfolio-position.interface';
|
||
|
import { ExchangeRateDataService } from '../services/exchange-rate-data.service';
|
||
|
import { EvaluationResult } from './interfaces/evaluation-result.interface';
|
||
|
import { RuleInterface } from './interfaces/rule.interface';
|
||
|
|
||
|
export abstract class Rule implements RuleInterface {
|
||
|
private name: string;
|
||
|
|
||
|
public constructor(
|
||
|
public exchangeRateDataService: ExchangeRateDataService,
|
||
|
{
|
||
|
name
|
||
|
}: {
|
||
|
name: string;
|
||
|
}
|
||
|
) {
|
||
|
this.name = name;
|
||
|
}
|
||
|
|
||
|
public abstract evaluate(
|
||
|
aPortfolioPositionMap: {
|
||
|
[symbol: string]: PortfolioPosition;
|
||
|
},
|
||
|
aFees: number,
|
||
|
aRuleSettingsMap?: {
|
||
|
[key: string]: any;
|
||
|
}
|
||
|
): EvaluationResult;
|
||
|
|
||
|
public getName() {
|
||
|
return this.name;
|
||
|
}
|
||
|
|
||
|
public groupPositionsByAttribute(
|
||
|
aPositions: { [symbol: string]: PortfolioPosition },
|
||
|
aAttribute: keyof PortfolioPosition,
|
||
|
aBaseCurrency: Currency
|
||
|
) {
|
||
|
return Array.from(
|
||
|
groupBy(aAttribute, Object.values(aPositions)).entries()
|
||
|
).map(([attributeValue, objs]) => ({
|
||
|
groupKey: attributeValue,
|
||
|
investment: objs.reduce(
|
||
|
(previousValue, currentValue) =>
|
||
|
previousValue + currentValue.investment,
|
||
|
0
|
||
|
),
|
||
|
value: objs.reduce(
|
||
|
(previousValue, currentValue) =>
|
||
|
previousValue +
|
||
|
this.exchangeRateDataService.toCurrency(
|
||
|
currentValue.quantity * currentValue.marketPrice,
|
||
|
currentValue.currency,
|
||
|
aBaseCurrency
|
||
|
),
|
||
|
0
|
||
|
)
|
||
|
}));
|
||
|
}
|
||
|
}
|