Feature/add investment value to chart (#2948)
* Add investment value to chart * Update changelog
This commit is contained in:
parent
faad65b6f3
commit
c9237146e2
@ -15,6 +15,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed an issue with the currency conversion in the investment timeline
|
||||||
- Fixed the export in the lazy-loaded activities table on the portfolio activities page (experimental)
|
- Fixed the export in the lazy-loaded activities table on the portfolio activities page (experimental)
|
||||||
|
|
||||||
## 2.46.0 - 2024-01-28
|
## 2.46.0 - 2024-01-28
|
||||||
|
@ -1,6 +0,0 @@
|
|||||||
export type Accuracy = 'day' | 'month' | 'year';
|
|
||||||
|
|
||||||
export interface TimelineSpecification {
|
|
||||||
accuracy: Accuracy;
|
|
||||||
start: string;
|
|
||||||
}
|
|
@ -68,14 +68,20 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2021-12-18').getTime());
|
.mockImplementation(() => parseDate('2021-12-18').getTime());
|
||||||
|
|
||||||
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
|
start: parseDate('2021-11-22')
|
||||||
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
parseDate('2021-11-22')
|
parseDate('2021-11-22')
|
||||||
);
|
);
|
||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
@ -135,7 +141,8 @@ describe('PortfolioCalculator', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(investmentsByMonth).toEqual([
|
expect(investmentsByMonth).toEqual([
|
||||||
{ date: '2021-11-01', investment: new Big('12.6') }
|
{ date: '2021-11-01', investment: 0 },
|
||||||
|
{ date: '2021-12-01', investment: 0 }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -57,14 +57,20 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2021-12-18').getTime());
|
.mockImplementation(() => parseDate('2021-12-18').getTime());
|
||||||
|
|
||||||
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
|
start: parseDate('2021-11-30')
|
||||||
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
parseDate('2021-11-30')
|
parseDate('2021-11-30')
|
||||||
);
|
);
|
||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
@ -123,7 +129,8 @@ describe('PortfolioCalculator', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(investmentsByMonth).toEqual([
|
expect(investmentsByMonth).toEqual([
|
||||||
{ date: '2021-11-01', investment: new Big('273.2') }
|
{ date: '2021-11-01', investment: 273.2 },
|
||||||
|
{ date: '2021-12-01', investment: 0 }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -81,14 +81,20 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2018-01-01').getTime());
|
.mockImplementation(() => parseDate('2018-01-01').getTime());
|
||||||
|
|
||||||
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
|
start: parseDate('2015-01-01')
|
||||||
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
parseDate('2015-01-01')
|
parseDate('2015-01-01')
|
||||||
);
|
);
|
||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
@ -155,42 +161,43 @@ describe('PortfolioCalculator', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(investmentsByMonth).toEqual([
|
expect(investmentsByMonth).toEqual([
|
||||||
{ date: '2015-01-01', investment: new Big('640.86') },
|
{ date: '2015-01-01', investment: 637.0853345999999 },
|
||||||
{ date: '2015-02-01', investment: new Big('0') },
|
{ date: '2015-02-01', investment: 0 },
|
||||||
{ date: '2015-03-01', investment: new Big('0') },
|
{ date: '2015-03-01', investment: 0 },
|
||||||
{ date: '2015-04-01', investment: new Big('0') },
|
{ date: '2015-04-01', investment: 0 },
|
||||||
{ date: '2015-05-01', investment: new Big('0') },
|
{ date: '2015-05-01', investment: 0 },
|
||||||
{ date: '2015-06-01', investment: new Big('0') },
|
{ date: '2015-06-01', investment: 0 },
|
||||||
{ date: '2015-07-01', investment: new Big('0') },
|
{ date: '2015-07-01', investment: 0 },
|
||||||
{ date: '2015-08-01', investment: new Big('0') },
|
{ date: '2015-08-01', investment: 0 },
|
||||||
{ date: '2015-09-01', investment: new Big('0') },
|
{ date: '2015-09-01', investment: 0 },
|
||||||
{ date: '2015-10-01', investment: new Big('0') },
|
{ date: '2015-10-01', investment: 0 },
|
||||||
{ date: '2015-11-01', investment: new Big('0') },
|
{ date: '2015-11-01', investment: 0 },
|
||||||
{ date: '2015-12-01', investment: new Big('0') },
|
{ date: '2015-12-01', investment: 0 },
|
||||||
{ date: '2016-01-01', investment: new Big('0') },
|
{ date: '2016-01-01', investment: 0 },
|
||||||
{ date: '2016-02-01', investment: new Big('0') },
|
{ date: '2016-02-01', investment: 0 },
|
||||||
{ date: '2016-03-01', investment: new Big('0') },
|
{ date: '2016-03-01', investment: 0 },
|
||||||
{ date: '2016-04-01', investment: new Big('0') },
|
{ date: '2016-04-01', investment: 0 },
|
||||||
{ date: '2016-05-01', investment: new Big('0') },
|
{ date: '2016-05-01', investment: 0 },
|
||||||
{ date: '2016-06-01', investment: new Big('0') },
|
{ date: '2016-06-01', investment: 0 },
|
||||||
{ date: '2016-07-01', investment: new Big('0') },
|
{ date: '2016-07-01', investment: 0 },
|
||||||
{ date: '2016-08-01', investment: new Big('0') },
|
{ date: '2016-08-01', investment: 0 },
|
||||||
{ date: '2016-09-01', investment: new Big('0') },
|
{ date: '2016-09-01', investment: 0 },
|
||||||
{ date: '2016-10-01', investment: new Big('0') },
|
{ date: '2016-10-01', investment: 0 },
|
||||||
{ date: '2016-11-01', investment: new Big('0') },
|
{ date: '2016-11-01', investment: 0 },
|
||||||
{ date: '2016-12-01', investment: new Big('0') },
|
{ date: '2016-12-01', investment: 0 },
|
||||||
{ date: '2017-01-01', investment: new Big('0') },
|
{ date: '2017-01-01', investment: 0 },
|
||||||
{ date: '2017-02-01', investment: new Big('0') },
|
{ date: '2017-02-01', investment: 0 },
|
||||||
{ date: '2017-03-01', investment: new Big('0') },
|
{ date: '2017-03-01', investment: 0 },
|
||||||
{ date: '2017-04-01', investment: new Big('0') },
|
{ date: '2017-04-01', investment: 0 },
|
||||||
{ date: '2017-05-01', investment: new Big('0') },
|
{ date: '2017-05-01', investment: 0 },
|
||||||
{ date: '2017-06-01', investment: new Big('0') },
|
{ date: '2017-06-01', investment: 0 },
|
||||||
{ date: '2017-07-01', investment: new Big('0') },
|
{ date: '2017-07-01', investment: 0 },
|
||||||
{ date: '2017-08-01', investment: new Big('0') },
|
{ date: '2017-08-01', investment: 0 },
|
||||||
{ date: '2017-09-01', investment: new Big('0') },
|
{ date: '2017-09-01', investment: 0 },
|
||||||
{ date: '2017-10-01', investment: new Big('0') },
|
{ date: '2017-10-01', investment: 0 },
|
||||||
{ date: '2017-11-01', investment: new Big('0') },
|
{ date: '2017-11-01', investment: 0 },
|
||||||
{ date: '2017-12-01', investment: new Big('-14156.4') }
|
{ date: '2017-12-01', investment: -318.54266729999995 },
|
||||||
|
{ date: '2018-01-01', investment: 0 }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -70,14 +70,20 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2023-07-10').getTime());
|
.mockImplementation(() => parseDate('2023-07-10').getTime());
|
||||||
|
|
||||||
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
|
start: parseDate('2023-01-03')
|
||||||
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
parseDate('2023-01-03')
|
parseDate('2023-01-03')
|
||||||
);
|
);
|
||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
@ -137,7 +143,31 @@ describe('PortfolioCalculator', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(investmentsByMonth).toEqual([
|
expect(investmentsByMonth).toEqual([
|
||||||
{ date: '2023-01-01', investment: new Big('89.12') }
|
{ date: '2023-01-01', investment: 82.329056 },
|
||||||
|
{
|
||||||
|
date: '2023-02-01',
|
||||||
|
investment: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2023-03-01',
|
||||||
|
investment: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2023-04-01',
|
||||||
|
investment: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2023-05-01',
|
||||||
|
investment: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2023-06-01',
|
||||||
|
investment: 0
|
||||||
|
},
|
||||||
|
{
|
||||||
|
date: '2023-07-01',
|
||||||
|
investment: 0
|
||||||
|
}
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -45,14 +45,20 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2021-12-18').getTime());
|
.mockImplementation(() => parseDate('2021-12-18').getTime());
|
||||||
|
|
||||||
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
|
start: new Date()
|
||||||
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
new Date()
|
new Date()
|
||||||
);
|
);
|
||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
|
@ -68,14 +68,20 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2022-04-11').getTime());
|
.mockImplementation(() => parseDate('2022-04-11').getTime());
|
||||||
|
|
||||||
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
|
start: parseDate('2022-03-07')
|
||||||
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
parseDate('2022-03-07')
|
parseDate('2022-03-07')
|
||||||
);
|
);
|
||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
@ -137,8 +143,8 @@ describe('PortfolioCalculator', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(investmentsByMonth).toEqual([
|
expect(investmentsByMonth).toEqual([
|
||||||
{ date: '2022-03-01', investment: new Big('151.6') },
|
{ date: '2022-03-01', investment: 151.6 },
|
||||||
{ date: '2022-04-01', investment: new Big('-85.73') }
|
{ date: '2022-04-01', investment: -75.8 }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -68,9 +68,9 @@ describe('PortfolioCalculator', () => {
|
|||||||
.spyOn(Date, 'now')
|
.spyOn(Date, 'now')
|
||||||
.mockImplementation(() => parseDate('2022-04-11').getTime());
|
.mockImplementation(() => parseDate('2022-04-11').getTime());
|
||||||
|
|
||||||
const chartData = await portfolioCalculator.getChartData(
|
const chartData = await portfolioCalculator.getChartData({
|
||||||
parseDate('2022-03-07')
|
start: parseDate('2022-03-07')
|
||||||
);
|
});
|
||||||
|
|
||||||
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
||||||
parseDate('2022-03-07')
|
parseDate('2022-03-07')
|
||||||
@ -78,13 +78,16 @@ describe('PortfolioCalculator', () => {
|
|||||||
|
|
||||||
const investments = portfolioCalculator.getInvestments();
|
const investments = portfolioCalculator.getInvestments();
|
||||||
|
|
||||||
const investmentsByMonth =
|
const investmentsByMonth = portfolioCalculator.getInvestmentsByGroup({
|
||||||
portfolioCalculator.getInvestmentsByGroup('month');
|
data: chartData,
|
||||||
|
groupBy: 'month'
|
||||||
|
});
|
||||||
|
|
||||||
spy.mockRestore();
|
spy.mockRestore();
|
||||||
|
|
||||||
expect(chartData[0]).toEqual({
|
expect(chartData[0]).toEqual({
|
||||||
date: '2022-03-07',
|
date: '2022-03-07',
|
||||||
|
investmentValueWithCurrencyEffect: 151.6,
|
||||||
netPerformance: 0,
|
netPerformance: 0,
|
||||||
netPerformanceInPercentage: 0,
|
netPerformanceInPercentage: 0,
|
||||||
netPerformanceInPercentageWithCurrencyEffect: 0,
|
netPerformanceInPercentageWithCurrencyEffect: 0,
|
||||||
@ -97,6 +100,7 @@ describe('PortfolioCalculator', () => {
|
|||||||
|
|
||||||
expect(chartData[chartData.length - 1]).toEqual({
|
expect(chartData[chartData.length - 1]).toEqual({
|
||||||
date: '2022-04-11',
|
date: '2022-04-11',
|
||||||
|
investmentValueWithCurrencyEffect: 0,
|
||||||
netPerformance: 19.86,
|
netPerformance: 19.86,
|
||||||
netPerformanceInPercentage: 13.100263852242744,
|
netPerformanceInPercentage: 13.100263852242744,
|
||||||
netPerformanceInPercentageWithCurrencyEffect: 13.100263852242744,
|
netPerformanceInPercentageWithCurrencyEffect: 13.100263852242744,
|
||||||
@ -163,8 +167,8 @@ describe('PortfolioCalculator', () => {
|
|||||||
]);
|
]);
|
||||||
|
|
||||||
expect(investmentsByMonth).toEqual([
|
expect(investmentsByMonth).toEqual([
|
||||||
{ date: '2022-03-01', investment: new Big('151.6') },
|
{ date: '2022-03-01', investment: 151.6 },
|
||||||
{ date: '2022-04-01', investment: new Big('-171.46') }
|
{ date: '2022-04-01', investment: -151.6 }
|
||||||
]);
|
]);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -3,6 +3,8 @@ import { IDataGatheringItem } from '@ghostfolio/api/services/interfaces/interfac
|
|||||||
import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper';
|
import { DATE_FORMAT, parseDate, resetHours } from '@ghostfolio/common/helper';
|
||||||
import {
|
import {
|
||||||
DataProviderInfo,
|
DataProviderInfo,
|
||||||
|
HistoricalDataItem,
|
||||||
|
InvestmentItem,
|
||||||
ResponseError,
|
ResponseError,
|
||||||
SymbolMetrics,
|
SymbolMetrics,
|
||||||
TimelinePosition
|
TimelinePosition
|
||||||
@ -14,16 +16,11 @@ import Big from 'big.js';
|
|||||||
import {
|
import {
|
||||||
addDays,
|
addDays,
|
||||||
addMilliseconds,
|
addMilliseconds,
|
||||||
addMonths,
|
|
||||||
addYears,
|
|
||||||
differenceInDays,
|
differenceInDays,
|
||||||
endOfDay,
|
endOfDay,
|
||||||
format,
|
format,
|
||||||
isBefore,
|
isBefore,
|
||||||
isSameDay,
|
isSameDay,
|
||||||
isSameMonth,
|
|
||||||
isSameYear,
|
|
||||||
set,
|
|
||||||
subDays
|
subDays
|
||||||
} from 'date-fns';
|
} from 'date-fns';
|
||||||
import { cloneDeep, first, isNumber, last, sortBy, uniq } from 'lodash';
|
import { cloneDeep, first, isNumber, last, sortBy, uniq } from 'lodash';
|
||||||
@ -32,10 +29,6 @@ import { CurrentRateService } from './current-rate.service';
|
|||||||
import { CurrentPositions } from './interfaces/current-positions.interface';
|
import { CurrentPositions } from './interfaces/current-positions.interface';
|
||||||
import { PortfolioOrderItem } from './interfaces/portfolio-calculator.interface';
|
import { PortfolioOrderItem } from './interfaces/portfolio-calculator.interface';
|
||||||
import { PortfolioOrder } from './interfaces/portfolio-order.interface';
|
import { PortfolioOrder } from './interfaces/portfolio-order.interface';
|
||||||
import {
|
|
||||||
Accuracy,
|
|
||||||
TimelineSpecification
|
|
||||||
} from './interfaces/timeline-specification.interface';
|
|
||||||
import { TransactionPointSymbol } from './interfaces/transaction-point-symbol.interface';
|
import { TransactionPointSymbol } from './interfaces/transaction-point-symbol.interface';
|
||||||
import { TransactionPoint } from './interfaces/transaction-point.interface';
|
import { TransactionPoint } from './interfaces/transaction-point.interface';
|
||||||
|
|
||||||
@ -179,7 +172,15 @@ export class PortfolioCalculator {
|
|||||||
this.transactionPoints = transactionPoints;
|
this.transactionPoints = transactionPoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
public async getChartData(start: Date, end = new Date(Date.now()), step = 1) {
|
public async getChartData({
|
||||||
|
end = new Date(Date.now()),
|
||||||
|
start,
|
||||||
|
step = 1
|
||||||
|
}: {
|
||||||
|
end?: Date;
|
||||||
|
start: Date;
|
||||||
|
step?: number;
|
||||||
|
}): Promise<HistoricalDataItem[]> {
|
||||||
const symbols: { [symbol: string]: boolean } = {};
|
const symbols: { [symbol: string]: boolean } = {};
|
||||||
|
|
||||||
const transactionPointsBeforeEndDate =
|
const transactionPointsBeforeEndDate =
|
||||||
@ -203,13 +204,15 @@ export class PortfolioCalculator {
|
|||||||
dates.push(resetHours(end));
|
dates.push(resetHours(end));
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) {
|
if (transactionPointsBeforeEndDate.length > 0) {
|
||||||
dataGatheringItems.push({
|
for (const item of transactionPointsBeforeEndDate[firstIndex - 1].items) {
|
||||||
dataSource: item.dataSource,
|
dataGatheringItems.push({
|
||||||
symbol: item.symbol
|
dataSource: item.dataSource,
|
||||||
});
|
symbol: item.symbol
|
||||||
currencies[item.symbol] = item.currency;
|
});
|
||||||
symbols[item.symbol] = true;
|
currencies[item.symbol] = item.currency;
|
||||||
|
symbols[item.symbol] = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const { dataProviderInfos, values: marketSymbols } =
|
const { dataProviderInfos, values: marketSymbols } =
|
||||||
@ -248,6 +251,7 @@ export class PortfolioCalculator {
|
|||||||
|
|
||||||
const accumulatedValuesByDate: {
|
const accumulatedValuesByDate: {
|
||||||
[date: string]: {
|
[date: string]: {
|
||||||
|
investmentValueWithCurrencyEffect: Big;
|
||||||
totalCurrentValue: Big;
|
totalCurrentValue: Big;
|
||||||
totalCurrentValueWithCurrencyEffect: Big;
|
totalCurrentValueWithCurrencyEffect: Big;
|
||||||
totalInvestmentValue: Big;
|
totalInvestmentValue: Big;
|
||||||
@ -263,7 +267,8 @@ export class PortfolioCalculator {
|
|||||||
[symbol: string]: {
|
[symbol: string]: {
|
||||||
currentValues: { [date: string]: Big };
|
currentValues: { [date: string]: Big };
|
||||||
currentValuesWithCurrencyEffect: { [date: string]: Big };
|
currentValuesWithCurrencyEffect: { [date: string]: Big };
|
||||||
investmentValues: { [date: string]: Big };
|
investmentValuesAccumulated: { [date: string]: Big };
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect: { [date: string]: Big };
|
||||||
investmentValuesWithCurrencyEffect: { [date: string]: Big };
|
investmentValuesWithCurrencyEffect: { [date: string]: Big };
|
||||||
netPerformanceValues: { [date: string]: Big };
|
netPerformanceValues: { [date: string]: Big };
|
||||||
netPerformanceValuesWithCurrencyEffect: { [date: string]: Big };
|
netPerformanceValuesWithCurrencyEffect: { [date: string]: Big };
|
||||||
@ -276,7 +281,8 @@ export class PortfolioCalculator {
|
|||||||
const {
|
const {
|
||||||
currentValues,
|
currentValues,
|
||||||
currentValuesWithCurrencyEffect,
|
currentValuesWithCurrencyEffect,
|
||||||
investmentValues,
|
investmentValuesAccumulated,
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect,
|
||||||
investmentValuesWithCurrencyEffect,
|
investmentValuesWithCurrencyEffect,
|
||||||
netPerformanceValues,
|
netPerformanceValues,
|
||||||
netPerformanceValuesWithCurrencyEffect,
|
netPerformanceValuesWithCurrencyEffect,
|
||||||
@ -296,7 +302,8 @@ export class PortfolioCalculator {
|
|||||||
valuesBySymbol[symbol] = {
|
valuesBySymbol[symbol] = {
|
||||||
currentValues,
|
currentValues,
|
||||||
currentValuesWithCurrencyEffect,
|
currentValuesWithCurrencyEffect,
|
||||||
investmentValues,
|
investmentValuesAccumulated,
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect,
|
||||||
investmentValuesWithCurrencyEffect,
|
investmentValuesWithCurrencyEffect,
|
||||||
netPerformanceValues,
|
netPerformanceValues,
|
||||||
netPerformanceValuesWithCurrencyEffect,
|
netPerformanceValuesWithCurrencyEffect,
|
||||||
@ -318,8 +325,13 @@ export class PortfolioCalculator {
|
|||||||
symbolValues.currentValuesWithCurrencyEffect?.[dateString] ??
|
symbolValues.currentValuesWithCurrencyEffect?.[dateString] ??
|
||||||
new Big(0);
|
new Big(0);
|
||||||
|
|
||||||
const investmentValue =
|
const investmentValueAccumulated =
|
||||||
symbolValues.investmentValues?.[dateString] ?? new Big(0);
|
symbolValues.investmentValuesAccumulated?.[dateString] ?? new Big(0);
|
||||||
|
|
||||||
|
const investmentValueAccumulatedWithCurrencyEffect =
|
||||||
|
symbolValues.investmentValuesAccumulatedWithCurrencyEffect?.[
|
||||||
|
dateString
|
||||||
|
] ?? new Big(0);
|
||||||
|
|
||||||
const investmentValueWithCurrencyEffect =
|
const investmentValueWithCurrencyEffect =
|
||||||
symbolValues.investmentValuesWithCurrencyEffect?.[dateString] ??
|
symbolValues.investmentValuesWithCurrencyEffect?.[dateString] ??
|
||||||
@ -341,6 +353,10 @@ export class PortfolioCalculator {
|
|||||||
] ?? new Big(0);
|
] ?? new Big(0);
|
||||||
|
|
||||||
accumulatedValuesByDate[dateString] = {
|
accumulatedValuesByDate[dateString] = {
|
||||||
|
investmentValueWithCurrencyEffect: (
|
||||||
|
accumulatedValuesByDate[dateString]
|
||||||
|
?.investmentValueWithCurrencyEffect ?? new Big(0)
|
||||||
|
).add(investmentValueWithCurrencyEffect),
|
||||||
totalCurrentValue: (
|
totalCurrentValue: (
|
||||||
accumulatedValuesByDate[dateString]?.totalCurrentValue ?? new Big(0)
|
accumulatedValuesByDate[dateString]?.totalCurrentValue ?? new Big(0)
|
||||||
).add(currentValue),
|
).add(currentValue),
|
||||||
@ -351,11 +367,11 @@ export class PortfolioCalculator {
|
|||||||
totalInvestmentValue: (
|
totalInvestmentValue: (
|
||||||
accumulatedValuesByDate[dateString]?.totalInvestmentValue ??
|
accumulatedValuesByDate[dateString]?.totalInvestmentValue ??
|
||||||
new Big(0)
|
new Big(0)
|
||||||
).add(investmentValue),
|
).add(investmentValueAccumulated),
|
||||||
totalInvestmentValueWithCurrencyEffect: (
|
totalInvestmentValueWithCurrencyEffect: (
|
||||||
accumulatedValuesByDate[dateString]
|
accumulatedValuesByDate[dateString]
|
||||||
?.totalInvestmentValueWithCurrencyEffect ?? new Big(0)
|
?.totalInvestmentValueWithCurrencyEffect ?? new Big(0)
|
||||||
).add(investmentValueWithCurrencyEffect),
|
).add(investmentValueAccumulatedWithCurrencyEffect),
|
||||||
totalNetPerformanceValue: (
|
totalNetPerformanceValue: (
|
||||||
accumulatedValuesByDate[dateString]?.totalNetPerformanceValue ??
|
accumulatedValuesByDate[dateString]?.totalNetPerformanceValue ??
|
||||||
new Big(0)
|
new Big(0)
|
||||||
@ -378,6 +394,7 @@ export class PortfolioCalculator {
|
|||||||
|
|
||||||
return Object.entries(accumulatedValuesByDate).map(([date, values]) => {
|
return Object.entries(accumulatedValuesByDate).map(([date, values]) => {
|
||||||
const {
|
const {
|
||||||
|
investmentValueWithCurrencyEffect,
|
||||||
totalCurrentValue,
|
totalCurrentValue,
|
||||||
totalCurrentValueWithCurrencyEffect,
|
totalCurrentValueWithCurrencyEffect,
|
||||||
totalInvestmentValue,
|
totalInvestmentValue,
|
||||||
@ -407,6 +424,8 @@ export class PortfolioCalculator {
|
|||||||
date,
|
date,
|
||||||
netPerformanceInPercentage,
|
netPerformanceInPercentage,
|
||||||
netPerformanceInPercentageWithCurrencyEffect,
|
netPerformanceInPercentageWithCurrencyEffect,
|
||||||
|
investmentValueWithCurrencyEffect:
|
||||||
|
investmentValueWithCurrencyEffect.toNumber(),
|
||||||
netPerformance: totalNetPerformanceValue.toNumber(),
|
netPerformance: totalNetPerformanceValue.toNumber(),
|
||||||
netPerformanceWithCurrencyEffect:
|
netPerformanceWithCurrencyEffect:
|
||||||
totalNetPerformanceValueWithCurrencyEffect.toNumber(),
|
totalNetPerformanceValueWithCurrencyEffect.toNumber(),
|
||||||
@ -671,95 +690,27 @@ export class PortfolioCalculator {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
public getInvestmentsByGroup(
|
public getInvestmentsByGroup({
|
||||||
groupBy: GroupBy
|
data,
|
||||||
): { date: string; investment: Big }[] {
|
groupBy
|
||||||
if (this.orders.length === 0) {
|
}: {
|
||||||
return [];
|
data: HistoricalDataItem[];
|
||||||
}
|
groupBy: GroupBy;
|
||||||
|
}): InvestmentItem[] {
|
||||||
|
const groupedData: { [dateGroup: string]: Big } = {};
|
||||||
|
|
||||||
const investments: { date: string; investment: Big }[] = [];
|
for (const { date, investmentValueWithCurrencyEffect } of data) {
|
||||||
let currentDate: Date;
|
const dateGroup =
|
||||||
let investmentByGroup = new Big(0);
|
groupBy === 'month' ? date.substring(0, 7) : date.substring(0, 4);
|
||||||
|
groupedData[dateGroup] = (groupedData[dateGroup] ?? new Big(0)).plus(
|
||||||
for (const [index, order] of this.orders.entries()) {
|
investmentValueWithCurrencyEffect
|
||||||
if (
|
|
||||||
isSameYear(parseDate(order.date), currentDate) &&
|
|
||||||
(groupBy === 'year' || isSameMonth(parseDate(order.date), currentDate))
|
|
||||||
) {
|
|
||||||
// Same group: Add up investments
|
|
||||||
investmentByGroup = investmentByGroup.plus(
|
|
||||||
order.quantity.mul(order.unitPrice).mul(this.getFactor(order.type))
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// New group: Store previous group and reset
|
|
||||||
if (currentDate) {
|
|
||||||
investments.push({
|
|
||||||
date: format(
|
|
||||||
set(currentDate, {
|
|
||||||
date: 1,
|
|
||||||
month: groupBy === 'year' ? 0 : currentDate.getMonth()
|
|
||||||
}),
|
|
||||||
DATE_FORMAT
|
|
||||||
),
|
|
||||||
investment: investmentByGroup
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
currentDate = parseDate(order.date);
|
|
||||||
investmentByGroup = order.quantity
|
|
||||||
.mul(order.unitPrice)
|
|
||||||
.mul(this.getFactor(order.type));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (index === this.orders.length - 1) {
|
|
||||||
// Store current group (latest order)
|
|
||||||
investments.push({
|
|
||||||
date: format(
|
|
||||||
set(currentDate, {
|
|
||||||
date: 1,
|
|
||||||
month: groupBy === 'year' ? 0 : currentDate.getMonth()
|
|
||||||
}),
|
|
||||||
DATE_FORMAT
|
|
||||||
),
|
|
||||||
investment: investmentByGroup
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Fill in the missing dates with investment = 0
|
|
||||||
const startDate = parseDate(first(this.orders).date);
|
|
||||||
const endDate = parseDate(last(this.orders).date);
|
|
||||||
|
|
||||||
const allDates: string[] = [];
|
|
||||||
currentDate = startDate;
|
|
||||||
|
|
||||||
while (currentDate <= endDate) {
|
|
||||||
allDates.push(
|
|
||||||
format(
|
|
||||||
set(currentDate, {
|
|
||||||
date: 1,
|
|
||||||
month: groupBy === 'year' ? 0 : currentDate.getMonth()
|
|
||||||
}),
|
|
||||||
DATE_FORMAT
|
|
||||||
)
|
|
||||||
);
|
);
|
||||||
currentDate.setMonth(currentDate.getMonth() + 1);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const date of allDates) {
|
return Object.keys(groupedData).map((dateGroup) => ({
|
||||||
const existingInvestment = investments.find((investment) => {
|
date: groupBy === 'month' ? `${dateGroup}-01` : `${dateGroup}-01-01`,
|
||||||
return investment.date === date;
|
investment: groupedData[dateGroup].toNumber()
|
||||||
});
|
}));
|
||||||
|
|
||||||
if (!existingInvestment) {
|
|
||||||
investments.push({ date, investment: new Big(0) });
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return sortBy(investments, ({ date }) => {
|
|
||||||
return date;
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private calculateOverallPerformance(positions: TimelinePosition[]) {
|
private calculateOverallPerformance(positions: TimelinePosition[]) {
|
||||||
@ -886,17 +837,6 @@ export class PortfolioCalculator {
|
|||||||
return factor;
|
return factor;
|
||||||
}
|
}
|
||||||
|
|
||||||
private addToDate(date: Date, accuracy: Accuracy): Date {
|
|
||||||
switch (accuracy) {
|
|
||||||
case 'day':
|
|
||||||
return addDays(date, 1);
|
|
||||||
case 'month':
|
|
||||||
return addMonths(date, 1);
|
|
||||||
case 'year':
|
|
||||||
return addYears(date, 1);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private getSymbolMetrics({
|
private getSymbolMetrics({
|
||||||
end,
|
end,
|
||||||
exchangeRates,
|
exchangeRates,
|
||||||
@ -933,7 +873,10 @@ export class PortfolioCalculator {
|
|||||||
let initialValueWithCurrencyEffect: Big;
|
let initialValueWithCurrencyEffect: Big;
|
||||||
let investmentAtStartDate: Big;
|
let investmentAtStartDate: Big;
|
||||||
let investmentAtStartDateWithCurrencyEffect: Big;
|
let investmentAtStartDateWithCurrencyEffect: Big;
|
||||||
const investmentValues: { [date: string]: Big } = {};
|
const investmentValuesAccumulated: { [date: string]: Big } = {};
|
||||||
|
const investmentValuesAccumulatedWithCurrencyEffect: {
|
||||||
|
[date: string]: Big;
|
||||||
|
} = {};
|
||||||
const investmentValuesWithCurrencyEffect: { [date: string]: Big } = {};
|
const investmentValuesWithCurrencyEffect: { [date: string]: Big } = {};
|
||||||
let lastAveragePrice = new Big(0);
|
let lastAveragePrice = new Big(0);
|
||||||
let lastAveragePriceWithCurrencyEffect = new Big(0);
|
let lastAveragePriceWithCurrencyEffect = new Big(0);
|
||||||
@ -975,7 +918,8 @@ export class PortfolioCalculator {
|
|||||||
hasErrors: false,
|
hasErrors: false,
|
||||||
initialValue: new Big(0),
|
initialValue: new Big(0),
|
||||||
initialValueWithCurrencyEffect: new Big(0),
|
initialValueWithCurrencyEffect: new Big(0),
|
||||||
investmentValues: {},
|
investmentValuesAccumulated: {},
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect: {},
|
||||||
investmentValuesWithCurrencyEffect: {},
|
investmentValuesWithCurrencyEffect: {},
|
||||||
netPerformance: new Big(0),
|
netPerformance: new Big(0),
|
||||||
netPerformancePercentage: new Big(0),
|
netPerformancePercentage: new Big(0),
|
||||||
@ -1014,7 +958,8 @@ export class PortfolioCalculator {
|
|||||||
hasErrors: true,
|
hasErrors: true,
|
||||||
initialValue: new Big(0),
|
initialValue: new Big(0),
|
||||||
initialValueWithCurrencyEffect: new Big(0),
|
initialValueWithCurrencyEffect: new Big(0),
|
||||||
investmentValues: {},
|
investmentValuesAccumulated: {},
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect: {},
|
||||||
investmentValuesWithCurrencyEffect: {},
|
investmentValuesWithCurrencyEffect: {},
|
||||||
netPerformance: new Big(0),
|
netPerformance: new Big(0),
|
||||||
netPerformancePercentage: new Big(0),
|
netPerformancePercentage: new Big(0),
|
||||||
@ -1407,11 +1352,15 @@ export class PortfolioCalculator {
|
|||||||
feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect)
|
feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect)
|
||||||
);
|
);
|
||||||
|
|
||||||
investmentValues[order.date] = totalInvestment;
|
investmentValuesAccumulated[order.date] = totalInvestment;
|
||||||
|
|
||||||
investmentValuesWithCurrencyEffect[order.date] =
|
investmentValuesAccumulatedWithCurrencyEffect[order.date] =
|
||||||
totalInvestmentWithCurrencyEffect;
|
totalInvestmentWithCurrencyEffect;
|
||||||
|
|
||||||
|
investmentValuesWithCurrencyEffect[order.date] = (
|
||||||
|
investmentValuesWithCurrencyEffect[order.date] ?? new Big(0)
|
||||||
|
).add(transactionInvestmentWithCurrencyEffect);
|
||||||
|
|
||||||
timeWeightedInvestmentValues[order.date] =
|
timeWeightedInvestmentValues[order.date] =
|
||||||
totalInvestmentDays > 0
|
totalInvestmentDays > 0
|
||||||
? sumOfTimeWeightedInvestments.div(totalInvestmentDays)
|
? sumOfTimeWeightedInvestments.div(totalInvestmentDays)
|
||||||
@ -1569,7 +1518,8 @@ export class PortfolioCalculator {
|
|||||||
grossPerformancePercentageWithCurrencyEffect,
|
grossPerformancePercentageWithCurrencyEffect,
|
||||||
initialValue,
|
initialValue,
|
||||||
initialValueWithCurrencyEffect,
|
initialValueWithCurrencyEffect,
|
||||||
investmentValues,
|
investmentValuesAccumulated,
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect,
|
||||||
investmentValuesWithCurrencyEffect,
|
investmentValuesWithCurrencyEffect,
|
||||||
netPerformancePercentage,
|
netPerformancePercentage,
|
||||||
netPerformancePercentageWithCurrencyEffect,
|
netPerformancePercentageWithCurrencyEffect,
|
||||||
@ -1591,15 +1541,4 @@ export class PortfolioCalculator {
|
|||||||
timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect
|
timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private isNextItemActive(
|
|
||||||
timelineSpecification: TimelineSpecification[],
|
|
||||||
currentDate: Date,
|
|
||||||
i: number
|
|
||||||
) {
|
|
||||||
return (
|
|
||||||
i + 1 < timelineSpecification.length &&
|
|
||||||
!isBefore(currentDate, parseDate(timelineSpecification[i + 1].start))
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -79,7 +79,7 @@ import {
|
|||||||
subDays,
|
subDays,
|
||||||
subYears
|
subYears
|
||||||
} from 'date-fns';
|
} from 'date-fns';
|
||||||
import { isEmpty, last, sortBy, uniq, uniqBy } from 'lodash';
|
import { isEmpty, last, uniq, uniqBy } from 'lodash';
|
||||||
|
|
||||||
import {
|
import {
|
||||||
HistoricalDataContainer,
|
HistoricalDataContainer,
|
||||||
@ -293,77 +293,32 @@ export class PortfolioService {
|
|||||||
|
|
||||||
portfolioCalculator.setTransactionPoints(transactionPoints);
|
portfolioCalculator.setTransactionPoints(transactionPoints);
|
||||||
|
|
||||||
|
const { items } = await this.getChart({
|
||||||
|
dateRange,
|
||||||
|
impersonationId,
|
||||||
|
portfolioOrders,
|
||||||
|
transactionPoints,
|
||||||
|
userId,
|
||||||
|
userCurrency: this.request.user.Settings.settings.baseCurrency,
|
||||||
|
withDataDecimation: false
|
||||||
|
});
|
||||||
|
|
||||||
let investments: InvestmentItem[];
|
let investments: InvestmentItem[];
|
||||||
|
|
||||||
if (groupBy) {
|
if (groupBy) {
|
||||||
investments = portfolioCalculator
|
investments = portfolioCalculator.getInvestmentsByGroup({
|
||||||
.getInvestmentsByGroup(groupBy)
|
groupBy,
|
||||||
.map((item) => {
|
data: items
|
||||||
return {
|
|
||||||
date: item.date,
|
|
||||||
investment: item.investment.toNumber()
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add investment of current group
|
|
||||||
const dateOfCurrentGroup = format(
|
|
||||||
set(new Date(), {
|
|
||||||
date: 1,
|
|
||||||
month: groupBy === 'year' ? 0 : new Date().getMonth()
|
|
||||||
}),
|
|
||||||
DATE_FORMAT
|
|
||||||
);
|
|
||||||
const investmentOfCurrentGroup = investments.filter(({ date }) => {
|
|
||||||
return date === dateOfCurrentGroup;
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (investmentOfCurrentGroup.length <= 0) {
|
|
||||||
investments.push({
|
|
||||||
date: dateOfCurrentGroup,
|
|
||||||
investment: 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
investments = portfolioCalculator
|
investments = items.map(({ date, investmentValueWithCurrencyEffect }) => {
|
||||||
.getInvestments()
|
return {
|
||||||
.map(({ date, investment }) => {
|
date,
|
||||||
return {
|
investment: investmentValueWithCurrencyEffect
|
||||||
date,
|
};
|
||||||
investment: investment.toNumber()
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
// Add investment of today
|
|
||||||
const investmentOfToday = investments.filter(({ date }) => {
|
|
||||||
return date === format(new Date(), DATE_FORMAT);
|
|
||||||
});
|
});
|
||||||
|
|
||||||
if (investmentOfToday.length <= 0) {
|
|
||||||
const pastInvestments = investments.filter(({ date }) => {
|
|
||||||
return isBefore(parseDate(date), new Date());
|
|
||||||
});
|
|
||||||
const lastInvestment = pastInvestments[pastInvestments.length - 1];
|
|
||||||
|
|
||||||
investments.push({
|
|
||||||
date: format(new Date(), DATE_FORMAT),
|
|
||||||
investment: lastInvestment?.investment ?? 0
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
investments = sortBy(investments, ({ date }) => {
|
|
||||||
return date;
|
|
||||||
});
|
|
||||||
|
|
||||||
const startDate = this.getStartDate(
|
|
||||||
dateRange,
|
|
||||||
parseDate(investments[0]?.date)
|
|
||||||
);
|
|
||||||
|
|
||||||
investments = investments.filter(({ date }) => {
|
|
||||||
return !isBefore(parseDate(date), startDate);
|
|
||||||
});
|
|
||||||
|
|
||||||
let streaks: PortfolioInvestments['streaks'];
|
let streaks: PortfolioInvestments['streaks'];
|
||||||
|
|
||||||
if (savingsRate) {
|
if (savingsRate) {
|
||||||
@ -1448,7 +1403,8 @@ export class PortfolioService {
|
|||||||
portfolioOrders,
|
portfolioOrders,
|
||||||
transactionPoints,
|
transactionPoints,
|
||||||
userCurrency,
|
userCurrency,
|
||||||
userId
|
userId,
|
||||||
|
withDataDecimation = true
|
||||||
}: {
|
}: {
|
||||||
dateRange?: DateRange;
|
dateRange?: DateRange;
|
||||||
impersonationId: string;
|
impersonationId: string;
|
||||||
@ -1456,6 +1412,7 @@ export class PortfolioService {
|
|||||||
transactionPoints: TransactionPoint[];
|
transactionPoints: TransactionPoint[];
|
||||||
userCurrency: string;
|
userCurrency: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
|
withDataDecimation?: boolean;
|
||||||
}): Promise<HistoricalDataContainer> {
|
}): Promise<HistoricalDataContainer> {
|
||||||
if (transactionPoints.length === 0) {
|
if (transactionPoints.length === 0) {
|
||||||
return {
|
return {
|
||||||
@ -1481,16 +1438,18 @@ export class PortfolioService {
|
|||||||
const portfolioStart = parseDate(transactionPoints[0].date);
|
const portfolioStart = parseDate(transactionPoints[0].date);
|
||||||
const startDate = this.getStartDate(dateRange, portfolioStart);
|
const startDate = this.getStartDate(dateRange, portfolioStart);
|
||||||
|
|
||||||
const daysInMarket = differenceInDays(new Date(), startDate);
|
let step = 1;
|
||||||
const step = Math.round(
|
|
||||||
daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS)
|
|
||||||
);
|
|
||||||
|
|
||||||
const items = await portfolioCalculator.getChartData(
|
if (withDataDecimation) {
|
||||||
startDate,
|
const daysInMarket = differenceInDays(new Date(), startDate);
|
||||||
endDate,
|
step = Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS));
|
||||||
step
|
}
|
||||||
);
|
|
||||||
|
const items = await portfolioCalculator.getChartData({
|
||||||
|
step,
|
||||||
|
end: endDate,
|
||||||
|
start: startDate
|
||||||
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
items,
|
items,
|
||||||
|
@ -2,6 +2,7 @@ export interface HistoricalDataItem {
|
|||||||
averagePrice?: number;
|
averagePrice?: number;
|
||||||
date: string;
|
date: string;
|
||||||
grossPerformancePercent?: number;
|
grossPerformancePercent?: number;
|
||||||
|
investmentValueWithCurrencyEffect?: number;
|
||||||
marketPrice?: number;
|
marketPrice?: number;
|
||||||
netPerformance?: number;
|
netPerformance?: number;
|
||||||
netPerformanceInPercentage?: number;
|
netPerformanceInPercentage?: number;
|
||||||
|
@ -19,6 +19,7 @@ import type { FilterGroup } from './filter-group.interface';
|
|||||||
import type { Filter } from './filter.interface';
|
import type { Filter } from './filter.interface';
|
||||||
import type { HistoricalDataItem } from './historical-data-item.interface';
|
import type { HistoricalDataItem } from './historical-data-item.interface';
|
||||||
import type { InfoItem } from './info-item.interface';
|
import type { InfoItem } from './info-item.interface';
|
||||||
|
import type { InvestmentItem } from './investment-item.interface';
|
||||||
import type { LineChartItem } from './line-chart-item.interface';
|
import type { LineChartItem } from './line-chart-item.interface';
|
||||||
import type { PortfolioChart } from './portfolio-chart.interface';
|
import type { PortfolioChart } from './portfolio-chart.interface';
|
||||||
import type { PortfolioDetails } from './portfolio-details.interface';
|
import type { PortfolioDetails } from './portfolio-details.interface';
|
||||||
@ -74,6 +75,7 @@ export {
|
|||||||
HistoricalDataItem,
|
HistoricalDataItem,
|
||||||
ImportResponse,
|
ImportResponse,
|
||||||
InfoItem,
|
InfoItem,
|
||||||
|
InvestmentItem,
|
||||||
LineChartItem,
|
LineChartItem,
|
||||||
OAuthResponse,
|
OAuthResponse,
|
||||||
PortfolioChart,
|
PortfolioChart,
|
||||||
|
@ -14,7 +14,10 @@ export interface SymbolMetrics {
|
|||||||
hasErrors: boolean;
|
hasErrors: boolean;
|
||||||
initialValue: Big;
|
initialValue: Big;
|
||||||
initialValueWithCurrencyEffect: Big;
|
initialValueWithCurrencyEffect: Big;
|
||||||
investmentValues: {
|
investmentValuesAccumulated: {
|
||||||
|
[date: string]: Big;
|
||||||
|
};
|
||||||
|
investmentValuesAccumulatedWithCurrencyEffect: {
|
||||||
[date: string]: Big;
|
[date: string]: Big;
|
||||||
};
|
};
|
||||||
investmentValuesWithCurrencyEffect: {
|
investmentValuesWithCurrencyEffect: {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user