- MoexHttpClient: infrastructure (axios, rate limiter, circuit breaker) - MoexSecuritiesClient: search and security descriptions - MoexMarketDataClient: share/bond market data and batch queries - MoexCandlesClient: candle data - MoexHistoryClient: share/bond history - MoexDividendsClient: dividend data - Removed @Global() from MoexClientModule - Updated all 7 consumers with explicit DI - All 141 tests passing
51 lines
2.3 KiB
TypeScript
51 lines
2.3 KiB
TypeScript
import { Injectable } from '@nestjs/common';
|
|
import { MoexHttpClient } from './moex-http.client';
|
|
import { MoexHistoryEntry, MoexBondHistoryEntry } from './moex-client.types';
|
|
|
|
@Injectable()
|
|
export class MoexHistoryClient {
|
|
constructor(private readonly http: MoexHttpClient) {}
|
|
|
|
async getHistory(secid: string, from: string, till: string): Promise<MoexHistoryEntry[]> {
|
|
const data = await this.http.request<Record<string, unknown>>(
|
|
`/engines/stock/markets/shares/securities/${secid}`,
|
|
{ from, till },
|
|
);
|
|
const tableName = Object.keys(data).find(
|
|
(k) => k.startsWith('history') && !k.includes('cursor'),
|
|
);
|
|
if (!tableName) return [];
|
|
return this.http.extractTable(data, tableName).map((h) => ({
|
|
tradeDate: h.TRADEDATE as string,
|
|
open: h.OPEN != null ? parseFloat(h.OPEN as string) : null,
|
|
low: h.LOW != null ? parseFloat(h.LOW as string) : null,
|
|
high: h.HIGH != null ? parseFloat(h.HIGH as string) : null,
|
|
close: h.CLOSE != null ? parseFloat(h.CLOSE as string) : null,
|
|
waprice: h.WAPRICE != null ? parseFloat(h.WAPRICE as string) : null,
|
|
volume: parseInt((h.VOLUME as string) || '0', 10),
|
|
value: parseFloat((h.VALUE as string) || '0'),
|
|
numtrades: parseInt((h.NUMTRADES as string) || '0', 10),
|
|
}));
|
|
}
|
|
|
|
async getBondHistory(secid: string, from: string, till: string): Promise<MoexBondHistoryEntry[]> {
|
|
const data = await this.http.request<Record<string, unknown>>(
|
|
`/engines/stock/markets/bonds/securities/${secid}`,
|
|
{ from, till },
|
|
);
|
|
const tableName = Object.keys(data).find(
|
|
(k) => k.startsWith('history') && !k.includes('cursor'),
|
|
);
|
|
if (!tableName) return [];
|
|
return this.http.extractTable(data, tableName).map((h) => ({
|
|
tradeDate: h.TRADEDATE as string,
|
|
close: h.CLOSE != null ? parseFloat(h.CLOSE as string) : null,
|
|
legalClosePrice: h.LEGALCLOSEPRICE != null ? parseFloat(h.LEGALCLOSEPRICE as string) : null,
|
|
waprice: h.WAPRICE != null ? parseFloat(h.WAPRICE as string) : null,
|
|
yieldClose: h.YIELDCLOSE != null ? parseFloat(h.YIELDCLOSE as string) : null,
|
|
duration: h.DURATION != null ? parseFloat(h.DURATION as string) : null,
|
|
accruedInt: h.ACCINT != null ? parseFloat(h.ACCINT as string) : null,
|
|
}));
|
|
}
|
|
}
|