Browse Source

Respect data source in the data provider service

pull/375/head
Thomas 4 years ago
parent
commit
b67288e7f7
  1. 3
      apps/api/src/app/portfolio/current-rate.service.spec.ts
  2. 5
      apps/api/src/app/portfolio/portfolio.service.ts
  3. 1
      apps/api/src/services/data-gathering.service.ts
  4. 13
      apps/api/src/services/data-provider/data-provider.service.ts
  5. 3
      apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts
  6. 43
      apps/api/src/services/exchange-rate-data.service.ts
  7. 2
      prisma/migrations/20210916182355_added_data_source_to_market_data/migration.sql
  8. 5
      prisma/schema.prisma

3
apps/api/src/app/portfolio/current-rate.service.spec.ts

@ -14,6 +14,7 @@ jest.mock('./market-data.service', () => {
date, date,
symbol, symbol,
createdAt: date, createdAt: date,
dataSource: DataSource.YAHOO,
id: 'aefcbe3a-ee10-4c4f-9f2d-8ffad7b05584', id: 'aefcbe3a-ee10-4c4f-9f2d-8ffad7b05584',
marketPrice: 1847.839966 marketPrice: 1847.839966
}); });
@ -30,6 +31,7 @@ jest.mock('./market-data.service', () => {
return Promise.resolve<MarketData[]>([ return Promise.resolve<MarketData[]>([
{ {
createdAt: dateRangeStart, createdAt: dateRangeStart,
dataSource: DataSource.YAHOO,
date: dateRangeStart, date: dateRangeStart,
id: '8fa48fde-f397-4b0d-adbc-fb940e830e6d', id: '8fa48fde-f397-4b0d-adbc-fb940e830e6d',
marketPrice: 1841.823902, marketPrice: 1841.823902,
@ -37,6 +39,7 @@ jest.mock('./market-data.service', () => {
}, },
{ {
createdAt: dateRangeEnd, createdAt: dateRangeEnd,
dataSource: DataSource.YAHOO,
date: dateRangeEnd, date: dateRangeEnd,
id: '082d6893-df27-4c91-8a5d-092e84315b56', id: '082d6893-df27-4c91-8a5d-092e84315b56',
marketPrice: 1847.839966, marketPrice: 1847.839966,

5
apps/api/src/app/portfolio/portfolio.service.ts

@ -333,6 +333,7 @@ export class PortfolioService {
const { const {
averagePrice, averagePrice,
currency, currency,
dataSource,
firstBuyDate, firstBuyDate,
marketPrice, marketPrice,
quantity, quantity,
@ -358,7 +359,7 @@ export class PortfolioService {
); );
const historicalData = await this.dataProviderService.getHistorical( const historicalData = await this.dataProviderService.getHistorical(
[aSymbol], [{ dataSource, symbol: aSymbol }],
'day', 'day',
parseISO(firstBuyDate), parseISO(firstBuyDate),
new Date() new Date()
@ -434,7 +435,7 @@ export class PortfolioService {
const marketPrice = currentData[aSymbol]?.marketPrice; const marketPrice = currentData[aSymbol]?.marketPrice;
let historicalData = await this.dataProviderService.getHistorical( let historicalData = await this.dataProviderService.getHistorical(
[aSymbol], [{ dataSource: DataSource.YAHOO, symbol: aSymbol }],
'day', 'day',
portfolioStart, portfolioStart,
new Date() new Date()

1
apps/api/src/services/data-gathering.service.ts

@ -206,6 +206,7 @@ export class DataGatheringService {
try { try {
await this.prismaService.marketData.create({ await this.prismaService.marketData.create({
data: { data: {
dataSource,
symbol, symbol,
date: currentDate, date: currentDate,
marketPrice: lastMarketPrice marketPrice: lastMarketPrice

13
apps/api/src/services/data-provider/data-provider.service.ts

@ -66,7 +66,7 @@ export class DataProviderService {
} }
public async getHistorical( public async getHistorical(
aSymbols: string[], aItems: IDataGatheringItem[],
aGranularity: Granularity = 'month', aGranularity: Granularity = 'month',
from: Date, from: Date,
to: Date to: Date
@ -90,8 +90,17 @@ export class DataProviderService {
)}'` )}'`
: ''; : '';
const dataSources = aItems.map((item) => {
return item.dataSource;
});
const symbols = aItems.map((item) => {
return item.symbol;
});
try { try {
const queryRaw = `SELECT * FROM "MarketData" WHERE "symbol" IN ('${aSymbols.join( const queryRaw = `SELECT * FROM "MarketData" WHERE "dataSource" IN ('${dataSources.join(
`','`
)}') AND "symbol" IN ('${symbols.join(
`','` `','`
)}') ${granularityQuery} ${rangeQuery} ORDER BY date;`; )}') ${granularityQuery} ${rangeQuery} ORDER BY date;`;

3
apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts

@ -94,6 +94,7 @@ export class RakutenRapidApiService implements DataProviderInterface {
await this.prismaService.marketData.create({ await this.prismaService.marketData.create({
data: { data: {
symbol, symbol,
dataSource: DataSource.RAKUTEN,
date: subWeeks(getToday(), 1), date: subWeeks(getToday(), 1),
marketPrice: fgi.oneWeekAgo.value marketPrice: fgi.oneWeekAgo.value
} }
@ -102,6 +103,7 @@ export class RakutenRapidApiService implements DataProviderInterface {
await this.prismaService.marketData.create({ await this.prismaService.marketData.create({
data: { data: {
symbol, symbol,
dataSource: DataSource.RAKUTEN,
date: subMonths(getToday(), 1), date: subMonths(getToday(), 1),
marketPrice: fgi.oneMonthAgo.value marketPrice: fgi.oneMonthAgo.value
} }
@ -110,6 +112,7 @@ export class RakutenRapidApiService implements DataProviderInterface {
await this.prismaService.marketData.create({ await this.prismaService.marketData.create({
data: { data: {
symbol, symbol,
dataSource: DataSource.RAKUTEN,
date: subYears(getToday(), 1), date: subYears(getToday(), 1),
marketPrice: fgi.oneYearAgo.value marketPrice: fgi.oneYearAgo.value
} }

43
apps/api/src/services/exchange-rate-data.service.ts

@ -6,10 +6,11 @@ import { format } from 'date-fns';
import { isEmpty, isNumber } from 'lodash'; import { isEmpty, isNumber } from 'lodash';
import { DataProviderService } from './data-provider/data-provider.service'; import { DataProviderService } from './data-provider/data-provider.service';
import { IDataGatheringItem } from './interfaces/interfaces';
@Injectable() @Injectable()
export class ExchangeRateDataService { export class ExchangeRateDataService {
private currencyPairs: string[] = []; private currencyPairs: IDataGatheringItem[] = [];
private exchangeRates: { [currencyPair: string]: number } = {}; private exchangeRates: { [currencyPair: string]: number } = {};
public constructor(private dataProviderService: DataProviderService) { public constructor(private dataProviderService: DataProviderService) {
@ -20,8 +21,8 @@ export class ExchangeRateDataService {
this.currencyPairs = []; this.currencyPairs = [];
this.exchangeRates = {}; this.exchangeRates = {};
for (const { currency1, currency2 } of currencyPairs) { for (const { currency1, currency2, dataSource } of currencyPairs) {
this.addCurrencyPairs(currency1, currency2); this.addCurrencyPairs({ currency1, currency2, dataSource });
} }
await this.loadCurrencies(); await this.loadCurrencies();
@ -39,8 +40,8 @@ export class ExchangeRateDataService {
// Load currencies directly from data provider as a fallback // Load currencies directly from data provider as a fallback
// if historical data is not yet available // if historical data is not yet available
const historicalData = await this.dataProviderService.get( const historicalData = await this.dataProviderService.get(
this.currencyPairs.map((currencyPair) => { this.currencyPairs.map(({ dataSource, symbol }) => {
return { dataSource: DataSource.YAHOO, symbol: currencyPair }; return { dataSource, symbol };
}) })
); );
@ -67,21 +68,21 @@ export class ExchangeRateDataService {
}; };
}); });
this.currencyPairs.forEach((pair) => { this.currencyPairs.forEach(({ symbol }) => {
const [currency1, currency2] = pair.match(/.{1,3}/g); const [currency1, currency2] = symbol.match(/.{1,3}/g);
const date = format(getYesterday(), DATE_FORMAT); const date = format(getYesterday(), DATE_FORMAT);
this.exchangeRates[pair] = resultExtended[pair]?.[date]?.marketPrice; this.exchangeRates[symbol] = resultExtended[symbol]?.[date]?.marketPrice;
if (!this.exchangeRates[pair]) { if (!this.exchangeRates[symbol]) {
// Not found, calculate indirectly via USD // Not found, calculate indirectly via USD
this.exchangeRates[pair] = this.exchangeRates[symbol] =
resultExtended[`${currency1}${Currency.USD}`]?.[date]?.marketPrice * resultExtended[`${currency1}${Currency.USD}`]?.[date]?.marketPrice *
resultExtended[`${Currency.USD}${currency2}`]?.[date]?.marketPrice; resultExtended[`${Currency.USD}${currency2}`]?.[date]?.marketPrice;
// Calculate the opposite direction // Calculate the opposite direction
this.exchangeRates[`${currency2}${currency1}`] = this.exchangeRates[`${currency2}${currency1}`] =
1 / this.exchangeRates[pair]; 1 / this.exchangeRates[symbol];
} }
}); });
} }
@ -123,8 +124,22 @@ export class ExchangeRateDataService {
return aValue; return aValue;
} }
private addCurrencyPairs(aCurrency1: Currency, aCurrency2: Currency) { private addCurrencyPairs({
this.currencyPairs.push(`${aCurrency1}${aCurrency2}`); currency1,
this.currencyPairs.push(`${aCurrency2}${aCurrency1}`); currency2,
dataSource
}: {
currency1: Currency;
currency2: Currency;
dataSource: DataSource;
}) {
this.currencyPairs.push({
dataSource,
symbol: `${currency1}${currency2}`
});
this.currencyPairs.push({
dataSource,
symbol: `${currency2}${currency1}`
});
} }
} }

2
prisma/migrations/20210916182355_added_data_source_to_market_data/migration.sql

@ -0,0 +1,2 @@
-- AlterTable
ALTER TABLE "MarketData" ADD COLUMN "dataSource" "DataSource" NOT NULL DEFAULT E'YAHOO';

5
prisma/schema.prisma

@ -61,9 +61,10 @@ model AuthDevice {
} }
model MarketData { model MarketData {
createdAt DateTime @default(now()) createdAt DateTime @default(now())
dataSource DataSource @default(YAHOO)
date DateTime date DateTime
id String @default(uuid()) id String @default(uuid())
symbol String symbol String
marketPrice Float marketPrice Float

Loading…
Cancel
Save