Browse Source

Feature/respect data source in data provider service (#375)

* Respect data source in the data provider service

* Update changelog
pull/370/head
Thomas Kaul 4 years ago
committed by Thomas
parent
commit
6d9f4a1337
  1. 15
      CHANGELOG.md
  2. 3
      apps/api/src/app/portfolio/current-rate.service.spec.ts
  3. 5
      apps/api/src/app/portfolio/portfolio.service.ts
  4. 1
      apps/api/src/services/data-gathering.service.ts
  5. 13
      apps/api/src/services/data-provider/data-provider.service.ts
  6. 3
      apps/api/src/services/data-provider/rakuten-rapid-api/rakuten-rapid-api.service.ts
  7. 43
      apps/api/src/services/exchange-rate-data.service.ts
  8. 2
      prisma/migrations/20210916182355_added_data_source_to_market_data/migration.sql
  9. 1
      prisma/schema.prisma

15
CHANGELOG.md

@ -7,16 +7,25 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Unreleased
### Fixed
### Added
- Hid the net performance in the _Presenter View_ (portfolio holdings and summary tab on the home page)
- Hid the sign if the performance is zero in the value component
- Added the data source attribute to the symbol profile model
### Changed
- Respected the data source attribute in the data provider service
- Respected the data source attribute in the symbol data endpoint
- Improved the search functionality of the data management (multiple data sources)
### Fixed
- Hid the net performance in the _Presenter View_ (portfolio holdings and summary tab on the home page)
- Hid the sign if the performance is zero in the value component
### Todo
- Apply data migration (`yarn database:push`)
## 1.53.0 - 13.09.2021
### Changed

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

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

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

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

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

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

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

@ -66,7 +66,7 @@ export class DataProviderService {
}
public async getHistorical(
aSymbols: string[],
aItems: IDataGatheringItem[],
aGranularity: Granularity = 'month',
from: 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 {
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;`;

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({
data: {
symbol,
dataSource: DataSource.RAKUTEN,
date: subWeeks(getToday(), 1),
marketPrice: fgi.oneWeekAgo.value
}
@ -102,6 +103,7 @@ export class RakutenRapidApiService implements DataProviderInterface {
await this.prismaService.marketData.create({
data: {
symbol,
dataSource: DataSource.RAKUTEN,
date: subMonths(getToday(), 1),
marketPrice: fgi.oneMonthAgo.value
}
@ -110,6 +112,7 @@ export class RakutenRapidApiService implements DataProviderInterface {
await this.prismaService.marketData.create({
data: {
symbol,
dataSource: DataSource.RAKUTEN,
date: subYears(getToday(), 1),
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 { DataProviderService } from './data-provider/data-provider.service';
import { IDataGatheringItem } from './interfaces/interfaces';
@Injectable()
export class ExchangeRateDataService {
private currencyPairs: string[] = [];
private currencyPairs: IDataGatheringItem[] = [];
private exchangeRates: { [currencyPair: string]: number } = {};
public constructor(private dataProviderService: DataProviderService) {
@ -20,8 +21,8 @@ export class ExchangeRateDataService {
this.currencyPairs = [];
this.exchangeRates = {};
for (const { currency1, currency2 } of currencyPairs) {
this.addCurrencyPairs(currency1, currency2);
for (const { currency1, currency2, dataSource } of currencyPairs) {
this.addCurrencyPairs({ currency1, currency2, dataSource });
}
await this.loadCurrencies();
@ -39,8 +40,8 @@ export class ExchangeRateDataService {
// Load currencies directly from data provider as a fallback
// if historical data is not yet available
const historicalData = await this.dataProviderService.get(
this.currencyPairs.map((currencyPair) => {
return { dataSource: DataSource.YAHOO, symbol: currencyPair };
this.currencyPairs.map(({ dataSource, symbol }) => {
return { dataSource, symbol };
})
);
@ -67,21 +68,21 @@ export class ExchangeRateDataService {
};
});
this.currencyPairs.forEach((pair) => {
const [currency1, currency2] = pair.match(/.{1,3}/g);
this.currencyPairs.forEach(({ symbol }) => {
const [currency1, currency2] = symbol.match(/.{1,3}/g);
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
this.exchangeRates[pair] =
this.exchangeRates[symbol] =
resultExtended[`${currency1}${Currency.USD}`]?.[date]?.marketPrice *
resultExtended[`${Currency.USD}${currency2}`]?.[date]?.marketPrice;
// Calculate the opposite direction
this.exchangeRates[`${currency2}${currency1}`] =
1 / this.exchangeRates[pair];
1 / this.exchangeRates[symbol];
}
});
}
@ -123,8 +124,22 @@ export class ExchangeRateDataService {
return aValue;
}
private addCurrencyPairs(aCurrency1: Currency, aCurrency2: Currency) {
this.currencyPairs.push(`${aCurrency1}${aCurrency2}`);
this.currencyPairs.push(`${aCurrency2}${aCurrency1}`);
private addCurrencyPairs({
currency1,
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';

1
prisma/schema.prisma

@ -62,6 +62,7 @@ model AuthDevice {
model MarketData {
createdAt DateTime @default(now())
dataSource DataSource @default(YAHOO)
date DateTime
id String @default(uuid())
symbol String

Loading…
Cancel
Save