|
|
@ -15,6 +15,7 @@ import { RulesService } from '@ghostfolio/api/services/rules.service'; |
|
|
|
import { |
|
|
|
PortfolioItem, |
|
|
|
PortfolioOverview, |
|
|
|
PortfolioPerformance, |
|
|
|
Position |
|
|
|
} from '@ghostfolio/common/interfaces'; |
|
|
|
import { DateRange, RequestWithUser } from '@ghostfolio/common/types'; |
|
|
@ -438,6 +439,64 @@ export class PortfolioService { |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
public async getPerformance( |
|
|
|
aImpersonationId: string, |
|
|
|
aDateRange: DateRange = 'max' |
|
|
|
): Promise<{ hasErrors: boolean; performance: PortfolioPerformance }> { |
|
|
|
const impersonationUserId = |
|
|
|
await this.impersonationService.validateImpersonationId( |
|
|
|
aImpersonationId, |
|
|
|
this.request.user.id |
|
|
|
); |
|
|
|
const userId = impersonationUserId || this.request.user.id; |
|
|
|
|
|
|
|
const portfolioCalculator = new PortfolioCalculator( |
|
|
|
this.currentRateService, |
|
|
|
this.request.user.Settings.currency |
|
|
|
); |
|
|
|
|
|
|
|
const transactionPoints = await this.getTransactionPoints(userId); |
|
|
|
|
|
|
|
portfolioCalculator.setTransactionPoints(transactionPoints); |
|
|
|
|
|
|
|
const portfolioStart = parseDate(transactionPoints[0].date); |
|
|
|
const startDate = this.getStartDate(aDateRange, portfolioStart); |
|
|
|
const currentPositions = await portfolioCalculator.getCurrentPositions( |
|
|
|
startDate |
|
|
|
); |
|
|
|
|
|
|
|
let currentValue = new Big(0); |
|
|
|
let grossPerformance = new Big(0); |
|
|
|
let grossPerformancePercentage = new Big(1); |
|
|
|
for (const currentPosition of currentPositions.positions) { |
|
|
|
currentValue = currentValue.add( |
|
|
|
new Big(currentPosition.marketPrice).mul(currentPosition.quantity) |
|
|
|
); |
|
|
|
grossPerformance = grossPerformance.plus( |
|
|
|
currentPosition.grossPerformance |
|
|
|
); |
|
|
|
grossPerformancePercentage = grossPerformancePercentage.mul( |
|
|
|
currentPosition.grossPerformancePercentage.plus(1) |
|
|
|
); |
|
|
|
} |
|
|
|
|
|
|
|
const currentGrossPerformance = grossPerformance.toNumber(); |
|
|
|
const currentGrossPerformancePercent = grossPerformancePercentage |
|
|
|
.minus(1) |
|
|
|
.toNumber(); |
|
|
|
return { |
|
|
|
hasErrors: currentPositions.hasErrors, |
|
|
|
performance: { |
|
|
|
currentGrossPerformance, |
|
|
|
currentGrossPerformancePercent, |
|
|
|
// TODO: the next two should include fees
|
|
|
|
currentNetPerformance: currentGrossPerformance, |
|
|
|
currentNetPerformancePercent: currentGrossPerformancePercent, |
|
|
|
currentValue: currentValue.toNumber() |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
private getStartDate(aDateRange: DateRange, portfolioStart: Date) { |
|
|
|
switch (aDateRange) { |
|
|
|
case '1d': |
|
|
|