Fix chart tooltip of benchmark comparator (#3167)

* Fix chart tooltip of benchmark comparator

* Update changelog
pull/3199/head^2
helgehatt 2 months ago committed by GitHub
parent 0edebe30e1
commit b41eb60348
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -11,6 +11,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Extended the export functionality by the user accounts currency
### Fixed
- Fixed the chart tooltip of the benchmark comparator
## 2.67.0 - 2024-03-26
### Added

@ -13,7 +13,8 @@ import {
import {
DATE_FORMAT,
calculateBenchmarkTrend,
parseDate
parseDate,
resetHours
} from '@ghostfolio/common/helper';
import {
Benchmark,
@ -27,7 +28,13 @@ import { BenchmarkTrend } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { SymbolProfile } from '@prisma/client';
import { Big } from 'big.js';
import { format, isSameDay, subDays } from 'date-fns';
import {
differenceInDays,
eachDayOfInterval,
format,
isSameDay,
subDays
} from 'date-fns';
import { isNumber, last, uniqBy } from 'lodash';
import ms from 'ms';
@ -208,15 +215,28 @@ export class BenchmarkService {
public async getMarketDataBySymbol({
dataSource,
endDate = new Date(),
startDate,
symbol,
userCurrency
}: {
endDate?: Date;
startDate: Date;
userCurrency: string;
} & UniqueAsset): Promise<BenchmarkMarketDataDetails> {
const marketData: { date: string; value: number }[] = [];
const days = differenceInDays(endDate, startDate) + 1;
const dates = eachDayOfInterval(
{
start: startDate,
end: endDate
},
{ step: Math.round(days / Math.min(days, MAX_CHART_ITEMS)) }
).map((date) => {
return resetHours(date);
});
const [currentSymbolItem, marketDataItems] = await Promise.all([
this.symbolService.get({
dataGatheringItem: {
@ -232,7 +252,7 @@ export class BenchmarkService {
dataSource,
symbol,
date: {
gte: startDate
in: dates
}
}
})
@ -266,17 +286,7 @@ export class BenchmarkService {
return { marketData };
}
const step = Math.round(
marketDataItems.length / Math.min(marketDataItems.length, MAX_CHART_ITEMS)
);
let i = 0;
for (let marketDataItem of marketDataItems) {
if (i % step !== 0) {
continue;
}
const exchangeRate =
exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[
format(marketDataItem.date, DATE_FORMAT)
@ -299,15 +309,15 @@ export class BenchmarkService {
});
}
const includesToday = isSameDay(
const includesEndDate = isSameDay(
parseDate(last(marketData).date),
new Date()
endDate
);
if (currentSymbolItem?.marketPrice && !includesToday) {
if (currentSymbolItem?.marketPrice && !includesEndDate) {
const exchangeRate =
exchangeRates[`${currentSymbolItem.currency}${userCurrency}`]?.[
format(new Date(), DATE_FORMAT)
format(endDate, DATE_FORMAT)
];
const exchangeRateFactor =
@ -316,7 +326,7 @@ export class BenchmarkService {
: 1;
marketData.push({
date: format(new Date(), DATE_FORMAT),
date: format(endDate, DATE_FORMAT),
value:
this.calculateChangeInPercentage(
marketPriceAtStartDate,

@ -34,7 +34,7 @@ export class CurrentRateService {
}: GetValuesParams): Promise<GetValuesObject> {
const dataProviderInfos: DataProviderInfo[] = [];
const includeToday =
const includesToday =
(!dateQuery.lt || isBefore(new Date(), dateQuery.lt)) &&
(!dateQuery.gte || isBefore(dateQuery.gte, new Date())) &&
(!dateQuery.in || this.containsToday(dateQuery.in));
@ -43,7 +43,7 @@ export class CurrentRateService {
const quoteErrors: ResponseError['errors'] = [];
const today = resetHours(new Date());
if (includeToday) {
if (includesToday) {
promises.push(
this.dataProviderService
.getQuotes({ items: dataGatheringItems, user: this.request?.user })

@ -3,6 +3,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
import { parseDate } from '@ghostfolio/common/helper';
import { Big } from 'big.js';
import { subDays } from 'date-fns';
import { CurrentRateServiceMock } from './current-rate.service.mock';
import { PortfolioCalculator } from './portfolio-calculator';
@ -46,13 +47,12 @@ describe('PortfolioCalculator', () => {
.spyOn(Date, 'now')
.mockImplementation(() => parseDate('2021-12-18').getTime());
const chartData = await portfolioCalculator.getChartData({
start: new Date()
});
const start = subDays(new Date(Date.now()), 10);
const chartData = await portfolioCalculator.getChartData({ start });
const currentPositions = await portfolioCalculator.getCurrentPositions(
new Date()
);
const currentPositions =
await portfolioCalculator.getCurrentPositions(start);
const investments = portfolioCalculator.getInvestments();

@ -18,6 +18,7 @@ import {
addDays,
addMilliseconds,
differenceInDays,
eachDayOfInterval,
endOfDay,
format,
isBefore,
@ -199,29 +200,31 @@ export class PortfolioCalculator {
}) ?? [];
const currencies: { [symbol: string]: string } = {};
const dates: Date[] = [];
const dataGatheringItems: IDataGatheringItem[] = [];
const firstIndex = transactionPointsBeforeEndDate.length;
let day = start;
let dates = eachDayOfInterval({ start, end }, { step }).map((date) => {
return resetHours(date);
});
while (isBefore(day, end)) {
dates.push(resetHours(day));
day = addDays(day, step);
}
const includesEndDate = isSameDay(last(dates), end);
if (!isSameDay(last(dates), end)) {
if (!includesEndDate) {
dates.push(resetHours(end));
}
if (transactionPointsBeforeEndDate.length > 0) {
for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) {
for (const {
currency,
dataSource,
symbol
} of transactionPointsBeforeEndDate[firstIndex - 1].items) {
dataGatheringItems.push({
dataSource: item.dataSource,
symbol: item.symbol
dataSource,
symbol
});
currencies[item.symbol] = item.currency;
symbols[item.symbol] = true;
currencies[symbol] = currency;
symbols[symbol] = true;
}
}

@ -1482,17 +1482,13 @@ export class PortfolioService {
userId = await this.getUserId(impersonationId, userId);
const endDate = new Date();
const portfolioStart = parseDate(transactionPoints[0].date);
const startDate = this.getStartDate(dateRange, portfolioStart);
let step = 1;
if (withDataDecimation) {
const daysInMarket = differenceInDays(new Date(), startDate);
step = Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS));
}
const endDate = new Date();
const daysInMarket = differenceInDays(endDate, startDate) + 1;
const step = withDataDecimation
? Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS))
: 1;
const items = await portfolioCalculator.getChartData({
step,

@ -98,6 +98,12 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
}
private initialize() {
const benchmarkDataValues: { [date: string]: number } = {};
for (const { date, value } of this.benchmarkDataItems) {
benchmarkDataValues[date] = value;
}
const data: ChartData<'line'> = {
datasets: [
{
@ -113,8 +119,11 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
backgroundColor: `rgb(${secondaryColorRgb.r}, ${secondaryColorRgb.g}, ${secondaryColorRgb.b})`,
borderColor: `rgb(${secondaryColorRgb.r}, ${secondaryColorRgb.g}, ${secondaryColorRgb.b})`,
borderWidth: 2,
data: this.benchmarkDataItems.map(({ date, value }) => {
return { x: parseDate(date).getTime(), y: value };
data: this.performanceDataItems.map(({ date }) => {
return {
x: parseDate(date).getTime(),
y: benchmarkDataValues[date]
};
}),
label: this.benchmark?.name ?? $localize`Benchmark`
}
@ -228,7 +237,7 @@ export class BenchmarkComparatorComponent implements OnChanges, OnDestroy {
locale: this.locale,
unit: '%'
}),
mode: 'x',
mode: 'index',
position: <unknown>'top',
xAlign: 'center',
yAlign: 'bottom'

Loading…
Cancel
Save