etreschenkov 2026-04-10 12:08:35 +03:00
parent c8716d1c08
commit d686200604

View file

@ -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<Market> marketImdg;
private final Imdg<RiskParameter> riskParameterImdg;
private final Imdg<Rates> ratesImdg;
private final Imdg<ClearingCalendar> 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;