Browse Source

Refactor PortfolioSnapshotProcessor

pull/3725/head
Thomas Kaul 12 months ago
parent
commit
0b1cadabd9
  1. 13
      apps/api/src/app/portfolio/calculator/portfolio-calculator.ts
  2. 9
      apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts
  3. 1
      apps/api/src/services/portfolio-snapshot/interfaces/portfolio-snapshot-queue-job.interface.ts
  4. 11
      apps/api/src/services/portfolio-snapshot/portfolio-snapshot.module.ts
  5. 42
      apps/api/src/services/portfolio-snapshot/portfolio-snapshot.processor.ts

13
apps/api/src/app/portfolio/calculator/portfolio-calculator.ts

@ -160,7 +160,7 @@ export abstract class PortfolioCalculator {
): PortfolioSnapshot; ): PortfolioSnapshot;
@LogPerformance @LogPerformance
private async computeSnapshot(): Promise<PortfolioSnapshot> { public async computeSnapshot(): Promise<PortfolioSnapshot> {
const lastTransactionPoint = last(this.transactionPoints); const lastTransactionPoint = last(this.transactionPoints);
const transactionPoints = this.transactionPoints?.filter(({ date }) => { const transactionPoints = this.transactionPoints?.filter(({ date }) => {
@ -1018,6 +1018,7 @@ export abstract class PortfolioCalculator {
let cachedPortfolioSnapshot: PortfolioSnapshot; let cachedPortfolioSnapshot: PortfolioSnapshot;
let isCachedPortfolioSnapshotExpired = false; let isCachedPortfolioSnapshotExpired = false;
const jobId = this.userId;
try { try {
const cachedPortfolioSnapshotValue = await this.redisCacheService.get( const cachedPortfolioSnapshotValue = await this.redisCacheService.get(
@ -1056,12 +1057,13 @@ export abstract class PortfolioCalculator {
this.portfolioSnapshotService.addJobToQueue({ this.portfolioSnapshotService.addJobToQueue({
data: { data: {
filters: this.filters, filters: this.filters,
userCurrency: this.currency,
userId: this.userId userId: this.userId
}, },
name: PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, name: PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME,
opts: { opts: {
...PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS ...PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS,
// jobId jobId
// priority // priority
} }
}); });
@ -1072,12 +1074,13 @@ export abstract class PortfolioCalculator {
const job = await this.portfolioSnapshotService.addJobToQueue({ const job = await this.portfolioSnapshotService.addJobToQueue({
data: { data: {
filters: this.filters, filters: this.filters,
userCurrency: this.currency,
userId: this.userId userId: this.userId
}, },
name: PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, name: PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME,
opts: { opts: {
...PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS ...PORTFOLIO_SNAPSHOT_PROCESS_JOB_OPTIONS,
// jobId jobId
// priority // priority
} }
}); });

9
apps/api/src/app/portfolio/calculator/twr/portfolio-calculator-novn-buy-and-sell.spec.ts

@ -14,7 +14,6 @@ import { RedisCacheService } from '@ghostfolio/api/app/redis-cache/redis-cache.s
import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock'; import { RedisCacheServiceMock } from '@ghostfolio/api/app/redis-cache/redis-cache.service.mock';
import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service'; import { ConfigurationService } from '@ghostfolio/api/services/configuration/configuration.service';
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 { PortfolioSnapshotProcessor } from '@ghostfolio/api/services/portfolio-snapshot/portfolio-snapshot.processor';
import { PortfolioSnapshotService } from '@ghostfolio/api/services/portfolio-snapshot/portfolio-snapshot.service'; import { PortfolioSnapshotService } from '@ghostfolio/api/services/portfolio-snapshot/portfolio-snapshot.service';
import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/portfolio-snapshot/portfolio-snapshot.service.mock'; import { PortfolioSnapshotServiceMock } from '@ghostfolio/api/services/portfolio-snapshot/portfolio-snapshot.service.mock';
import { parseDate } from '@ghostfolio/common/helper'; import { parseDate } from '@ghostfolio/common/helper';
@ -129,13 +128,7 @@ describe('PortfolioCalculator', () => {
userId: userDummyData.id userId: userDummyData.id
}); });
const portfolioSnapshotProcessor = new PortfolioSnapshotProcessor( const portfolioSnapshot = await portfolioCalculator.computeSnapshot();
null,
null
);
const portfolioSnapshot =
await portfolioSnapshotProcessor.computeSnapshot();
const investments = portfolioCalculator.getInvestments(); const investments = portfolioCalculator.getInvestments();

1
apps/api/src/services/portfolio-snapshot/interfaces/portfolio-snapshot-queue-job.interface.ts

@ -2,5 +2,6 @@ import { Filter } from '@ghostfolio/common/interfaces';
export interface IPortfolioSnapshotQueueJob { export interface IPortfolioSnapshotQueueJob {
filters: Filter[]; filters: Filter[];
userCurrency: string;
userId: string; userId: string;
} }

11
apps/api/src/services/portfolio-snapshot/portfolio-snapshot.module.ts

@ -1,3 +1,6 @@
import { OrderModule } from '@ghostfolio/api/app/order/order.module';
import { PortfolioCalculatorFactory } from '@ghostfolio/api/app/portfolio/calculator/portfolio-calculator.factory';
import { CurrentRateService } from '@ghostfolio/api/app/portfolio/current-rate.service';
import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module'; import { RedisCacheModule } from '@ghostfolio/api/app/redis-cache/redis-cache.module';
import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module'; import { ConfigurationModule } from '@ghostfolio/api/services/configuration/configuration.module';
import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module'; import { DataProviderModule } from '@ghostfolio/api/services/data-provider/data-provider.module';
@ -27,12 +30,18 @@ import { PortfolioSnapshotProcessor } from './portfolio-snapshot.processor';
DataProviderModule, DataProviderModule,
ExchangeRateDataModule, ExchangeRateDataModule,
MarketDataModule, MarketDataModule,
OrderModule,
PrismaModule, PrismaModule,
PropertyModule, PropertyModule,
RedisCacheModule, RedisCacheModule,
SymbolProfileModule SymbolProfileModule
], ],
providers: [PortfolioSnapshotProcessor, PortfolioSnapshotService], providers: [
CurrentRateService,
PortfolioCalculatorFactory,
PortfolioSnapshotProcessor,
PortfolioSnapshotService
],
exports: [BullModule, PortfolioSnapshotService] exports: [BullModule, PortfolioSnapshotService]
}) })
export class PortfolioSnapshotQueueModule {} export class PortfolioSnapshotQueueModule {}

42
apps/api/src/services/portfolio-snapshot/portfolio-snapshot.processor.ts

@ -1,3 +1,8 @@
import { OrderService } from '@ghostfolio/api/app/order/order.service';
import {
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';
@ -6,11 +11,9 @@ import {
PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME, PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME,
PORTFOLIO_SNAPSHOT_QUEUE PORTFOLIO_SNAPSHOT_QUEUE
} from '@ghostfolio/common/config'; } from '@ghostfolio/common/config';
import { PortfolioSnapshot } from '@ghostfolio/common/models';
import { Process, Processor } from '@nestjs/bull'; import { Process, Processor } from '@nestjs/bull';
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import * as Big from 'big.js';
import { Job } from 'bull'; import { Job } from 'bull';
import { addMilliseconds } from 'date-fns'; import { addMilliseconds } from 'date-fns';
@ -20,7 +23,9 @@ import { IPortfolioSnapshotQueueJob } from './interfaces/portfolio-snapshot-queu
@Processor(PORTFOLIO_SNAPSHOT_QUEUE) @Processor(PORTFOLIO_SNAPSHOT_QUEUE)
export class PortfolioSnapshotProcessor { export class PortfolioSnapshotProcessor {
public constructor( public constructor(
private readonly calculatorFactory: PortfolioCalculatorFactory,
private readonly configurationService: ConfigurationService, private readonly configurationService: ConfigurationService,
private readonly orderService: OrderService,
private readonly redisCacheService: RedisCacheService private readonly redisCacheService: RedisCacheService
) {} ) {}
@ -34,7 +39,22 @@ export class PortfolioSnapshotProcessor {
`PortfolioSnapshotProcessor (${PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME})` `PortfolioSnapshotProcessor (${PORTFOLIO_SNAPSHOT_PROCESS_JOB_NAME})`
); );
const snapshot = await this.computeSnapshot(); const { activities } =
await this.orderService.getOrdersForPortfolioCalculator({
filters: job.data.filters,
userCurrency: job.data.userCurrency,
userId: job.data.userId
});
const portfolioCalculator = this.calculatorFactory.createCalculator({
activities,
calculationType: PerformanceCalculationType.TWR,
currency: job.data.userCurrency,
filters: job.data.filters,
userId: job.data.userId
});
const snapshot = await portfolioCalculator.computeSnapshot();
Logger.log( Logger.log(
`Portfolio snapshot calculation of user ${job.data.userId} has been completed`, `Portfolio snapshot calculation of user ${job.data.userId} has been completed`,
@ -68,20 +88,4 @@ export class PortfolioSnapshotProcessor {
throw new Error(error); throw new Error(error);
} }
} }
// TODO
public async computeSnapshot(): Promise<PortfolioSnapshot> {
return {
currentValueInBaseCurrency: new Big(0),
hasErrors: false,
historicalData: [],
positions: [],
totalFeesWithCurrencyEffect: new Big(0),
totalInterestWithCurrencyEffect: new Big(0),
totalInvestment: new Big(0),
totalInvestmentWithCurrencyEffect: new Big(0),
totalLiabilitiesWithCurrencyEffect: new Big(0),
totalValuablesWithCurrencyEffect: new Big(0)
};
}
} }

Loading…
Cancel
Save