fix performance of combination of investments

pull/239/head
Valentin Zickner 3 years ago committed by Thomas
parent f9b9dc32cb
commit 9c51a257ae

@ -623,6 +623,9 @@ describe('PortfolioCalculator', () => {
expect(currentPositions).toEqual({
hasErrors: false,
currentValue: new Big('657.62'),
grossPerformance: new Big('-61.84'),
grossPerformancePercentage: new Big('-0.08456342256692519389'),
positions: [
{
averagePrice: new Big('719.46'),
@ -658,6 +661,9 @@ describe('PortfolioCalculator', () => {
expect(currentPositions).toEqual({
hasErrors: false,
currentValue: new Big('657.62'),
grossPerformance: new Big('-61.84'),
grossPerformancePercentage: new Big('-0.08456342256692519389'),
positions: [
{
averagePrice: new Big('719.46'),
@ -693,6 +699,9 @@ describe('PortfolioCalculator', () => {
expect(currentPositions).toEqual({
hasErrors: false,
currentValue: new Big('657.62'),
grossPerformance: new Big('-9.04'),
grossPerformancePercentage: new Big('-0.01206012060120601206'),
positions: [
{
averagePrice: new Big('719.46'),
@ -728,6 +737,9 @@ describe('PortfolioCalculator', () => {
expect(currentPositions).toEqual({
hasErrors: false,
currentValue: new Big('4871.5'),
grossPerformance: new Big('240.4'),
grossPerformancePercentage: new Big('0.08908669575467971768'),
positions: [
{
averagePrice: new Big('178.438'),
@ -805,6 +817,9 @@ describe('PortfolioCalculator', () => {
spy.mockRestore();
expect(currentPositions).toEqual({
hasErrors: false,
currentValue: new Big('3897.2'),
grossPerformance: new Big('303.2'),
grossPerformancePercentage: new Big('0.2759628350186678759'),
positions: [
{
averagePrice: new Big('146.185'),
@ -875,6 +890,9 @@ describe('PortfolioCalculator', () => {
expect(currentPositions).toEqual({
hasErrors: false,
currentValue: new Big('1192327.999656600298238721'),
grossPerformance: new Big('92327.999656600898394721'),
grossPerformancePercentage: new Big('0.09788598099999947809'),
positions: [
{
averagePrice: new Big('1.01287018290924923237'), // 1'100'000 / 1'086'022.689344542

@ -114,11 +114,17 @@ export class PortfolioCalculator {
public async getCurrentPositions(start: Date): Promise<{
hasErrors: boolean;
positions: TimelinePosition[];
grossPerformance: Big;
grossPerformancePercentage: Big;
currentValue: Big;
}> {
if (!this.transactionPoints?.length) {
return {
hasErrors: false,
positions: []
positions: [],
grossPerformance: new Big(0),
grossPerformancePercentage: new Big(0),
currentValue: new Big(0)
};
}
@ -197,6 +203,8 @@ export class PortfolioCalculator {
const invalidSymbols = [];
const lastInvestments: { [symbol: string]: Big } = {};
const lastQuantities: { [symbol: string]: Big } = {};
const initialValues: { [symbol: string]: Big } = {};
for (let i = firstIndex; i < this.transactionPoints.length; i++) {
const currentDate =
i === firstIndex ? startString : this.transactionPoints[i].date;
@ -233,6 +241,9 @@ export class PortfolioCalculator {
initialValue = item.investment;
investedValue = item.investment;
}
if (i === firstIndex || !initialValues[item.symbol]) {
initialValues[item.symbol] = initialValue;
}
if (!initialValue) {
invalidSymbols.push(item.symbol);
hasErrors = true;
@ -287,7 +298,48 @@ export class PortfolioCalculator {
});
}
return { hasErrors, positions };
let currentValue = new Big(0);
let overallGrossPerformance = new Big(0);
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 {
hasErrors,
positions,
grossPerformance: overallGrossPerformance,
grossPerformancePercentage:
grossPerformancePercentage.div(completeInitialValue),
currentValue
};
}
public async calculateTimeline(

@ -484,34 +484,12 @@ export class PortfolioService {
startDate
);
let currentValue = new Big(0);
let grossPerformance = new Big(0);
let grossPerformancePercentage = new Big(1);
let hasErrors = false;
for (const currentPosition of currentPositions.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) {
grossPerformancePercentage = grossPerformancePercentage.mul(
currentPosition.grossPerformancePercentage.plus(1)
);
} else {
hasErrors = true;
}
}
const currentGrossPerformance = grossPerformance.toNumber();
const currentGrossPerformancePercent = grossPerformancePercentage
.minus(1)
.toNumber();
const hasErrors = currentPositions.hasErrors;
const currentValue = currentPositions.currentValue.toNumber();
const currentGrossPerformance =
currentPositions.grossPerformance.toNumber();
const currentGrossPerformancePercent =
currentPositions.grossPerformancePercentage.toNumber();
return {
hasErrors: currentPositions.hasErrors || hasErrors,
performance: {
@ -520,7 +498,7 @@ export class PortfolioService {
// TODO: the next two should include fees
currentNetPerformance: currentGrossPerformance,
currentNetPerformancePercent: currentGrossPerformancePercent,
currentValue: currentValue.toNumber()
currentValue: currentValue
}
};
}

Loading…
Cancel
Save