Browse Source

fix: gold and other things aren't stocks and has their own boards

Signed-off-by: Anatoly Popov <me@aensidhe.ru>
pull/4641/head
Anatoly Popov 2 months ago
parent
commit
d0ccc8be66
Failed to extract signature
  1. 72
      apps/api/src/services/data-provider/moex/moex.service.ts

72
apps/api/src/services/data-provider/moex/moex.service.ts

@ -17,6 +17,7 @@ import {
import { Injectable, Logger } from '@nestjs/common'; import { Injectable, Logger } from '@nestjs/common';
import { $Enums, SymbolProfile } from '@prisma/client'; import { $Enums, SymbolProfile } from '@prisma/client';
import { isISO4217CurrencyCode } from 'class-validator';
import { import {
subYears, subYears,
format, format,
@ -182,6 +183,26 @@ function getYahooSymbolFromMoex(symbol: string): string {
return `${symbol}.ME`; return `${symbol}.ME`;
} }
async function getSecuritySpecification(
symbol: string,
dataSectionName: string,
key: string
): Promise<Map<string | number, Map<string, string | number>>> {
const securitySpecificationResponse =
await moexClient.security.getSecuritySpecification({ security: symbol });
const errorMessage = securitySpecificationResponse.issError;
if (errorMessage) {
Logger.warn(errorMessage, 'MoexService.getAssetProfile');
return new Map<string | number, Map<string, string | number>>();
}
return response_data_to_map(
securitySpecificationResponse.data[dataSectionName],
key
);
}
interface SecurityTypeMap { interface SecurityTypeMap {
[key: string]: [$Enums.AssetClass?, $Enums.AssetSubClass?]; [key: string]: [$Enums.AssetClass?, $Enums.AssetSubClass?];
} }
@ -302,16 +323,9 @@ export class MoexService implements DataProviderInterface {
}: { }: {
symbol: string; symbol: string;
}): Promise<Partial<SymbolProfile>> { }): Promise<Partial<SymbolProfile>> {
const securitySpecificationResponse = const securitySpecification = await getSecuritySpecification(
await moexClient.security.getSecuritySpecification({ security: symbol }); symbol,
const errorMessage = securitySpecificationResponse.issError; 'description',
if (errorMessage) {
Logger.warn(errorMessage, 'MoexService.getAssetProfile');
return {};
}
const securitySpecification = response_data_to_map(
securitySpecificationResponse.data.description,
'name' 'name'
); );
@ -326,13 +340,19 @@ export class MoexService implements DataProviderInterface {
const [assetClass, assetSubClass] = const [assetClass, assetSubClass] =
securityTypeMap[type.get('value').toString()] ?? []; securityTypeMap[type.get('value').toString()] ?? [];
let currency = faceunit
? getCurrency(faceunit.get('value').toString().toUpperCase())
: 'RUB';
if (!isISO4217CurrencyCode(currency)) {
currency = 'RUB';
}
return { return {
assetClass: assetClass, assetClass: assetClass,
assetSubClass: assetSubClass, assetSubClass: assetSubClass,
createdAt: issueDate ? new Date(issueDate.get('value')) : new Date(), createdAt: issueDate ? new Date(issueDate.get('value')) : new Date(),
currency: faceunit currency,
? getCurrency(faceunit.get('value').toString())
: 'RUB',
dataSource: this.getName(), dataSource: this.getName(),
id: symbol, id: symbol,
isin: isin ? isin.get('value').toString() : null, isin: isin ? isin.get('value').toString() : null,
@ -416,6 +436,17 @@ export class MoexService implements DataProviderInterface {
async getHistorical({ from, symbol, to }: GetHistoricalParams): Promise<{ async getHistorical({ from, symbol, to }: GetHistoricalParams): Promise<{
[symbol: string]: { [date: string]: IDataProviderHistoricalResponse }; [symbol: string]: { [date: string]: IDataProviderHistoricalResponse };
}> { }> {
const securitySpecification = await getSecuritySpecification(
symbol,
'boards',
'is_primary'
);
const primaryBoard = securitySpecification.get(1);
const board_id = primaryBoard.get('boardid');
const market = primaryBoard.get('market');
const engine = primaryBoard.get('engine');
const params: Record<string, any> = { const params: Record<string, any> = {
sort_order: 'desc', sort_order: 'desc',
marketprice_board: '1', marketprice_board: '1',
@ -429,11 +460,16 @@ export class MoexService implements DataProviderInterface {
async (x) => { async (x) => {
params['start'] = x; params['start'] = x;
return await moexClient.request( return await moexClient.request(
`history/engines/stock/markets/shares/securities/${symbol}`, `history/engines/${engine}/markets/${market}/securities/${symbol}`,
params params
); );
}, },
(x) => x.data.history (x) => {
return {
columns: x.data.history.columns,
data: x.data.history.data.filter((x) => x[0] === board_id)
};
}
); );
const history = response_data_to_map(historyResponse, 'TRADEDATE'); const history = response_data_to_map(historyResponse, 'TRADEDATE');
@ -444,9 +480,13 @@ export class MoexService implements DataProviderInterface {
result[symbol] = {}; result[symbol] = {};
for (const [key, value] of history.entries()) { for (const [key, value] of history.entries()) {
const price = value.get('LEGALCLOSEPRICE'); const price = value.get('LEGALCLOSEPRICE') ?? value.get('CLOSE');
if (typeof price === 'number') if (typeof price === 'number')
result[symbol][key] = { marketPrice: price }; result[symbol][key] = { marketPrice: price };
else
Logger.error(
`We have quote, but can't get price. Symbol ${symbol}, columns are [${historyResponse.columns.join(', ')}]`
);
} }
return result; return result;

Loading…
Cancel
Save