Browse Source

fix calculation for overall gross performance percentage

pull/237/head
Valentin Zickner 4 years ago
parent
commit
aadc63cbab
  1. 18
      apps/api/src/app/core/portfolio-calculator.spec.ts
  2. 94
      apps/api/src/app/core/portfolio-calculator.ts

18
apps/api/src/app/core/portfolio-calculator.spec.ts

@ -636,7 +636,7 @@ describe('PortfolioCalculator', () => {
hasErrors: false, hasErrors: false,
currentValue: new Big('657.62'), currentValue: new Big('657.62'),
grossPerformance: new Big('-61.84'), grossPerformance: new Big('-61.84'),
grossPerformancePercentage: new Big('-0.08456342256692519389'), grossPerformancePercentage: new Big('-0.08595335390431712673'),
positions: [ positions: [
{ {
averagePrice: new Big('719.46'), averagePrice: new Big('719.46'),
@ -674,7 +674,7 @@ describe('PortfolioCalculator', () => {
hasErrors: false, hasErrors: false,
currentValue: new Big('657.62'), currentValue: new Big('657.62'),
grossPerformance: new Big('-61.84'), grossPerformance: new Big('-61.84'),
grossPerformancePercentage: new Big('-0.08456342256692519389'), grossPerformancePercentage: new Big('-0.08595335390431712673'),
positions: [ positions: [
{ {
averagePrice: new Big('719.46'), averagePrice: new Big('719.46'),
@ -712,7 +712,7 @@ describe('PortfolioCalculator', () => {
hasErrors: false, hasErrors: false,
currentValue: new Big('657.62'), currentValue: new Big('657.62'),
grossPerformance: new Big('-9.04'), grossPerformance: new Big('-9.04'),
grossPerformancePercentage: new Big('-0.01206012060120601206'), grossPerformancePercentage: new Big('-0.01356013560135601356'),
positions: [ positions: [
{ {
averagePrice: new Big('719.46'), averagePrice: new Big('719.46'),
@ -750,7 +750,7 @@ describe('PortfolioCalculator', () => {
hasErrors: false, hasErrors: false,
currentValue: new Big('4871.5'), currentValue: new Big('4871.5'),
grossPerformance: new Big('240.4'), grossPerformance: new Big('240.4'),
grossPerformancePercentage: new Big('0.08908669575467971768'), grossPerformancePercentage: new Big('0.08839407904876477102'),
positions: [ positions: [
{ {
averagePrice: new Big('178.438'), averagePrice: new Big('178.438'),
@ -830,7 +830,7 @@ describe('PortfolioCalculator', () => {
hasErrors: false, hasErrors: false,
currentValue: new Big('3897.2'), currentValue: new Big('3897.2'),
grossPerformance: new Big('303.2'), grossPerformance: new Big('303.2'),
grossPerformancePercentage: new Big('0.2759628350186678759'), grossPerformancePercentage: new Big('0.27537838148272398344'),
positions: [ positions: [
{ {
averagePrice: new Big('146.185'), averagePrice: new Big('146.185'),
@ -903,7 +903,7 @@ describe('PortfolioCalculator', () => {
hasErrors: false, hasErrors: false,
currentValue: new Big('1192327.999656600298238721'), currentValue: new Big('1192327.999656600298238721'),
grossPerformance: new Big('92327.999656600898394721'), grossPerformance: new Big('92327.999656600898394721'),
grossPerformancePercentage: new Big('0.09788598099999947809'), grossPerformancePercentage: new Big('0.09788498099999947809'),
positions: [ positions: [
{ {
averagePrice: new Big('1.01287018290924923237'), // 1'100'000 / 1'086'022.689344542 averagePrice: new Big('1.01287018290924923237'), // 1'100'000 / 1'086'022.689344542
@ -989,9 +989,9 @@ describe('PortfolioCalculator', () => {
spy.mockRestore(); spy.mockRestore();
expect(currentPositions).toEqual({ expect(currentPositions).toEqual({
currentValue: '517', currentValue: new Big('517'),
grossPerformance: '17', // 517 - 500 grossPerformance: new Big('17'), // 517 - 500
grossPerformancePercentage: '0.034', // ((200 * 2.5) + (300 * 4)) / (200 + 300) = 3.4% grossPerformancePercentage: new Big('0.034'), // ((200 * 0.025) + (300 * 0.04)) / (200 + 300) = 3.4%
hasErrors: false, hasErrors: false,
positions: [ positions: [
{ {

94
apps/api/src/app/core/portfolio-calculator.ts

@ -297,48 +297,15 @@ export class PortfolioCalculator {
transactionCount: item.transactionCount transactionCount: item.transactionCount
}); });
} }
const overall = this.calculateOverallGrossPerformance(
let currentValue = new Big(0); positions,
let overallGrossPerformance = new Big(0); initialValues
let grossPerformancePercentage = new Big(1); );
let completeInitialValue = new Big(0);
for (const currentPosition of positions) {
currentValue = currentValue.add(
new Big(currentPosition.marketPrice).mul(currentPosition.quantity)
);
if (currentPosition.grossPerformance) {
overallGrossPerformance = overallGrossPerformance.plus(
currentPosition.grossPerformance
);
} else {
hasErrors = true;
}
if (
currentPosition.grossPerformancePercentage &&
initialValues[currentPosition.symbol]
) {
const currentInitialValue = initialValues[currentPosition.symbol];
completeInitialValue = completeInitialValue.plus(currentInitialValue);
grossPerformancePercentage = grossPerformancePercentage.plus(
currentPosition.grossPerformancePercentage.mul(currentInitialValue)
);
} else {
console.log(initialValues);
console.error(
'initial value is missing for symbol',
currentPosition.symbol
);
hasErrors = true;
}
}
return { return {
hasErrors, ...overall,
positions, hasErrors: hasErrors || overall.hasErrors,
grossPerformance: overallGrossPerformance, positions
grossPerformancePercentage:
grossPerformancePercentage.div(completeInitialValue),
currentValue
}; };
} }
@ -404,6 +371,53 @@ export class PortfolioCalculator {
return flatten(timelinePeriods); return flatten(timelinePeriods);
} }
private calculateOverallGrossPerformance(
positions: TimelinePosition[],
initialValues: { [p: string]: Big }
) {
let hasErrors = false;
let currentValue = new Big(0);
let grossPerformance = new Big(0);
let grossPerformancePercentage = new Big(0);
let completeInitialValue = new Big(0);
for (const currentPosition of positions) {
currentValue = currentValue.add(
new Big(currentPosition.marketPrice).mul(currentPosition.quantity)
);
if (currentPosition.grossPerformance) {
grossPerformance = grossPerformance.plus(
currentPosition.grossPerformance
);
} else {
hasErrors = true;
}
if (
currentPosition.grossPerformancePercentage &&
initialValues[currentPosition.symbol]
) {
const currentInitialValue = initialValues[currentPosition.symbol];
completeInitialValue = completeInitialValue.plus(currentInitialValue);
grossPerformancePercentage = grossPerformancePercentage.plus(
currentPosition.grossPerformancePercentage.mul(currentInitialValue)
);
} else {
console.error(
'initial value is missing for symbol',
currentPosition.symbol
);
hasErrors = true;
}
}
return {
currentValue,
grossPerformance,
grossPerformancePercentage:
grossPerformancePercentage.div(completeInitialValue),
hasErrors
};
}
private async getTimePeriodForDate( private async getTimePeriodForDate(
j: number, j: number,
startDate: Date, startDate: Date,

Loading…
Cancel
Save