Feature/extend holding endpoint by performances (#4660)
* Extend holding endpoint by performances * Update changelog
This commit is contained in:
parent
40d3eaa023
commit
c38dab5ab0
@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
|
||||
## Unreleased
|
||||
|
||||
### Added
|
||||
|
||||
- Extended the endpoint to get a holding by the date of the last all time high and the current change to the all time high
|
||||
|
||||
### Changed
|
||||
|
||||
- Improved the language localization for Turkish (`tr`)
|
||||
|
@ -8,6 +8,7 @@ import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service';
|
||||
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
|
||||
import { UserModule } from '@ghostfolio/api/app/user/user.module';
|
||||
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
|
||||
import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module';
|
||||
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
|
||||
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module';
|
||||
@ -27,6 +28,7 @@ import { AiService } from './ai.service';
|
||||
controllers: [AiController],
|
||||
imports: [
|
||||
ApiModule,
|
||||
BenchmarkModule,
|
||||
ConfigurationModule,
|
||||
DataProviderModule,
|
||||
ExchangeRateDataModule,
|
||||
|
@ -9,6 +9,7 @@ import { RulesService } from '@ghostfolio/api/app/portfolio/rules.service';
|
||||
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
|
||||
import { UserModule } from '@ghostfolio/api/app/user/user.module';
|
||||
import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module';
|
||||
import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module';
|
||||
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module';
|
||||
import { ImpersonationModule } from '@ghostfolio/api/services/impersonation/impersonation.module';
|
||||
@ -25,6 +26,7 @@ import { PublicController } from './public.controller';
|
||||
controllers: [PublicController],
|
||||
imports: [
|
||||
AccessModule,
|
||||
BenchmarkModule,
|
||||
DataProviderModule,
|
||||
ExchangeRateDataModule,
|
||||
ImpersonationModule,
|
||||
|
@ -9,6 +9,7 @@ import { RedactValuesInResponseModule } from '@ghostfolio/api/interceptors/redac
|
||||
import { TransformDataSourceInRequestModule } from '@ghostfolio/api/interceptors/transform-data-source-in-request/transform-data-source-in-request.module';
|
||||
import { TransformDataSourceInResponseModule } from '@ghostfolio/api/interceptors/transform-data-source-in-response/transform-data-source-in-response.module';
|
||||
import { ApiModule } from '@ghostfolio/api/services/api/api.module';
|
||||
import { BenchmarkModule } from '@ghostfolio/api/services/benchmark/benchmark.module';
|
||||
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
|
||||
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
|
||||
import { ExchangeRateDataModule } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.module';
|
||||
@ -33,6 +34,7 @@ import { RulesService } from './rules.service';
|
||||
imports: [
|
||||
AccessModule,
|
||||
ApiModule,
|
||||
BenchmarkModule,
|
||||
ConfigurationModule,
|
||||
DataGatheringModule,
|
||||
DataProviderModule,
|
||||
|
@ -20,6 +20,7 @@ import { RegionalMarketClusterRiskEmergingMarkets } from '@ghostfolio/api/models
|
||||
import { RegionalMarketClusterRiskEurope } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/europe';
|
||||
import { RegionalMarketClusterRiskJapan } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/japan';
|
||||
import { RegionalMarketClusterRiskNorthAmerica } from '@ghostfolio/api/models/rules/regional-market-cluster-risk/north-america';
|
||||
import { BenchmarkService } from '@ghostfolio/api/services/benchmark/benchmark.service';
|
||||
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
|
||||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
|
||||
import { ImpersonationService } from '@ghostfolio/api/services/impersonation/impersonation.service';
|
||||
@ -100,6 +101,7 @@ export class PortfolioService {
|
||||
public constructor(
|
||||
private readonly accountBalanceService: AccountBalanceService,
|
||||
private readonly accountService: AccountService,
|
||||
private readonly benchmarkService: BenchmarkService,
|
||||
private readonly calculatorFactory: PortfolioCalculatorFactory,
|
||||
private readonly dataProviderService: DataProviderService,
|
||||
private readonly exchangeRateDataService: ExchangeRateDataService,
|
||||
@ -669,6 +671,7 @@ export class PortfolioService {
|
||||
netPerformancePercent: undefined,
|
||||
netPerformancePercentWithCurrencyEffect: undefined,
|
||||
netPerformanceWithCurrencyEffect: undefined,
|
||||
performances: undefined,
|
||||
quantity: undefined,
|
||||
SymbolProfile: undefined,
|
||||
tags: [],
|
||||
@ -752,6 +755,10 @@ export class PortfolioService {
|
||||
activitiesOfHolding[0].unitPriceInAssetProfileCurrency,
|
||||
marketPrice
|
||||
);
|
||||
let marketPriceMaxDate =
|
||||
marketPrice > activitiesOfHolding[0].unitPriceInAssetProfileCurrency
|
||||
? new Date()
|
||||
: activitiesOfHolding[0].date;
|
||||
let marketPriceMin = Math.min(
|
||||
activitiesOfHolding[0].unitPriceInAssetProfileCurrency,
|
||||
marketPrice
|
||||
@ -793,7 +800,10 @@ export class PortfolioService {
|
||||
quantity: currentQuantity
|
||||
});
|
||||
|
||||
marketPriceMax = Math.max(marketPrice ?? 0, marketPriceMax);
|
||||
if (marketPrice > marketPriceMax) {
|
||||
marketPriceMax = marketPrice;
|
||||
marketPriceMaxDate = parseISO(date);
|
||||
}
|
||||
marketPriceMin = Math.min(
|
||||
marketPrice ?? Number.MAX_SAFE_INTEGER,
|
||||
marketPriceMin
|
||||
@ -809,6 +819,12 @@ export class PortfolioService {
|
||||
});
|
||||
}
|
||||
|
||||
const performancePercent =
|
||||
this.benchmarkService.calculateChangeInPercentage(
|
||||
marketPriceMax,
|
||||
marketPrice
|
||||
);
|
||||
|
||||
return {
|
||||
firstBuyDate,
|
||||
marketPrice,
|
||||
@ -846,6 +862,12 @@ export class PortfolioService {
|
||||
]?.toNumber(),
|
||||
netPerformanceWithCurrencyEffect:
|
||||
position.netPerformanceWithCurrencyEffectMap?.['max']?.toNumber(),
|
||||
performances: {
|
||||
allTimeHigh: {
|
||||
performancePercent,
|
||||
date: marketPriceMaxDate
|
||||
}
|
||||
},
|
||||
quantity: quantity.toNumber(),
|
||||
value: this.exchangeRateDataService.toCurrency(
|
||||
quantity.mul(marketPrice ?? 0).toNumber(),
|
||||
@ -885,6 +907,7 @@ export class PortfolioService {
|
||||
|
||||
const historicalDataArray: HistoricalDataItem[] = [];
|
||||
let marketPriceMax = marketPrice;
|
||||
let marketPriceMaxDate = new Date();
|
||||
let marketPriceMin = marketPrice;
|
||||
|
||||
for (const [date, { marketPrice }] of Object.entries(
|
||||
@ -895,13 +918,22 @@ export class PortfolioService {
|
||||
value: marketPrice
|
||||
});
|
||||
|
||||
marketPriceMax = Math.max(marketPrice ?? 0, marketPriceMax);
|
||||
if (marketPrice > marketPriceMax) {
|
||||
marketPriceMax = marketPrice;
|
||||
marketPriceMaxDate = parseISO(date);
|
||||
}
|
||||
marketPriceMin = Math.min(
|
||||
marketPrice ?? Number.MAX_SAFE_INTEGER,
|
||||
marketPriceMin
|
||||
);
|
||||
}
|
||||
|
||||
const performancePercent =
|
||||
this.benchmarkService.calculateChangeInPercentage(
|
||||
marketPriceMax,
|
||||
marketPrice
|
||||
);
|
||||
|
||||
return {
|
||||
marketPrice,
|
||||
marketPriceMax,
|
||||
@ -925,6 +957,12 @@ export class PortfolioService {
|
||||
netPerformancePercent: undefined,
|
||||
netPerformancePercentWithCurrencyEffect: undefined,
|
||||
netPerformanceWithCurrencyEffect: undefined,
|
||||
performances: {
|
||||
allTimeHigh: {
|
||||
performancePercent,
|
||||
date: marketPriceMaxDate
|
||||
}
|
||||
},
|
||||
quantity: 0,
|
||||
tags: [],
|
||||
transactionCount: undefined,
|
||||
|
@ -1,5 +1,6 @@
|
||||
import { Activity } from '@ghostfolio/api/app/order/interfaces/activities.interface';
|
||||
import {
|
||||
Benchmark,
|
||||
DataProviderInfo,
|
||||
EnhancedSymbolProfile,
|
||||
HistoricalDataItem
|
||||
@ -29,6 +30,7 @@ export interface PortfolioHoldingResponse {
|
||||
netPerformancePercent: number;
|
||||
netPerformancePercentWithCurrencyEffect: number;
|
||||
netPerformanceWithCurrencyEffect: number;
|
||||
performances: Benchmark['performances'];
|
||||
quantity: number;
|
||||
SymbolProfile: EnhancedSymbolProfile;
|
||||
tags: Tag[];
|
||||
|
Loading…
x
Reference in New Issue
Block a user