|
|
@ -1,12 +1,11 @@ |
|
|
|
import { SymbolProfileService } from '@ghostfolio/api/services/symbol-profile.service'; |
|
|
|
import { |
|
|
|
PROPERTY_LAST_DATA_GATHERING, |
|
|
|
PROPERTY_LOCKED_DATA_GATHERING, |
|
|
|
ghostfolioFearAndGreedIndexSymbol |
|
|
|
PROPERTY_LOCKED_DATA_GATHERING |
|
|
|
} from '@ghostfolio/common/config'; |
|
|
|
import { DATE_FORMAT, resetHours } from '@ghostfolio/common/helper'; |
|
|
|
import { Inject, Injectable, Logger } from '@nestjs/common'; |
|
|
|
import { DataSource, MarketData } from '@prisma/client'; |
|
|
|
import { DataSource } from '@prisma/client'; |
|
|
|
import { |
|
|
|
differenceInHours, |
|
|
|
format, |
|
|
@ -17,7 +16,6 @@ import { |
|
|
|
subDays |
|
|
|
} from 'date-fns'; |
|
|
|
|
|
|
|
import { ConfigurationService } from './configuration.service'; |
|
|
|
import { DataProviderService } from './data-provider/data-provider.service'; |
|
|
|
import { DataEnhancerInterface } from './data-provider/interfaces/data-enhancer.interface'; |
|
|
|
import { ExchangeRateDataService } from './exchange-rate-data.service'; |
|
|
@ -29,7 +27,6 @@ export class DataGatheringService { |
|
|
|
private dataGatheringProgress: number; |
|
|
|
|
|
|
|
public constructor( |
|
|
|
private readonly configurationService: ConfigurationService, |
|
|
|
@Inject('DataEnhancers') |
|
|
|
private readonly dataEnhancers: DataEnhancerInterface[], |
|
|
|
private readonly dataProviderService: DataProviderService, |
|
|
@ -448,11 +445,7 @@ export class DataGatheringService { |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
return [ |
|
|
|
...this.getBenchmarksToGather(startDate), |
|
|
|
...currencyPairsToGather, |
|
|
|
...symbolProfilesToGather |
|
|
|
]; |
|
|
|
return [...currencyPairsToGather, ...symbolProfilesToGather]; |
|
|
|
} |
|
|
|
|
|
|
|
public async reset() { |
|
|
@ -468,23 +461,27 @@ export class DataGatheringService { |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private getBenchmarksToGather(startDate: Date): IDataGatheringItem[] { |
|
|
|
const benchmarksToGather: IDataGatheringItem[] = []; |
|
|
|
|
|
|
|
if (this.configurationService.get('ENABLE_FEATURE_FEAR_AND_GREED_INDEX')) { |
|
|
|
benchmarksToGather.push({ |
|
|
|
dataSource: DataSource.RAKUTEN, |
|
|
|
date: startDate, |
|
|
|
symbol: ghostfolioFearAndGreedIndexSymbol |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
return benchmarksToGather; |
|
|
|
} |
|
|
|
|
|
|
|
private async getSymbols7D(): Promise<IDataGatheringItem[]> { |
|
|
|
const startDate = subDays(resetHours(new Date()), 7); |
|
|
|
|
|
|
|
// Only consider symbols with incomplete market data for the last
|
|
|
|
// 7 days
|
|
|
|
const symbolsToGather = ( |
|
|
|
await this.prismaService.marketData.groupBy({ |
|
|
|
_count: true, |
|
|
|
by: ['symbol'], |
|
|
|
where: { |
|
|
|
date: { gt: startDate } |
|
|
|
} |
|
|
|
}) |
|
|
|
) |
|
|
|
.filter((group) => { |
|
|
|
return group._count < 6; |
|
|
|
}) |
|
|
|
.map((group) => { |
|
|
|
return group.symbol; |
|
|
|
}); |
|
|
|
|
|
|
|
const symbolProfilesToGather = ( |
|
|
|
await this.prismaService.symbolProfile.findMany({ |
|
|
|
orderBy: [{ symbol: 'asc' }], |
|
|
@ -494,12 +491,16 @@ export class DataGatheringService { |
|
|
|
symbol: true |
|
|
|
} |
|
|
|
}) |
|
|
|
).map((symbolProfile) => { |
|
|
|
return { |
|
|
|
...symbolProfile, |
|
|
|
date: startDate |
|
|
|
}; |
|
|
|
}); |
|
|
|
) |
|
|
|
.filter((symbolProfile) => { |
|
|
|
return symbolsToGather.includes(symbolProfile.symbol); |
|
|
|
}) |
|
|
|
.map((symbolProfile) => { |
|
|
|
return { |
|
|
|
...symbolProfile, |
|
|
|
date: startDate |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
const currencyPairsToGather = this.exchangeRateDataService |
|
|
|
.getCurrencyPairs() |
|
|
@ -511,30 +512,22 @@ export class DataGatheringService { |
|
|
|
}; |
|
|
|
}); |
|
|
|
|
|
|
|
return [ |
|
|
|
...this.getBenchmarksToGather(startDate), |
|
|
|
...currencyPairsToGather, |
|
|
|
...symbolProfilesToGather |
|
|
|
]; |
|
|
|
return [...currencyPairsToGather, ...symbolProfilesToGather]; |
|
|
|
} |
|
|
|
|
|
|
|
private async getSymbolsProfileData(): Promise<IDataGatheringItem[]> { |
|
|
|
const startDate = subDays(resetHours(new Date()), 7); |
|
|
|
|
|
|
|
const distinctOrders = await this.prismaService.order.findMany({ |
|
|
|
distinct: ['symbol'], |
|
|
|
orderBy: [{ symbol: 'asc' }], |
|
|
|
select: { dataSource: true, symbol: true } |
|
|
|
}); |
|
|
|
|
|
|
|
return [...this.getBenchmarksToGather(startDate), ...distinctOrders].filter( |
|
|
|
(distinctOrder) => { |
|
|
|
return ( |
|
|
|
distinctOrder.dataSource !== DataSource.GHOSTFOLIO && |
|
|
|
distinctOrder.dataSource !== DataSource.RAKUTEN |
|
|
|
); |
|
|
|
} |
|
|
|
); |
|
|
|
return distinctOrders.filter((distinctOrder) => { |
|
|
|
return ( |
|
|
|
distinctOrder.dataSource !== DataSource.GHOSTFOLIO && |
|
|
|
distinctOrder.dataSource !== DataSource.RAKUTEN |
|
|
|
); |
|
|
|
}); |
|
|
|
} |
|
|
|
|
|
|
|
private async isDataGatheringNeeded() { |
|
|
|