Refactoring

pull/239/head
Thomas 3 years ago
parent 8571709014
commit cbdb68e2f8

@ -7,7 +7,7 @@ import { TimelineSpecification } from '@ghostfolio/api/app/core/interfaces/timel
import { TransactionPoint } from '@ghostfolio/api/app/core/interfaces/transaction-point.interface';
import { PortfolioCalculator } from '@ghostfolio/api/app/core/portfolio-calculator';
import { OrderType } from '@ghostfolio/api/models/order-type';
import { resetHours } from '@ghostfolio/common/helper';
import { DATE_FORMAT, resetHours } from '@ghostfolio/common/helper';
import { Currency } from '@prisma/client';
import Big from 'big.js';
import {
@ -25,7 +25,7 @@ function mockGetValue(symbol: string, date: Date) {
if (isSameDay(today, date)) {
return { marketPrice: 213.32 };
} else {
const startDate = parse('2019-02-01', 'yyyy-MM-dd', new Date());
const startDate = parse('2019-02-01', DATE_FORMAT, new Date());
const daysInBetween = differenceInCalendarDays(date, startDate);
const marketPrice = new Big('144.38').plus(
@ -36,10 +36,10 @@ function mockGetValue(symbol: string, date: Date) {
} else if (symbol === 'AMZN') {
return { marketPrice: 2021.99 };
} else if (symbol === 'TSLA') {
if (isSameDay(parse('2021-07-26', 'yyyy-MM-dd', new Date()), date)) {
if (isSameDay(parse('2021-07-26', DATE_FORMAT, new Date()), date)) {
return { marketPrice: 657.62 };
}
if (isSameDay(parse('2021-01-02', 'yyyy-MM-dd', new Date()), date)) {
if (isSameDay(parse('2021-01-02', DATE_FORMAT, new Date()), date)) {
return { marketPrice: 666.66 };
}
return { marketPrice: 0 };
@ -607,7 +607,7 @@ describe('PortfolioCalculator', () => {
.spyOn(Date, 'now')
.mockImplementation(() => new Date(Date.UTC(2021, 6, 26)).getTime()); // 2021-07-26
const currentPositions = await portfolioCalculator.getCurrentPositions(
parse('2020-01-21', 'yyyy-MM-dd', new Date())
parse('2020-01-21', DATE_FORMAT, new Date())
);
spy.mockRestore();
@ -642,7 +642,7 @@ describe('PortfolioCalculator', () => {
.spyOn(Date, 'now')
.mockImplementation(() => new Date(Date.UTC(2021, 6, 26)).getTime()); // 2021-07-26
const currentPositions = await portfolioCalculator.getCurrentPositions(
parse('2021-01-01', 'yyyy-MM-dd', new Date())
parse('2021-01-01', DATE_FORMAT, new Date())
);
spy.mockRestore();
@ -677,7 +677,7 @@ describe('PortfolioCalculator', () => {
.spyOn(Date, 'now')
.mockImplementation(() => new Date(Date.UTC(2021, 6, 26)).getTime()); // 2021-07-26
const currentPositions = await portfolioCalculator.getCurrentPositions(
parse('2021-01-02', 'yyyy-MM-dd', new Date())
parse('2021-01-02', DATE_FORMAT, new Date())
);
spy.mockRestore();
@ -712,7 +712,7 @@ describe('PortfolioCalculator', () => {
.spyOn(Date, 'now')
.mockImplementation(() => new Date(Date.UTC(2020, 9, 24)).getTime()); // 2020-10-24
const currentPositions = await portfolioCalculator.getCurrentPositions(
parse('2019-01-01', 'yyyy-MM-dd', new Date())
parse('2019-01-01', DATE_FORMAT, new Date())
);
spy.mockRestore();
@ -788,7 +788,7 @@ describe('PortfolioCalculator', () => {
// gross performance percentage: 1.100526008 * 1.034838024 = 1.138866159 => 13.89 %
const currentPositions = await portfolioCalculator.getCurrentPositions(
parse('2020-01-01', 'yyyy-MM-dd', new Date())
parse('2020-01-01', DATE_FORMAT, new Date())
);
spy.mockRestore();

@ -1,4 +1,5 @@
import { baseCurrency, benchmarks } from '@ghostfolio/common/config';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { isApiTokenAuthorized } from '@ghostfolio/common/permissions';
import { RequestWithUser } from '@ghostfolio/common/types';
import {
@ -82,7 +83,7 @@ export class ExperimentalController {
let date = new Date();
if (dateString) {
date = parse(dateString, 'yyyy-MM-dd', new Date());
date = parse(dateString, DATE_FORMAT, new Date());
}
return this.experimentalService.getValue(orders, date, baseCurrency);

@ -14,7 +14,7 @@ import { ImpersonationService } from '@ghostfolio/api/services/impersonation.ser
import { IOrder } from '@ghostfolio/api/services/interfaces/interfaces';
import { Type } from '@ghostfolio/api/services/interfaces/interfaces';
import { RulesService } from '@ghostfolio/api/services/rules.service';
import { parseDate } from '@ghostfolio/common/helper';
import { DATE_FORMAT, parseDate } from '@ghostfolio/common/helper';
import {
PortfolioItem,
PortfolioOverview,
@ -57,6 +57,7 @@ import {
export class PortfolioService {
public constructor(
private readonly accountService: AccountService,
private readonly currentRateService: CurrentRateService,
private readonly dataProviderService: DataProviderService,
private readonly exchangeRateDataService: ExchangeRateDataService,
private readonly impersonationService: ImpersonationService,
@ -64,8 +65,7 @@ export class PortfolioService {
private readonly redisCacheService: RedisCacheService,
@Inject(REQUEST) private readonly request: RequestWithUser,
private readonly rulesService: RulesService,
private readonly userService: UserService,
private readonly currentRateService: CurrentRateService
private readonly userService: UserService
) {}
public async createPortfolio(aUserId: string): Promise<Portfolio> {
@ -163,32 +163,31 @@ export class PortfolioService {
if (transactionPoints.length === 0) {
return [];
}
const dateFormat = 'yyyy-MM-dd';
let portfolioStart = parse(
transactionPoints[0].date,
dateFormat,
DATE_FORMAT,
new Date()
);
portfolioStart = this.getStartDate(aDateRange, portfolioStart);
const timelineSpecification: TimelineSpecification[] = [
{
start: format(portfolioStart, dateFormat),
start: format(portfolioStart, DATE_FORMAT),
accuracy: 'day'
}
];
const timeline = await portfolioCalculator.calculateTimeline(
timelineSpecification,
format(new Date(), dateFormat)
format(new Date(), DATE_FORMAT)
);
return timeline
.filter((timelineItem) => timelineItem !== null)
.map((timelineItem) => ({
date: timelineItem.date,
value: timelineItem.grossPerformance.toNumber(),
marketPrice: timelineItem.value
marketPrice: timelineItem.value,
value: timelineItem.grossPerformance.toNumber()
}));
}
@ -270,7 +269,7 @@ export class PortfolioService {
for (const [date, { marketPrice }] of Object.entries(
historicalData[aSymbol]
)) {
const currentDate = parse(date, 'yyyy-MM-dd', new Date());
const currentDate = parse(date, DATE_FORMAT, new Date());
if (
isSameDay(currentDate, parseISO(orders[0]?.getDate())) ||
isAfter(currentDate, parseISO(orders[0]?.getDate()))
@ -533,7 +532,7 @@ export class PortfolioService {
const portfolioOrders: PortfolioOrder[] = orders.map((order) => ({
currency: order.currency,
date: format(order.date, 'yyyy-MM-dd'),
date: format(order.date, DATE_FORMAT),
name: order.SymbolProfile?.name,
quantity: new Big(order.quantity),
symbol: order.symbol,

@ -1,6 +1,6 @@
import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { UNKNOWN_KEY, baseCurrency } from '@ghostfolio/common/config';
import { getUtc, getYesterday } from '@ghostfolio/common/helper';
import { DATE_FORMAT, getUtc, getYesterday } from '@ghostfolio/common/helper';
import {
AccountType,
Currency,
@ -30,8 +30,8 @@ jest.mock('../app/account/account.service', () => {
jest.mock('../services/data-provider.service', () => {
return {
DataProviderService: jest.fn().mockImplementation(() => {
const today = format(new Date(), 'yyyy-MM-dd');
const yesterday = format(getYesterday(), 'yyyy-MM-dd');
const today = format(new Date(), DATE_FORMAT);
const yesterday = format(getYesterday(), DATE_FORMAT);
return {
get: () => {

@ -1,7 +1,12 @@
import { AccountService } from '@ghostfolio/api/app/account/account.service';
import { CashDetails } from '@ghostfolio/api/app/account/interfaces/cash-details.interface';
import { UNKNOWN_KEY, ghostfolioCashSymbol } from '@ghostfolio/common/config';
import { getToday, getYesterday, resetHours } from '@ghostfolio/common/helper';
import {
DATE_FORMAT,
getToday,
getYesterday,
resetHours
} from '@ghostfolio/common/helper';
import {
PortfolioItem,
PortfolioPerformance,
@ -731,7 +736,7 @@ export class Portfolio implements PortfolioInterface {
investment: 0,
investmentInOriginalCurrency: 0,
marketPrice:
historicalData[symbol]?.[format(currentDate, 'yyyy-MM-dd')]
historicalData[symbol]?.[format(currentDate, DATE_FORMAT)]
?.marketPrice || 0,
quantity: 0,
transactionCount: 0
@ -774,7 +779,7 @@ export class Portfolio implements PortfolioInterface {
investment: 0,
investmentInOriginalCurrency: 0,
marketPrice:
historicalData[symbol]?.[format(yesterday, 'yyyy-MM-dd')]
historicalData[symbol]?.[format(yesterday, DATE_FORMAT)]
?.marketPrice || 0,
name: '',
quantity: 0,

@ -1,5 +1,6 @@
import { benchmarks, currencyPairs } from '@ghostfolio/common/config';
import {
DATE_FORMAT,
getUtc,
isGhostfolioScraperApiSymbol,
isRakutenRapidApiSymbol,
@ -193,11 +194,11 @@ export class DataGatheringService {
)
) {
if (
historicalData[symbol]?.[format(currentDate, 'yyyy-MM-dd')]
historicalData[symbol]?.[format(currentDate, DATE_FORMAT)]
?.marketPrice
) {
lastMarketPrice =
historicalData[symbol]?.[format(currentDate, 'yyyy-MM-dd')]
historicalData[symbol]?.[format(currentDate, DATE_FORMAT)]
?.marketPrice;
}

@ -1,4 +1,5 @@
import {
DATE_FORMAT,
isGhostfolioScraperApiSymbol,
isRakutenRapidApiSymbol
} from '@ghostfolio/common/helper';
@ -100,9 +101,9 @@ export class DataProviderService {
const rangeQuery =
from && to
? `AND date >= '${format(from, 'yyyy-MM-dd')}' AND date <= '${format(
? `AND date >= '${format(from, DATE_FORMAT)}' AND date <= '${format(
to,
'yyyy-MM-dd'
DATE_FORMAT
)}'`
: '';
@ -120,7 +121,7 @@ export class DataProviderService {
r[symbol] = {
...(r[symbol] || {}),
[format(new Date(date), 'yyyy-MM-dd')]: { marketPrice }
[format(new Date(date), DATE_FORMAT)]: { marketPrice }
};
return r;

@ -1,4 +1,5 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { Granularity } from '@ghostfolio/common/types';
import { Injectable } from '@nestjs/common';
import { DataSource } from '@prisma/client';
@ -66,8 +67,8 @@ export class AlphaVantageService implements DataProviderInterface {
historicalData['Time Series (Digital Currency Daily)']
).sort()) {
if (
isAfter(from, parse(key, 'yyyy-MM-dd', new Date())) &&
isBefore(to, parse(key, 'yyyy-MM-dd', new Date()))
isAfter(from, parse(key, DATE_FORMAT, new Date())) &&
isBefore(to, parse(key, DATE_FORMAT, new Date()))
) {
response[symbol][key] = {
marketPrice: parseFloat(timeSeries['4a. close (USD)'])

@ -1,4 +1,5 @@
import {
DATE_FORMAT,
getYesterday,
isGhostfolioScraperApiSymbol
} from '@ghostfolio/common/helper';
@ -95,7 +96,7 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
return {
[symbol]: {
[format(getYesterday(), 'yyyy-MM-dd')]: {
[format(getYesterday(), DATE_FORMAT)]: {
marketPrice: value
}
}
@ -109,14 +110,13 @@ export class GhostfolioScraperApiService implements DataProviderInterface {
public async getScraperConfigurations(): Promise<ScraperConfig[]> {
try {
const {
value: scraperConfigString
} = await this.prisma.property.findFirst({
select: {
value: true
},
where: { key: 'SCRAPER_CONFIG' }
});
const { value: scraperConfigString } =
await this.prisma.property.findFirst({
select: {
value: true
},
where: { key: 'SCRAPER_CONFIG' }
});
return JSON.parse(scraperConfigString);
} catch {}

@ -1,4 +1,5 @@
import {
DATE_FORMAT,
getToday,
getYesterday,
isRakutenRapidApiSymbol
@ -117,7 +118,7 @@ export class RakutenRapidApiService implements DataProviderInterface {
return {
'GF.FEAR_AND_GREED_INDEX': {
[format(getYesterday(), 'yyyy-MM-dd')]: {
[format(getYesterday(), DATE_FORMAT)]: {
marketPrice: fgi.previousClose.value
}
}

@ -1,6 +1,11 @@
import { LookupItem } from '@ghostfolio/api/app/symbol/interfaces/lookup-item.interface';
import { UNKNOWN_KEY } from '@ghostfolio/common/config';
import { isCrypto, isCurrency, parseCurrency } from '@ghostfolio/common/helper';
import {
DATE_FORMAT,
isCrypto,
isCurrency,
parseCurrency
} from '@ghostfolio/common/helper';
import { Granularity } from '@ghostfolio/common/types';
import { Injectable } from '@nestjs/common';
import { DataSource } from '@prisma/client';
@ -103,8 +108,8 @@ export class YahooFinanceService implements DataProviderInterface {
[symbol: string]: IYahooFinanceHistoricalResponse[];
} = await yahooFinance.historical({
symbols: yahooSymbols,
from: format(from, 'yyyy-MM-dd'),
to: format(to, 'yyyy-MM-dd')
from: format(from, DATE_FORMAT),
to: format(to, DATE_FORMAT)
});
const response: {
@ -117,7 +122,7 @@ export class YahooFinanceService implements DataProviderInterface {
response[symbol] = {};
timeSeries.forEach((timeSerie) => {
response[symbol][format(timeSerie.date, 'yyyy-MM-dd')] = {
response[symbol][format(timeSerie.date, DATE_FORMAT)] = {
marketPrice: timeSerie.close,
performance: timeSerie.open - timeSerie.close
};

@ -1,4 +1,4 @@
import { getYesterday } from '@ghostfolio/common/helper';
import { DATE_FORMAT, getYesterday } from '@ghostfolio/common/helper';
import { Injectable } from '@nestjs/common';
import { Currency } from '@prisma/client';
import { format } from 'date-fns';
@ -51,7 +51,7 @@ export class ExchangeRateDataService {
this.pairs.forEach((pair) => {
const [currency1, currency2] = pair.match(/.{1,3}/g);
const date = format(getYesterday(), 'yyyy-MM-dd');
const date = format(getYesterday(), DATE_FORMAT);
this.currencies[pair] = resultExtended[pair]?.[date]?.marketPrice;

@ -6,6 +6,7 @@ import {
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DataService } from '@ghostfolio/client/services/data.service';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { isToday, parse } from 'date-fns';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -66,7 +67,7 @@ export class PerformanceChartDialog {
value: benchmarkItem.value * coefficient
});
} else if (
isToday(parse(historicalDataItem.date, 'yyyy-MM-dd', new Date()))
isToday(parse(historicalDataItem.date, DATE_FORMAT, new Date()))
) {
this.benchmarkDataItems.push({
date: historicalDataItem.date,

@ -7,6 +7,7 @@ import {
} from '@angular/core';
import { MAT_DIALOG_DATA, MatDialogRef } from '@angular/material/dialog';
import { DataService } from '@ghostfolio/client/services/data.service';
import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { format, isSameMonth, isToday, parseISO } from 'date-fns';
import { Subject } from 'rxjs';
import { takeUntil } from 'rxjs/operators';
@ -115,13 +116,13 @@ export class PositionDetailDialog implements OnDestroy {
} else {
// Add market price
this.historicalDataItems.push({
date: format(new Date(), 'yyyy-MM-dd'),
date: format(new Date(), DATE_FORMAT),
value: this.marketPrice
});
// Add benchmark
this.benchmarkDataItems.push({
date: format(new Date(), 'yyyy-MM-dd'),
date: format(new Date(), DATE_FORMAT),
value: averagePrice
});
}

Loading…
Cancel
Save