Feature/increase fear and greed index to 90 days (#652)

* Increase fear and greed index to 90 days

* Update changelog
This commit is contained in:
Thomas Kaul 2022-01-27 21:01:38 +01:00 committed by GitHub
parent 5d3bbb8f30
commit 65e151151b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 23 additions and 34 deletions

View File

@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
- Improved the annualized performance in the new calculation engine - Improved the annualized performance in the new calculation engine
- Increased the historical data chart of the _Fear & Greed Index_ (market mood) to 90 days
## 1.107.0 - 24.01.2022 ## 1.107.0 - 24.01.2022

View File

@ -1,17 +1,12 @@
import { IDataProviderHistoricalResponse } from '@ghostfolio/api/services/interfaces/interfaces'; import { IDataProviderHistoricalResponse } from '@ghostfolio/api/services/interfaces/interfaces';
import type { RequestWithUser } from '@ghostfolio/common/types';
import { import {
Controller, Controller,
DefaultValuePipe,
Get, Get,
HttpException, HttpException,
Inject,
Param, Param,
ParseBoolPipe,
Query, Query,
UseGuards UseGuards
} from '@nestjs/common'; } from '@nestjs/common';
import { REQUEST } from '@nestjs/core';
import { AuthGuard } from '@nestjs/passport'; import { AuthGuard } from '@nestjs/passport';
import { DataSource } from '@prisma/client'; import { DataSource } from '@prisma/client';
import { StatusCodes, getReasonPhrase } from 'http-status-codes'; import { StatusCodes, getReasonPhrase } from 'http-status-codes';
@ -23,10 +18,7 @@ import { SymbolService } from './symbol.service';
@Controller('symbol') @Controller('symbol')
export class SymbolController { export class SymbolController {
public constructor( public constructor(private readonly symbolService: SymbolService) {}
private readonly symbolService: SymbolService,
@Inject(REQUEST) private readonly request: RequestWithUser
) {}
/** /**
* Must be before /:symbol * Must be before /:symbol
@ -54,8 +46,7 @@ export class SymbolController {
public async getSymbolData( public async getSymbolData(
@Param('dataSource') dataSource: DataSource, @Param('dataSource') dataSource: DataSource,
@Param('symbol') symbol: string, @Param('symbol') symbol: string,
@Query('includeHistoricalData', new DefaultValuePipe(false), ParseBoolPipe) @Query('includeHistoricalData') includeHistoricalData?: number
includeHistoricalData: boolean
): Promise<SymbolItem> { ): Promise<SymbolItem> {
if (!DataSource[dataSource]) { if (!DataSource[dataSource]) {
throw new HttpException( throw new HttpException(

View File

@ -5,7 +5,6 @@ import {
IDataProviderHistoricalResponse IDataProviderHistoricalResponse
} from '@ghostfolio/api/services/interfaces/interfaces'; } from '@ghostfolio/api/services/interfaces/interfaces';
import { MarketDataService } from '@ghostfolio/api/services/market-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data.service';
import { PrismaService } from '@ghostfolio/api/services/prisma.service';
import { DATE_FORMAT } from '@ghostfolio/common/helper'; import { DATE_FORMAT } from '@ghostfolio/common/helper';
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { DataSource } from '@prisma/client'; import { DataSource } from '@prisma/client';
@ -18,25 +17,24 @@ import { SymbolItem } from './interfaces/symbol-item.interface';
export class SymbolService { export class SymbolService {
public constructor( public constructor(
private readonly dataProviderService: DataProviderService, private readonly dataProviderService: DataProviderService,
private readonly marketDataService: MarketDataService, private readonly marketDataService: MarketDataService
private readonly prismaService: PrismaService
) {} ) {}
public async get({ public async get({
dataGatheringItem, dataGatheringItem,
includeHistoricalData = false includeHistoricalData
}: { }: {
dataGatheringItem: IDataGatheringItem; dataGatheringItem: IDataGatheringItem;
includeHistoricalData?: boolean; includeHistoricalData?: number;
}): Promise<SymbolItem> { }): Promise<SymbolItem> {
const response = await this.dataProviderService.get([dataGatheringItem]); const response = await this.dataProviderService.get([dataGatheringItem]);
const { currency, marketPrice } = response[dataGatheringItem.symbol] ?? {}; const { currency, marketPrice } = response[dataGatheringItem.symbol] ?? {};
if (dataGatheringItem.dataSource && marketPrice) { if (dataGatheringItem.dataSource && marketPrice) {
let historicalData: HistoricalDataItem[]; let historicalData: HistoricalDataItem[] = [];
if (includeHistoricalData) { if (includeHistoricalData > 0) {
const days = 30; const days = includeHistoricalData;
const marketData = await this.marketDataService.getRange({ const marketData = await this.marketDataService.getRange({
dateQuery: { gte: subDays(new Date(), days) }, dateQuery: { gte: subDays(new Date(), days) },

View File

@ -20,6 +20,7 @@ export class HomeMarketComponent implements OnDestroy, OnInit {
public hasPermissionToAccessFearAndGreedIndex: boolean; public hasPermissionToAccessFearAndGreedIndex: boolean;
public historicalData: HistoricalDataItem[]; public historicalData: HistoricalDataItem[];
public isLoading = true; public isLoading = true;
public readonly numberOfDays = 90;
public user: User; public user: User;
private unsubscribeSubject = new Subject<void>(); private unsubscribeSubject = new Subject<void>();
@ -49,7 +50,7 @@ export class HomeMarketComponent implements OnDestroy, OnInit {
this.dataService this.dataService
.fetchSymbolItem({ .fetchSymbolItem({
dataSource: DataSource.RAKUTEN, dataSource: DataSource.RAKUTEN,
includeHistoricalData: true, includeHistoricalData: this.numberOfDays,
symbol: ghostfolioFearAndGreedIndexSymbol symbol: ghostfolioFearAndGreedIndexSymbol
}) })
.pipe(takeUntil(this.unsubscribeSubject)) .pipe(takeUntil(this.unsubscribeSubject))

View File

@ -1,18 +1,10 @@
<div <div
class=" class="align-items-center container d-flex flex-grow-1 h-100 justify-content-center w-100"
align-items-center
container
d-flex
flex-grow-1
h-100
justify-content-center
w-100
"
> >
<div class="no-gutters row w-100"> <div class="no-gutters row w-100">
<div class="col-xs-12 col-md-8 offset-md-2"> <div class="col-xs-12 col-md-8 offset-md-2">
<div class="mb-2 text-center text-muted"> <div class="mb-2 text-center text-muted">
<small i18n>Last 30 Days</small> <small i18n>Last {{ numberOfDays }} Days</small>
</div> </div>
<gf-line-chart <gf-line-chart
class="mb-5" class="mb-5"

View File

@ -1,4 +1,4 @@
import { HttpClient } from '@angular/common/http'; import { HttpClient, HttpParams } from '@angular/common/http';
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto'; import { CreateAccessDto } from '@ghostfolio/api/app/access/create-access.dto';
import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto'; import { CreateAccountDto } from '@ghostfolio/api/app/account/create-account.dto';
@ -138,15 +138,21 @@ export class DataService {
public fetchSymbolItem({ public fetchSymbolItem({
dataSource, dataSource,
includeHistoricalData = false, includeHistoricalData,
symbol symbol
}: { }: {
dataSource: DataSource; dataSource: DataSource;
includeHistoricalData?: boolean; includeHistoricalData?: number;
symbol: string; symbol: string;
}) { }) {
let params = new HttpParams();
if (includeHistoricalData) {
params = params.append('includeHistoricalData', includeHistoricalData);
}
return this.http.get<SymbolItem>(`/api/symbol/${dataSource}/${symbol}`, { return this.http.get<SymbolItem>(`/api/symbol/${dataSource}/${symbol}`, {
params: { includeHistoricalData } params
}); });
} }