Browse Source

Clean up

pull/3393/head
Thomas Kaul 1 year ago
parent
commit
50d8dc3851
  1. 2
      apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts
  2. 15
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  3. 155
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts
  4. 3
      apps/api/src/services/configuration/configuration.service.ts
  5. 2
      libs/common/src/lib/interfaces/symbol-metrics.interface.ts

2
apps/api/src/app/portfolio/calculator/mwr/portfolio-calculator.ts

@ -16,7 +16,6 @@ export class MWRPortfolioCalculator extends PortfolioCalculator {
dataSource,
end,
exchangeRates,
isChartMode = false,
marketSymbolMap,
start,
step = 1,
@ -24,7 +23,6 @@ export class MWRPortfolioCalculator extends PortfolioCalculator {
}: {
end: Date;
exchangeRates: { [dateString: string]: number };
isChartMode?: boolean;
marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
};

15
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -320,11 +320,9 @@ export abstract class PortfolioCalculator {
investmentValuesWithCurrencyEffect,
netPerformance,
netPerformancePercentage,
netPerformancePercentageWithCurrencyEffect,
netPerformancePercentageWithCurrencyEffectMap,
netPerformanceValues,
netPerformanceValuesWithCurrencyEffect,
netPerformanceWithCurrencyEffect,
netPerformanceWithCurrencyEffectMap,
timeWeightedInvestment,
timeWeightedInvestmentValues,
@ -344,7 +342,6 @@ export abstract class PortfolioCalculator {
end: this.endDate,
exchangeRates:
exchangeRatesByCurrency[`${item.currency}${this.currency}`],
isChartMode: true,
start: this.startDate,
symbol: item.symbol
});
@ -673,11 +670,10 @@ export abstract class PortfolioCalculator {
const { historicalData } = this.snapshot;
const newChartData: HistoricalDataItem[] = [];
const chart: HistoricalDataItem[] = [];
let netPerformanceAtStartDate: number;
let netPerformanceWithCurrencyEffectAtStartDate: number;
let netPerformanceInPercentageWithCurrencyEffectAtStartDate: number;
let totalInvestmentValuesWithCurrencyEffect: number[] = [];
for (let historicalDataItem of historicalData) {
@ -689,9 +685,6 @@ export abstract class PortfolioCalculator {
netPerformanceWithCurrencyEffectAtStartDate =
historicalDataItem.netPerformanceWithCurrencyEffect;
netPerformanceInPercentageWithCurrencyEffectAtStartDate =
historicalDataItem.netPerformanceInPercentageWithCurrencyEffect;
}
const netPerformanceSinceStartDate =
@ -713,7 +706,7 @@ export abstract class PortfolioCalculator {
totalInvestmentValuesWithCurrencyEffect.length
: 0;
newChartData.push({
chart.push({
...historicalDataItem,
netPerformance:
historicalDataItem.netPerformance - netPerformanceAtStartDate,
@ -733,7 +726,7 @@ export abstract class PortfolioCalculator {
}
}
return { chart: newChartData };
return { chart };
}
public getStartDate() {
@ -768,7 +761,6 @@ export abstract class PortfolioCalculator {
dataSource,
end,
exchangeRates,
isChartMode,
marketSymbolMap,
start,
symbol
@ -776,7 +768,6 @@ export abstract class PortfolioCalculator {
chartDateMap: { [date: string]: boolean };
end: Date;
exchangeRates: { [dateString: string]: number };
isChartMode?: boolean;
marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
};

155
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts

@ -31,7 +31,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let grossPerformanceWithCurrencyEffect = new Big(0);
let hasErrors = false;
let netPerformance = new Big(0);
let netPerformanceWithCurrencyEffect = new Big(0);
let totalFeesWithCurrencyEffect = new Big(0);
let totalInterestWithCurrencyEffect = new Big(0);
let totalInvestment = new Big(0);
@ -76,11 +75,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
);
netPerformance = netPerformance.plus(currentPosition.netPerformance);
netPerformanceWithCurrencyEffect =
netPerformanceWithCurrencyEffect.plus(
currentPosition.netPerformancePercentageWithCurrencyEffectMap['max']
);
} else if (!currentPosition.quantity.eq(0)) {
hasErrors = true;
}
@ -123,7 +117,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
dataSource,
end,
exchangeRates,
isChartMode = false,
marketSymbolMap,
start,
symbol
@ -131,7 +124,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
chartDateMap?: { [date: string]: boolean };
end: Date;
exchangeRates: { [dateString: string]: number };
isChartMode?: boolean;
marketSymbolMap: {
[date: string]: { [symbol: string]: Big };
};
@ -211,11 +203,9 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
investmentValuesWithCurrencyEffect: {},
netPerformance: new Big(0),
netPerformancePercentage: new Big(0),
netPerformancePercentageWithCurrencyEffect: new Big(0),
netPerformancePercentageWithCurrencyEffectMap: {},
netPerformanceValues: {},
netPerformanceValuesWithCurrencyEffect: {},
netPerformanceWithCurrencyEffect: new Big(0),
netPerformanceWithCurrencyEffectMap: {},
timeWeightedInvestment: new Big(0),
timeWeightedInvestmentValues: {},
@ -263,12 +253,10 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
investmentValuesWithCurrencyEffect: {},
netPerformance: new Big(0),
netPerformancePercentage: new Big(0),
netPerformancePercentageWithCurrencyEffect: new Big(0),
netPerformancePercentageWithCurrencyEffectMap: {},
netPerformanceWithCurrencyEffectMap: {},
netPerformanceValues: {},
netPerformanceValuesWithCurrencyEffect: {},
netPerformanceWithCurrencyEffect: new Big(0),
timeWeightedInvestment: new Big(0),
timeWeightedInvestmentValues: {},
timeWeightedInvestmentValuesWithCurrencyEffect: {},
@ -319,46 +307,43 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let day = start;
let lastUnitPrice: Big;
if (isChartMode) {
const ordersByDate: { [date: string]: PortfolioOrderItem[] } = {};
const ordersByDate: { [date: string]: PortfolioOrderItem[] } = {};
for (const order of orders) {
ordersByDate[order.date] = ordersByDate[order.date] ?? [];
ordersByDate[order.date].push(order);
}
for (const order of orders) {
ordersByDate[order.date] = ordersByDate[order.date] ?? [];
ordersByDate[order.date].push(order);
}
while (isBefore(day, end)) {
const dateString = format(day, DATE_FORMAT);
while (isBefore(day, end)) {
const dateString = format(day, DATE_FORMAT);
if (ordersByDate[dateString]?.length > 0) {
for (let order of ordersByDate[dateString]) {
order.unitPriceFromMarketData =
marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice;
}
} else if (chartDateMap[dateString]) {
orders.push({
date: dateString,
fee: new Big(0),
feeInBaseCurrency: new Big(0),
quantity: new Big(0),
SymbolProfile: {
dataSource,
symbol
},
type: 'BUY',
unitPrice: marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice,
unitPriceFromMarketData:
marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice
});
if (ordersByDate[dateString]?.length > 0) {
for (let order of ordersByDate[dateString]) {
order.unitPriceFromMarketData =
marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice;
}
} else if (chartDateMap[dateString]) {
orders.push({
date: dateString,
fee: new Big(0),
feeInBaseCurrency: new Big(0),
quantity: new Big(0),
SymbolProfile: {
dataSource,
symbol
},
type: 'BUY',
unitPrice: marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice,
unitPriceFromMarketData:
marketSymbolMap[dateString]?.[symbol] ?? lastUnitPrice
});
}
const lastOrder = last(orders);
const lastOrder = last(orders);
lastUnitPrice =
lastOrder.unitPriceFromMarketData ?? lastOrder.unitPrice;
lastUnitPrice = lastOrder.unitPriceFromMarketData ?? lastOrder.unitPrice;
day = addDays(day, 1);
}
day = addDays(day, 1);
}
// Sort orders so that the start and end placeholder order are at the correct
@ -681,44 +666,42 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
);
}
if (isChartMode) {
currentValues[order.date] = valueOfInvestment;
currentValues[order.date] = valueOfInvestment;
currentValuesWithCurrencyEffect[order.date] =
valueOfInvestmentWithCurrencyEffect;
currentValuesWithCurrencyEffect[order.date] =
valueOfInvestmentWithCurrencyEffect;
netPerformanceValues[order.date] = grossPerformance
.minus(grossPerformanceAtStartDate)
.minus(fees.minus(feesAtStartDate));
netPerformanceValues[order.date] = grossPerformance
.minus(grossPerformanceAtStartDate)
.minus(fees.minus(feesAtStartDate));
netPerformanceValuesWithCurrencyEffect[order.date] =
grossPerformanceWithCurrencyEffect
.minus(grossPerformanceAtStartDateWithCurrencyEffect)
.minus(
feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect)
);
netPerformanceValuesWithCurrencyEffect[order.date] =
grossPerformanceWithCurrencyEffect
.minus(grossPerformanceAtStartDateWithCurrencyEffect)
.minus(
feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect)
);
investmentValuesAccumulated[order.date] = totalInvestment;
investmentValuesAccumulated[order.date] = totalInvestment;
investmentValuesAccumulatedWithCurrencyEffect[order.date] =
totalInvestmentWithCurrencyEffect;
investmentValuesAccumulatedWithCurrencyEffect[order.date] =
totalInvestmentWithCurrencyEffect;
investmentValuesWithCurrencyEffect[order.date] = (
investmentValuesWithCurrencyEffect[order.date] ?? new Big(0)
).add(transactionInvestmentWithCurrencyEffect);
investmentValuesWithCurrencyEffect[order.date] = (
investmentValuesWithCurrencyEffect[order.date] ?? new Big(0)
).add(transactionInvestmentWithCurrencyEffect);
timeWeightedInvestmentValues[order.date] =
totalInvestmentDays > 0
? sumOfTimeWeightedInvestments.div(totalInvestmentDays)
: new Big(0);
timeWeightedInvestmentValues[order.date] =
totalInvestmentDays > 0
? sumOfTimeWeightedInvestments.div(totalInvestmentDays)
: new Big(0);
timeWeightedInvestmentValuesWithCurrencyEffect[order.date] =
totalInvestmentDays > 0
? sumOfTimeWeightedInvestmentsWithCurrencyEffect.div(
totalInvestmentDays
)
: new Big(0);
}
timeWeightedInvestmentValuesWithCurrencyEffect[order.date] =
totalInvestmentDays > 0
? sumOfTimeWeightedInvestmentsWithCurrencyEffect.div(
totalInvestmentDays
)
: new Big(0);
}
if (PortfolioCalculator.ENABLE_LOGGING) {
@ -760,11 +743,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
.minus(grossPerformanceAtStartDate)
.minus(fees.minus(feesAtStartDate));
const totalNetPerformanceWithCurrencyEffect =
grossPerformanceWithCurrencyEffect
.minus(grossPerformanceAtStartDateWithCurrencyEffect)
.minus(feesWithCurrencyEffect.minus(feesAtStartDateWithCurrencyEffect));
const timeWeightedAverageInvestmentBetweenStartAndEndDate =
totalInvestmentDays > 0
? sumOfTimeWeightedInvestments.div(totalInvestmentDays)
@ -810,15 +788,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
)
: new Big(0);
const netPerformancePercentageWithCurrencyEffect =
timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect.gt(
0
)
? totalNetPerformanceWithCurrencyEffect.div(
timeWeightedAverageInvestmentBetweenStartAndEndDateWithCurrencyEffect
)
: new Big(0);
const netPerformancePercentageWithCurrencyEffectMap: {
[key: DateRange]: Big;
} = {};
@ -946,9 +915,9 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
Net performance: ${totalNetPerformance.toFixed(
2
)} / ${netPerformancePercentage.mul(100).toFixed(2)}%
Net performance with currency effect: ${totalNetPerformanceWithCurrencyEffect.toFixed(
2
)} / ${netPerformancePercentageWithCurrencyEffect.mul(100).toFixed(2)}%`
Net performance with currency effect: ${netPerformancePercentageWithCurrencyEffectMap[
'max'
].toFixed(2)}%`
);
}
@ -964,7 +933,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
investmentValuesAccumulatedWithCurrencyEffect,
investmentValuesWithCurrencyEffect,
netPerformancePercentage,
netPerformancePercentageWithCurrencyEffect,
netPerformancePercentageWithCurrencyEffectMap,
netPerformanceValues,
netPerformanceValuesWithCurrencyEffect,
@ -987,7 +955,6 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
totalGrossPerformanceWithCurrencyEffect,
hasErrors: totalUnits.gt(0) && (!initialValue || !unitPriceAtEndDate),
netPerformance: totalNetPerformance,
netPerformanceWithCurrencyEffect: totalNetPerformanceWithCurrencyEffect,
timeWeightedInvestment:
timeWeightedAverageInvestmentBetweenStartAndEndDate,
timeWeightedInvestmentWithCurrencyEffect:

3
apps/api/src/services/configuration/configuration.service.ts

@ -4,6 +4,7 @@ import { DEFAULT_ROOT_URL } from '@ghostfolio/common/config';
import { Injectable } from '@nestjs/common';
import { DataSource } from '@prisma/client';
import { bool, cleanEnv, host, json, num, port, str, url } from 'envalid';
import ms from 'ms';
@Injectable()
export class ConfigurationService {
@ -20,7 +21,7 @@ export class ConfigurationService {
API_KEY_FINANCIAL_MODELING_PREP: str({ default: '' }),
API_KEY_OPEN_FIGI: str({ default: '' }),
API_KEY_RAPID_API: str({ default: '' }),
CACHE_QUOTES_TTL: num({ default: 60 }),
CACHE_QUOTES_TTL: num({ default: ms('1 minute') / 1000 }),
CACHE_TTL: num({ default: 1 }),
DATA_SOURCE_EXCHANGE_RATES: str({ default: DataSource.YAHOO }),
DATA_SOURCE_IMPORT: str({ default: DataSource.YAHOO }),

2
libs/common/src/lib/interfaces/symbol-metrics.interface.ts

@ -28,13 +28,11 @@ 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: {

Loading…
Cancel
Save