http://jira.mfd.msk:8088/browse/CLS-591
This commit is contained in:
parent
e8cba0467a
commit
c86f1e907a
7 changed files with 125 additions and 52 deletions
|
|
@ -15,6 +15,7 @@ public class ClearingServiceSettings {
|
|||
private KafkaConsumerSettings kafkaConsumer;
|
||||
private KafkaProducerSettings kafkaProducer;
|
||||
private SessionStageSettings sessionStage;
|
||||
private TradeSettings trade = new TradeSettings();
|
||||
|
||||
public HazelcastClientParams getHazelcast() {
|
||||
return hazelcast;
|
||||
|
|
@ -47,4 +48,12 @@ public class ClearingServiceSettings {
|
|||
public void setSessionStage(SessionStageSettings sessionStage) {
|
||||
this.sessionStage = sessionStage;
|
||||
}
|
||||
|
||||
public TradeSettings getTrade() {
|
||||
return trade;
|
||||
}
|
||||
|
||||
public void setTrade(TradeSettings trade) {
|
||||
this.trade = trade;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,14 @@
|
|||
package ru.spcex.clearing.config.element;
|
||||
|
||||
|
||||
public class TradeSettings {
|
||||
private Boolean valuation = false;
|
||||
|
||||
public Boolean getValuation() {
|
||||
return valuation;
|
||||
}
|
||||
|
||||
public void setValuation(Boolean valuation) {
|
||||
this.valuation = valuation;
|
||||
}
|
||||
}
|
||||
|
|
@ -1,42 +0,0 @@
|
|||
package ru.spcex.clearing.service.builder;
|
||||
|
||||
import ru.clearing.classes.statics.data.payment.PaymentInstruction;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class PaymentInstructionBuilderDepositReturn {
|
||||
|
||||
private ImdgProvider imdgProvider;
|
||||
private Long sessionId;
|
||||
private BigDecimal amount;
|
||||
private Registry lm_tRgs;
|
||||
|
||||
public static PaymentInstructionBuilderDepositReturn builder(ImdgProvider imdgProvider) {
|
||||
return new PaymentInstructionBuilderDepositReturn(imdgProvider);
|
||||
}
|
||||
|
||||
private PaymentInstructionBuilderDepositReturn(ImdgProvider imdgProvider) {
|
||||
this.imdgProvider = imdgProvider;
|
||||
}
|
||||
|
||||
public PaymentInstructionBuilderDepositReturn sessionId(Long sessionId) {
|
||||
this.sessionId = sessionId;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaymentInstructionBuilderDepositReturn amount(BigDecimal amount) {
|
||||
this.amount = amount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaymentInstructionBuilderDepositReturn lm_tRgs(Registry rgs) {
|
||||
this.lm_tRgs = rgs;
|
||||
return this;
|
||||
}
|
||||
|
||||
public PaymentInstruction build() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
|
@ -11,29 +11,35 @@ import org.springframework.stereotype.Component;
|
|||
import ru.clearing.classes.statics.data.account.ClientCode;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.execution.ExecutionFond;
|
||||
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeCashFlow;
|
||||
import ru.clearing.classes.statics.data.instrument.issue.FixedIncomeSecurity;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.STrades;
|
||||
import ru.clearing.classes.statics.data.registry.TradingClearingRegistry;
|
||||
import ru.clearing.classes.statics.data.security.Security;
|
||||
import ru.spcex.clearing.config.element.ClearingServiceSettings;
|
||||
import ru.spcex.clearing.error.ClearingError;
|
||||
import ru.spcex.clearing.error.ClearingException;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.notification.NotificationSender;
|
||||
import ru.spcex.clearing.platform.messaging.domain.Consts;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.DealRegisterNewRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.registry.ExecutionType;
|
||||
import ru.spcex.clearing.platform.messaging.service.sender.KafkaSender;
|
||||
import ru.spcex.clearing.service.validation.ValidationStored;
|
||||
import ru.spcex.platform.enumeration.CurrencyCode;
|
||||
import ru.spcex.platform.enumeration.Section;
|
||||
import ru.spcex.platform.enumeration.Side;
|
||||
import ru.spcex.platform.enumeration.*;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicate;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
import ru.spcex.platform.utils.enumeration.*;
|
||||
import ru.spcex.platform.utils.log.ExceptionUtils;
|
||||
import ru.spcex.platform.utils.time.TimeUtil;
|
||||
import ru.spcex.platform.utils.validation.IValidator;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
|
|
@ -41,6 +47,8 @@ import java.util.Map;
|
|||
import java.util.Optional;
|
||||
import java.util.function.Function;
|
||||
|
||||
import static ru.spcex.platform.utils.number.BigDecimalUtil.safeBD;
|
||||
|
||||
@Component
|
||||
@EnableScheduling
|
||||
public class ExecutionFondComponent {
|
||||
|
|
@ -50,6 +58,7 @@ public class ExecutionFondComponent {
|
|||
private final Imdg<ExecutionFond> executionFondImdg;
|
||||
private final Imdg<Listing> listingImdg;
|
||||
private final Imdg<ClientCode> clientCodeImdg;
|
||||
private final Imdg<FixedIncomeCashFlow> fixedIncomeCashFlowImdg;
|
||||
private final Imdg<ru.clearing.classes.statics.data.misc.Market> marketImdg;
|
||||
|
||||
//fixme ждать ТЗ
|
||||
|
|
@ -58,19 +67,27 @@ public class ExecutionFondComponent {
|
|||
private final IMessageResolver msgResolver = new SimpleMessageResolver();
|
||||
private final Function<STrades, IValidator> stradesValidator;
|
||||
private final KafkaSender kafkaSender;
|
||||
private final NotificationSender notifications;
|
||||
private final boolean valuation;
|
||||
private static MathContext prec2 = new MathContext(2, RoundingMode.HALF_UP);
|
||||
|
||||
|
||||
@Autowired
|
||||
public ExecutionFondComponent(ImdgProvider imdgProvider, Producer<String, Object> kafka,
|
||||
public ExecutionFondComponent(ImdgProvider imdgProvider,
|
||||
ClearingServiceSettings settings,
|
||||
Producer<String, Object> kafka,
|
||||
@Qualifier("sTradesValidatorFond") Function<STrades, IValidator> stradesValidator,
|
||||
@Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafkaSender) {
|
||||
@Qualifier("kafkaSenderWithoutRequestInfo") KafkaSender kafkaSender, NotificationSender notifications) {
|
||||
this.sTradeImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_STrades, STrades.class);
|
||||
this.executionFondImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ExecutionFond, ExecutionFond.class);
|
||||
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
this.clientCodeImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClientCode, ClientCode.class);
|
||||
this.marketImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Market, ru.clearing.classes.statics.data.misc.Market.class);
|
||||
this.fixedIncomeCashFlowImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_FixedIncomeCashFlow, FixedIncomeCashFlow.class);
|
||||
this.valuation = settings.getTrade().getValuation(); //fixme
|
||||
this.stradesValidator = stradesValidator;
|
||||
this.kafkaSender = kafkaSender;
|
||||
this.notifications = notifications;
|
||||
|
||||
resetTradingDay();
|
||||
}
|
||||
|
|
@ -165,6 +182,7 @@ public class ExecutionFondComponent {
|
|||
protected ExecutionFond createExecutionFond(STrades sTrades,
|
||||
IValidator validator) throws ClearingException {
|
||||
Security security = validator.getStored(ValidationStored.STradesSecurity);
|
||||
// Listing listing = listingImdg.getFirstObjectByFieldValues(Map.of("securityId", security.getId()));
|
||||
Company company = validator.getStored(ValidationStored.STradesCompany);
|
||||
Company counterCompany = validator.getStored(ValidationStored.STradesCounterCompany);
|
||||
TradingClearingRegistry rgstr = validator.getStored(ValidationStored.STradesTradingClearingRegistry);
|
||||
|
|
@ -212,7 +230,64 @@ public class ExecutionFondComponent {
|
|||
eFond.setSecurityId(security.getId());
|
||||
eFond.setInterestAmount(sTrades.getAccruedint());
|
||||
eFond.setExchangeOrderId(sTrades.getOrderNum());
|
||||
eFond.setSettlementAmount(sTrades.getValue());
|
||||
if (valuation) {
|
||||
BigDecimal lots = safeBD(sTrades.getQty());// eFond.getLots
|
||||
BigDecimal price = safeBD(sTrades.getPrice());// eFond.setPrice
|
||||
BigDecimal settlementAmount = BigDecimal.ZERO;
|
||||
if (InstrumentType.BOND.equalsByKey(security.getInstrumentType())) {
|
||||
FixedIncomeSecurity fixedIncome = (FixedIncomeSecurity) security;
|
||||
BigDecimal nominalValue;
|
||||
Listing listing = listingImdg.getFirstObjectBySQL("securityId = %d and market = '%s'".formatted(fixedIncome.getId(), sTrades.getClassCode()));
|
||||
BigDecimal lotSize = listing != null ? safeBD(listing.getLotSize()) : BigDecimal.ZERO;
|
||||
BigDecimal ncd = safeBD(sTrades.getAccruedint());// eFond.interestAmount
|
||||
if (BondType.I.equalsByKey(fixedIncome.getBondType())) {
|
||||
ImdgPredicateBuilder pb = fixedIncomeCashFlowImdg.predicateBuilder();
|
||||
ImdgPredicate prdct = pb.and(
|
||||
pb.equals("securityId", fixedIncome.getId()),
|
||||
sTrades.getSettleDate() != null ?
|
||||
pb.equals("valueDate", sTrades.getSettleDate()) : pb.alwaysFalse()
|
||||
//fixme в тз settlementDate
|
||||
);
|
||||
FixedIncomeCashFlow cashFlow = fixedIncomeCashFlowImdg.getFirstObjectByPredicate(prdct);
|
||||
if (cashFlow != null) {
|
||||
nominalValue = safeBD(cashFlow.getNominalValue());
|
||||
} else {
|
||||
nominalValue = BigDecimal.ZERO;
|
||||
}
|
||||
} else {
|
||||
nominalValue = safeBD(fixedIncome.getNominalValue());
|
||||
}
|
||||
{
|
||||
lotSize.multiply(lots);
|
||||
settlementAmount = lotSize.multiply(lots)
|
||||
.multiply(nominalValue)
|
||||
.multiply(price)
|
||||
.divide(new BigDecimal(100), prec2) //first rounding
|
||||
.add(ncd.setScale(2, RoundingMode.HALF_UP)); //second rounding
|
||||
}
|
||||
eFond.setSettlementAmount(settlementAmount);
|
||||
//ОКРУГЛЕНИЕ( NV* quantity * price/100) + ОКРУГЛЕНИЕ (executionFond.interestAmount) для каждой сделки
|
||||
} else if (InstrumentType.EQTY.equalsByKey(security.getInstrumentType())) {
|
||||
settlementAmount = lots.multiply(price, prec2);
|
||||
}
|
||||
eFond.setSettlementAmount(settlementAmount);
|
||||
if (settlementAmount.compareTo(safeBD(sTrades.getValue())) != 0) {
|
||||
log.warn("sTrades.TradeNum={} sTrades.value({}) != eFond({})",
|
||||
sTrades.getTradeNum(),
|
||||
safeBD(sTrades.getValue()),
|
||||
settlementAmount);
|
||||
notifications.sendNotification(
|
||||
ObjectType.vfrs,
|
||||
"Для сделки %s объем сделки в ТС %s не совпадает с расчитанным в КС %s"
|
||||
.formatted(sTrades.getTradeNum(),
|
||||
safeBD(sTrades.getValue()).toString(),
|
||||
settlementAmount.toString()),
|
||||
Priority.HIGH
|
||||
);
|
||||
}
|
||||
} else {
|
||||
eFond.setSettlementAmount(sTrades.getValue());
|
||||
}
|
||||
eFond.setCounterPartyId(counterCompany.getId());
|
||||
{
|
||||
ImdgPredicateBuilder strPb = sTradeImdg.predicateBuilder();
|
||||
|
|
|
|||
|
|
@ -34,7 +34,10 @@ import ru.spcex.platform.utils.enumeration.IMessageResolver;
|
|||
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.util.*;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
|
@ -269,15 +272,23 @@ public class FinishingSession implements ISessionStage {
|
|||
|
||||
protected Collection<ExecutionFond> findExecutionFondBySessionId(Set<Long> exchangeIds) {
|
||||
ImdgPredicateBuilder pb = executionFondImdg.predicateBuilder();
|
||||
ImdgPredicate prdct = pb.in("exchangeExecutionId", exchangeIds.toArray(new Long[0]));
|
||||
ImdgPredicate prdct = pb.and(
|
||||
pb.in("exchangeExecutionId", exchangeIds.toArray(new Long[0])),
|
||||
pb.not(pb.equals("settlementDate", LocalDate.now()))
|
||||
);
|
||||
Collection<ExecutionFond> result = executionFondImdg.getCollectionObjectsByPredicate(prdct);
|
||||
log.trace("found {} ExecutionFond from first day", result.size());
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Collection<ExecutionDeposit> findExecutionDepositBySessionId(Long sessionId) {
|
||||
Collection<ExecutionDeposit> result = executionDepositImdg.getCollectionObjectsByFieldValues(Map.of("sessionId", sessionId));
|
||||
log.trace("found {} ExecutionDeposit by sessionId={}", result.size(), sessionId);
|
||||
ImdgPredicateBuilder pb = executionDepositImdg.predicateBuilder();
|
||||
ImdgPredicate prdct = pb.and(
|
||||
pb.equals("sessionId", sessionId),
|
||||
pb.equals("firstLegSettlementDate", LocalDate.now())
|
||||
);
|
||||
Collection<ExecutionDeposit> result = executionDepositImdg.getCollectionObjectsByPredicate(prdct);
|
||||
log.trace("found {} ExecutionDeposit by {}", result.size(), prdct);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -107,4 +107,9 @@ public class ImdgPredicateBuilderHazelcast implements ImdgPredicateBuilder {
|
|||
public ImdgPredicate alwaysTrue() {
|
||||
return new ImdgPredicateHazelcast(Predicates.alwaysTrue());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ImdgPredicate alwaysFalse() {
|
||||
return new ImdgPredicateHazelcast(Predicates.alwaysFalse());
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -21,4 +21,5 @@ public interface ImdgPredicateBuilder {
|
|||
ImdgPredicate regex(String key, String regex);
|
||||
|
||||
ImdgPredicate alwaysTrue();
|
||||
ImdgPredicate alwaysFalse();
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue