Feature/rework portfolio calculator (#3393)
* Rework portfolio calculation * Update changelog --------- Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>
This commit is contained in:
@@ -36,48 +36,36 @@ export function getIntervalFromDateRange(
|
||||
aDateRange: DateRange,
|
||||
portfolioStart = new Date(0)
|
||||
) {
|
||||
let endDate = endOfDay(new Date(Date.now()));
|
||||
let endDate = endOfDay(new Date());
|
||||
let startDate = portfolioStart;
|
||||
|
||||
switch (aDateRange) {
|
||||
case '1d':
|
||||
startDate = max([
|
||||
startDate,
|
||||
subDays(resetHours(new Date(Date.now())), 1)
|
||||
]);
|
||||
startDate = max([startDate, subDays(resetHours(new Date()), 1)]);
|
||||
break;
|
||||
case 'mtd':
|
||||
startDate = max([
|
||||
startDate,
|
||||
subDays(startOfMonth(resetHours(new Date(Date.now()))), 1)
|
||||
subDays(startOfMonth(resetHours(new Date())), 1)
|
||||
]);
|
||||
break;
|
||||
case 'wtd':
|
||||
startDate = max([
|
||||
startDate,
|
||||
subDays(
|
||||
startOfWeek(resetHours(new Date(Date.now())), { weekStartsOn: 1 }),
|
||||
1
|
||||
)
|
||||
subDays(startOfWeek(resetHours(new Date()), { weekStartsOn: 1 }), 1)
|
||||
]);
|
||||
break;
|
||||
case 'ytd':
|
||||
startDate = max([
|
||||
startDate,
|
||||
subDays(startOfYear(resetHours(new Date(Date.now()))), 1)
|
||||
subDays(startOfYear(resetHours(new Date())), 1)
|
||||
]);
|
||||
break;
|
||||
case '1y':
|
||||
startDate = max([
|
||||
startDate,
|
||||
subYears(resetHours(new Date(Date.now())), 1)
|
||||
]);
|
||||
startDate = max([startDate, subYears(resetHours(new Date()), 1)]);
|
||||
break;
|
||||
case '5y':
|
||||
startDate = max([
|
||||
startDate,
|
||||
subYears(resetHours(new Date(Date.now())), 5)
|
||||
]);
|
||||
startDate = max([startDate, subYears(resetHours(new Date()), 5)]);
|
||||
break;
|
||||
case 'max':
|
||||
break;
|
||||
|
@@ -1,5 +1,21 @@
|
||||
import { Big } from 'big.js';
|
||||
|
||||
export function transformToMapOfBig({
|
||||
value
|
||||
}: {
|
||||
value: { [key: string]: string };
|
||||
}): {
|
||||
[key: string]: Big;
|
||||
} {
|
||||
const mapOfBig: { [key: string]: Big } = {};
|
||||
|
||||
for (const key in value) {
|
||||
mapOfBig[key] = new Big(value[key]);
|
||||
}
|
||||
|
||||
return mapOfBig;
|
||||
}
|
||||
|
||||
export function transformToBig({ value }: { value: string }): Big {
|
||||
if (value === null) {
|
||||
return null;
|
||||
|
@@ -2,10 +2,6 @@ export interface PortfolioPerformance {
|
||||
annualizedPerformancePercent?: number;
|
||||
currentNetWorth?: number;
|
||||
currentValueInBaseCurrency: number;
|
||||
grossPerformance: number;
|
||||
grossPerformancePercentage: number;
|
||||
grossPerformancePercentageWithCurrencyEffect: number;
|
||||
grossPerformanceWithCurrencyEffect: number;
|
||||
netPerformance: number;
|
||||
netPerformancePercentage: number;
|
||||
netPerformancePercentageWithCurrencyEffect: number;
|
||||
|
@@ -1,6 +1,7 @@
|
||||
import { Market, MarketAdvanced } from '@ghostfolio/common/types';
|
||||
|
||||
import { AssetClass, AssetSubClass, DataSource, Tag } from '@prisma/client';
|
||||
|
||||
import { Market, MarketAdvanced, MarketState } from '../types';
|
||||
import { Country } from './country.interface';
|
||||
import { Holding } from './holding.interface';
|
||||
import { Sector } from './sector.interface';
|
||||
@@ -28,7 +29,6 @@ export interface PortfolioPosition {
|
||||
marketPrice: number;
|
||||
markets?: { [key in Market]: number };
|
||||
marketsAdvanced?: { [key in MarketAdvanced]: number };
|
||||
marketState: MarketState;
|
||||
name: string;
|
||||
netPerformance: number;
|
||||
netPerformancePercent: number;
|
||||
|
@@ -17,6 +17,8 @@ export interface PortfolioSummary extends PortfolioPerformance {
|
||||
filteredValueInPercentage?: number;
|
||||
fireWealth: number;
|
||||
firstOrderDate: Date;
|
||||
grossPerformance: number;
|
||||
grossPerformanceWithCurrencyEffect: number;
|
||||
interest: number;
|
||||
items: number;
|
||||
liabilities: number;
|
||||
|
@@ -1,3 +1,5 @@
|
||||
import { DateRange } from '@ghostfolio/common/types';
|
||||
|
||||
import { Big } from 'big.js';
|
||||
|
||||
export interface SymbolMetrics {
|
||||
@@ -26,12 +28,12 @@ export interface SymbolMetrics {
|
||||
};
|
||||
netPerformance: Big;
|
||||
netPerformancePercentage: Big;
|
||||
netPerformancePercentageWithCurrencyEffect: Big;
|
||||
netPerformancePercentageWithCurrencyEffectMap: { [key: DateRange]: Big };
|
||||
netPerformanceValues: {
|
||||
[date: string]: Big;
|
||||
};
|
||||
netPerformanceValuesWithCurrencyEffect: { [date: string]: Big };
|
||||
netPerformanceWithCurrencyEffect: Big;
|
||||
netPerformanceWithCurrencyEffectMap: { [key: DateRange]: Big };
|
||||
timeWeightedInvestment: Big;
|
||||
timeWeightedInvestmentValues: {
|
||||
[date: string]: Big;
|
||||
|
@@ -1,5 +1,8 @@
|
||||
import { transformToBig } from '@ghostfolio/common/class-transformer';
|
||||
import { AssetProfileIdentifier } from '@ghostfolio/common/interfaces';
|
||||
import {
|
||||
AssetProfileIdentifier,
|
||||
HistoricalDataItem
|
||||
} from '@ghostfolio/common/interfaces';
|
||||
import { TimelinePosition } from '@ghostfolio/common/models';
|
||||
|
||||
import { Big } from 'big.js';
|
||||
@@ -9,49 +12,12 @@ export class PortfolioSnapshot {
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
currentValueInBaseCurrency: Big;
|
||||
|
||||
errors?: AssetProfileIdentifier[];
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
grossPerformance: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
grossPerformanceWithCurrencyEffect: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
grossPerformancePercentage: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
grossPerformancePercentageWithCurrencyEffect: Big;
|
||||
|
||||
hasErrors: boolean;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netAnnualizedPerformance?: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netAnnualizedPerformanceWithCurrencyEffect?: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netPerformance: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netPerformanceWithCurrencyEffect: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netPerformancePercentage: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netPerformancePercentageWithCurrencyEffect: Big;
|
||||
historicalData: HistoricalDataItem[];
|
||||
|
||||
@Type(() => TimelinePosition)
|
||||
positions: TimelinePosition[];
|
||||
|
@@ -1,4 +1,8 @@
|
||||
import { transformToBig } from '@ghostfolio/common/class-transformer';
|
||||
import {
|
||||
transformToBig,
|
||||
transformToMapOfBig
|
||||
} from '@ghostfolio/common/class-transformer';
|
||||
import { DateRange } from '@ghostfolio/common/types';
|
||||
|
||||
import { DataSource, Tag } from '@prisma/client';
|
||||
import { Big } from 'big.js';
|
||||
@@ -65,13 +69,11 @@ export class TimelinePosition {
|
||||
@Type(() => Big)
|
||||
netPerformancePercentage: Big;
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netPerformancePercentageWithCurrencyEffect: Big;
|
||||
@Transform(transformToMapOfBig, { toClassOnly: true })
|
||||
netPerformancePercentageWithCurrencyEffectMap: { [key: DateRange]: Big };
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
netPerformanceWithCurrencyEffect: Big;
|
||||
@Transform(transformToMapOfBig, { toClassOnly: true })
|
||||
netPerformanceWithCurrencyEffectMap: { [key: DateRange]: Big };
|
||||
|
||||
@Transform(transformToBig, { toClassOnly: true })
|
||||
@Type(() => Big)
|
||||
|
Reference in New Issue
Block a user