refactor: replace ignored numeric literals with constants

This commit is contained in:
2026-09-28 16:37:01 +03:00
committed by ksv741
parent a970eaaf7a
commit b78c215ff1
60 changed files with 510 additions and 283 deletions
@@ -14,8 +14,11 @@ import {
type IdentifiedBond = TbankBond & { uid: string };
import { ISO_DATE_LENGTH, ISO_DATE_START } from '../../../../../common/time';
import { money } from '../infrastructure/bond-money.mapper';
const MIN_LOT_EXCLUSIVE = 0;
@Injectable()
export class BondCatalogService {
constructor(private readonly discovery: CatalogDiscoveryService) {}
@@ -100,13 +103,13 @@ function toBond(bond: IdentifiedBond): BondDto {
currency: bond.currency?.toUpperCase() || null,
bondType: bond.bondType || null,
sector: bond.sector || null,
lot: bond.lot && bond.lot > 0 ? bond.lot : null,
lot: bond.lot && bond.lot > MIN_LOT_EXCLUSIVE ? bond.lot : null,
historyFrom: timestamp(bond.first_1dayCandleDate),
nominal: money(bond.nominal),
initialNominal: money(bond.initialNominal),
aci: money(bond.aciValue),
maturityDate: timestamp(bond.maturityDate)?.slice(0, 10) ?? null,
callDate: timestamp(bond.callDate)?.slice(0, 10) ?? null,
maturityDate: timestamp(bond.maturityDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null,
callDate: timestamp(bond.callDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null,
couponQuantityPerYear: bond.couponQuantityPerYear ?? null,
floatingCoupon: bond.floatingCouponFlag ?? null,
perpetual: bond.perpetualFlag ?? null,
@@ -6,6 +6,7 @@ import {
formatDecimal,
multiply,
} from '../../../../../common/decimal';
import { ISO_DATE_LENGTH, ISO_DATE_START } from '../../../../../common/time';
import {
TbankAccessService,
type TbankBond,
@@ -30,6 +31,12 @@ import {
BondPositionDto,
} from '../presentation/bond.dto';
import { bondQuote } from './bond-market.service';
const INCOME_FORECAST_YEARS = 1;
const ZERO_QUANTITY = 0n;
const MIN_COUPON_PERIOD_EXCLUSIVE = 0;
const ZERO_AMOUNT = 0n;
const ISO_YEAR_LENGTH = 4;
const INCOME_HISTORY_YEARS = 5;
const COUPON_YIELD_DECIMAL_PLACES = 4;
@@ -77,8 +84,8 @@ export class BondIncomeService {
): Promise<BondCouponsResourceDto> {
const connection = await this.access.local(userId);
const today = moscowDay(new Date().toISOString());
const from = `${Number(today.slice(0, ISO_YEAR_LENGTH)) - INCOME_HISTORY_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
const to = `${Number(today.slice(0, ISO_YEAR_LENGTH)) + 1}${today.slice(ISO_YEAR_LENGTH)}`;
const from = `${Number(today.slice(ISO_DATE_START, ISO_YEAR_LENGTH)) - INCOME_HISTORY_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
const to = `${Number(today.slice(ISO_DATE_START, ISO_YEAR_LENGTH)) + INCOME_FORECAST_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
const portfolio = await this.portfolios.read(userId, 'all', observe);
const sources = await this.sources.readMany(
userId,
@@ -139,13 +146,13 @@ export function bondCoupons(
const { from, to, today } = window;
const quantity =
position?.accounts.length &&
position.accounts.every((p) => decimalFromString(p.quantity).value > 0n) ?
position.accounts.every((p) => decimalFromString(p.quantity).value > ZERO_QUANTITY) ?
decimalFromString(position.quantity) :
null;
const coupons = events
.map((event) => {
const paymentDate = timestamp(event.couponDate)?.slice(0, 10) ?? null;
const recordDate = timestamp(event.fixDate)?.slice(0, 10) ?? null;
const paymentDate = timestamp(event.couponDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null;
const recordDate = timestamp(event.fixDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null;
const perBond = money(event.payOneBond);
const timing = !paymentDate ?
('undated' as const) :
@@ -198,10 +205,10 @@ export function bondMetrics(
const effectiveYield = values.effectiveYield ?? null;
const creditRating = values.creditRating ?? null;
const today = moscowDay(new Date().toISOString());
const to = `${Number(today.slice(0, ISO_YEAR_LENGTH)) + 1}${today.slice(ISO_YEAR_LENGTH)}`;
const to = `${Number(today.slice(ISO_DATE_START, ISO_YEAR_LENGTH)) + INCOME_FORECAST_YEARS}${today.slice(ISO_YEAR_LENGTH)}`;
const next = events
?.filter((event) => {
const date = timestamp(event.couponDate)?.slice(0, 10);
const date = timestamp(event.couponDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH);
return date && date >= today && date <= to;
})
.sort(
@@ -210,15 +217,15 @@ export function bondMetrics(
const coupon = money(next?.payOneBond);
const period = next?.couponPeriod;
const couponPeriodDays =
period && Number.isInteger(period) && period > 0 ? period : null;
period && Number.isInteger(period) && period > MIN_COUPON_PERIOD_EXCLUSIVE ? period : null;
const clean = quote?.cleanPrice;
const couponYieldPercent =
coupon &&
couponPeriodDays &&
clean &&
coupon.currency === clean.currency &&
decimalFromString(coupon.value).value >= 0n &&
decimalFromString(clean.value).value > 0n ?
decimalFromString(coupon.value).value >= ZERO_AMOUNT &&
decimalFromString(clean.value).value > ZERO_AMOUNT ?
formatDecimal(
divide(
multiply(
@@ -242,7 +249,7 @@ export function bondMetrics(
return {
creditRating,
coupon,
couponDate: timestamp(next?.couponDate)?.slice(0, 10) ?? null,
couponDate: timestamp(next?.couponDate)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null,
couponType,
couponPeriodDays,
couponYieldPercent,
@@ -10,6 +10,7 @@ import {
multiply,
subtract,
} from '../../../../../common/decimal';
import { ISO_DATE_LENGTH, ISO_DATE_START } from '../../../../../common/time';
import { decimal } from '../../../../../integrations/tbank/decimal';
import { CandleService } from '../../application/candle.service';
import {
@@ -24,6 +25,8 @@ import {
BondQuoteResourceDto,
} from '../presentation/bond.dto';
const ZERO_AMOUNT = 0n;
const PRICE_DECIMAL_PLACES = 9;
@Injectable()
export class BondMarketService {
@@ -80,7 +83,7 @@ export function bondQuote(
const cleanPrice =
pricePercent !== null &&
nominal &&
decimalFromString(nominal.value).value > 0n ?
decimalFromString(nominal.value).value > ZERO_AMOUNT ?
{
currency: nominal.currency,
value: formatDecimal(
@@ -118,7 +121,7 @@ export function bondQuote(
last?.price && previous?.close ?
formatDecimal(subtract(decimal(last.price), decimal(previous.close))) :
null,
previousCloseDate: timestamp(previous?.time)?.slice(0, 10) ?? null,
previousCloseDate: timestamp(previous?.time)?.slice(ISO_DATE_START, ISO_DATE_LENGTH) ?? null,
unavailable,
observedAt,
};