Browse Source

Refactor interest calculation

pull/3267/head
Thomas Kaul 1 year ago
parent
commit
6eb9e445d4
  1. 22
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  2. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts
  3. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts
  4. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy.spec.ts
  5. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts
  6. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts
  7. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts
  8. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts
  9. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts
  10. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell-partially.spec.ts
  11. 1
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts
  12. 17
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator.ts
  13. 1
      apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts
  14. 1
      apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts
  15. 11
      apps/api/src/app/portfolio/portfolio.service.ts
  16. 2
      libs/common/src/lib/interfaces/symbol-metrics.interface.ts

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

@ -138,6 +138,7 @@ export abstract class PortfolioCalculator {
netPerformanceWithCurrencyEffect: new Big(0), netPerformanceWithCurrencyEffect: new Big(0),
positions: [], positions: [],
totalFeesWithCurrencyEffect: new Big(0), totalFeesWithCurrencyEffect: new Big(0),
totalInterestWithCurrencyEffect: new Big(0),
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0) totalInvestmentWithCurrencyEffect: new Big(0)
}; };
@ -260,7 +261,6 @@ export abstract class PortfolioCalculator {
); );
const { const {
feesWithCurrencyEffect,
grossPerformance, grossPerformance,
grossPerformancePercentage, grossPerformancePercentage,
grossPerformancePercentageWithCurrencyEffect, grossPerformancePercentageWithCurrencyEffect,
@ -350,7 +350,8 @@ export abstract class PortfolioCalculator {
...overall, ...overall,
errors, errors,
positions, positions,
hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors hasErrors: hasAnySymbolMetricsErrors || overall.hasErrors,
totalInterestWithCurrencyEffect: lastTransactionPoint.interest
}; };
} }
@ -668,6 +669,12 @@ export abstract class PortfolioCalculator {
return this.snapshot.totalFeesWithCurrencyEffect; return this.snapshot.totalFeesWithCurrencyEffect;
} }
public async getInterestInBaseCurrency() {
await this.snapshotPromise;
return this.snapshot.totalInterestWithCurrencyEffect;
}
public getInvestments(): { date: string; investment: Big }[] { public getInvestments(): { date: string; investment: Big }[] {
if (this.transactionPoints.length === 0) { if (this.transactionPoints.length === 0) {
return []; return [];
@ -761,7 +768,7 @@ export abstract class PortfolioCalculator {
unitPrice unitPrice
} of this.orders) { } of this.orders) {
if ( if (
[/*'DIVIDEND', 'FEE',*/ 'INTEREST', 'ITEM', 'LIABILITY'].includes(type) [/*'DIVIDEND', 'FEE', 'INTEREST',*/ 'ITEM', 'LIABILITY'].includes(type)
) { ) {
continue; continue;
} }
@ -844,16 +851,25 @@ export abstract class PortfolioCalculator {
fees = fee; fees = fee;
} }
let interest = new Big(0);
if (type === 'INTEREST') {
interest = quantity.mul(unitPrice);
}
if (lastDate !== date || lastTransactionPoint === null) { if (lastDate !== date || lastTransactionPoint === null) {
lastTransactionPoint = { lastTransactionPoint = {
date, date,
fees, fees,
interest,
items: newItems items: newItems
}; };
this.transactionPoints.push(lastTransactionPoint); this.transactionPoints.push(lastTransactionPoint);
} else { } else {
lastTransactionPoint.fees = lastTransactionPoint.fees.plus(fees); lastTransactionPoint.fees = lastTransactionPoint.fees.plus(fees);
lastTransactionPoint.interest =
lastTransactionPoint.interest.plus(interest);
lastTransactionPoint.items = newItems; lastTransactionPoint.items = newItems;
} }

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell-in-two-activities.spec.ts

@ -174,6 +174,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('3.2'), totalFeesWithCurrencyEffect: new Big('3.2'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0') totalInvestmentWithCurrencyEffect: new Big('0')
}); });

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-baln-buy-and-sell.spec.ts

@ -157,6 +157,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('3.2'), totalFeesWithCurrencyEffect: new Big('3.2'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0') totalInvestmentWithCurrencyEffect: new Big('0')
}); });

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

@ -142,6 +142,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('1.55'), totalFeesWithCurrencyEffect: new Big('1.55'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('273.2'), totalInvestment: new Big('273.2'),
totalInvestmentWithCurrencyEffect: new Big('273.2') totalInvestmentWithCurrencyEffect: new Big('273.2')
}); });

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-btcusd-buy-and-sell-partially.spec.ts

@ -176,6 +176,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('0'), totalFeesWithCurrencyEffect: new Big('0'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('320.43'), totalInvestment: new Big('320.43'),
totalInvestmentWithCurrencyEffect: new Big('318.542667299999967957') totalInvestmentWithCurrencyEffect: new Big('318.542667299999967957')
}); });

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-fee.spec.ts

