Browse Source

Add start date and normalize benchmark

pull/1230/head
Thomas 3 years ago
parent
commit
73bfc4cfdf
  1. 11
      apps/api/src/app/benchmark/benchmark.controller.ts
  2. 19
      apps/api/src/app/benchmark/benchmark.service.ts
  3. 10
      apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts
  4. 15
      apps/client/src/app/services/data.service.ts

11
apps/api/src/app/benchmark/benchmark.controller.ts

@ -29,13 +29,20 @@ export class BenchmarkController {
}; };
} }
@Get(':dataSource/:symbol') @Get(':dataSource/:symbol/:startDateString')
@UseInterceptors(TransformDataSourceInRequestInterceptor) @UseInterceptors(TransformDataSourceInRequestInterceptor)
@UseGuards(AuthGuard('jwt')) @UseGuards(AuthGuard('jwt'))
public async getBenchmarkMarketDataBySymbol( public async getBenchmarkMarketDataBySymbol(
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('startDateString') startDateString: string,
@Param('symbol') symbol: string @Param('symbol') symbol: string
): Promise<BenchmarkMarketDataDetails> { ): Promise<BenchmarkMarketDataDetails> {
return this.benchmarkService.getMarketDataBySymbol({ dataSource, symbol }); const startDate = new Date(startDateString);
return this.benchmarkService.getMarketDataBySymbol({
dataSource,
startDate,
symbol
});
} }
} }

19
apps/api/src/app/benchmark/benchmark.service.ts

@ -119,23 +119,36 @@ export class BenchmarkService {
public async getMarketDataBySymbol({ public async getMarketDataBySymbol({
dataSource, dataSource,
startDate,
symbol symbol
}: UniqueAsset): Promise<BenchmarkMarketDataDetails> { }: { startDate: Date } & UniqueAsset): Promise<BenchmarkMarketDataDetails> {
const marketDataItems = await this.marketDataService.marketDataItems({ const marketDataItems = await this.marketDataService.marketDataItems({
orderBy: { orderBy: {
date: 'asc' date: 'asc'
}, },
where: { where: {
dataSource, dataSource,
symbol symbol,
date: {
gte: startDate
}
} }
}); });
const marketPriceAtStartDate = new Big(
marketDataItems?.[0]?.marketPrice ?? 0
);
return { return {
marketData: marketDataItems.map((marketDataItem) => { marketData: marketDataItems.map((marketDataItem) => {
return { return {
date: format(marketDataItem.date, DATE_FORMAT), date: format(marketDataItem.date, DATE_FORMAT),
value: marketDataItem.marketPrice value: marketPriceAtStartDate.eq(0)
? 0
: new Big(marketDataItem.marketPrice)
.div(marketPriceAtStartDate)
.minus(1)
.toNumber() * 100
}; };
}) })
}; };

10
apps/client/src/app/pages/portfolio/analysis/analysis-page.component.ts

@ -28,6 +28,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
public bottom3: Position[]; public bottom3: Position[];
public daysInMarket: number; public daysInMarket: number;
public deviceType: string; public deviceType: string;
public firstOrderDate: Date;
public hasImpersonationId: boolean; public hasImpersonationId: boolean;
public investments: InvestmentItem[]; public investments: InvestmentItem[];
public investmentsByMonth: InvestmentItem[]; public investmentsByMonth: InvestmentItem[];
@ -67,6 +68,7 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
.fetchChart({ range: 'max', version: 2 }) .fetchChart({ range: 'max', version: 2 })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ chart }) => { .subscribe(({ chart }) => {
this.firstOrderDate = new Date(chart?.[0]?.date);
this.performanceDataItems = chart; this.performanceDataItems = chart;
this.changeDetectorRef.markForCheck(); this.changeDetectorRef.markForCheck();
@ -122,9 +124,13 @@ export class AnalysisPageComponent implements OnDestroy, OnInit {
}); });
} }
public onChangeBenchmark(aBenchmark: UniqueAsset) { public onChangeBenchmark({ dataSource, symbol }: UniqueAsset) {
this.dataService this.dataService
.fetchBenchmarkBySymbol(aBenchmark) .fetchBenchmarkBySymbol({
dataSource,
symbol,
startDate: this.firstOrderDate
})
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))
.subscribe(({ marketData }) => { .subscribe(({ marketData }) => {
this.benchmarkDataItems = marketData.map(({ date, value }) => { this.benchmarkDataItems = marketData.map(({ date, value }) => {

15
apps/client/src/app/services/data.service.ts

@ -14,6 +14,7 @@ import { UserItem } from '@ghostfolio/api/app/user/interfaces/user-item.interfac
import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto'; import { UpdateUserSettingDto } from '@ghostfolio/api/app/user/update-user-setting.dto';
import { UpdateUserSettingsDto } from '@ghostfolio/api/app/user/update-user-settings.dto'; import { UpdateUserSettingsDto } from '@ghostfolio/api/app/user/update-user-settings.dto';
import { PropertyDto } from '@ghostfolio/api/services/property/property.dto'; import { PropertyDto } from '@ghostfolio/api/services/property/property.dto';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { import {
Access, Access,
Accounts, Accounts,
@ -32,12 +33,13 @@ import {
PortfolioPublicDetails, PortfolioPublicDetails,
PortfolioReport, PortfolioReport,
PortfolioSummary, PortfolioSummary,
UniqueAsset,
User User
} from '@ghostfolio/common/interfaces'; } from '@ghostfolio/common/interfaces';
import { filterGlobalPermissions } from '@ghostfolio/common/permissions'; import { filterGlobalPermissions } from '@ghostfolio/common/permissions';
import { AccountWithValue, DateRange } from '@ghostfolio/common/types'; import { AccountWithValue, DateRange } from '@ghostfolio/common/types';
import { DataSource, Order as OrderModel } from '@prisma/client'; import { DataSource, Order as OrderModel } from '@prisma/client';
import { parseISO } from 'date-fns'; import { format, parseISO } from 'date-fns';
import { cloneDeep, groupBy } from 'lodash'; import { cloneDeep, groupBy } from 'lodash';
import { Observable } from 'rxjs'; import { Observable } from 'rxjs';
import { map } from 'rxjs/operators'; import { map } from 'rxjs/operators';
@ -184,13 +186,16 @@ export class DataService {
public fetchBenchmarkBySymbol({ public fetchBenchmarkBySymbol({
dataSource, dataSource,
startDate,
symbol symbol
}: { }: {
dataSource: DataSource; startDate: Date;
symbol: string; } & UniqueAsset): Observable<BenchmarkMarketDataDetails> {
}): Observable<BenchmarkMarketDataDetails> {
return this.http.get<BenchmarkMarketDataDetails>( return this.http.get<BenchmarkMarketDataDetails>(
`/api/v1/benchmark/${dataSource}/${symbol}` `/api/v1/benchmark/${dataSource}/${symbol}/${format(
startDate,
DATE_FORMAT
)}`
); );
} }

Loading…
Cancel
Save