Feature/add performance calculation type to user settings (#4567)
* Add performance calculation type to user settings * Update changelog
This commit is contained in:
parent
26b705cfea
commit
71fc3906c7
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Extended the benchmark detail dialog by the current market price
|
- Extended the benchmark detail dialog by the current market price
|
||||||
|
- Added the performance calculation type to the user settings (experimental)
|
||||||
- Added `watchlist` to the `User` database schema as a preparation for watching assets
|
- Added `watchlist` to the `User` database schema as a preparation for watching assets
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
@ -4,12 +4,17 @@ import {
|
|||||||
SymbolMetrics
|
SymbolMetrics
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { PortfolioSnapshot } from '@ghostfolio/common/models';
|
import { PortfolioSnapshot } from '@ghostfolio/common/models';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
export class MwrPortfolioCalculator extends PortfolioCalculator {
|
export class MwrPortfolioCalculator extends PortfolioCalculator {
|
||||||
protected calculateOverallPerformance(): PortfolioSnapshot {
|
protected calculateOverallPerformance(): PortfolioSnapshot {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getPerformanceCalculationType() {
|
||||||
|
return PerformanceCalculationType.MWR;
|
||||||
|
}
|
||||||
|
|
||||||
protected getSymbolMetrics({}: {
|
protected getSymbolMetrics({}: {
|
||||||
end: Date;
|
end: Date;
|
||||||
exchangeRates: { [dateString: string]: number };
|
exchangeRates: { [dateString: string]: number };
|
||||||
|
@ -5,20 +5,16 @@ import { ConfigurationService } from '@ghostfolio/api/services/configuration/con
|
|||||||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
|
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data/exchange-rate-data.service';
|
||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { Filter, HistoricalDataItem } from '@ghostfolio/common/interfaces';
|
import { Filter, HistoricalDataItem } from '@ghostfolio/common/interfaces';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
|
|
||||||
import { MwrPortfolioCalculator } from './mwr/portfolio-calculator';
|
import { MwrPortfolioCalculator } from './mwr/portfolio-calculator';
|
||||||
import { PortfolioCalculator } from './portfolio-calculator';
|
import { PortfolioCalculator } from './portfolio-calculator';
|
||||||
import { RoaiPortfolioCalculator } from './roai/portfolio-calculator';
|
import { RoaiPortfolioCalculator } from './roai/portfolio-calculator';
|
||||||
|
import { RoiPortfolioCalculator } from './roi/portfolio-calculator';
|
||||||
import { TwrPortfolioCalculator } from './twr/portfolio-calculator';
|
import { TwrPortfolioCalculator } from './twr/portfolio-calculator';
|
||||||
|
|
||||||
export enum PerformanceCalculationType {
|
|
||||||
MWR = 'MWR', // Money-Weighted Rate of Return
|
|
||||||
ROAI = 'ROAI', // Return on Average Investment
|
|
||||||
TWR = 'TWR' // Time-Weighted Rate of Return
|
|
||||||
}
|
|
||||||
|
|
||||||
@Injectable()
|
@Injectable()
|
||||||
export class PortfolioCalculatorFactory {
|
export class PortfolioCalculatorFactory {
|
||||||
public constructor(
|
public constructor(
|
||||||
@ -58,6 +54,7 @@ export class PortfolioCalculatorFactory {
|
|||||||
portfolioSnapshotService: this.portfolioSnapshotService,
|
portfolioSnapshotService: this.portfolioSnapshotService,
|
||||||
redisCacheService: this.redisCacheService
|
redisCacheService: this.redisCacheService
|
||||||
});
|
});
|
||||||
|
|
||||||
case PerformanceCalculationType.ROAI:
|
case PerformanceCalculationType.ROAI:
|
||||||
return new RoaiPortfolioCalculator({
|
return new RoaiPortfolioCalculator({
|
||||||
accountBalanceItems,
|
accountBalanceItems,
|
||||||
@ -71,6 +68,21 @@ export class PortfolioCalculatorFactory {
|
|||||||
portfolioSnapshotService: this.portfolioSnapshotService,
|
portfolioSnapshotService: this.portfolioSnapshotService,
|
||||||
redisCacheService: this.redisCacheService
|
redisCacheService: this.redisCacheService
|
||||||
});
|
});
|
||||||
|
|
||||||
|
case PerformanceCalculationType.ROI:
|
||||||
|
return new RoiPortfolioCalculator({
|
||||||
|
accountBalanceItems,
|
||||||
|
activities,
|
||||||
|
currency,
|
||||||
|
filters,
|
||||||
|
userId,
|
||||||
|
configurationService: this.configurationService,
|
||||||
|
currentRateService: this.currentRateService,
|
||||||
|
exchangeRateDataService: this.exchangeRateDataService,
|
||||||
|
portfolioSnapshotService: this.portfolioSnapshotService,
|
||||||
|
redisCacheService: this.redisCacheService
|
||||||
|
});
|
||||||
|
|
||||||
case PerformanceCalculationType.TWR:
|
case PerformanceCalculationType.TWR:
|
||||||
return new TwrPortfolioCalculator({
|
return new TwrPortfolioCalculator({
|
||||||
accountBalanceItems,
|
accountBalanceItems,
|
||||||
@ -84,6 +96,7 @@ export class PortfolioCalculatorFactory {
|
|||||||
portfolioSnapshotService: this.portfolioSnapshotService,
|
portfolioSnapshotService: this.portfolioSnapshotService,
|
||||||
redisCacheService: this.redisCacheService
|
redisCacheService: this.redisCacheService
|
||||||
});
|
});
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new Error('Invalid calculation type');
|
throw new Error('Invalid calculation type');
|
||||||
}
|
}
|
||||||
|
@ -35,6 +35,7 @@ import {
|
|||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models';
|
import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models';
|
||||||
import { GroupBy } from '@ghostfolio/common/types';
|
import { GroupBy } from '@ghostfolio/common/types';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
@ -623,6 +624,8 @@ export abstract class PortfolioCalculator {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected abstract getPerformanceCalculationType(): PerformanceCalculationType;
|
||||||
|
|
||||||
public getDataProviderInfos() {
|
public getDataProviderInfos() {
|
||||||
return this.dataProviderInfos;
|
return this.dataProviderInfos;
|
||||||
}
|
}
|
||||||
@ -1073,6 +1076,7 @@ export abstract class PortfolioCalculator {
|
|||||||
// Compute in the background
|
// Compute in the background
|
||||||
this.portfolioSnapshotService.addJobToQueue({
|
this.portfolioSnapshotService.addJobToQueue({
|
||||||
data: {
|
data: {
|
||||||
|
calculationType: this.getPerformanceCalculationType(),
|
||||||
filters: this.filters,
|
filters: this.filters,
|
||||||
userCurrency: this.currency,
|
userCurrency: this.currency,
|
||||||
userId: this.userId
|
userId: this.userId
|
||||||
@ -1089,6 +1093,7 @@ export abstract class PortfolioCalculator {
|
|||||||
// Wait for computation
|
// Wait for computation
|
||||||
await this.portfolioSnapshotService.addJobToQueue({
|
await this.portfolioSnapshotService.addJobToQueue({
|
||||||
data: {
|
data: {
|
||||||
|
calculationType: this.getPerformanceCalculationType(),
|
||||||
filters: this.filters,
|
filters: this.filters,
|
||||||
userCurrency: this.currency,
|
userCurrency: this.currency,
|
||||||
userId: this.userId
|
userId: this.userId
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -18,6 +15,7 @@ import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-r
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -18,6 +15,7 @@ import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-r
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PortfolioCalculatorFactory,
|
|
||||||
PerformanceCalculationType
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -17,6 +14,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -4,10 +4,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -18,6 +15,7 @@ import { ExchangeRateDataServiceMock } from '@ghostfolio/api/services/exchange-r
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -1,8 +1,5 @@
|
|||||||
import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
import { userDummyData } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -12,6 +9,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
|
|
||||||
|
@ -6,10 +6,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -19,6 +16,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
@ -6,10 +6,7 @@ import {
|
|||||||
symbolProfileDummyData,
|
symbolProfileDummyData,
|
||||||
userDummyData
|
userDummyData
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator-test-utils';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
|
||||||
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
import { CurrentRateServiceMock } from '@ghostfolio/api/app/portfolio/current-rate.service.mock';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
@ -19,6 +16,7 @@ import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-
|
|||||||
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
import { PortfolioSnapshotService } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service';
|
||||||
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/queues/portfolio-snapshot/portfolio-snapshot.service.mock';
|
||||||
import { parseDate } from '@ghostfolio/common/helper';
|
import { parseDate } from '@ghostfolio/common/helper';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
import { join } from 'path';
|
import { join } from 'path';
|
||||||
|
@ -9,6 +9,7 @@ import {
|
|||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models';
|
import { PortfolioSnapshot, TimelinePosition } from '@ghostfolio/common/models';
|
||||||
import { DateRange } from '@ghostfolio/common/types';
|
import { DateRange } from '@ghostfolio/common/types';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Logger } from '@nestjs/common';
|
import { Logger } from '@nestjs/common';
|
||||||
import { Big } from 'big.js';
|
import { Big } from 'big.js';
|
||||||
@ -112,6 +113,10 @@ export class RoaiPortfolioCalculator extends PortfolioCalculator {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getPerformanceCalculationType() {
|
||||||
|
return PerformanceCalculationType.ROAI;
|
||||||
|
}
|
||||||
|
|
||||||
protected getSymbolMetrics({
|
protected getSymbolMetrics({
|
||||||
chartDateMap,
|
chartDateMap,
|
||||||
dataSource,
|
dataSource,
|
||||||
|
@ -0,0 +1,29 @@
|
|||||||
|
import { PortfolioCalculator } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator';
|
||||||
|
import {
|
||||||
|
AssetProfileIdentifier,
|
||||||
|
SymbolMetrics
|
||||||
|
} from '@ghostfolio/common/interfaces';
|
||||||
|
import { PortfolioSnapshot } from '@ghostfolio/common/models';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
|
export class RoiPortfolioCalculator extends PortfolioCalculator {
|
||||||
|
protected calculateOverallPerformance(): PortfolioSnapshot {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getPerformanceCalculationType() {
|
||||||
|
return PerformanceCalculationType.ROI;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected getSymbolMetrics({}: {
|
||||||
|
end: Date;
|
||||||
|
exchangeRates: { [dateString: string]: number };
|
||||||
|
marketSymbolMap: {
|
||||||
|
[date: string]: { [symbol: string]: Big };
|
||||||
|
};
|
||||||
|
start: Date;
|
||||||
|
step?: number;
|
||||||
|
} & AssetProfileIdentifier): SymbolMetrics {
|
||||||
|
throw new Error('Method not implemented.');
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,17 @@ import {
|
|||||||
SymbolMetrics
|
SymbolMetrics
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { PortfolioSnapshot } from '@ghostfolio/common/models';
|
import { PortfolioSnapshot } from '@ghostfolio/common/models';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
export class TwrPortfolioCalculator extends PortfolioCalculator {
|
export class TwrPortfolioCalculator extends PortfolioCalculator {
|
||||||
protected calculateOverallPerformance(): PortfolioSnapshot {
|
protected calculateOverallPerformance(): PortfolioSnapshot {
|
||||||
throw new Error('Method not implemented.');
|
throw new Error('Method not implemented.');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected getPerformanceCalculationType() {
|
||||||
|
return PerformanceCalculationType.TWR;
|
||||||
|
}
|
||||||
|
|
||||||
protected getSymbolMetrics({}: {
|
protected getSymbolMetrics({}: {
|
||||||
end: Date;
|
end: Date;
|
||||||
exchangeRates: { [dateString: string]: number };
|
exchangeRates: { [dateString: string]: number };
|
||||||
|
@ -50,13 +50,14 @@ import {
|
|||||||
UserSettings
|
UserSettings
|
||||||
} from '@ghostfolio/common/interfaces';
|
} from '@ghostfolio/common/interfaces';
|
||||||
import { TimelinePosition } from '@ghostfolio/common/models';
|
import { TimelinePosition } from '@ghostfolio/common/models';
|
||||||
import type {
|
import {
|
||||||
AccountWithValue,
|
AccountWithValue,
|
||||||
DateRange,
|
DateRange,
|
||||||
GroupBy,
|
GroupBy,
|
||||||
RequestWithUser,
|
RequestWithUser,
|
||||||
UserWithSettings
|
UserWithSettings
|
||||||
} from '@ghostfolio/common/types';
|
} from '@ghostfolio/common/types';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Inject, Injectable } from '@nestjs/common';
|
import { Inject, Injectable } from '@nestjs/common';
|
||||||
import { REQUEST } from '@nestjs/core';
|
import { REQUEST } from '@nestjs/core';
|
||||||
@ -85,10 +86,7 @@ import {
|
|||||||
import { isEmpty } from 'lodash';
|
import { isEmpty } from 'lodash';
|
||||||
|
|
||||||
import { PortfolioCalculator } from './calculator/portfolio-calculator';
|
import { PortfolioCalculator } from './calculator/portfolio-calculator';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from './calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from './calculator/portfolio-calculator.factory';
|
|
||||||
import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface';
|
import { PortfolioHoldingDetail } from './interfaces/portfolio-holding-detail.interface';
|
||||||
import { RulesService } from './rules.service';
|
import { RulesService } from './rules.service';
|
||||||
|
|
||||||
@ -278,14 +276,16 @@ export class PortfolioService {
|
|||||||
savingsRate: number;
|
savingsRate: number;
|
||||||
}): Promise<PortfolioInvestments> {
|
}): Promise<PortfolioInvestments> {
|
||||||
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
||||||
|
const user = await this.userService.user({ id: userId });
|
||||||
|
const userCurrency = this.getUserCurrency(user);
|
||||||
|
|
||||||
const { endDate, startDate } = getIntervalFromDateRange(dateRange);
|
const { endDate, startDate } = getIntervalFromDateRange(dateRange);
|
||||||
|
|
||||||
const { activities } =
|
const { activities } =
|
||||||
await this.orderService.getOrdersForPortfolioCalculator({
|
await this.orderService.getOrdersForPortfolioCalculator({
|
||||||
filters,
|
filters,
|
||||||
userId,
|
userCurrency,
|
||||||
userCurrency: this.getUserCurrency()
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (activities.length === 0) {
|
if (activities.length === 0) {
|
||||||
@ -299,8 +299,8 @@ export class PortfolioService {
|
|||||||
activities,
|
activities,
|
||||||
filters,
|
filters,
|
||||||
userId,
|
userId,
|
||||||
calculationType: PerformanceCalculationType.ROAI,
|
calculationType: this.getUserPerformanceCalculationType(user),
|
||||||
currency: this.request.user.Settings.settings.baseCurrency
|
currency: userCurrency
|
||||||
});
|
});
|
||||||
|
|
||||||
const { historicalData } = await portfolioCalculator.getSnapshot();
|
const { historicalData } = await portfolioCalculator.getSnapshot();
|
||||||
@ -376,7 +376,7 @@ export class PortfolioService {
|
|||||||
activities,
|
activities,
|
||||||
filters,
|
filters,
|
||||||
userId,
|
userId,
|
||||||
calculationType: PerformanceCalculationType.ROAI,
|
calculationType: this.getUserPerformanceCalculationType(user),
|
||||||
currency: userCurrency
|
currency: userCurrency
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -684,7 +684,7 @@ export class PortfolioService {
|
|||||||
const portfolioCalculator = this.calculatorFactory.createCalculator({
|
const portfolioCalculator = this.calculatorFactory.createCalculator({
|
||||||
activities,
|
activities,
|
||||||
userId,
|
userId,
|
||||||
calculationType: PerformanceCalculationType.ROAI,
|
calculationType: this.getUserPerformanceCalculationType(user),
|
||||||
currency: userCurrency
|
currency: userCurrency
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -935,12 +935,13 @@ export class PortfolioService {
|
|||||||
})?.id;
|
})?.id;
|
||||||
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
const userId = await this.getUserId(impersonationId, this.request.user.id);
|
||||||
const user = await this.userService.user({ id: userId });
|
const user = await this.userService.user({ id: userId });
|
||||||
|
const userCurrency = this.getUserCurrency(user);
|
||||||
|
|
||||||
const { activities } =
|
const { activities } =
|
||||||
await this.orderService.getOrdersForPortfolioCalculator({
|
await this.orderService.getOrdersForPortfolioCalculator({
|
||||||
filters,
|
filters,
|
||||||
userId,
|
userCurrency,
|
||||||
userCurrency: this.getUserCurrency()
|
userId
|
||||||
});
|
});
|
||||||
|
|
||||||
if (activities.length === 0) {
|
if (activities.length === 0) {
|
||||||
@ -954,8 +955,8 @@ export class PortfolioService {
|
|||||||
activities,
|
activities,
|
||||||
filters,
|
filters,
|
||||||
userId,
|
userId,
|
||||||
calculationType: PerformanceCalculationType.ROAI,
|
calculationType: this.getUserPerformanceCalculationType(user),
|
||||||
currency: this.request.user.Settings.settings.baseCurrency
|
currency: userCurrency
|
||||||
});
|
});
|
||||||
|
|
||||||
const portfolioSnapshot = await portfolioCalculator.getSnapshot();
|
const portfolioSnapshot = await portfolioCalculator.getSnapshot();
|
||||||
@ -1120,7 +1121,7 @@ export class PortfolioService {
|
|||||||
activities,
|
activities,
|
||||||
filters,
|
filters,
|
||||||
userId,
|
userId,
|
||||||
calculationType: PerformanceCalculationType.ROAI,
|
calculationType: this.getUserPerformanceCalculationType(user),
|
||||||
currency: userCurrency
|
currency: userCurrency
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -2021,6 +2022,12 @@ export class PortfolioService {
|
|||||||
return impersonationUserId || aUserId;
|
return impersonationUserId || aUserId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private getUserPerformanceCalculationType(
|
||||||
|
aUser: UserWithSettings
|
||||||
|
): PerformanceCalculationType {
|
||||||
|
return aUser?.Settings?.settings.performanceCalculationType;
|
||||||
|
}
|
||||||
|
|
||||||
private async getValueOfAccountsAndPlatforms({
|
private async getValueOfAccountsAndPlatforms({
|
||||||
activities,
|
activities,
|
||||||
filters = [],
|
filters = [],
|
||||||
|
@ -41,6 +41,7 @@ import {
|
|||||||
permissions
|
permissions
|
||||||
} from '@ghostfolio/common/permissions';
|
} from '@ghostfolio/common/permissions';
|
||||||
import { UserWithSettings } from '@ghostfolio/common/types';
|
import { UserWithSettings } from '@ghostfolio/common/types';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
import { Injectable } from '@nestjs/common';
|
import { Injectable } from '@nestjs/common';
|
||||||
import { EventEmitter2 } from '@nestjs/event-emitter';
|
import { EventEmitter2 } from '@nestjs/event-emitter';
|
||||||
@ -246,6 +247,12 @@ export class UserService {
|
|||||||
? 'max'
|
? 'max'
|
||||||
: ((user.Settings.settings as UserSettings)?.dateRange ?? 'max');
|
: ((user.Settings.settings as UserSettings)?.dateRange ?? 'max');
|
||||||
|
|
||||||
|
// Set default value for performance calculation type
|
||||||
|
if (!(user.Settings.settings as UserSettings)?.performanceCalculationType) {
|
||||||
|
(user.Settings.settings as UserSettings).performanceCalculationType =
|
||||||
|
PerformanceCalculationType.ROAI;
|
||||||
|
}
|
||||||
|
|
||||||
// Set default value for view mode
|
// Set default value for view mode
|
||||||
if (!(user.Settings.settings as UserSettings).viewMode) {
|
if (!(user.Settings.settings as UserSettings).viewMode) {
|
||||||
(user.Settings.settings as UserSettings).viewMode = 'DEFAULT';
|
(user.Settings.settings as UserSettings).viewMode = 'DEFAULT';
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
import { Filter } from '@ghostfolio/common/interfaces';
|
import { Filter } from '@ghostfolio/common/interfaces';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
export interface IPortfolioSnapshotQueueJob {
|
export interface IPortfolioSnapshotQueueJob {
|
||||||
|
calculationType: PerformanceCalculationType;
|
||||||
filters: Filter[];
|
filters: Filter[];
|
||||||
userCurrency: string;
|
userCurrency: string;
|
||||||
userId: string;
|
userId: string;
|
||||||
|
@ -1,9 +1,6 @@
|
|||||||
import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service';
|
import { AccountBalanceService } from '@ghostfolio/api/app/account-balance/account-balance.service';
|
||||||
import { OrderService } from '@ghostfolio/api/app/order/order.service';
|
import { OrderService } from '@ghostfolio/api/app/order/order.service';
|
||||||
import {
|
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
||||||
PerformanceCalculationType,
|
|
||||||
PortfolioCalculatorFactory
|
|
||||||
} from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
|
|
||||||
import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface';
|
import { PortfolioSnapshotValue } from '@ghostfolio/api/app/portfolio/interfaces/snapshot-value.interface';
|
||||||
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.service';
|
||||||
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
|
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
|
||||||
@ -68,7 +65,7 @@ export class PortfolioSnapshotProcessor {
|
|||||||
const portfolioCalculator = this.calculatorFactory.createCalculator({
|
const portfolioCalculator = this.calculatorFactory.createCalculator({
|
||||||
accountBalanceItems,
|
accountBalanceItems,
|
||||||
activities,
|
activities,
|
||||||
calculationType: PerformanceCalculationType.ROAI,
|
calculationType: job.data.calculationType,
|
||||||
currency: job.data.userCurrency,
|
currency: job.data.userCurrency,
|
||||||
filters: job.data.filters,
|
filters: job.data.filters,
|
||||||
userId: job.data.userId
|
userId: job.data.userId
|
||||||
|
@ -2,25 +2,7 @@
|
|||||||
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Settings</h1>
|
<h1 class="d-none d-sm-block h3 mb-3 text-center" i18n>Settings</h1>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col">
|
<div class="col">
|
||||||
<div class="align-items-center d-flex py-1">
|
<div class="d-flex py-1">
|
||||||
<div class="pr-1 w-50">
|
|
||||||
<div i18n>Presenter View</div>
|
|
||||||
<div class="hint-text text-muted" i18n>
|
|
||||||
Protection for sensitive information like absolute performances and
|
|
||||||
quantity values
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pl-1 w-50">
|
|
||||||
<mat-slide-toggle
|
|
||||||
color="primary"
|
|
||||||
hideIcon="true"
|
|
||||||
[checked]="user.settings.isRestrictedView"
|
|
||||||
[disabled]="!hasPermissionToUpdateUserSettings"
|
|
||||||
(change)="onRestrictedViewChange($event)"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="d-flex mt-4 py-1">
|
|
||||||
<form #changeUserSettingsForm="ngForm" class="w-100">
|
<form #changeUserSettingsForm="ngForm" class="w-100">
|
||||||
<div class="d-flex mb-2">
|
<div class="d-flex mb-2">
|
||||||
<div class="align-items-center d-flex pt-1 pt-1 w-50">
|
<div class="align-items-center d-flex pt-1 pt-1 w-50">
|
||||||
@ -43,6 +25,32 @@
|
|||||||
</mat-form-field>
|
</mat-form-field>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@if (user?.settings?.isExperimentalFeatures && !user?.subscription) {
|
||||||
|
<div class="d-flex mb-2">
|
||||||
|
<div class="align-items-center d-flex pt-1 pt-1 w-50">
|
||||||
|
<ng-container i18n>Performance Calculation</ng-container>
|
||||||
|
</div>
|
||||||
|
<div class="pl-1 w-50">
|
||||||
|
<mat-form-field appearance="outline" class="w-100 without-hint">
|
||||||
|
<mat-select
|
||||||
|
name="performanceCalculationType"
|
||||||
|
[disabled]="true"
|
||||||
|
[value]="user.settings.performanceCalculationType"
|
||||||
|
(selectionChange)="
|
||||||
|
onChangeUserSetting(
|
||||||
|
'performanceCalculationType',
|
||||||
|
$event.value
|
||||||
|
)
|
||||||
|
"
|
||||||
|
>
|
||||||
|
<mat-option value="ROAI"
|
||||||
|
>Return on Average Investment (ROAI)</mat-option
|
||||||
|
>
|
||||||
|
</mat-select>
|
||||||
|
</mat-form-field>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
}
|
||||||
<div class="align-items-center d-flex mb-2">
|
<div class="align-items-center d-flex mb-2">
|
||||||
<div class="pr-1 w-50">
|
<div class="pr-1 w-50">
|
||||||
<div i18n>Language</div>
|
<div i18n>Language</div>
|
||||||
@ -172,6 +180,24 @@
|
|||||||
</div>
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="align-items-center d-flex mt-4 py-1">
|
||||||
|
<div class="pr-1 w-50">
|
||||||
|
<div i18n>Presenter View</div>
|
||||||
|
<div class="hint-text text-muted" i18n>
|
||||||
|
Protection for sensitive information like absolute performances and
|
||||||
|
quantity values
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="pl-1 w-50">
|
||||||
|
<mat-slide-toggle
|
||||||
|
color="primary"
|
||||||
|
hideIcon="true"
|
||||||
|
[checked]="user.settings.isRestrictedView"
|
||||||
|
[disabled]="!hasPermissionToUpdateUserSettings"
|
||||||
|
(change)="onRestrictedViewChange($event)"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
<div class="d-flex mt-4 py-1">
|
<div class="d-flex mt-4 py-1">
|
||||||
<div class="pr-1 w-50">
|
<div class="pr-1 w-50">
|
||||||
<div i18n>Zen Mode</div>
|
<div i18n>Zen Mode</div>
|
||||||
|
@ -5,6 +5,7 @@ import {
|
|||||||
HoldingsViewMode,
|
HoldingsViewMode,
|
||||||
ViewMode
|
ViewMode
|
||||||
} from '@ghostfolio/common/types';
|
} from '@ghostfolio/common/types';
|
||||||
|
import { PerformanceCalculationType } from '@ghostfolio/common/types/performance-calculation-type.type';
|
||||||
|
|
||||||
export interface UserSettings {
|
export interface UserSettings {
|
||||||
annualInterestRate?: number;
|
annualInterestRate?: number;
|
||||||
@ -22,6 +23,7 @@ export interface UserSettings {
|
|||||||
isRestrictedView?: boolean;
|
isRestrictedView?: boolean;
|
||||||
language?: string;
|
language?: string;
|
||||||
locale?: string;
|
locale?: string;
|
||||||
|
performanceCalculationType?: PerformanceCalculationType;
|
||||||
projectedTotalAmount?: number;
|
projectedTotalAmount?: number;
|
||||||
retirementDate?: string;
|
retirementDate?: string;
|
||||||
savingsRate?: number;
|
savingsRate?: number;
|
||||||
|
@ -0,0 +1,6 @@
|
|||||||
|
export enum PerformanceCalculationType {
|
||||||
|
MWR = 'MWR', // Money-Weighted Rate of Return
|
||||||
|
ROAI = 'ROAI', // Return on Average Investment
|
||||||
|
ROI = 'ROI', // Return on Investment
|
||||||
|
TWR = 'TWR' // Time-Weighted Rate of Return
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user