@ -123,6 +123,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('49'), totalFeesWithCurrencyEffect: new Big('49'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0') totalInvestmentWithCurrencyEffect: new Big('0')
}); });

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-googl-buy.spec.ts

@ -155,6 +155,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('1'), totalFeesWithCurrencyEffect: new Big('1'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('89.12'), totalInvestment: new Big('89.12'),
totalInvestmentWithCurrencyEffect: new Big('82.329056') totalInvestmentWithCurrencyEffect: new Big('82.329056')
}); });

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-msft-buy-with-dividend.spec.ts

@ -131,6 +131,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('19'), totalFeesWithCurrencyEffect: new Big('19'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('298.58'), totalInvestment: new Big('298.58'),
totalInvestmentWithCurrencyEffect: new Big('298.58') totalInvestmentWithCurrencyEffect: new Big('298.58')
}); });

1
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-no-orders.spec.ts

@ -81,6 +81,7 @@ describe('PortfolioCalculator', () => {
netPerformanceWithCurrencyEffect: new Big(0), netPerformanceWithCurrencyEffect: new Big(0),
positions: [], positions: [],
totalFeesWithCurrencyEffect: new Big('0'), totalFeesWithCurrencyEffect: new Big('0'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0) totalInvestmentWithCurrencyEffect: new Big(0)
}); });

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

@ -159,6 +159,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('4.25'), totalFeesWithCurrencyEffect: new Big('4.25'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('75.80'), totalInvestment: new Big('75.80'),
totalInvestmentWithCurrencyEffect: new Big('75.80') totalInvestmentWithCurrencyEffect: new Big('75.80')
}); });

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

@ -183,6 +183,7 @@ describe('PortfolioCalculator', () => {
} }
], ],
totalFeesWithCurrencyEffect: new Big('0'), totalFeesWithCurrencyEffect: new Big('0'),
totalInterestWithCurrencyEffect: new Big('0'),
totalInvestment: new Big('0'), totalInvestment: new Big('0'),
totalInvestmentWithCurrencyEffect: new Big('0') totalInvestmentWithCurrencyEffect: new Big('0')
}); });

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

@ -31,6 +31,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let netPerformance = new Big(0); let netPerformance = new Big(0);
let netPerformanceWithCurrencyEffect = new Big(0); let netPerformanceWithCurrencyEffect = new Big(0);
let totalFeesWithCurrencyEffect = new Big(0); let totalFeesWithCurrencyEffect = new Big(0);
let totalInterestWithCurrencyEffect = new Big(0);
let totalInvestment = new Big(0); let totalInvestment = new Big(0);
let totalInvestmentWithCurrencyEffect = new Big(0); let totalInvestmentWithCurrencyEffect = new Big(0);
let totalTimeWeightedInvestment = new Big(0); let totalTimeWeightedInvestment = new Big(0);
@ -109,6 +110,7 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
netPerformance, netPerformance,
netPerformanceWithCurrencyEffect, netPerformanceWithCurrencyEffect,
totalFeesWithCurrencyEffect, totalFeesWithCurrencyEffect,
totalInterestWithCurrencyEffect,
totalInvestment, totalInvestment,
totalInvestmentWithCurrencyEffect, totalInvestmentWithCurrencyEffect,
netPerformancePercentage: totalTimeWeightedInvestment.eq(0) netPerformancePercentage: totalTimeWeightedInvestment.eq(0)
@ -186,6 +188,8 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
let totalDividend = new Big(0); let totalDividend = new Big(0);
let totalDividendInBaseCurrency = new Big(0); let totalDividendInBaseCurrency = new Big(0);
let totalInterest = new Big(0);
let totalInterestInBaseCurrency = new Big(0);
let totalInvestment = new Big(0); let totalInvestment = new Big(0);
let totalInvestmentFromBuyTransactions = new Big(0); let totalInvestmentFromBuyTransactions = new Big(0);
let totalInvestmentFromBuyTransactionsWithCurrencyEffect = new Big(0); let totalInvestmentFromBuyTransactionsWithCurrencyEffect = new Big(0);
@ -229,6 +233,8 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
timeWeightedInvestmentWithCurrencyEffect: new Big(0), timeWeightedInvestmentWithCurrencyEffect: new Big(0),
totalDividend: new Big(0), totalDividend: new Big(0),
totalDividendInBaseCurrency: new Big(0), totalDividendInBaseCurrency: new Big(0),
totalInterest: new Big(0),
totalInterestInBaseCurrency: new Big(0),
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0) totalInvestmentWithCurrencyEffect: new Big(0)
}; };
@ -272,6 +278,8 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
timeWeightedInvestmentWithCurrencyEffect: new Big(0), timeWeightedInvestmentWithCurrencyEffect: new Big(0),
totalDividend: new Big(0), totalDividend: new Big(0),
totalDividendInBaseCurrency: new Big(0), totalDividendInBaseCurrency: new Big(0),
totalInterest: new Big(0),
totalInterestInBaseCurrency: new Big(0),
totalInvestment: new Big(0), totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0) totalInvestmentWithCurrencyEffect: new Big(0)
}; };
@ -521,6 +529,13 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus( totalDividendInBaseCurrency = totalDividendInBaseCurrency.plus(
dividend.mul(exchangeRateAtOrderDate ?? 1) dividend.mul(exchangeRateAtOrderDate ?? 1)
); );
} else if (order.type === 'INTEREST') {
const interest = order.quantity.mul(order.unitPrice);
totalInterest = totalInterest.plus(interest);
totalInterestInBaseCurrency = totalInterestInBaseCurrency.plus(
interest.mul(exchangeRateAtOrderDate ?? 1)
);
} }
const valueOfInvestment = totalUnits.mul(order.unitPriceInBaseCurrency); const valueOfInvestment = totalUnits.mul(order.unitPriceInBaseCurrency);
@ -834,6 +849,8 @@ export class TWRPortfolioCalculator extends PortfolioCalculator {
timeWeightedInvestmentValuesWithCurrencyEffect, timeWeightedInvestmentValuesWithCurrencyEffect,
totalDividend, totalDividend,
totalDividendInBaseCurrency, totalDividendInBaseCurrency,
totalInterest,
totalInterestInBaseCurrency,
totalInvestment, totalInvestment,
totalInvestmentWithCurrencyEffect, totalInvestmentWithCurrencyEffect,
grossPerformance: totalGrossPerformance, grossPerformance: totalGrossPerformance,

1
apps/api/src/app/portfolio/interfaces/portfolio-snapshot.interface.ts

@ -16,6 +16,7 @@ export interface PortfolioSnapshot extends ResponseError {
netPerformancePercentageWithCurrencyEffect: Big; netPerformancePercentageWithCurrencyEffect: Big;
positions: TimelinePosition[]; positions: TimelinePosition[];
totalFeesWithCurrencyEffect: Big; totalFeesWithCurrencyEffect: Big;
totalInterestWithCurrencyEffect: Big;
totalInvestment: Big; totalInvestment: Big;
totalInvestmentWithCurrencyEffect: Big; totalInvestmentWithCurrencyEffect: Big;
} }

