|
|
|
@ -396,115 +396,9 @@ describe('PortfolioCalculator', () => {
|
|
|
|
|
const portfolioItemsAtTransactionPoints =
|
|
|
|
|
portfolioCalculator.getTransactionPoints();
|
|
|
|
|
|
|
|
|
|
expect(portfolioItemsAtTransactionPoints).toEqual([
|
|
|
|
|
{
|
|
|
|
|
date: '2019-02-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('10'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('1443.8'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2019-08-03',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('20'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('2923.7'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2019-09-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('10109.95'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('20'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('2923.7'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2020-02-02',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('10109.95'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('652.55'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2020-08-02',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('652.55'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2021-02-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('15'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('2684.05'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 4
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2021-08-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('25'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('4460.95'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 5
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]);
|
|
|
|
|
expect(portfolioItemsAtTransactionPoints).toEqual(
|
|
|
|
|
transactionPointsBuyAndSell
|
|
|
|
|
);
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with mixed symbols', () => {
|
|
|
|
@ -740,6 +634,138 @@ describe('PortfolioCalculator', () => {
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with buy and sell', async () => {
|
|
|
|
|
const portfolioCalculator = new PortfolioCalculator(
|
|
|
|
|
currentRateService,
|
|
|
|
|
Currency.USD
|
|
|
|
|
);
|
|
|
|
|
portfolioCalculator.setTransactionPoints(transactionPointsBuyAndSell);
|
|
|
|
|
|
|
|
|
|
const spy = jest
|
|
|
|
|
.spyOn(Date, 'now')
|
|
|
|
|
.mockImplementation(() => new Date(Date.UTC(2020, 9, 24)).getTime()); // 2020-10-24
|
|
|
|
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
|
|
|
|
parseDate('2019-01-01')
|
|
|
|
|
);
|
|
|
|
|
spy.mockRestore();
|
|
|
|
|
|
|
|
|
|
expect(currentPositions).toEqual({
|
|
|
|
|
hasErrors: false,
|
|
|
|
|
currentValue: new Big('4871.5'),
|
|
|
|
|
grossPerformance: new Big('240.4'),
|
|
|
|
|
grossPerformancePercentage: new Big('0.01104605615757711361'),
|
|
|
|
|
totalInvestment: new Big('4460.95'),
|
|
|
|
|
positions: [
|
|
|
|
|
{
|
|
|
|
|
averagePrice: new Big('0'),
|
|
|
|
|
currency: 'USD',
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
grossPerformance: new Big('0'),
|
|
|
|
|
grossPerformancePercentage: new Big('0'),
|
|
|
|
|
investment: new Big('0'),
|
|
|
|
|
marketPrice: 2021.99,
|
|
|
|
|
quantity: new Big('0'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
averagePrice: new Big('178.438'),
|
|
|
|
|
currency: 'USD',
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
grossPerformance: new Big('240.4'),
|
|
|
|
|
grossPerformancePercentage: new Big(
|
|
|
|
|
'0.08839407904876477101219019935616297754969945667391763908415656216989674494965785538864363782688167989866968512455219637257546280462751601552'
|
|
|
|
|
),
|
|
|
|
|
investment: new Big('4460.95'),
|
|
|
|
|
marketPrice: 194.86,
|
|
|
|
|
quantity: new Big('25'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
transactionCount: 5
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with buy, sell, buy', async () => {
|
|
|
|
|
const portfolioCalculator = new PortfolioCalculator(
|
|
|
|
|
currentRateService,
|
|
|
|
|
Currency.USD
|
|
|
|
|
);
|
|
|
|
|
portfolioCalculator.setTransactionPoints([
|
|
|
|
|
{
|
|
|
|
|
date: '2019-09-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('805.9'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2020-08-02',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('0'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('0'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2021-02-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('1013.9'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
]);
|
|
|
|
|
|
|
|
|
|
const spy = jest
|
|
|
|
|
.spyOn(Date, 'now')
|
|
|
|
|
.mockImplementation(() => new Date(Date.UTC(2021, 7, 1)).getTime()); // 2021-08-01
|
|
|
|
|
const currentPositions = await portfolioCalculator.getCurrentPositions(
|
|
|
|
|
parseDate('2019-02-01')
|
|
|
|
|
);
|
|
|
|
|
spy.mockRestore();
|
|
|
|
|
|
|
|
|
|
expect(currentPositions).toEqual({
|
|
|
|
|
hasErrors: false,
|
|
|
|
|
currentValue: new Big('1086.7'),
|
|
|
|
|
grossPerformance: new Big('207.6'),
|
|
|
|
|
grossPerformancePercentage: new Big('0.2516103956224511062'),
|
|
|
|
|
totalInvestment: new Big('1013.9'),
|
|
|
|
|
positions: [
|
|
|
|
|
{
|
|
|
|
|
averagePrice: new Big('202.78'),
|
|
|
|
|
currency: 'USD',
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
grossPerformance: new Big('207.6'),
|
|
|
|
|
grossPerformancePercentage: new Big(
|
|
|
|
|
'0.2516103956224511061954915466429950404846'
|
|
|
|
|
),
|
|
|
|
|
investment: new Big('1013.9'),
|
|
|
|
|
marketPrice: 217.34,
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
});
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
it('with performance since Jan 1st, 2020', async () => {
|
|
|
|
|
const portfolioCalculator = new PortfolioCalculator(
|
|
|
|
|
currentRateService,
|
|
|
|
@ -1776,3 +1802,137 @@ const ordersVTITransactionPoints: TransactionPoint[] = [
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|
|
|
|
|
|
const transactionPointsBuyAndSell = [
|
|
|
|
|
{
|
|
|
|
|
date: '2019-02-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('10'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('1443.8'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2019-08-03',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('20'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('2923.7'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2019-09-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('10109.95'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('20'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('2923.7'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2020-02-02',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('10109.95'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 1
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('652.55'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2020-08-02',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('0'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('0'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('5'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('652.55'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 3
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2021-02-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('0'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('0'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('15'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('2684.05'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 4
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
date: '2021-08-01',
|
|
|
|
|
items: [
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('0'),
|
|
|
|
|
symbol: 'AMZN',
|
|
|
|
|
investment: new Big('0'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-09-01',
|
|
|
|
|
transactionCount: 2
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
quantity: new Big('25'),
|
|
|
|
|
symbol: 'VTI',
|
|
|
|
|
investment: new Big('4460.95'),
|
|
|
|
|
currency: Currency.USD,
|
|
|
|
|
firstBuyDate: '2019-02-01',
|
|
|
|
|
transactionCount: 5
|
|
|
|
|
}
|
|
|
|
|
]
|
|
|
|
|
}
|
|
|
|
|
];
|
|
|
|
|