moex-vibe/apps/backend/src/modules/candles/candles.service.ts
Sergey Krylov 75fead68b8 refactor: split MoexClientService into domain-specific clients
- 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
2026-06-25 20:49:17 +03:00

49 lines
1.3 KiB
TypeScript

import { Injectable } from '@nestjs/common';
import { MoexCandlesClient } from '../moex-client/moex-candles.client';
import { CacheService } from '../cache/cache.service';
import { CandleInterval } from './dto/candles-query.dto';
import { ApiEnvelopePayload } from '../../common/dto/api-response.dto';
@Injectable()
export class CandlesService {
constructor(
private readonly moexCandles: MoexCandlesClient,
private readonly cache: CacheService,
) {}
private mapInterval(interval: CandleInterval): 60 | 24 {
return interval === CandleInterval.HOUR ? 60 : 24;
}
async getCandles(
market: 'shares' | 'bonds',
secid: string,
interval: CandleInterval,
from: string,
till: string,
) {
const moexInterval = this.mapInterval(interval);
const { data, fromCache, cachedAt } = await this.cache.getOrFetch(
'candles',
[market, secid, String(moexInterval), from, till],
() => this.moexCandles.getCandles('stock', market, secid, moexInterval, from, till),
'candlesTtl',
);
return new ApiEnvelopePayload(
data.map((c) => ({
open: c.open,
high: c.high,
low: c.low,
close: c.close,
volume: c.volume,
value: c.value,
begin: c.begin,
end: c.end,
})),
fromCache,
cachedAt,
);
}
}