Browse Source

Refactoring

pull/2575/head
Thomas 2 years ago
parent
commit
75ba2c595e
  1. 35
      apps/api/src/app/benchmark/benchmark.service.ts
  2. 59
      libs/common/src/lib/helper.ts
  3. 3
      libs/common/src/lib/interfaces/benchmark.interface.ts
  4. 0
      libs/common/src/lib/types/benchmark-trend.type.ts
  5. 2
      libs/common/src/lib/types/index.ts

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

@ -19,7 +19,7 @@ import {
BenchmarkResponse,
UniqueAsset
} from '@ghostfolio/common/interfaces';
import { BenchmarkTrend } from '@ghostfolio/common/types/benchmark-trend-type.type';
import { BenchmarkTrend } from '@ghostfolio/common/types';
import { Injectable, Logger } from '@nestjs/common';
import { DataSource, SymbolProfile } from '@prisma/client';
import Big from 'big.js';
@ -49,29 +49,28 @@ export class BenchmarkService {
return 0;
}
public async getBenchMarkTrends(dataSource: DataSource, symbol: string) {
return this.marketDataService
.marketDataItems({
public async getBenchmarkTrends({ dataSource, symbol }: UniqueAsset) {
const historicalData = await this.marketDataService.marketDataItems({
orderBy: {
date: 'desc'
},
select: {
date: true,
marketPrice: true
},
where: {
dataSource,
symbol,
date: { gte: subDays(new Date(), 400) }
}
})
.then((historicalData) => {
const fiftyDayAvg = calculateBenchmarkTrend(historicalData, 50);
const twoHundrredDayAvg = calculateBenchmarkTrend(historicalData, 200);
Logger.debug(`50d: ${fiftyDayAvg} and 200d: ${twoHundrredDayAvg}`);
});
return { trend200d: twoHundrredDayAvg, trend50d: fiftyDayAvg };
const fiftyDayAverage = calculateBenchmarkTrend({
historicalData,
days: 50
});
const twoHundredDayAverage = calculateBenchmarkTrend({
historicalData,
days: 200
});
return { trend50d: fiftyDayAverage, trend200d: twoHundredDayAverage };
}
public async getBenchmarks({ useCache = true } = {}): Promise<
@ -94,7 +93,7 @@ export class BenchmarkService {
const benchmarkAssetProfiles = await this.getBenchmarkAssetProfiles();
const promises: Promise<{ date: Date; marketPrice: number }>[] = [];
const movingAvgPromises: Promise<{
const movingAveragePromises: Promise<{
trend50d: BenchmarkTrend;
trend200d: BenchmarkTrend;
}>[] = [];
@ -107,12 +106,14 @@ export class BenchmarkService {
for (const { dataSource, symbol } of benchmarkAssetProfiles) {
promises.push(this.marketDataService.getMax({ dataSource, symbol }));
movingAvgPromises.push(this.getBenchMarkTrends(dataSource, symbol));
movingAveragePromises.push(
this.getBenchmarkTrends({ dataSource, symbol })
);
}
const [allTimeHighs, benchmarkTrends] = await Promise.all([
Promise.all(promises),
Promise.all(movingAvgPromises)
Promise.all(movingAveragePromises)
]);
let storeInCache = true;

59
libs/common/src/lib/helper.ts

@ -14,8 +14,7 @@ import { de, es, fr, it, nl, pl, pt, tr } from 'date-fns/locale';
import { ghostfolioScraperApiSymbolPrefix, locale } from './config';
import { Benchmark, UniqueAsset } from './interfaces';
import { ColorScheme } from './types';
import { BenchmarkTrend } from './types/benchmark-trend-type.type';
import { BenchmarkTrend, ColorScheme } from './types';
export const DATE_FORMAT = 'yyyy-MM-dd';
export const DATE_FORMAT_MONTHLY = 'MMMM yyyy';
@ -23,32 +22,50 @@ export const DATE_FORMAT_YEARLY = 'yyyy';
const NUMERIC_REGEXP = /[-]{0,1}[\d]*[.,]{0,1}[\d]+/g;
export function calculateBenchmarkTrend(
historicalData: MarketData[],
days: number
): BenchmarkTrend {
const hasEnoughData = historicalData.length >= 2 * days;
if (!hasEnoughData) return null;
const latestDataAvg = calculateMovingAverage(
historicalData.slice(0, days).map((hData) => new Big(hData.marketPrice)),
days
);
const oldDataAvg = calculateMovingAverage(
export function calculateBenchmarkTrend({
days,
historicalData
.slice(days, 2 * days)
.map((hData) => new Big(hData.marketPrice)),
days
);
return latestDataAvg > oldDataAvg
}: {
days: number;
historicalData: MarketData[];
}): BenchmarkTrend {
const hasEnoughData = historicalData.length >= 2 * days;
if (!hasEnoughData) {
return null;
}
const latestDataAverage = calculateMovingAverage({
days,
prices: historicalData.slice(0, days).map(({ marketPrice }) => {
return new Big(marketPrice);
})
});
const oldDataAverage = calculateMovingAverage({
days,
prices: historicalData.slice(days, 2 * days).map(({ marketPrice }) => {
return new Big(marketPrice);
})
});
return latestDataAverage > oldDataAverage
? 'UP'
: latestDataAvg < oldDataAvg
: latestDataAverage < oldDataAverage
? 'DOWN'
: 'NEUTRAL';
}
export function calculateMovingAverage(prices: Big[], days: number) {
export function calculateMovingAverage({
days,
prices
}: {
days: number;
prices: Big[];
}) {
return prices
.reduce((prev, curr) => prev.add(curr), new Big(0))
.reduce((previous, current) => {
return previous.add(current);
}, new Big(0))
.div(days)
.toNumber();
}

3
libs/common/src/lib/interfaces/benchmark.interface.ts

@ -1,4 +1,5 @@
import { BenchmarkTrend } from '../types/benchmark-trend-type.type';
import { BenchmarkTrend } from '@ghostfolio/common/types/';
import { EnhancedSymbolProfile } from './enhanced-symbol-profile.interface';
export interface Benchmark {

0
libs/common/src/lib/types/benchmark-trend-type.type.ts → libs/common/src/lib/types/benchmark-trend.type.ts

2
libs/common/src/lib/types/index.ts

@ -1,6 +1,7 @@
import type { AccessWithGranteeUser } from './access-with-grantee-user.type';
import type { AccountWithPlatform } from './account-with-platform.type';
import type { AccountWithValue } from './account-with-value.type';
import type { BenchmarkTrend } from './benchmark-trend.type';
import type { ColorScheme } from './color-scheme.type';
import type { DateRange } from './date-range.type';
import type { Granularity } from './granularity.type';
@ -20,6 +21,7 @@ export type {
AccessWithGranteeUser,
AccountWithPlatform,
AccountWithValue,
BenchmarkTrend,
ColorScheme,
DateRange,
Granularity,

Loading…
Cancel
Save