From d686200604eb038ce69cd034ddaad1473658bd30 Mon Sep 17 00:00:00 2001 From: etreschenkov Date: Fri, 10 Apr 2026 12:08:35 +0300 Subject: [PATCH] http://jira.mfd.msk:8088/browse/CLS-943 --- .../management/listener/TaskListener.java | 88 +++++++++++++++++-- 1 file changed, 83 insertions(+), 5 deletions(-) diff --git a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java index 764b9786c..a61cf9408 100644 --- a/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java +++ b/clearing-parent/default-management/src/main/java/ru/spcex/clearing/dflt/management/listener/TaskListener.java @@ -3,6 +3,7 @@ package ru.spcex.clearing.dflt.management.listener; import java.math.BigDecimal; import java.math.MathContext; import java.math.RoundingMode; +import java.time.DayOfWeek; import java.time.LocalDate; import java.util.Collection; import java.util.Optional; @@ -22,6 +23,7 @@ import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.misc.OvernightSettings; import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.TradingClearingRegistry; +import ru.clearing.classes.statics.data.scheduler.ClearingCalendar; import ru.clearing.classes.statics.data.security.CurrencyPairSecurity; import ru.clearing.classes.statics.data.security.Rates; import ru.clearing.classes.statics.data.security.RiskParameter; @@ -34,6 +36,7 @@ import ru.spcex.clearing.platform.messaging.domain.cud.misc.OvernightSettingsNew import ru.spcex.clearing.platform.messaging.service.QueueConsumer; import ru.spcex.clearing.util.security.UserRoleVerification; import ru.spcex.platform.enumeration.CompanyRole; +import ru.spcex.platform.enumeration.DayStatus; import ru.spcex.platform.enumeration.MarketType; import ru.spcex.platform.enumeration.OvernightType; import ru.spcex.platform.enumeration.Side; @@ -61,6 +64,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean { private final Imdg marketImdg; private final Imdg riskParameterImdg; private final Imdg ratesImdg; + private final Imdg clearingCalendarImdg; private final DefaultManagementSettings settings; @Autowired @@ -84,6 +88,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean { this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, Market.class); this.riskParameterImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_RiskParameter, RiskParameter.class); this.ratesImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Rates, Rates.class); + this.clearingCalendarImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingCalendar, ClearingCalendar.class); this.orderCurrencyService = orderCurrencyService; this.settings = settings; } @@ -378,6 +383,16 @@ public class TaskListener extends QueueConsumer implements InitializingBean { RiskParameter riskParameter, Side side, String comment) { + CurrencyPairSecurity currencyPairSecurity = currencyPairSecurityImdg.getSingleObjectByID(listing.getSecurityId()); + CurrencyPairDictionary currencyPairDictionary = currencyPairDictionaryImdg + .getSingleObjectByID(currencyPairSecurity.getCurrencyPairId()); + + BigDecimal s = defineTransferRate(currencyPairDictionary.getId(), registry.getSecuritySymbol()); + BigDecimal n = numberOfDaysOfTransfer(); + CalculationResultHolder resultHolder = calculationSwapSums(registry, listing.getLotSize().intValue(), s, n); + BigDecimal quantityLot = resultHolder.getSum3().abs(); + BigDecimal price = swapPriceCalc(currencyPairDictionary.getBaseCurrency(), s, n); + orderCurrency.setOvernightType("SWAP"); orderCurrency.setMarket(market.getCode()); orderCurrency.setListingId(listing.getId()); @@ -390,6 +405,8 @@ public class TaskListener extends QueueConsumer implements InitializingBean { orderCurrency.setStatus("CRET"); orderCurrency.setComment(comment); orderCurrency.setRegistryId(registry.getId()); + orderCurrency.setPrice(price); + orderCurrency.setQuantityLot(quantityLot); } private Listing findListingForRub(Registry registry, String market) { @@ -468,7 +485,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean { Registry amtRubRegistry = findAmtRegistry(registry, "RUB"); BigDecimal planPositionRub = amtRubRegistry.getBalance(); - Rates rates = findRates(registry); + Rates rates = findRates(registry.getSecuritySymbol()); BigDecimal ratesValue = rates.getValue(); BigDecimal sum2 = planPositionRub.divide(ratesValue, lotSize, RoundingMode.HALF_DOWN); @@ -495,7 +512,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean { //registry.securitySymbol == 'RUB' private CalculationResultHolder calculationSwapRubSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) { BigDecimal planPosition = registry.getBalance(); - Rates cnyRates = findRates(registry); + Rates cnyRates = findRates(registry.getSecuritySymbol()); BigDecimal ratesValue = cnyRates.getValue(); BigDecimal sum1 = planPosition.divide(ratesValue, MC); @@ -535,11 +552,11 @@ public class TaskListener extends QueueConsumer implements InitializingBean { ); } - private Rates findRates(Registry registry) { + private Rates findRates(String securitySymbol) { ImdgPredicateBuilder predicateBuilder = registryImdg.predicateBuilder(); return ratesImdg.getSingleObjectByPredicate( predicateBuilder.and( - predicateBuilder.equals("currency", registry.getSecuritySymbol()), + predicateBuilder.equals("currency", securitySymbol), predicateBuilder.equals("valueDate", LocalDate.now()), predicateBuilder.equals("workflowStatus", WorkflowStatus.Active.getKey()) ) @@ -557,6 +574,39 @@ public class TaskListener extends QueueConsumer implements InitializingBean { ); } + private BigDecimal swapPriceCalc(String baseCurrency, BigDecimal s, BigDecimal n) { + LocalDate now = LocalDate.now(); + ImdgPredicateBuilder predicateBuilder = ratesImdg.predicateBuilder(); + BigDecimal daysInYear = BigDecimal.valueOf(365); + + Rates rates = ratesImdg.getSingleObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("currency", baseCurrency), + predicateBuilder.equals("valueDate", now), + predicateBuilder.equals("workflowStatus", WorkflowStatus.Active.getKey()) + ) + ); + BigDecimal rateValue = rates.getValue(); + return rateValue.multiply(s, MC).multiply(n, MC).divide(daysInYear, MC); + } + + private BigDecimal defineTransferRate(Long currencyPairDictionaryId, String securitySymbol) { + ImdgPredicateBuilder predicateBuilder = riskParameterImdg.predicateBuilder(); + String securitySymbolCondition = securitySymbol.equals("RUB") ? "CNY" : securitySymbol; + RiskParameter riskParameter = riskParameterImdg.getSingleObjectByPredicate( + predicateBuilder.and( + predicateBuilder.equals("settlementType", "T0"), + predicateBuilder.equals("currencyPairId", currencyPairDictionaryId), + predicateBuilder.equals("baseCurrency", securitySymbolCondition) + ) + ); + return riskParameter.getQuoteValue(); + } + + private BigDecimal numberOfDaysOfTransfer() { + LocalDate nextWorkingDay = findNextWorkingDate(); + return BigDecimal.valueOf(nextWorkingDay.compareTo(LocalDate.now())); + } public static BigDecimal ceilMath(BigDecimal value, BigDecimal significance) { if (significance == null || significance.compareTo(BigDecimal.ZERO) <= 0) { throw new IllegalArgumentException("significance must be > 0"); @@ -568,7 +618,35 @@ public class TaskListener extends QueueConsumer implements InitializingBean { BigDecimal divided = value.divide(significance, 0, RoundingMode.CEILING); return divided.multiply(significance); } - + + private LocalDate findNextWorkingDate() { + LocalDate checkingDate = LocalDate.now().plusDays(1); + + ImdgPredicateBuilder predicateBuilder = clearingCalendarImdg.predicateBuilder(); + while (true) { + ClearingCalendar clearingCalendar = clearingCalendarImdg.getFirstObjectByPredicate( + predicateBuilder.equals("clearingDate", checkingDate) + ); + DayOfWeek dayOfWeek = checkingDate.getDayOfWeek(); + if (isWeekday(dayOfWeek)) { + if (clearingCalendar != null && DayStatus.Workday.equalsByKey(clearingCalendar.getDayStatus())) { + return checkingDate; + } + checkingDate = checkingDate.plusDays(1); + } else { + if (clearingCalendar != null && DayStatus.DayOff.equalsByKey(clearingCalendar.getDayStatus())) { + checkingDate = checkingDate.plusDays(1); + continue; + } + return checkingDate; + } + } + } + + private boolean isWeekday(DayOfWeek dayOfWeek) { + return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY; + } + public static class CalculationResultHolder { private BigDecimal sum1; private BigDecimal sum2;