Browse Source

Merge pull request #6 from gizmodus/feature/various-fixes

Various fixes:
pull/3393/head
gizmodus 1 year ago
committed by GitHub
parent
commit
f7d5c6bf8e
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 51
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  2. 14
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts
  3. 15
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts
  4. 13
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts

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

@ -36,7 +36,7 @@ import {
min, min,
subDays subDays
} from 'date-fns'; } from 'date-fns';
import { first, last, sortBy, sum, uniq, uniqBy } from 'lodash'; import { first, isNumber, last, sortBy, sum, uniq, uniqBy } from 'lodash';
export abstract class PortfolioCalculator { export abstract class PortfolioCalculator {
protected static readonly ENABLE_LOGGING = false; protected static readonly ENABLE_LOGGING = false;
@ -144,24 +144,11 @@ export abstract class PortfolioCalculator {
positions: TimelinePosition[] positions: TimelinePosition[]
): PortfolioSnapshot; ): PortfolioSnapshot;
private async computeSnapshot( private async computeSnapshot(): Promise<PortfolioSnapshot> {
start: Date,
end?: Date
): Promise<PortfolioSnapshot> {
const lastTransactionPoint = last(this.transactionPoints); const lastTransactionPoint = last(this.transactionPoints);
let endDate = end;
if (!endDate) {
endDate = new Date();
if (lastTransactionPoint) {
endDate = max([endDate, parseDate(lastTransactionPoint.date)]);
}
}
const transactionPoints = this.transactionPoints?.filter(({ date }) => { const transactionPoints = this.transactionPoints?.filter(({ date }) => {
return isBefore(parseDate(date), endDate); return isBefore(parseDate(date), this.endDate);
}); });
if (!transactionPoints.length) { if (!transactionPoints.length) {
@ -208,7 +195,7 @@ export abstract class PortfolioCalculator {
for (let i = 0; i < transactionPoints.length; i++) { for (let i = 0; i < transactionPoints.length; i++) {
if ( if (
!isBefore(parseDate(transactionPoints[i].date), start) && !isBefore(parseDate(transactionPoints[i].date), this.startDate) &&
firstTransactionPoint === null firstTransactionPoint === null
) { ) {
firstTransactionPoint = transactionPoints[i]; firstTransactionPoint = transactionPoints[i];
@ -219,8 +206,8 @@ export abstract class PortfolioCalculator {
let exchangeRatesByCurrency = let exchangeRatesByCurrency =
await this.exchangeRateDataService.getExchangeRatesByCurrency({ await this.exchangeRateDataService.getExchangeRatesByCurrency({
currencies: uniq(Object.values(currencies)), currencies: uniq(Object.values(currencies)),
endDate: endOfDay(endDate), endDate: endOfDay(this.endDate),
startDate: this.getStartDate(), startDate: this.startDate,
targetCurrency: this.currency targetCurrency: this.currency
}); });
@ -231,8 +218,8 @@ export abstract class PortfolioCalculator {
} = await this.currentRateService.getValues({ } = await this.currentRateService.getValues({
dataGatheringItems, dataGatheringItems,
dateQuery: { dateQuery: {
gte: this.getStartDate(), gte: this.startDate,
lt: endDate lt: this.endDate
} }
}); });
@ -256,14 +243,13 @@ export abstract class PortfolioCalculator {
} }
} }
const endDateString = format(endDate, DATE_FORMAT); const endDateString = format(this.endDate, DATE_FORMAT);
const chartStartDate = this.getStartDate(); const daysInMarket = differenceInDays(this.endDate, this.startDate);
const daysInMarket = differenceInDays(endDate, chartStartDate) + 1;
let chartDateMap = this.getChartDateMap({ let chartDateMap = this.getChartDateMap({
endDate, endDate: this.endDate,
startDate: chartStartDate, startDate: this.startDate,
step: Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS)) step: Math.round(daysInMarket / Math.min(daysInMarket, MAX_CHART_ITEMS))
}); });
@ -357,12 +343,12 @@ export abstract class PortfolioCalculator {
} = this.getSymbolMetrics({ } = this.getSymbolMetrics({
chartDateMap, chartDateMap,
marketSymbolMap, marketSymbolMap,
start,
dataSource: item.dataSource, dataSource: item.dataSource,
end: endDate, end: this.endDate,
exchangeRates: exchangeRates:
exchangeRatesByCurrency[`${item.currency}${this.currency}`], exchangeRatesByCurrency[`${item.currency}${this.currency}`],
isChartMode: true, isChartMode: true,
start: this.startDate,
symbol: item.symbol symbol: item.symbol
}); });
@ -710,7 +696,7 @@ export abstract class PortfolioCalculator {
!isBefore(parseDate(historicalDataItem.date), subDays(start, 1)) && !isBefore(parseDate(historicalDataItem.date), subDays(start, 1)) &&
!isAfter(parseDate(historicalDataItem.date), end) !isAfter(parseDate(historicalDataItem.date), end)
) { ) {
if (!netPerformanceAtStartDate) { if (!isNumber(netPerformanceAtStartDate)) {
netPerformanceAtStartDate = historicalDataItem.netPerformance; netPerformanceAtStartDate = historicalDataItem.netPerformance;
netPerformanceWithCurrencyEffectAtStartDate = netPerformanceWithCurrencyEffectAtStartDate =
@ -1039,10 +1025,7 @@ export abstract class PortfolioCalculator {
'PortfolioCalculator' 'PortfolioCalculator'
); );
} else { } else {
this.snapshot = await this.computeSnapshot( this.snapshot = await this.computeSnapshot();
this.startDate,
this.endDate
);
this.redisCacheService.set( this.redisCacheService.set(
this.redisCacheService.getPortfolioSnapshotKey({ this.redisCacheService.getPortfolioSnapshotKey({
@ -1061,7 +1044,7 @@ export abstract class PortfolioCalculator {
); );
} }
} else { } else {
this.snapshot = await this.computeSnapshot(this.startDate, this.endDate); this.snapshot = await this.computeSnapshot();
} }
} }
} }

14
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts

@ -149,13 +149,13 @@ describe('PortfolioCalculator', () => {
}, },
netPerformanceWithCurrencyEffect: new Big('23.05'), netPerformanceWithCurrencyEffect: new Big('23.05'),
netPerformanceWithCurrencyEffectMap: { netPerformanceWithCurrencyEffectMap: {
'1d': new Big('8.45'), // wrong '1d': new Big('10.00'), // 2 * (148.9 - 143.9) -> no fees in this time period
'1y': new Big('23.05'), // wrong '1y': new Big('23.05'), // 2 * (148.9 - 136.6) - 1.55
'5y': new Big('23.05'), // wrong '5y': new Big('23.05'), // 2 * (148.9 - 136.6) - 1.55
max: new Big('23.05'), // ok: 2 * (148.9 - 136.6) - 1.55 max: new Big('23.05'), // 2 * (148.9 - 136.6) - 1.55
mtd: new Big('23.05'), // wrong mtd: new Big('24.60'), // 2 * (148.9 - 136.6) -> no fees in this time period
wtd: new Big('12.25'), // wrong: 2 * (148.9 - 142) - 1.55 wtd: new Big('13.80'), // 2 * (148.9 - 142.0) -> no fees in this time period
ytd: new Big('23.05') // wrong ytd: new Big('23.05') // 2 * (148.9 - 136.6) - 1.55
}, },
marketPrice: 148.9, marketPrice: 148.9,
marketPriceInBaseCurrency: 148.9, marketPriceInBaseCurrency: 148.9,

15
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts

@ -120,6 +120,21 @@ describe('PortfolioCalculator', () => {
}); });
expect(portfolioSnapshot.historicalData[0]).toEqual({ expect(portfolioSnapshot.historicalData[0]).toEqual({
date: '2022-03-06',
investmentValueWithCurrencyEffect: 0,
netPerformance: 0,
netPerformanceInPercentage: 0,
netPerformanceInPercentageWithCurrencyEffect: 0,
netPerformanceWithCurrencyEffect: 0,
netWorth: 0,
totalAccountBalance: 0,
totalInvestment: 0,
totalInvestmentValueWithCurrencyEffect: 0,
value: 0,
valueWithCurrencyEffect: 0
});
expect(portfolioSnapshot.historicalData[1]).toEqual({
date: '2022-03-07', date: '2022-03-07',
investmentValueWithCurrencyEffect: 151.6, investmentValueWithCurrencyEffect: 151.6,
netPerformance: 0, netPerformance: 0,

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

@ -857,7 +857,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
'mtd', 'mtd',
'wtd', 'wtd',
'ytd' 'ytd'
// TODO // TODO:
// ...eachYearOfInterval({ end, start }) // ...eachYearOfInterval({ end, start })
// .filter((date) => { // .filter((date) => {
// return !isThisYear(date); // return !isThisYear(date);
@ -870,10 +870,10 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let { endDate, startDate } = getIntervalFromDateRange(dateRange); let { endDate, startDate } = getIntervalFromDateRange(dateRange);
if (isBefore(startDate, start)) { if (isBefore(startDate, start)) {
startDate = addDays(start, 1); startDate = start;
} }
const currentValuesAtStartDateWithCurrencyEffect = const currentValuesAtDateRangeStartWithCurrencyEffect =
currentValuesWithCurrencyEffect[format(startDate, DATE_FORMAT)] ?? currentValuesWithCurrencyEffect[format(startDate, DATE_FORMAT)] ??
new Big(0); new Big(0);
@ -882,9 +882,8 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
format(startDate, DATE_FORMAT) format(startDate, DATE_FORMAT)
] ?? new Big(0); ] ?? new Big(0);
// TODO: Rename? const grossPerformanceAtDateRangeStartWithCurrencyEffect =
const grossPerformanceAtStartDateWithCurrencyEffect2 = currentValuesAtDateRangeStartWithCurrencyEffect.minus(
currentValuesAtStartDateWithCurrencyEffect.minus(
investmentValuesAccumulatedAtStartDateWithCurrencyEffect investmentValuesAccumulatedAtStartDateWithCurrencyEffect
); );
@ -905,7 +904,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
) { ) {
average = average.add( average = average.add(
investmentValuesAccumulatedWithCurrencyEffect[date].add( investmentValuesAccumulatedWithCurrencyEffect[date].add(
grossPerformanceAtStartDateWithCurrencyEffect2 grossPerformanceAtDateRangeStartWithCurrencyEffect
) )
); );

Loading…
Cancel
Save