1
apps/api/src/app/portfolio/interfaces/transaction-point.interface.ts

@ -5,5 +5,6 @@ import { TransactionPointSymbol } from './transaction-point-symbol.interface';
export interface TransactionPoint { export interface TransactionPoint {
date: string; date: string;
fees: Big; fees: Big;
interest: Big;
items: TransactionPointSymbol[]; items: TransactionPointSymbol[];
} }

11
apps/api/src/app/portfolio/portfolio.service.ts

@ -1621,14 +1621,7 @@ export class PortfolioService {
const firstOrderDate = portfolioCalculator.getStartDate(); const firstOrderDate = portfolioCalculator.getStartDate();
// TODO const interest = await portfolioCalculator.getInterestInBaseCurrency();
const interest = this.getSumOfActivityType({
activities,
userCurrency,
activityType: 'INTEREST'
}).toNumber();
console.log(interest);
// TODO // TODO
const items = getSum( const items = getSum(
@ -1737,7 +1730,6 @@ export class PortfolioService {
cash, cash,
excludedAccountsAndActivities, excludedAccountsAndActivities,
firstOrderDate, firstOrderDate,
interest,
items, items,
liabilities, liabilities,
totalBuy, totalBuy,
@ -1759,6 +1751,7 @@ export class PortfolioService {
fireWealth: new Big(performanceInformation.performance.currentValue) fireWealth: new Big(performanceInformation.performance.currentValue)
.minus(emergencyFundPositionsValueInBaseCurrency) .minus(emergencyFundPositionsValueInBaseCurrency)
.toNumber(), .toNumber(),
interest: interest.toNumber(),
ordersCount: activities.filter(({ type }) => { ordersCount: activities.filter(({ type }) => {
return type === 'BUY' || type === 'SELL'; return type === 'BUY' || type === 'SELL';
}).length, }).length,

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

@ -42,6 +42,8 @@ export interface SymbolMetrics {
timeWeightedInvestmentWithCurrencyEffect: Big; timeWeightedInvestmentWithCurrencyEffect: Big;
totalDividend: Big; totalDividend: Big;
totalDividendInBaseCurrency: Big; totalDividendInBaseCurrency: Big;
totalInterest: Big;
totalInterestInBaseCurrency: Big;
totalInvestment: Big; totalInvestment: Big;
totalInvestmentWithCurrencyEffect: Big; totalInvestmentWithCurrencyEffect: Big;
} }

Loading…
Cancel
Save