Feature/extend emergency fund X-ray rule to support assets (#4485)

* Extend emergency fund X-ray rule to support assets

* Update changelog

---------

Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
This commit is contained in:
Shaunak Das 2025-03-26 01:24:56 +05:30 committed by GitHub
parent 31be526c11
commit a13d6140cf
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
2 changed files with 42 additions and 24 deletions

View File

@ -9,6 +9,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Improved the static portfolio analysis rule: Emergency fund setup by supporting assets
- Restricted the historical market data gathering to active asset profiles - Restricted the historical market data gathering to active asset profiles
## 2.148.0 - 2025-03-24 ## 2.148.0 - 2025-03-24

View File

@ -569,7 +569,7 @@ export class PortfolioService {
const emergencyFundInCash = emergencyFund const emergencyFundInCash = emergencyFund
.minus( .minus(
this.getEmergencyFundPositionsValueInBaseCurrency({ this.getEmergencyFundHoldingsValueInBaseCurrency({
holdings holdings
}) })
) )
@ -608,8 +608,8 @@ export class PortfolioService {
userCurrency, userCurrency,
userId, userId,
balanceInBaseCurrency: cashDetails.balanceInBaseCurrency, balanceInBaseCurrency: cashDetails.balanceInBaseCurrency,
emergencyFundPositionsValueInBaseCurrency: emergencyFundHoldingsValueInBaseCurrency:
this.getEmergencyFundPositionsValueInBaseCurrency({ this.getEmergencyFundHoldingsValueInBaseCurrency({
holdings holdings
}) })
}); });
@ -1263,7 +1263,11 @@ export class PortfolioService {
[ [
new EmergencyFundSetup( new EmergencyFundSetup(
this.exchangeRateDataService, this.exchangeRateDataService,
userSettings.emergencyFund this.getTotalEmergencyFund({
userSettings,
emergencyFundHoldingsValueInBaseCurrency:
this.getEmergencyFundHoldingsValueInBaseCurrency({ holdings })
}).toNumber()
) )
], ],
userSettings userSettings
@ -1585,7 +1589,7 @@ export class PortfolioService {
return dividendsByGroup; return dividendsByGroup;
} }
private getEmergencyFundPositionsValueInBaseCurrency({ private getEmergencyFundHoldingsValueInBaseCurrency({
holdings holdings
}: { }: {
holdings: PortfolioDetails['holdings']; holdings: PortfolioDetails['holdings'];
@ -1600,14 +1604,14 @@ export class PortfolioService {
); );
}); });
let valueInBaseCurrencyOfEmergencyFundPositions = new Big(0); let valueInBaseCurrencyOfEmergencyFundHoldings = new Big(0);
for (const { valueInBaseCurrency } of emergencyFundHoldings) { for (const { valueInBaseCurrency } of emergencyFundHoldings) {
valueInBaseCurrencyOfEmergencyFundPositions = valueInBaseCurrencyOfEmergencyFundHoldings =
valueInBaseCurrencyOfEmergencyFundPositions.plus(valueInBaseCurrency); valueInBaseCurrencyOfEmergencyFundHoldings.plus(valueInBaseCurrency);
} }
return valueInBaseCurrencyOfEmergencyFundPositions.toNumber(); return valueInBaseCurrencyOfEmergencyFundHoldings.toNumber();
} }
private getInitialCashPosition({ private getInitialCashPosition({
@ -1774,7 +1778,7 @@ export class PortfolioService {
private async getSummary({ private async getSummary({
balanceInBaseCurrency, balanceInBaseCurrency,
emergencyFundPositionsValueInBaseCurrency, emergencyFundHoldingsValueInBaseCurrency,
filteredValueInBaseCurrency, filteredValueInBaseCurrency,
impersonationId, impersonationId,
portfolioCalculator, portfolioCalculator,
@ -1782,7 +1786,7 @@ export class PortfolioService {
userId userId
}: { }: {
balanceInBaseCurrency: number; balanceInBaseCurrency: number;
emergencyFundPositionsValueInBaseCurrency: number; emergencyFundHoldingsValueInBaseCurrency: number;
filteredValueInBaseCurrency: Big; filteredValueInBaseCurrency: Big;
impersonationId: string; impersonationId: string;
portfolioCalculator: PortfolioCalculator; portfolioCalculator: PortfolioCalculator;
@ -1827,12 +1831,10 @@ export class PortfolioService {
const dividendInBaseCurrency = const dividendInBaseCurrency =
await portfolioCalculator.getDividendInBaseCurrency(); await portfolioCalculator.getDividendInBaseCurrency();
const emergencyFund = new Big( const totalEmergencyFund = this.getTotalEmergencyFund({
Math.max( emergencyFundHoldingsValueInBaseCurrency,
emergencyFundPositionsValueInBaseCurrency, userSettings: user.Settings?.settings as UserSettings
(user.Settings?.settings as UserSettings)?.emergencyFund ?? 0 });
)
);
const fees = await portfolioCalculator.getFeesInBaseCurrency(); const fees = await portfolioCalculator.getFeesInBaseCurrency();
@ -1858,8 +1860,8 @@ export class PortfolioService {
}).toNumber(); }).toNumber();
const cash = new Big(balanceInBaseCurrency) const cash = new Big(balanceInBaseCurrency)
.minus(emergencyFund) .minus(totalEmergencyFund)
.plus(emergencyFundPositionsValueInBaseCurrency) .plus(emergencyFundHoldingsValueInBaseCurrency)
.toNumber(); .toNumber();
const committedFunds = new Big(totalBuy).minus(totalSell); const committedFunds = new Big(totalBuy).minus(totalSell);
@ -1928,11 +1930,11 @@ export class PortfolioService {
currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(), currentValueInBaseCurrency: currentValueInBaseCurrency.toNumber(),
dividendInBaseCurrency: dividendInBaseCurrency.toNumber(), dividendInBaseCurrency: dividendInBaseCurrency.toNumber(),
emergencyFund: { emergencyFund: {
assets: emergencyFundPositionsValueInBaseCurrency, assets: emergencyFundHoldingsValueInBaseCurrency,
cash: emergencyFund cash: totalEmergencyFund
.minus(emergencyFundPositionsValueInBaseCurrency) .minus(emergencyFundHoldingsValueInBaseCurrency)
.toNumber(), .toNumber(),
total: emergencyFund.toNumber() total: totalEmergencyFund.toNumber()
}, },
fees: fees.toNumber(), fees: fees.toNumber(),
filteredValueInBaseCurrency: filteredValueInBaseCurrency.toNumber(), filteredValueInBaseCurrency: filteredValueInBaseCurrency.toNumber(),
@ -1940,7 +1942,7 @@ export class PortfolioService {
? filteredValueInBaseCurrency.div(netWorth).toNumber() ? filteredValueInBaseCurrency.div(netWorth).toNumber()
: undefined, : undefined,
fireWealth: new Big(currentValueInBaseCurrency) fireWealth: new Big(currentValueInBaseCurrency)
.minus(emergencyFundPositionsValueInBaseCurrency) .minus(emergencyFundHoldingsValueInBaseCurrency)
.toNumber(), .toNumber(),
grossPerformance: new Big(netPerformance).plus(fees).toNumber(), grossPerformance: new Big(netPerformance).plus(fees).toNumber(),
grossPerformanceWithCurrencyEffect: new Big( grossPerformanceWithCurrencyEffect: new Big(
@ -1985,6 +1987,21 @@ export class PortfolioService {
); );
} }
private getTotalEmergencyFund({
emergencyFundHoldingsValueInBaseCurrency,
userSettings
}: {
emergencyFundHoldingsValueInBaseCurrency: number;
userSettings: UserSettings;
}) {
return new Big(
Math.max(
emergencyFundHoldingsValueInBaseCurrency,
userSettings?.emergencyFund ?? 0
)
);
}
private getUserCurrency(aUser?: UserWithSettings) { private getUserCurrency(aUser?: UserWithSettings) {
return ( return (
aUser?.Settings?.settings.baseCurrency ?? aUser?.Settings?.settings.baseCurrency ??