|
|
@ -62,6 +62,19 @@ function mockGetValue(symbol: string, date: Date) {
|
|
|
|
)
|
|
|
|
)
|
|
|
|
.toNumber()
|
|
|
|
.toNumber()
|
|
|
|
};
|
|
|
|
};
|
|
|
|
|
|
|
|
case 'BALN.SW':
|
|
|
|
|
|
|
|
if (isSameDay(parseDate('2021-11-12'), date)) {
|
|
|
|
|
|
|
|
return { marketPrice: 146 };
|
|
|
|
|
|
|
|
} else if (isSameDay(parseDate('2021-11-22'), date)) {
|
|
|
|
|
|
|
|
return { marketPrice: 142.9 };
|
|
|
|
|
|
|
|
} else if (isSameDay(parseDate('2021-11-26'), date)) {
|
|
|
|
|
|
|
|
return { marketPrice: 139.9 };
|
|
|
|
|
|
|
|
} else if (isSameDay(parseDate('2021-11-30'), date)) {
|
|
|
|
|
|
|
|
return { marketPrice: 136.6 };
|
|
|
|
|
|
|
|
} else if (isSameDay(parseDate('2021-12-18'), date)) {
|
|
|
|
|
|
|
|
return { marketPrice: 143.9 };
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
default:
|
|
|
|
default:
|
|
|
|
return { marketPrice: 0 };
|
|
|
|
return { marketPrice: 0 };
|
|
|
|
}
|
|
|
|
}
|
|
|
@ -1486,6 +1499,126 @@ describe('PortfolioCalculator', () => {
|
|
|
|
})
|
|
|
|
})
|
|
|
|
);
|
|
|
|
);
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
it('with BALN.SW', async () => {
|
|
|
|
|
|
|
|
const portfolioCalculator = new PortfolioCalculator(
|
|
|
|
|
|
|
|
currentRateService,
|
|
|
|
|
|
|
|
'CHF'
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// date,type,ticker,currency,units,price,fee
|
|
|
|
|
|
|
|
portfolioCalculator.setTransactionPoints([
|
|
|
|
|
|
|
|
// 12.11.2021,BUY,BALN.SW,CHF,2.00,146.00,1.65
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
date: '2021-11-12',
|
|
|
|
|
|
|
|
items: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
quantity: new Big('2'),
|
|
|
|
|
|
|
|
symbol: 'BALN.SW',
|
|
|
|
|
|
|
|
investment: new Big('292'),
|
|
|
|
|
|
|
|
currency: 'CHF',
|
|
|
|
|
|
|
|
dataSource: DataSource.YAHOO,
|
|
|
|
|
|
|
|
firstBuyDate: '2021-11-12',
|
|
|
|
|
|
|
|
fee: new Big('1.65'),
|
|
|
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
// HWR: (End Value - (Initial Value + Cash Flow)) / (Initial Value + Cash Flow)
|
|
|
|
|
|
|
|
// End Value: 142.9 * 2 = 285.8
|
|
|
|
|
|
|
|
// Initial Value: 292 (Investment)
|
|
|
|
|
|
|
|
// Cash Flow: 0
|
|
|
|
|
|
|
|
// HWR_n0: (285.8 - 292) / 292 = -0.021232877
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 22.11.2021,BUY,BALN.SW,CHF,7.00,142.90,5.75
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
date: '2021-11-22',
|
|
|
|
|
|
|
|
items: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
quantity: new Big('9'), // 7 + 2
|
|
|
|
|
|
|
|
symbol: 'BALN.SW',
|
|
|
|
|
|
|
|
investment: new Big('1292.3'), // 142.9 * 7 + 146 * 2
|
|
|
|
|
|
|
|
currency: 'CHF',
|
|
|
|
|
|
|
|
dataSource: DataSource.YAHOO,
|
|
|
|
|
|
|
|
firstBuyDate: '2021-11-12',
|
|
|
|
|
|
|
|
fee: new Big('7.4'), // 1.65 + 5.75
|
|
|
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
// HWR: (End Value - (Initial Value + Cash Flow)) / (Initial Value + Cash Flow)
|
|
|
|
|
|
|
|
// End Value: 139.9 * 9 = 1259.1
|
|
|
|
|
|
|
|
// Initial Value: 285.8 (End Value n0)
|
|
|
|
|
|
|
|
// Cash Flow: 1000.3
|
|
|
|
|
|
|
|
// Initial Value + Cash Flow: 285.8 + 1000.3 = 1286.1
|
|
|
|
|
|
|
|
// HWR_n1: (1259.1 - 1286.1) / 1286.1 = -0.020993702
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 26.11.2021,BUY,BALN.SW,CHF,3.00,139.90,2.40
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
date: '2021-11-26',
|
|
|
|
|
|
|
|
items: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
quantity: new Big('12'), // 3 + 7 + 2
|
|
|
|
|
|
|
|
symbol: 'BALN.SW',
|
|
|
|
|
|
|
|
investment: new Big('1712'), // 139.9 * 3 + 142.9 * 7 + 146 * 2
|
|
|
|
|
|
|
|
currency: 'CHF',
|
|
|
|
|
|
|
|
dataSource: DataSource.YAHOO,
|
|
|
|
|
|
|
|
firstBuyDate: '2021-11-12',
|
|
|
|
|
|
|
|
fee: new Big('9.8'), // 2.40 + 1.65 + 5.75
|
|
|
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
},
|
|
|
|
|
|
|
|
// HWR: (End Value - (Initial Value + Cash Flow)) / (Initial Value + Cash Flow)
|
|
|
|
|
|
|
|
// End Value: 136.6 * 12 = 1639.2
|
|
|
|
|
|
|
|
// Initial Value: 1259.1 (End Value n1)
|
|
|
|
|
|
|
|
// Cash Flow: 139.9 * 3 = 419.7
|
|
|
|
|
|
|
|
// Initial Value + Cash Flow: 1259.1 + 419.7 = 1678.8
|
|
|
|
|
|
|
|
// HWR_n2: (1639.2 - 1678.8) / 1678.8 = -0.023588277
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// 30.11.2021,BUY,BALN.SW,CHF,2.00,136.60,1.55
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
date: '2021-11-30',
|
|
|
|
|
|
|
|
items: [
|
|
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
quantity: new Big('14'), // 2 + 3 + 7 + 2
|
|
|
|
|
|
|
|
symbol: 'BALN.SW',
|
|
|
|
|
|
|
|
investment: new Big('1985.2'), // 136.6 * 2 + 139.9 * 3 + 142.9 * 7 + 146 * 2
|
|
|
|
|
|
|
|
currency: 'CHF',
|
|
|
|
|
|
|
|
dataSource: DataSource.YAHOO,
|
|
|
|
|
|
|
|
firstBuyDate: '2021-11-12',
|
|
|
|
|
|
|
|
fee: new Big('11.35'), // 1.55 + 2.40 + 1.65 + 5.75
|
|
|
|
|
|
|
|
transactionCount: 4
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
]
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// HWR: (End Value - (Initial Value + Cash Flow)) / (Initial Value + Cash Flow)
|
|
|
|
|
|
|
|
// End Value: 143.9 * 14 = 2014.6
|
|
|
|
|
|
|
|
// Initial Value: 1639.2 (End Value n2)
|
|
|
|
|
|
|
|
// Cash Flow: 136.6 * 2 = 273.2
|
|
|
|
|
|
|
|
// Initial Value + Cash Flow: 1639.2 + 273.2 = 1912.4
|
|
|
|
|
|
|
|
// HWR_n3: (2014.6 - 1912.4) / 1912.4 = 0.053440703
|
|
|
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// HWR_total = 1 - (HWR_n0 + 1) * (HWR_n1 + 1) * (HWR_n2 + 1) * (HWR_n3 + 1)
|
|
|
|
|
|
|
|
// HWR_total = 1 - (-0.021232877 + 1) * (-0.020993702 + 1) * (-0.023588277 + 1) * (0.053440703 + 1) = 0.014383561
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const spy = jest
|
|
|
|
|
|
|
|
.spyOn(Date, 'now')
|
|
|
|
|
|
|
|
.mockImplementation(() => new Date(Date.UTC(2021, 11, 18)).getTime()); // 2021-12-18
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
|
|
|
|
|
|
|
parseDate('2021-11-01')
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
spy.mockRestore();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
expect(currentPositions).toBeDefined();
|
|
|
|
|
|
|
|
expect(currentPositions.grossPerformance).toEqual(new Big('29.4'));
|
|
|
|
|
|
|
|
expect(currentPositions.netPerformance).toEqual(new Big('18.05'));
|
|
|
|
|
|
|
|
expect(currentPositions.grossPerformancePercentage).toEqual(
|
|
|
|
|
|
|
|
new Big('-0.01438356164383561644')
|
|
|
|
|
|
|
|
);
|
|
|
|
|
|
|
|
});
|
|
|
|
});
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
|
|
describe('calculate timeline', () => {
|
|
|
|
describe('calculate timeline', () => {
|
|
|
|