etreschenkov 2026-04-29 15:12:28 +03:00
parent 4e52ce01d8
commit 9d89f94dba
7 changed files with 67 additions and 51 deletions

View file

@ -151,7 +151,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean {
kafkaSender.sendRequestToQueue(Consts.NOTIFICATION_NEW, newReq); kafkaSender.sendRequestToQueue(Consts.NOTIFICATION_NEW, newReq);
} }
log.info("SDOR export and send command to fix, request={}", req); log.info("export to tri...");
try { try {
Collection<OrderCurrency> orders = imdgQueryService.getClccOrderCurrencyIds(); Collection<OrderCurrency> orders = imdgQueryService.getClccOrderCurrencyIds();
String content = orderCurrencyTriExportService.exportToTri(orders); String content = orderCurrencyTriExportService.exportToTri(orders);
@ -159,6 +159,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean {
LocalDateTime.now().format(formatter))); LocalDateTime.now().format(formatter)));
Files.writeString(fileName, content, StandardCharsets.UTF_8); Files.writeString(fileName, content, StandardCharsets.UTF_8);
if (SendOrdersTypes.FIX == sendOrdersTypes) { if (SendOrdersTypes.FIX == sendOrdersTypes) {
log.info("send command to fix service...");
kafkaSender.sendRequestToQueue(Consts.SDOR_FIX_TASK, req.getRequestPayload()); kafkaSender.sendRequestToQueue(Consts.SDOR_FIX_TASK, req.getRequestPayload());
} }
} catch (IOException e) { } catch (IOException e) {

View file

@ -0,0 +1,10 @@
package ru.spcex.clearing.dflt.management.model;
import java.math.BigDecimal;
public record FinalCalculationResult(
BigDecimal price,
BigDecimal rate,
BigDecimal quantityLot
) {
}

View file

@ -209,7 +209,6 @@ public class ImdgQueryService {
public BigDecimal defineTransferRate(Long currencyPairDictionaryId, String securitySymbol) { public BigDecimal defineTransferRate(Long currencyPairDictionaryId, String securitySymbol) {
ImdgPredicateBuilder pb = riskParameterImdg.predicateBuilder(); ImdgPredicateBuilder pb = riskParameterImdg.predicateBuilder();
boolean isRub = "RUB".equals(securitySymbol); boolean isRub = "RUB".equals(securitySymbol);
String baseCurrency = isRub ? "CNY" : securitySymbol;
RiskParameter riskParameter = riskParameterImdg.getSingleObjectByPredicate( RiskParameter riskParameter = riskParameterImdg.getSingleObjectByPredicate(
pb.and( pb.and(
@ -217,7 +216,7 @@ public class ImdgQueryService {
pb.equals("currencyPairId", currencyPairDictionaryId) pb.equals("currencyPairId", currencyPairDictionaryId)
) )
); );
return isRub ? riskParameter.getQuoteValue() : riskParameter.getValue(); return isRub ? riskParameter.getQuoteValue() : riskParameter.getPenaltyValue();
} }
public CurrencyPairDictionary getCurrencyPairDictionaryBySecurityId(Long securityId) { public CurrencyPairDictionary getCurrencyPairDictionaryBySecurityId(Long securityId) {

View file

@ -8,12 +8,12 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
import ru.clearing.classes.statics.data.misc.Listing; import ru.clearing.classes.statics.data.misc.Listing;
import ru.clearing.classes.statics.data.misc.OrderCurrency;
import ru.clearing.classes.statics.data.misc.SCrossRate; import ru.clearing.classes.statics.data.misc.SCrossRate;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.security.Rates; import ru.clearing.classes.statics.data.security.Rates;
import ru.clearing.platform.dictionary.CurrencyPairDictionary; import ru.clearing.platform.dictionary.CurrencyPairDictionary;
import ru.spcex.clearing.dflt.management.model.CalculationResult; import ru.spcex.clearing.dflt.management.model.CalculationResult;
import ru.spcex.clearing.dflt.management.model.FinalCalculationResult;
import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext; import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext;
import ru.spcex.platform.enumeration.CurrencyCode; import ru.spcex.platform.enumeration.CurrencyCode;
import ru.spcex.platform.enumeration.SettleCode; import ru.spcex.platform.enumeration.SettleCode;
@ -32,10 +32,10 @@ public class OrderCalculationService {
this.transferDateService = transferDateService; this.transferDateService = transferDateService;
} }
public void calcAndEnrichSwap(OrderCurrency order, public FinalCalculationResult calcAndEnrichSwap(SettleCode settleCode,
OrderCurrencyContext context) { OrderCurrencyContext context) {
Registry registry = context.getRegistry(); Registry registry = context.getRegistry();
Listing listing = imdgQueryService.findListing(registry, context.getMarket().getCode(), order.getSettleCode()); Listing listing = imdgQueryService.findListing(registry, context.getMarket().getCode(), settleCode.getKey());
CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryBySecurityId(listing.getSecurityId()); CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryBySecurityId(listing.getSecurityId());
BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol()); BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol());
@ -48,15 +48,13 @@ public class OrderCalculationService {
BigDecimal quantityLot = result.sum3().abs(); BigDecimal quantityLot = result.sum3().abs();
BigDecimal price = swapPriceCalc(pair.getBaseCurrency(), s, n); BigDecimal price = swapPriceCalc(pair.getBaseCurrency(), s, n);
order.setPrice(price); return new FinalCalculationResult(price, s, quantityLot);
order.setQuantityLot(quantityLot);
order.setRate(s);
} }
public void calcAndEnrichSpot(OrderCurrency order, public FinalCalculationResult calcAndEnrichSpot(SettleCode settleCode,
OrderCurrencyContext context) { OrderCurrencyContext context) {
Registry registry = context.getRegistry(); Registry registry = context.getRegistry();
Listing listing = imdgQueryService.findListing(registry, context.getMarket().getCode(), order.getSettleCode()); Listing listing = imdgQueryService.findListing(registry, context.getMarket().getCode(), settleCode.getKey());
CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryBySecurityId(listing.getSecurityId()); CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryBySecurityId(listing.getSecurityId());
BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol()); BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol());
@ -69,7 +67,7 @@ public class OrderCalculationService {
SCrossRate rates = imdgQueryService.getSCrossRates(pair.getBaseCurrency(), LocalDate.now()); SCrossRate rates = imdgQueryService.getSCrossRates(pair.getBaseCurrency(), LocalDate.now());
BigDecimal quantityLot; BigDecimal quantityLot;
BigDecimal price; BigDecimal price;
if (SettleCode.T0.equalsByKey(order.getSettleCode())) { if (SettleCode.T0 == settleCode) {
quantityLot = result.sum3().abs(); quantityLot = result.sum3().abs();
price = rates.getUnitRate(); price = rates.getUnitRate();
} else { } else {
@ -78,9 +76,7 @@ public class OrderCalculationService {
price = rates.getUnitRate().add(delta); price = rates.getUnitRate().add(delta);
} }
order.setPrice(price); return new FinalCalculationResult(price, s, quantityLot);
order.setQuantityLot(quantityLot);
order.setRate(s);
} }
private CalculationResult calculationSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) { private CalculationResult calculationSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) {

View file

@ -7,6 +7,7 @@ import ru.clearing.classes.statics.data.misc.Market;
import ru.clearing.classes.statics.data.misc.OrderCurrency; import ru.clearing.classes.statics.data.misc.OrderCurrency;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo; import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
import ru.spcex.clearing.dflt.management.model.FinalCalculationResult;
import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext; import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext;
import ru.spcex.platform.enumeration.SettleCode; import ru.spcex.platform.enumeration.SettleCode;
import static ru.spcex.platform.enumeration.SettleCode.T0; import static ru.spcex.platform.enumeration.SettleCode.T0;
@ -20,7 +21,9 @@ public class OrderTemplateBuilder {
this.imdgQueryService = imdgQueryService; this.imdgQueryService = imdgQueryService;
} }
public OrderCurrency buildPrimaryTransfer(OrderCurrencyContext context, SettleCode settleCode) { public OrderCurrency buildPrimaryTransfer(OrderCurrencyContext context,
SettleCode settleCode,
FinalCalculationResult finalCalculationResult) {
OrderCurrency orderCurrency; OrderCurrency orderCurrency;
switch (context.getOrderCategory()) { switch (context.getOrderCategory()) {
case "PL" -> orderCurrency = buildPrimaryTransferPl(context); case "PL" -> orderCurrency = buildPrimaryTransferPl(context);
@ -28,11 +31,13 @@ public class OrderTemplateBuilder {
default -> throw new IllegalArgumentException("Unsupported order category: " + context.getOrderCategory()); default -> throw new IllegalArgumentException("Unsupported order category: " + context.getOrderCategory());
} }
Side side = resolvePrimaryTransferSide(context.getRegistry(), settleCode); Side side = resolvePrimaryTransferSide(context.getRegistry(), settleCode);
enrichOrder(orderCurrency, context, side, "overnight", settleCode); enrichOrder(orderCurrency, context, side, "overnight", settleCode, finalCalculationResult);
return orderCurrency; return orderCurrency;
} }
public OrderCurrency buildCounterTransfer(OrderCurrencyContext context, SettleCode settleCode) { public OrderCurrency buildCounterTransfer(OrderCurrencyContext context,
SettleCode settleCode,
FinalCalculationResult finalCalculationResult) {
OrderCurrency orderCurrency; OrderCurrency orderCurrency;
switch (context.getOrderCategory()) { switch (context.getOrderCategory()) {
case "PL" -> orderCurrency = buildCounterTransferPl(context); case "PL" -> orderCurrency = buildCounterTransferPl(context);
@ -41,11 +46,13 @@ public class OrderTemplateBuilder {
} }
; ;
Side side = resolveCounterTransferSide(context.getRegistry(), settleCode); Side side = resolveCounterTransferSide(context.getRegistry(), settleCode);
enrichOrder(orderCurrency, context, side, "overnight", settleCode); enrichOrder(orderCurrency, context, side, "overnight", settleCode, finalCalculationResult);
return orderCurrency; return orderCurrency;
} }
public OrderCurrency buildPrimaryBalancing(OrderCurrencyContext context, SettleCode settleCode) { public OrderCurrency buildPrimaryBalancing(OrderCurrencyContext context,
SettleCode settleCode,
FinalCalculationResult finalCalculationResult) {
OrderCurrency orderCurrency; OrderCurrency orderCurrency;
switch (context.getOrderCategory()) { switch (context.getOrderCategory()) {
case "PL" -> orderCurrency = buildPrimaryBalancingPl(context); case "PL" -> orderCurrency = buildPrimaryBalancingPl(context);
@ -54,11 +61,13 @@ public class OrderTemplateBuilder {
} }
; ;
Side side = resolvePrimaryBalancingSide(context.getRegistry(), settleCode); Side side = resolvePrimaryBalancingSide(context.getRegistry(), settleCode);
enrichOrder(orderCurrency, context, side, "balance", settleCode); enrichOrder(orderCurrency, context, side, "balance", settleCode, finalCalculationResult);
return orderCurrency; return orderCurrency;
} }
public OrderCurrency buildCounterBalancing(OrderCurrencyContext context, SettleCode settleCode) { public OrderCurrency buildCounterBalancing(OrderCurrencyContext context,
SettleCode settleCode,
FinalCalculationResult finalCalculationResult) {
OrderCurrency orderCurrency; OrderCurrency orderCurrency;
switch (context.getOrderCategory()) { switch (context.getOrderCategory()) {
case "PL" -> orderCurrency = buildCounterBalancingPl(context); case "PL" -> orderCurrency = buildCounterBalancingPl(context);
@ -67,7 +76,7 @@ public class OrderTemplateBuilder {
} }
; ;
Side side = resolveCounterBalancingSide(context.getRegistry(), settleCode); Side side = resolveCounterBalancingSide(context.getRegistry(), settleCode);
enrichOrder(orderCurrency, context, side, "balance", settleCode); enrichOrder(orderCurrency, context, side, "balance", settleCode, finalCalculationResult);
return orderCurrency; return orderCurrency;
} }
@ -195,7 +204,8 @@ public class OrderTemplateBuilder {
OrderCurrencyContext context, OrderCurrencyContext context,
Side side, Side side,
String comment, String comment,
SettleCode settleCode) { SettleCode settleCode,
FinalCalculationResult finalCalculationResult) {
Registry registry = context.getRegistry(); Registry registry = context.getRegistry();
Market market = context.getMarket(); Market market = context.getMarket();
Listing listing = imdgQueryService.findListing(registry, market.getCode(), settleCode.getKey()); Listing listing = imdgQueryService.findListing(registry, market.getCode(), settleCode.getKey());
@ -212,6 +222,10 @@ public class OrderTemplateBuilder {
order.setComment(comment); order.setComment(comment);
order.setRegistryId(registry.getId()); order.setRegistryId(registry.getId());
order.setCreated(Instant.now()); order.setCreated(Instant.now());
order.setPrice(finalCalculationResult.price());
order.setQuantityLot(finalCalculationResult.quantityLot());
order.setRate(finalCalculationResult.rate());
} }
public Side resolvePrimaryTransferSide(Registry registry, SettleCode settleCode) { public Side resolvePrimaryTransferSide(Registry registry, SettleCode settleCode) {

View file

@ -8,6 +8,7 @@ import ru.clearing.classes.statics.data.misc.OrderCurrency;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.security.RiskParameter; import ru.clearing.classes.statics.data.security.RiskParameter;
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo; import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
import ru.spcex.clearing.dflt.management.model.FinalCalculationResult;
import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext; import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.enumeration.CompanyRole; import ru.spcex.platform.enumeration.CompanyRole;
@ -58,25 +59,17 @@ public class SpotOvernightOrderService {
.overnightType(OvernightType.SPOT) .overnightType(OvernightType.SPOT)
.build(); .build();
OrderCurrency primaryTransferT0 = templateBuilder.buildPrimaryTransfer(context, SettleCode.T0); FinalCalculationResult finalCalculationResultT0 = swapCalculationService.calcAndEnrichSpot(SettleCode.T0, context);
OrderCurrency counterTransferT0 = templateBuilder.buildCounterTransfer(context, SettleCode.T0); FinalCalculationResult finalCalculationResultT1 = swapCalculationService.calcAndEnrichSpot(SettleCode.T1, context);
OrderCurrency primaryTransferT1 = templateBuilder.buildPrimaryTransfer(context, SettleCode.T1); OrderCurrency primaryTransferT0 = templateBuilder.buildPrimaryTransfer(context, SettleCode.T0, finalCalculationResultT0);
OrderCurrency counterTransferT1 = templateBuilder.buildCounterTransfer(context, SettleCode.T1); OrderCurrency counterTransferT0 = templateBuilder.buildCounterTransfer(context, SettleCode.T0, finalCalculationResultT0);
OrderCurrency primaryTransferT1 = templateBuilder.buildPrimaryTransfer(context, SettleCode.T1, finalCalculationResultT1);
OrderCurrency counterTransferT1 = templateBuilder.buildCounterTransfer(context, SettleCode.T1, finalCalculationResultT1);
OrderCurrency primaryBalancingT0 = templateBuilder.buildPrimaryBalancing(context, SettleCode.T0); OrderCurrency primaryBalancingT0 = templateBuilder.buildPrimaryBalancing(context, SettleCode.T0, finalCalculationResultT0);
OrderCurrency counterBalancingT0 = templateBuilder.buildCounterBalancing(context, SettleCode.T0); OrderCurrency counterBalancingT0 = templateBuilder.buildCounterBalancing(context, SettleCode.T0, finalCalculationResultT0);
OrderCurrency primaryBalancingT1 = templateBuilder.buildPrimaryBalancing(context, SettleCode.T1); OrderCurrency primaryBalancingT1 = templateBuilder.buildPrimaryBalancing(context, SettleCode.T1, finalCalculationResultT1);
OrderCurrency counterBalancingT1 = templateBuilder.buildCounterBalancing(context, SettleCode.T1); OrderCurrency counterBalancingT1 = templateBuilder.buildCounterBalancing(context, SettleCode.T1, finalCalculationResultT1);
swapCalculationService.calcAndEnrichSpot(primaryTransferT0, context);
swapCalculationService.calcAndEnrichSpot(counterTransferT0, context);
swapCalculationService.calcAndEnrichSpot(primaryTransferT1, context);
swapCalculationService.calcAndEnrichSpot(counterTransferT1, context);
swapCalculationService.calcAndEnrichSpot(primaryBalancingT0, context);
swapCalculationService.calcAndEnrichSpot(counterBalancingT0, context);
swapCalculationService.calcAndEnrichSpot(primaryBalancingT1, context);
swapCalculationService.calcAndEnrichSpot(counterBalancingT1, context);
orderCurrencyImdg.insert(primaryTransferT0); orderCurrencyImdg.insert(primaryTransferT0);
orderCurrencyImdg.insert(counterTransferT0); orderCurrencyImdg.insert(counterTransferT0);

View file

@ -1,5 +1,6 @@
package ru.spcex.clearing.dflt.management.service; package ru.spcex.clearing.dflt.management.service;
import java.math.BigDecimal;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service; import org.springframework.stereotype.Service;
@ -8,6 +9,7 @@ import ru.clearing.classes.statics.data.misc.OrderCurrency;
import ru.clearing.classes.statics.data.registry.Registry; import ru.clearing.classes.statics.data.registry.Registry;
import ru.clearing.classes.statics.data.security.RiskParameter; import ru.clearing.classes.statics.data.security.RiskParameter;
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo; import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
import ru.spcex.clearing.dflt.management.model.FinalCalculationResult;
import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext; import ru.spcex.clearing.dflt.management.model.OrderCurrencyContext;
import ru.spcex.clearing.imdg.IMDGDistributedNames; import ru.spcex.clearing.imdg.IMDGDistributedNames;
import ru.spcex.platform.enumeration.CompanyRole; import ru.spcex.platform.enumeration.CompanyRole;
@ -58,15 +60,16 @@ public class SwapOvernightOrderService {
.overnightType(OvernightType.SWAP) .overnightType(OvernightType.SWAP)
.build(); .build();
OrderCurrency primaryTransfer = templateBuilder.buildPrimaryTransfer(context, SettleCode.T1); FinalCalculationResult finalCalculationResult = swapCalculationService.calcAndEnrichSwap(SettleCode.T1, context);
OrderCurrency counterTransfer = templateBuilder.buildCounterTransfer(context, SettleCode.T1); if (finalCalculationResult.quantityLot().compareTo(BigDecimal.ZERO) > 0) {
OrderCurrency primaryBalancing = templateBuilder.buildPrimaryBalancing(context, SettleCode.T1); log.warn("QuantityLot greater than zero; skip forming order currency");
OrderCurrency counterBalancing = templateBuilder.buildCounterBalancing(context, SettleCode.T1); return;
}
swapCalculationService.calcAndEnrichSwap(primaryTransfer, context); OrderCurrency primaryTransfer = templateBuilder.buildPrimaryTransfer(context, SettleCode.T1, finalCalculationResult);
swapCalculationService.calcAndEnrichSwap(counterTransfer, context); OrderCurrency counterTransfer = templateBuilder.buildCounterTransfer(context, SettleCode.T1, finalCalculationResult);
swapCalculationService.calcAndEnrichSwap(primaryBalancing, context); OrderCurrency primaryBalancing = templateBuilder.buildPrimaryBalancing(context, SettleCode.T1, finalCalculationResult);
swapCalculationService.calcAndEnrichSwap(counterBalancing, context); OrderCurrency counterBalancing = templateBuilder.buildCounterBalancing(context, SettleCode.T1, finalCalculationResult);
orderCurrencyImdg.insert(primaryTransfer); orderCurrencyImdg.insert(primaryTransfer);
orderCurrencyImdg.insert(counterTransfer); orderCurrencyImdg.insert(counterTransfer);