|
|
@ -1,5 +1,11 @@ |
|
|
|
import { PortfolioCalculator, PortfolioOrder } from '@ghostfolio/api/app/core/portfolio-calculator'; |
|
|
|
import { CurrentRateService, GetValueParams } from '@ghostfolio/api/app/core/current-rate.service'; |
|
|
|
import { |
|
|
|
PortfolioCalculator, |
|
|
|
PortfolioOrder |
|
|
|
} from '@ghostfolio/api/app/core/portfolio-calculator'; |
|
|
|
import { |
|
|
|
CurrentRateService, |
|
|
|
GetValueParams |
|
|
|
} from '@ghostfolio/api/app/core/current-rate.service'; |
|
|
|
import { Currency } from '@prisma/client'; |
|
|
|
import { OrderType } from '@ghostfolio/api/models/order-type'; |
|
|
|
import Big from 'big.js'; |
|
|
@ -16,9 +22,11 @@ function dateEqual(date1: Date, date2: Date) { |
|
|
|
const date1Converted = toYearMonthDay(date1); |
|
|
|
const date2Converted = toYearMonthDay(date2); |
|
|
|
|
|
|
|
return date1Converted[0] === date2Converted[0]&& |
|
|
|
return ( |
|
|
|
date1Converted[0] === date2Converted[0] && |
|
|
|
date1Converted[1] === date2Converted[1] && |
|
|
|
date1Converted[2] === date2Converted[2] |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
jest.mock('./current-rate.service.ts', () => { |
|
|
@ -26,13 +34,17 @@ jest.mock('./current-rate.service.ts', () => { |
|
|
|
// eslint-disable-next-line @typescript-eslint/naming-convention
|
|
|
|
CurrentRateService: jest.fn().mockImplementation(() => { |
|
|
|
return { |
|
|
|
getValue: ({date, symbol, currency, userCurrency}: GetValueParams) => { |
|
|
|
getValue: ({ |
|
|
|
date, |
|
|
|
symbol, |
|
|
|
currency, |
|
|
|
userCurrency |
|
|
|
}: GetValueParams) => { |
|
|
|
const today = new Date(); |
|
|
|
if (dateEqual(today, date) && symbol === 'VTI') { |
|
|
|
return Promise.resolve(new Big('213.32')); |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return Promise.resolve(new Big('0')); |
|
|
|
} |
|
|
|
}; |
|
|
@ -41,7 +53,6 @@ jest.mock('./current-rate.service.ts', () => { |
|
|
|
}); |
|
|
|
|
|
|
|
describe('PortfolioCalculator', () => { |
|
|
|
|
|
|
|
let currentRateService: CurrentRateService; |
|
|
|
beforeEach(() => { |
|
|
|
currentRateService = new CurrentRateService(null, null); |
|
|
@ -49,11 +60,17 @@ describe('PortfolioCalculator', () => { |
|
|
|
|
|
|
|
describe('calculate transaction points', () => { |
|
|
|
it('with orders of only one symbol', () => { |
|
|
|
const portfolioCalculator = new PortfolioCalculator(currentRateService, Currency.USD); |
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
currentRateService, |
|
|
|
Currency.USD |
|
|
|
); |
|
|
|
portfolioCalculator.computeTransactionPoints(ordersVTI); |
|
|
|
const portfolioItemsAtTransactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
|
const portfolioItemsAtTransactionPoints = |
|
|
|
portfolioCalculator.getTransactionPoints(); |
|
|
|
|
|
|
|
expect(portfolioItemsAtTransactionPoints).toEqual(ordersVTITransactionPoints); |
|
|
|
expect(portfolioItemsAtTransactionPoints).toEqual( |
|
|
|
ordersVTITransactionPoints |
|
|
|
); |
|
|
|
}); |
|
|
|
|
|
|
|
it('with two orders at the same day of the same type', () => { |
|
|
@ -68,65 +85,79 @@ describe('PortfolioCalculator', () => { |
|
|
|
currency: Currency.USD |
|
|
|
} |
|
|
|
]; |
|
|
|
const portfolioCalculator = new PortfolioCalculator(currentRateService, Currency.USD); |
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
currentRateService, |
|
|
|
Currency.USD |
|
|
|
); |
|
|
|
portfolioCalculator.computeTransactionPoints(orders); |
|
|
|
const portfolioItemsAtTransactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
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: 'VTI', |
|
|
|
investment: new Big('652.55'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 3 |
|
|
|
}] |
|
|
|
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('35'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('6627.05'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 5 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('35'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('6627.05'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 5 |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
{ |
|
|
|
date: '2021-08-01', |
|
|
|
items: [{ |
|
|
|
quantity: new Big('45'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('8403.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 6 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('45'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('8403.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 6 |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
]); |
|
|
|
}); |
|
|
@ -143,104 +174,124 @@ describe('PortfolioCalculator', () => { |
|
|
|
currency: Currency.USD |
|
|
|
} |
|
|
|
]; |
|
|
|
const portfolioCalculator = new PortfolioCalculator(currentRateService, Currency.USD); |
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
currentRateService, |
|
|
|
Currency.USD |
|
|
|
); |
|
|
|
portfolioCalculator.computeTransactionPoints(orders); |
|
|
|
const portfolioItemsAtTransactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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: '2021-02-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('15'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('2684.05'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 4 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('5'), |
|
|
|
symbol: 'AMZN', |
|
|
|
investment: new Big('10109.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-09-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
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('5'), |
|
|
|
symbol: 'AMZN', |
|
|
|
investment: new Big('10109.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-09-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, { |
|
|
|
quantity: new Big('25'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('4460.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 5 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('5'), |
|
|
|
symbol: 'AMZN', |
|
|
|
investment: new Big('10109.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-09-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
quantity: new Big('25'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('4460.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 5 |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
]); |
|
|
|
}); |
|
|
@ -265,173 +316,208 @@ describe('PortfolioCalculator', () => { |
|
|
|
currency: Currency.USD |
|
|
|
} |
|
|
|
]; |
|
|
|
const portfolioCalculator = new PortfolioCalculator(currentRateService, Currency.USD); |
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
currentRateService, |
|
|
|
Currency.USD |
|
|
|
); |
|
|
|
portfolioCalculator.computeTransactionPoints(orders); |
|
|
|
const portfolioItemsAtTransactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('25'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('4460.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 5 |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
]); |
|
|
|
}); |
|
|
|
|
|
|
|
it('with mixed symbols', () => { |
|
|
|
const portfolioCalculator = new PortfolioCalculator(currentRateService, Currency.USD); |
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
currentRateService, |
|
|
|
Currency.USD |
|
|
|
); |
|
|
|
portfolioCalculator.computeTransactionPoints(ordersMixedSymbols); |
|
|
|
const portfolioItemsAtTransactionPoints = portfolioCalculator.getTransactionPoints(); |
|
|
|
const portfolioItemsAtTransactionPoints = |
|
|
|
portfolioCalculator.getTransactionPoints(); |
|
|
|
|
|
|
|
expect(portfolioItemsAtTransactionPoints).toEqual([ |
|
|
|
{ |
|
|
|
date: '2017-01-03', |
|
|
|
items: [{ |
|
|
|
quantity: new Big('50'), |
|
|
|
symbol: 'TSLA', |
|
|
|
investment: new Big('2148.5'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-01-03', |
|
|
|
transactionCount: 1 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('50'), |
|
|
|
symbol: 'TSLA', |
|
|
|
investment: new Big('2148.5'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-01-03', |
|
|
|
transactionCount: 1 |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
{ |
|
|
|
date: '2017-07-01', |
|
|
|
items: [{ |
|
|
|
quantity: new Big('0.5614682'), |
|
|
|
symbol: 'BTCUSD', |
|
|
|
investment: new Big('1999.9999999999998659756'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-07-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, { |
|
|
|
quantity: new Big('50'), |
|
|
|
symbol: 'TSLA', |
|
|
|
investment: new Big('2148.5'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-01-03', |
|
|
|
transactionCount: 1 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('0.5614682'), |
|
|
|
symbol: 'BTCUSD', |
|
|
|
investment: new Big('1999.9999999999998659756'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-07-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
quantity: new Big('50'), |
|
|
|
symbol: 'TSLA', |
|
|
|
investment: new Big('2148.5'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-01-03', |
|
|
|
transactionCount: 1 |
|
|
|
} |
|
|
|
] |
|
|
|
}, |
|
|
|
{ |
|
|
|
date: '2018-09-01', |
|
|
|
items: [{ |
|
|
|
quantity: new Big('5'), |
|
|
|
symbol: 'AMZN', |
|
|
|
investment: new Big('10109.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2018-09-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, { |
|
|
|
quantity: new Big('0.5614682'), |
|
|
|
symbol: 'BTCUSD', |
|
|
|
investment: new Big('1999.9999999999998659756'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-07-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, { |
|
|
|
quantity: new Big('50'), |
|
|
|
symbol: 'TSLA', |
|
|
|
investment: new Big('2148.5'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-01-03', |
|
|
|
transactionCount: 1 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('5'), |
|
|
|
symbol: 'AMZN', |
|
|
|
investment: new Big('10109.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2018-09-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
quantity: new Big('0.5614682'), |
|
|
|
symbol: 'BTCUSD', |
|
|
|
investment: new Big('1999.9999999999998659756'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-07-01', |
|
|
|
transactionCount: 1 |
|
|
|
}, |
|
|
|
{ |
|
|
|
quantity: new Big('50'), |
|
|
|
symbol: 'TSLA', |
|
|
|
investment: new Big('2148.5'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2017-01-03', |
|
|
|
transactionCount: 1 |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
]); |
|
|
|
}); |
|
|
|
}); |
|
|
|
|
|
|
|
describe('get current positions', () => { |
|
|
|
|
|
|
|
it('with just VTI', async () => { |
|
|
|
const portfolioCalculator = new PortfolioCalculator(currentRateService, Currency.USD); |
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
currentRateService, |
|
|
|
Currency.USD |
|
|
|
); |
|
|
|
portfolioCalculator.setTransactionPoints(ordersVTITransactionPoints); |
|
|
|
const currentPositions = await portfolioCalculator.getCurrentPositions(); |
|
|
|
|
|
|
@ -447,12 +533,8 @@ describe('PortfolioCalculator', () => { |
|
|
|
transactionCount: 5 |
|
|
|
} |
|
|
|
}); |
|
|
|
|
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}) |
|
|
|
|
|
|
|
}); |
|
|
|
}); |
|
|
|
}); |
|
|
|
const ordersMixedSymbols: PortfolioOrder[] = [ |
|
|
|
{ |
|
|
@ -527,57 +609,67 @@ const ordersVTI: PortfolioOrder[] = [ |
|
|
|
const ordersVTITransactionPoints = [ |
|
|
|
{ |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
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: 'VTI', |
|
|
|
investment: new Big('652.55'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 3 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
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 |
|
|
|
}] |
|
|
|
items: [ |
|
|
|
{ |
|
|
|
quantity: new Big('25'), |
|
|
|
symbol: 'VTI', |
|
|
|
investment: new Big('4460.95'), |
|
|
|
currency: Currency.USD, |
|
|
|
firstBuyDate: '2019-02-01', |
|
|
|
transactionCount: 5 |
|
|
|
} |
|
|
|
] |
|
|
|
} |
|
|
|
]; |
|
|
|