Browse Source

fix: prefer market data for quote fallback

pull/7812/head
jaredrainsha 4 days ago
parent
commit
7a9f2ebcc5
  1. 48
      apps/api/src/app/portfolio/current-rate.service.spec.ts
  2. 36
      apps/api/src/app/portfolio/current-rate.service.ts

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

@ -1,3 +1,4 @@
import { ActivitiesService } from '@ghostfolio/api/app/activities/activities.service';
import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service'; import { DataProviderService } from '@ghostfolio/api/services/data-provider/data-provider.service';
import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service'; import { MarketDataService } from '@ghostfolio/api/services/market-data/market-data.service';
import { PropertyService } from '@ghostfolio/api/services/property/property.service'; import { PropertyService } from '@ghostfolio/api/services/property/property.service';
@ -152,4 +153,51 @@ describe('CurrentRateService', () => {
] ]
}); });
}); });
it('uses the latest market price when the current quote is unavailable', async () => {
const historicalDate = new Date(Date.now() - 24 * 60 * 60 * 1000);
const activitiesService = {
getLatestActivity: jest.fn().mockResolvedValue({ unitPrice: 100 })
};
const dataProviderService = {
getQuotes: jest.fn().mockResolvedValue({})
};
const marketDataService = {
getRange: jest.fn().mockResolvedValue([
{
createdAt: historicalDate,
dataSource: DataSource.YAHOO,
date: historicalDate,
id: '40520fdf-4e31-47ab-8bd0-ca61c70d4684',
isCarriedForward: false,
marketPrice: 200,
state: 'CLOSE',
symbol: 'AMZN'
}
]),
getRangeCount: jest.fn().mockResolvedValue(1)
};
const service = new CurrentRateService(
activitiesService as unknown as ActivitiesService,
dataProviderService as unknown as DataProviderService,
marketDataService as unknown as MarketDataService,
null
);
const response = await service.getValues({
dataGatheringItems: [{ dataSource: DataSource.YAHOO, symbol: 'AMZN' }],
dateQuery: {
gte: historicalDate,
lt: new Date(Date.now() + 24 * 60 * 60 * 1000)
}
});
const latestValue = response.values
.filter(({ dataSource, symbol }) => {
return dataSource === DataSource.YAHOO && symbol === 'AMZN';
})
.sort((a, b) => b.date.getTime() - a.date.getTime())[0];
expect(latestValue.marketPrice).toBe(200);
expect(activitiesService.getLatestActivity).not.toHaveBeenCalled();
});
}); });

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

@ -126,7 +126,7 @@ export class CurrentRateService {
for (const { dataSource, symbol } of quoteErrors) { for (const { dataSource, symbol } of quoteErrors) {
try { try {
// If missing quote, fallback to the latest available historical market price // If missing quote, fallback to the latest available historical market price
let value: GetValueObject = response.values.find((currentValue) => { const hasValueForToday = response.values.some((currentValue) => {
return ( return (
currentValue.dataSource === dataSource && currentValue.dataSource === dataSource &&
currentValue.symbol === symbol && currentValue.symbol === symbol &&
@ -134,22 +134,8 @@ export class CurrentRateService {
); );
}); });
if (!value) { if (hasValueForToday) {
// Fallback to unit price of latest activity continue;
const latestActivity =
await this.activitiesService.getLatestActivity({
dataSource,
symbol
});
value = {
dataSource,
symbol,
date: today,
marketPrice: latestActivity?.unitPrice ?? 0
};
response.values.push(value);
} }
const [latestValue] = response.values const [latestValue] = response.values
@ -172,7 +158,21 @@ export class CurrentRateService {
return 0; return 0;
}); });
value.marketPrice = latestValue.marketPrice; // Fallback to unit price of latest activity
const latestActivity = latestValue
? undefined
: await this.activitiesService.getLatestActivity({
dataSource,
symbol
});
response.values.push({
dataSource,
symbol,
date: today,
marketPrice:
latestValue?.marketPrice ?? latestActivity?.unitPrice ?? 0
});
} catch {} } catch {}
} }
} }

Loading…
Cancel
Save