mirror of https://github.com/ghostfolio/ghostfolio
Browse Source
Co-authored-by: Thomas Kaul <4159106+dtslvr@users.noreply.github.com>feature/daily-exchange-rate
Valentin Zickner
3 years ago
7 changed files with 500 additions and 60 deletions
@ -0,0 +1,201 @@ |
|||
import { DateQuery } from '@ghostfolio/api/app/portfolio/interfaces/date-query.interface'; |
|||
import { ExchangeRateDataService } from '@ghostfolio/api/services/exchange-rate-data.service'; |
|||
import { MarketDataService } from '@ghostfolio/api/services/market-data.service'; |
|||
import { MarketData } from '@prisma/client'; |
|||
import { Big } from 'big.js'; |
|||
import { addDays, endOfDay, isBefore } from 'date-fns'; |
|||
|
|||
jest.mock('@ghostfolio/api/services/market-data.service', () => { |
|||
return { |
|||
MarketDataService: jest.fn().mockImplementation(() => { |
|||
return { |
|||
getRange: ({ |
|||
dateQuery, |
|||
symbols |
|||
}: { |
|||
dateQuery: DateQuery; |
|||
symbols: string[]; |
|||
}) => { |
|||
const exchangeRateMap = { |
|||
USDEUR: 1, |
|||
USDCHF: 2, |
|||
USDUSD: 0 |
|||
}; |
|||
const result = []; |
|||
let j = 1; |
|||
for ( |
|||
let i = dateQuery.gte; |
|||
isBefore(i, dateQuery.lt); |
|||
i = addDays(i, 1) |
|||
) { |
|||
const marketPrice = j++; |
|||
for (const symbol of symbols) { |
|||
result.push({ |
|||
createdAt: i, |
|||
date: i, |
|||
id: '8fa48fde-f397-4b0d-adbc-fb940e830e6d', |
|||
marketPrice: marketPrice * exchangeRateMap[symbol] + 1, |
|||
symbol: symbol |
|||
}); |
|||
} |
|||
} |
|||
return Promise.resolve<MarketData[]>(result); |
|||
} |
|||
}; |
|||
}) |
|||
}; |
|||
}); |
|||
|
|||
describe('ExchangeRateDataService', () => { |
|||
let exchangeRateDataService: ExchangeRateDataService; |
|||
let marketDataService: MarketDataService; |
|||
|
|||
beforeAll(async () => { |
|||
marketDataService = new MarketDataService(null); |
|||
exchangeRateDataService = new ExchangeRateDataService( |
|||
null, |
|||
marketDataService, |
|||
null |
|||
); |
|||
}); |
|||
|
|||
describe('getExchangeRates', () => { |
|||
it('source and destination USD', async () => { |
|||
const startDate = new Date(2021, 0, 1); |
|||
const exchangeRates = await exchangeRateDataService.getExchangeRates({ |
|||
dateQuery: { |
|||
gte: startDate, |
|||
lt: endOfDay(startDate) |
|||
}, |
|||
sourceCurrencies: ['USD'], |
|||
destinationCurrency: 'USD' |
|||
}); |
|||
|
|||
expect(exchangeRates).toEqual([ |
|||
{ |
|||
date: startDate, |
|||
exchangeRates: { |
|||
USD: new Big(1) |
|||
} |
|||
} |
|||
]); |
|||
}); |
|||
|
|||
it('source USD and destination CHF', async () => { |
|||
const startDate = new Date(2021, 0, 1); |
|||
const exchangeRates = await exchangeRateDataService.getExchangeRates({ |
|||
dateQuery: { |
|||
gte: startDate, |
|||
lt: endOfDay(startDate) |
|||
}, |
|||
sourceCurrencies: ['USD'], |
|||
destinationCurrency: 'CHF' |
|||
}); |
|||
|
|||
expect(exchangeRates).toEqual([ |
|||
{ |
|||
date: startDate, |
|||
exchangeRates: { |
|||
USD: new Big(3) |
|||
} |
|||
} |
|||
]); |
|||
}); |
|||
|
|||
it('source CHF and destination USD', async () => { |
|||
const startDate = new Date(2021, 0, 1); |
|||
const exchangeRates = await exchangeRateDataService.getExchangeRates({ |
|||
dateQuery: { |
|||
gte: startDate, |
|||
lt: endOfDay(startDate) |
|||
}, |
|||
sourceCurrencies: ['CHF'], |
|||
destinationCurrency: 'USD' |
|||
}); |
|||
|
|||
expect(exchangeRates).toEqual([ |
|||
{ |
|||
date: startDate, |
|||
exchangeRates: { |
|||
CHF: new Big(1).div(3) |
|||
} |
|||
} |
|||
]); |
|||
}); |
|||
|
|||
it('source CHF and destination EUR', async () => { |
|||
const startDate = new Date(2021, 0, 1); |
|||
const exchangeRates = await exchangeRateDataService.getExchangeRates({ |
|||
dateQuery: { |
|||
gte: startDate, |
|||
lt: endOfDay(startDate) |
|||
}, |
|||
sourceCurrencies: ['CHF'], |
|||
destinationCurrency: 'EUR' |
|||
}); |
|||
|
|||
expect(exchangeRates).toEqual([ |
|||
{ |
|||
date: startDate, |
|||
exchangeRates: { |
|||
CHF: new Big(2).div(3) |
|||
} |
|||
} |
|||
]); |
|||
}); |
|||
|
|||
it('source CHF,EUR,USD and destination EUR', async () => { |
|||
const startDate = new Date(2021, 0, 1); |
|||
const exchangeRates = await exchangeRateDataService.getExchangeRates({ |
|||
dateQuery: { |
|||
gte: startDate, |
|||
lt: endOfDay(startDate) |
|||
}, |
|||
sourceCurrencies: ['CHF', 'USD', 'EUR'], |
|||
destinationCurrency: 'EUR' |
|||
}); |
|||
|
|||
expect(exchangeRates).toEqual([ |
|||
{ |
|||
date: startDate, |
|||
exchangeRates: { |
|||
CHF: new Big(2).div(3), |
|||
USD: new Big(2), |
|||
EUR: new Big(1) |
|||
} |
|||
} |
|||
]); |
|||
}); |
|||
|
|||
it('with multiple days', async () => { |
|||
const startDate = new Date(2021, 0, 1); |
|||
const exchangeRates = await exchangeRateDataService.getExchangeRates({ |
|||
dateQuery: { |
|||
gte: startDate, |
|||
lt: endOfDay(addDays(startDate, 1)) |
|||
}, |
|||
sourceCurrencies: ['CHF', 'USD', 'EUR'], |
|||
destinationCurrency: 'EUR' |
|||
}); |
|||
|
|||
expect(exchangeRates).toEqual([ |
|||
{ |
|||
date: startDate, |
|||
exchangeRates: { |
|||
CHF: new Big(2).div(3), |
|||
USD: new Big(2), |
|||
EUR: new Big(1) |
|||
} |
|||
}, |
|||
{ |
|||
date: addDays(startDate, 1), |
|||
exchangeRates: { |
|||
CHF: new Big(3).div(5), |
|||
USD: new Big(3), |
|||
EUR: new Big(1) |
|||
} |
|||
} |
|||
]); |
|||
}); |
|||
}); |
|||
}); |
@ -0,0 +1,6 @@ |
|||
import Big from 'big.js'; |
|||
|
|||
export interface DateBasedExchangeRate { |
|||
date: Date; |
|||
exchangeRates: { [currency: string]: Big }; |
|||
} |
Loading…
Reference in new issue