some refactoring
This commit is contained in:
parent
c16bf5ea3b
commit
3e2c1cf629
10 changed files with 966 additions and 612 deletions
|
|
@ -1,10 +1,5 @@
|
|||
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;
|
||||
import org.apache.kafka.clients.consumer.Consumer;
|
||||
|
|
@ -14,83 +9,41 @@ import org.slf4j.LoggerFactory;
|
|||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.CompanyRoleSet;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
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;
|
||||
import ru.clearing.platform.dictionary.CurrencyPairDictionary;
|
||||
import ru.spcex.clearing.dflt.management.config.settings.DefaultManagementSettings;
|
||||
import ru.spcex.clearing.dflt.management.service.OrderCurrencyService;
|
||||
import ru.spcex.clearing.dflt.management.service.ImdgQueryService;
|
||||
import ru.spcex.clearing.dflt.management.service.SpotOvernightOrderService;
|
||||
import ru.spcex.clearing.dflt.management.service.SwapOvernightOrderService;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.clearing.platform.messaging.domain.BaseRequest;
|
||||
import ru.spcex.clearing.platform.messaging.domain.cud.misc.OvernightSettingsNewRequest;
|
||||
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;
|
||||
import ru.spcex.platform.enumeration.Task;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
import ru.spcex.platform.utils.enumeration.IEnumKey;
|
||||
|
||||
@Service
|
||||
public class TaskListener extends QueueConsumer implements InitializingBean {
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
private final OrderCurrencyService orderCurrencyService;
|
||||
private final ImdgProvider imdgProvider;
|
||||
private final ImdgQueryService imdgQueryService;
|
||||
private final Imdg<Registry> registryImdg;
|
||||
private final Imdg<ClearingMemberCategory> categoryImdg;
|
||||
private final Imdg<OvernightSettings> overnightSettingsImdg;
|
||||
private final Imdg<CompanyRoleSet> companyRoleSetImdg;
|
||||
private final Imdg<Company> companyImdg;
|
||||
private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
|
||||
private final Imdg<CurrencyPairDictionary> currencyPairDictionaryImdg;
|
||||
private final Imdg<CurrencyPairSecurity> currencyPairSecurityImdg;
|
||||
private final Imdg<Listing> listingImdg;
|
||||
private final Imdg<Market> marketImdg;
|
||||
private final Imdg<RiskParameter> riskParameterImdg;
|
||||
private final Imdg<Rates> ratesImdg;
|
||||
private final Imdg<ClearingCalendar> clearingCalendarImdg;
|
||||
private final DefaultManagementSettings settings;
|
||||
private final SwapOvernightOrderService swapOvernightOrderService;
|
||||
private final SpotOvernightOrderService spotOvernightOrderService;
|
||||
|
||||
@Autowired
|
||||
public TaskListener(Consumer<String, Object> kafkaQueue,
|
||||
Producer<String, Object> kafkaProducer,
|
||||
ImdgQueryService imdgQueryService,
|
||||
ImdgProvider imdgProvider,
|
||||
UserRoleVerification userRoleVerification,
|
||||
OrderCurrencyService orderCurrencyService,
|
||||
DefaultManagementSettings settings) {
|
||||
SwapOvernightOrderService swapOvernightOrderService,
|
||||
SpotOvernightOrderService spotOvernightOrderService) {
|
||||
super(kafkaQueue, kafkaProducer);
|
||||
this.imdgProvider = imdgProvider;
|
||||
this.imdgQueryService = imdgQueryService;
|
||||
this.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
this.overnightSettingsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OvernightSettings, OvernightSettings.class);
|
||||
this.categoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
|
||||
this.companyRoleSetImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanyRoleSet, CompanyRoleSet.class);
|
||||
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
this.currencyPairDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairDictionary, CurrencyPairDictionary.class);
|
||||
this.currencyPairSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class);
|
||||
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
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;
|
||||
this.swapOvernightOrderService = swapOvernightOrderService;
|
||||
this.spotOvernightOrderService = spotOvernightOrderService;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
@ -104,7 +57,7 @@ public class TaskListener extends QueueConsumer implements InitializingBean {
|
|||
private void createOrder(BaseRequest<OvernightSettingsNewRequest> newReq) {
|
||||
log.info("CROR createOrder started, request={}", newReq);
|
||||
|
||||
Collection<Long> registryIds = orderCurrencyService.getCurrencyRegistry();
|
||||
Collection<Long> registryIds = imdgQueryService.getCurrencyRegistry();
|
||||
if (registryIds == null || registryIds.isEmpty()) {
|
||||
log.info("No registries found for CROR processing");
|
||||
return;
|
||||
|
|
@ -119,13 +72,12 @@ public class TaskListener extends QueueConsumer implements InitializingBean {
|
|||
}
|
||||
|
||||
OvernightType overnightType = resolveOvernightType(registry);
|
||||
|
||||
log.info("Processing registry id={}, companyId={}, overnightType={}",
|
||||
registry.getId(), registry.getCompanyId(), overnightType);
|
||||
|
||||
switch (overnightType) {
|
||||
case SWAP -> createSwapOrders(registry);
|
||||
case SPOT -> createSpotOrders(registry);
|
||||
case SWAP -> swapOvernightOrderService.process(registry);
|
||||
case SPOT -> spotOvernightOrderService.process(registry);
|
||||
default ->
|
||||
log.warn("Unsupported overnightType={} for registry id={}", overnightType, registry.getId());
|
||||
}
|
||||
|
|
@ -139,558 +91,10 @@ public class TaskListener extends QueueConsumer implements InitializingBean {
|
|||
|
||||
private OvernightType resolveOvernightType(Registry registry) {
|
||||
Optional<OvernightSettings> settingsOpt =
|
||||
orderCurrencyService.findOvernightSettingsByCompany(registry.getCompanyId());
|
||||
imdgQueryService.findOvernightSettingsByCompany(registry.getCompanyId());
|
||||
|
||||
return settingsOpt
|
||||
.map(settings -> IEnumKey.getEnumByKey(OvernightType.class, settings.getOvernightType()))
|
||||
.orElse(OvernightType.SWAP);
|
||||
}
|
||||
|
||||
private void createSpotOrders(Registry registry) {
|
||||
|
||||
}
|
||||
|
||||
private void createSwapOrders(Registry registry) {
|
||||
OrderCurrency primaryTransferOrder = new OrderCurrency();
|
||||
OrderCurrency counterTransferOrder = new OrderCurrency();
|
||||
OrderCurrency primaryBalancingOrder = new OrderCurrency();
|
||||
OrderCurrency counterBalancingOrder = new OrderCurrency();
|
||||
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
ClearingMemberCategory category = categoryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", registry.getCompanyId())
|
||||
);
|
||||
String orderCategory = category.getClearingMemberCategory().equals("P") ? "PL" : "UK";
|
||||
Side primaryTransferSide = Side.SELL;
|
||||
Side counterTransferSide = Side.BUY;
|
||||
|
||||
Side primaryBalancingSide = Side.BUY;
|
||||
Side counterBalancingSide = Side.SELL;
|
||||
|
||||
if (registry.getSecuritySymbol().equals("RUB")) {
|
||||
primaryTransferSide = primaryTransferSide.revers();
|
||||
counterTransferSide = counterTransferSide.revers();
|
||||
primaryBalancingSide = primaryBalancingSide.revers();
|
||||
counterBalancingSide = counterBalancingSide.revers();
|
||||
}
|
||||
|
||||
Market market = marketImdg.getSingleObjectByPredicate(predicateBuilder.equals("marketType", MarketType.SCSW));
|
||||
Listing listing;
|
||||
RiskParameter riskParameter;
|
||||
if (registry.getSecuritySymbol().equals("RUB")) {
|
||||
listing = findListingForRub(registry, market.getCode());
|
||||
riskParameter = findRiskParameterForRub();
|
||||
} else {
|
||||
listing = findListingForOtherCurrency(registry, market.getCode());
|
||||
riskParameter = findRiskParameterForOtherCurrency(registry);
|
||||
}
|
||||
|
||||
if (orderCategory.equals("PL")) {
|
||||
fillPrimaryTransferP(primaryTransferOrder, registry);
|
||||
fillCounterTransferP(counterTransferOrder, registry);
|
||||
fillPrimaryBalancingP(primaryBalancingOrder, registry);
|
||||
fillCounterBalancingP(counterBalancingOrder, registry);
|
||||
} else if (orderCategory.equals("UK")) {
|
||||
fillPrimaryTransferUK(primaryTransferOrder, registry);
|
||||
fillCounterTransferUK(counterTransferOrder, registry);
|
||||
fillPrimaryBalancingUK(primaryBalancingOrder, registry);
|
||||
fillCounterBalancingUK(counterBalancingOrder, registry);
|
||||
}
|
||||
|
||||
fillSwapOrder(primaryTransferOrder, registry, listing, market, riskParameter, primaryTransferSide, "overnight");
|
||||
fillSwapOrder(counterTransferOrder, registry, listing, market, riskParameter, counterTransferSide, "overnight");
|
||||
fillSwapOrder(primaryBalancingOrder, registry, listing, market, riskParameter, primaryBalancingSide, "balance");
|
||||
fillSwapOrder(counterBalancingOrder, registry, listing, market, riskParameter, counterBalancingSide, "balance");
|
||||
}
|
||||
|
||||
private void fillPrimaryTransferUK(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
orderCurrency.setAccount(registry.getTradingClearingRegistry());
|
||||
orderCurrency.setTradingClearingRegistryId(registry.getTradingClearingRegistryId());
|
||||
orderCurrency.setCompanyId(registry.getCompanyId());
|
||||
orderCurrency.setTradingCode(registry.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(companyRoleSet.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(company.getTradingCode());
|
||||
orderCurrency.setType("CMOV");
|
||||
}
|
||||
|
||||
private void fillCounterTransferUK(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
orderCurrency.setAccount(tradingClearingRegistry.getCode());
|
||||
orderCurrency.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
orderCurrency.setCompanyId(company.getId());
|
||||
orderCurrency.setTradingCode(company.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(registry.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(registry.getTradingCode());
|
||||
orderCurrency.setType("CMOV");
|
||||
}
|
||||
|
||||
private void fillPrimaryBalancingUK(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
ClearingMemberCategory category = categoryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("clearingMemberCategory", "P")
|
||||
);
|
||||
TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", category.getCompanyId())
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(category.getCompanyId());
|
||||
|
||||
CompanyRoleSet clccCompanyRole = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company clssCompany = companyImdg.getSingleObjectByID(category.getCompanyId());
|
||||
|
||||
orderCurrency.setAccount(tradingClearingRegistry.getCode());
|
||||
orderCurrency.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
orderCurrency.setCompanyId(company.getId());
|
||||
orderCurrency.setTradingCode(company.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(clccCompanyRole.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(clssCompany.getTradingCode());
|
||||
orderCurrency.setType("CMBL");
|
||||
}
|
||||
|
||||
private void fillCounterBalancingUK(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
ClearingMemberCategory categoryP = categoryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("clearingMemberCategory", "P")
|
||||
);
|
||||
Company companyP = companyImdg.getSingleObjectByID(categoryP.getCompanyId());
|
||||
|
||||
orderCurrency.setAccount(tradingClearingRegistry.getCode());
|
||||
orderCurrency.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
orderCurrency.setCompanyId(company.getId());
|
||||
orderCurrency.setTradingCode(company.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(categoryP.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(companyP.getTradingCode());
|
||||
orderCurrency.setType("CMBL");
|
||||
}
|
||||
|
||||
|
||||
private void fillPrimaryTransferP(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
orderCurrency.setAccount(registry.getTradingClearingRegistry());
|
||||
orderCurrency.setTradingClearingRegistryId(registry.getTradingClearingRegistryId());
|
||||
orderCurrency.setCompanyId(registry.getCompanyId());
|
||||
orderCurrency.setTradingCode(registry.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(companyRoleSet.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(company.getTradingCode());
|
||||
orderCurrency.setType("PLOV");
|
||||
}
|
||||
|
||||
private void fillCounterTransferP(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
orderCurrency.setAccount(tradingClearingRegistry.getCode());
|
||||
orderCurrency.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
orderCurrency.setCompanyId(company.getId());
|
||||
orderCurrency.setTradingCode(company.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(registry.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(registry.getTradingCode());
|
||||
orderCurrency.setType("PLOV");
|
||||
}
|
||||
|
||||
private void fillPrimaryBalancingP(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.RGCM)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
CompanyRoleSet clccCompanyRole = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company clssCompany = companyImdg.getSingleObjectByID(clccCompanyRole.getCompanyId());
|
||||
|
||||
orderCurrency.setAccount(tradingClearingRegistry.getCode());
|
||||
orderCurrency.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
orderCurrency.setCompanyId(company.getId());
|
||||
orderCurrency.setTradingCode(company.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(clccCompanyRole.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(clssCompany.getTradingCode());
|
||||
orderCurrency.setType("PLBL");
|
||||
}
|
||||
|
||||
private void fillCounterBalancingP(OrderCurrency orderCurrency, Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = categoryImdg.predicateBuilder();
|
||||
CompanyRoleSet companyRoleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.CLCC)
|
||||
);
|
||||
Company company = companyImdg.getSingleObjectByID(companyRoleSet.getCompanyId());
|
||||
|
||||
TradingClearingRegistry tradingClearingRegistry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
CompanyRoleSet rgcmCompanyRole = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.equals("companyRole", CompanyRole.RGCM)
|
||||
);
|
||||
Company rgcmCompany = companyImdg.getSingleObjectByID(rgcmCompanyRole.getCompanyId());
|
||||
|
||||
orderCurrency.setAccount(tradingClearingRegistry.getCode());
|
||||
orderCurrency.setTradingClearingRegistryId(tradingClearingRegistry.getId());
|
||||
orderCurrency.setCompanyId(company.getId());
|
||||
orderCurrency.setTradingCode(company.getTradingCode());
|
||||
orderCurrency.setCounterPartyId(rgcmCompanyRole.getCompanyId());
|
||||
orderCurrency.setCounterTradingCode(rgcmCompany.getTradingCode());
|
||||
orderCurrency.setType("PLBL");
|
||||
|
||||
}
|
||||
|
||||
private void fillSwapOrder(OrderCurrency orderCurrency,
|
||||
Registry registry,
|
||||
Listing listing,
|
||||
Market market,
|
||||
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());
|
||||
orderCurrency.setSecuritySymbol(listing.getSymbolCode());
|
||||
orderCurrency.setSecurityId(listing.getSecurityId());
|
||||
orderCurrency.setLotSize(listing.getLotSize());
|
||||
orderCurrency.setRate(riskParameter.getQuoteValue());
|
||||
orderCurrency.setSide(side.getKey());
|
||||
orderCurrency.setSettleCode("T1");
|
||||
orderCurrency.setStatus("CRET");
|
||||
orderCurrency.setComment(comment);
|
||||
orderCurrency.setRegistryId(registry.getId());
|
||||
orderCurrency.setPrice(price);
|
||||
orderCurrency.setQuantityLot(quantityLot);
|
||||
}
|
||||
|
||||
private Listing findListingForRub(Registry registry, String market) {
|
||||
ImdgPredicateBuilder predicateBuilder = currencyPairDictionaryImdg.predicateBuilder();
|
||||
CurrencyPairDictionary currencyPairDictionary = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("baseCurrency", "CNY"),
|
||||
predicateBuilder.equals("quoteCurrency", registry.getSecuritySymbol())
|
||||
));
|
||||
Collection<Long> securitiesIds = currencyPairSecurityImdg.getCollectionIdsByPredicate(
|
||||
predicateBuilder.equals("currencyPairId", currencyPairDictionary.getId())
|
||||
);
|
||||
Listing listing = listingImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.in("securityId", securitiesIds.toArray(new Long[0])),
|
||||
predicateBuilder.equals("market", market)
|
||||
)
|
||||
);
|
||||
return listing;
|
||||
}
|
||||
|
||||
private Listing findListingForOtherCurrency(Registry registry, String market) {
|
||||
ImdgPredicateBuilder predicateBuilder = currencyPairDictionaryImdg.predicateBuilder();
|
||||
CurrencyPairDictionary currencyPairDictionary = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("baseCurrency", registry.getSecuritySymbol()),
|
||||
predicateBuilder.equals("quoteCurrency", "RUB")
|
||||
));
|
||||
Collection<Long> securitiesIds = currencyPairSecurityImdg.getCollectionIdsByPredicate(
|
||||
predicateBuilder.equals("currencyPairId", currencyPairDictionary.getId())
|
||||
);
|
||||
Listing listing = listingImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.in("securityId", securitiesIds.toArray(new Long[0])),
|
||||
predicateBuilder.equals("market", market)
|
||||
)
|
||||
);
|
||||
return listing;
|
||||
}
|
||||
|
||||
private RiskParameter findRiskParameterForRub() {
|
||||
ImdgPredicateBuilder predicateBuilder = currencyPairDictionaryImdg.predicateBuilder();
|
||||
CurrencyPairDictionary currencyPairDictionary = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("baseCurrency", "CNY")
|
||||
));
|
||||
return riskParameterImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("currencyPairId", currencyPairDictionary.getId()),
|
||||
predicateBuilder.equals("settlementType", "T0")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private RiskParameter findRiskParameterForOtherCurrency(Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = currencyPairDictionaryImdg.predicateBuilder();
|
||||
CurrencyPairDictionary currencyPairDictionary = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("baseCurrency", registry.getSecuritySymbol())
|
||||
));
|
||||
return riskParameterImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("currencyPairId", currencyPairDictionary.getId()),
|
||||
predicateBuilder.equals("settlementType", "T0")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static final MathContext MC = new MathContext(20, RoundingMode.HALF_UP);
|
||||
|
||||
//registry.securitySymbol != 'RUB'
|
||||
private CalculationResultHolder calculationSwapSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) {
|
||||
BigDecimal planPosition = registry.getBalance();
|
||||
BigDecimal sum1 = planPosition.abs();
|
||||
|
||||
Registry amtRubRegistry = findAmtRegistry(registry, "RUB");
|
||||
BigDecimal planPositionRub = amtRubRegistry.getBalance();
|
||||
|
||||
Rates rates = findRates(registry.getSecuritySymbol());
|
||||
BigDecimal ratesValue = rates.getValue();
|
||||
|
||||
BigDecimal sum2 = planPositionRub.divide(ratesValue, lotSize, RoundingMode.HALF_DOWN);
|
||||
|
||||
BigDecimal ceilSum1 = sum1.setScale(0, RoundingMode.CEILING);
|
||||
BigDecimal sum3 = ceilSum1.min(sum2);
|
||||
BigDecimal sum4 = sum3
|
||||
.multiply(ratesValue, MC)
|
||||
.negate();
|
||||
BigDecimal sum5 = sum3.negate();
|
||||
|
||||
BigDecimal daysInYear = BigDecimal.valueOf(365);
|
||||
// (S / 365) * n
|
||||
BigDecimal carryPart = s.divide(daysInYear, MC).multiply(n, MC);
|
||||
// 1 + S / 365 * n
|
||||
BigDecimal multiplier = BigDecimal.ONE.add(carryPart, MC);
|
||||
|
||||
BigDecimal sum6 = sum3
|
||||
.multiply(ratesValue, MC)
|
||||
.multiply(multiplier, MC);
|
||||
return new CalculationResultHolder(sum1, sum2, sum3, sum4, sum5, sum6);
|
||||
}
|
||||
|
||||
//registry.securitySymbol == 'RUB'
|
||||
private CalculationResultHolder calculationSwapRubSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) {
|
||||
BigDecimal planPosition = registry.getBalance();
|
||||
Rates cnyRates = findRates(registry.getSecuritySymbol());
|
||||
BigDecimal ratesValue = cnyRates.getValue();
|
||||
BigDecimal sum1 = planPosition.divide(ratesValue, MC);
|
||||
|
||||
Registry amtRubRegistry = findAmtRegistry(registry, "CNY");
|
||||
BigDecimal planPositionCny = amtRubRegistry.getBalance();
|
||||
|
||||
BigDecimal sum2 = planPositionCny.divide(ratesValue, lotSize, RoundingMode.HALF_DOWN);
|
||||
|
||||
BigDecimal ceilSum1 = sum1.setScale(0, RoundingMode.CEILING);
|
||||
BigDecimal sum3 = ceilSum1.min(sum2).negate();
|
||||
BigDecimal sum4 = sum3
|
||||
.multiply(ratesValue, MC)
|
||||
.negate();
|
||||
BigDecimal sum5 = sum3.negate();
|
||||
|
||||
BigDecimal daysInYear = BigDecimal.valueOf(365);
|
||||
// (S / 365) * n
|
||||
BigDecimal carryPart = s.divide(daysInYear, MC).multiply(n, MC);
|
||||
// 1 + S / 365 * n
|
||||
BigDecimal multiplier = BigDecimal.ONE.add(carryPart, MC);
|
||||
|
||||
BigDecimal sum6 = sum3
|
||||
.multiply(ratesValue, MC)
|
||||
.multiply(multiplier, MC);
|
||||
return new CalculationResultHolder(sum1, sum2, sum3, sum4, sum5, sum6);
|
||||
}
|
||||
|
||||
private Registry findAmtRegistry(Registry registry, String securitySymbol) {
|
||||
ImdgPredicateBuilder predicateBuilder = registryImdg.predicateBuilder();
|
||||
return registryImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.regex("registryCode", "^PM.*T"),
|
||||
predicateBuilder.equals("securitySymbol", securitySymbol),
|
||||
predicateBuilder.equals("tradingClearingRegistryId", registry.getId()),
|
||||
predicateBuilder.equals("companyId", registry.getCompanyId())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private Rates findRates(String securitySymbol) {
|
||||
ImdgPredicateBuilder predicateBuilder = registryImdg.predicateBuilder();
|
||||
return ratesImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("currency", securitySymbol),
|
||||
predicateBuilder.equals("valueDate", LocalDate.now()),
|
||||
predicateBuilder.equals("workflowStatus", WorkflowStatus.Active.getKey())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private Rates findCnyRates(Registry registry) {
|
||||
ImdgPredicateBuilder predicateBuilder = registryImdg.predicateBuilder();
|
||||
return ratesImdg.getSingleObjectByPredicate(
|
||||
predicateBuilder.and(
|
||||
predicateBuilder.equals("currency", "CNY"),
|
||||
predicateBuilder.equals("valueDate", LocalDate.now()),
|
||||
predicateBuilder.equals("workflowStatus", WorkflowStatus.Active.getKey())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
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");
|
||||
}
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("value must not be null");
|
||||
}
|
||||
|
||||
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;
|
||||
private BigDecimal sum3;
|
||||
private BigDecimal sum4;
|
||||
private BigDecimal sum5;
|
||||
private BigDecimal sum6;
|
||||
|
||||
public CalculationResultHolder(BigDecimal sum1,
|
||||
BigDecimal sum2,
|
||||
BigDecimal sum3,
|
||||
BigDecimal sum4,
|
||||
BigDecimal sum5,
|
||||
BigDecimal sum6) {
|
||||
this.sum1 = sum1;
|
||||
this.sum2 = sum2;
|
||||
this.sum3 = sum3;
|
||||
this.sum4 = sum4;
|
||||
this.sum5 = sum5;
|
||||
this.sum6 = sum6;
|
||||
}
|
||||
|
||||
public BigDecimal getSum1() {
|
||||
return sum1;
|
||||
}
|
||||
|
||||
public BigDecimal getSum2() {
|
||||
return sum2;
|
||||
}
|
||||
|
||||
public BigDecimal getSum3() {
|
||||
return sum3;
|
||||
}
|
||||
|
||||
public BigDecimal getSum4() {
|
||||
return sum4;
|
||||
}
|
||||
|
||||
public BigDecimal getSum5() {
|
||||
return sum5;
|
||||
}
|
||||
|
||||
public BigDecimal getSum6() {
|
||||
return sum6;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
package ru.spcex.clearing.dflt.management.model;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public record CalculationResult(
|
||||
BigDecimal sum1,
|
||||
BigDecimal sum2,
|
||||
BigDecimal sum3,
|
||||
BigDecimal sum4,
|
||||
BigDecimal sum5,
|
||||
BigDecimal sum6
|
||||
) {
|
||||
}
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
package ru.spcex.clearing.dflt.management.model;
|
||||
|
||||
public record CounterpartyInfo(
|
||||
Long companyId,
|
||||
String tradingCode,
|
||||
Long registryId,
|
||||
String registryCode
|
||||
) {}
|
||||
|
|
@ -0,0 +1,119 @@
|
|||
package ru.spcex.clearing.dflt.management.model;
|
||||
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.security.RiskParameter;
|
||||
|
||||
public class SwapContext {
|
||||
private final Registry registry;
|
||||
private final String orderCategory;
|
||||
private final Market market;
|
||||
private final Listing listing;
|
||||
private final RiskParameter riskParameter;
|
||||
private final CounterpartyInfo categoryP;
|
||||
private final CounterpartyInfo clcc;
|
||||
private final CounterpartyInfo rgcm;
|
||||
|
||||
private SwapContext(Builder builder) {
|
||||
this.registry = builder.registry;
|
||||
this.orderCategory = builder.orderCategory;
|
||||
this.market = builder.market;
|
||||
this.listing = builder.listing;
|
||||
this.riskParameter = builder.riskParameter;
|
||||
this.categoryP = builder.categoryP;
|
||||
this.clcc = builder.clcc;
|
||||
this.rgcm = builder.rgcm;
|
||||
}
|
||||
|
||||
public Registry getRegistry() {
|
||||
return registry;
|
||||
}
|
||||
|
||||
public String getOrderCategory() {
|
||||
return orderCategory;
|
||||
}
|
||||
|
||||
public Market getMarket() {
|
||||
return market;
|
||||
}
|
||||
|
||||
public Listing getListing() {
|
||||
return listing;
|
||||
}
|
||||
|
||||
public RiskParameter getRiskParameter() {
|
||||
return riskParameter;
|
||||
}
|
||||
|
||||
public CounterpartyInfo getCategoryP() {
|
||||
return categoryP;
|
||||
}
|
||||
|
||||
public CounterpartyInfo getClcc() {
|
||||
return clcc;
|
||||
}
|
||||
|
||||
public CounterpartyInfo getRgcm() {
|
||||
return rgcm;
|
||||
}
|
||||
|
||||
public static Builder builder() {
|
||||
return new Builder();
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
private Registry registry;
|
||||
private String orderCategory;
|
||||
private Market market;
|
||||
private Listing listing;
|
||||
private RiskParameter riskParameter;
|
||||
private CounterpartyInfo categoryP;
|
||||
private CounterpartyInfo clcc;
|
||||
private CounterpartyInfo rgcm;
|
||||
|
||||
public Builder registry(Registry registry) {
|
||||
this.registry = registry;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder orderCategory(String orderCategory) {
|
||||
this.orderCategory = orderCategory;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder market(Market market) {
|
||||
this.market = market;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder listing(Listing listing) {
|
||||
this.listing = listing;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder riskParameter(RiskParameter riskParameter) {
|
||||
this.riskParameter = riskParameter;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder categoryP(CounterpartyInfo categoryP) {
|
||||
this.categoryP = categoryP;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder clcc(CounterpartyInfo clcc) {
|
||||
this.clcc = clcc;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Builder rgcm(CounterpartyInfo rgcm) {
|
||||
this.rgcm = rgcm;
|
||||
return this;
|
||||
}
|
||||
|
||||
public SwapContext build() {
|
||||
return new SwapContext(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,261 @@
|
|||
package ru.spcex.clearing.dflt.management.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.LocalDate;
|
||||
import java.util.Collection;
|
||||
import java.util.Optional;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.company.ClearingMemberCategory;
|
||||
import ru.clearing.classes.statics.data.company.Company;
|
||||
import ru.clearing.classes.statics.data.company.CompanyRoleSet;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
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.security.CurrencyPairSecurity;
|
||||
import ru.clearing.classes.statics.data.security.Rates;
|
||||
import ru.clearing.classes.statics.data.security.RiskParameter;
|
||||
import ru.clearing.platform.dictionary.CurrencyPairDictionary;
|
||||
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.CompanyRole;
|
||||
import ru.spcex.platform.enumeration.MarketType;
|
||||
import ru.spcex.platform.enumeration.RegistryStatus;
|
||||
import ru.spcex.platform.enumeration.WorkflowStatus;
|
||||
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;
|
||||
|
||||
@Service
|
||||
public class ImdgQueryService {
|
||||
private final Imdg<ClearingMemberCategory> categoryImdg;
|
||||
private final Imdg<CompanyRoleSet> companyRoleSetImdg;
|
||||
private final Imdg<Company> companyImdg;
|
||||
private final Imdg<TradingClearingRegistry> tradingClearingRegistryImdg;
|
||||
private final Imdg<CurrencyPairDictionary> currencyPairDictionaryImdg;
|
||||
private final Imdg<CurrencyPairSecurity> currencyPairSecurityImdg;
|
||||
private final Imdg<Listing> listingImdg;
|
||||
private final Imdg<Market> marketImdg;
|
||||
private final Imdg<RiskParameter> riskParameterImdg;
|
||||
private final Imdg<Rates> ratesImdg;
|
||||
private final Imdg<Registry> registryImdg;
|
||||
private final Imdg<OvernightSettings> overnightSettingsImdg;
|
||||
|
||||
|
||||
public ImdgQueryService(ImdgProvider imdgProvider) {
|
||||
this.categoryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingMemberCategory, ClearingMemberCategory.class);
|
||||
this.companyRoleSetImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CompanyRoleSet, CompanyRoleSet.class);
|
||||
this.companyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Company, Company.class);
|
||||
this.tradingClearingRegistryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_TradingClearingRegistry, TradingClearingRegistry.class);
|
||||
this.currencyPairDictionaryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairDictionary, CurrencyPairDictionary.class);
|
||||
this.currencyPairSecurityImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_CurrencyPairSecurity, CurrencyPairSecurity.class);
|
||||
this.listingImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Listing, Listing.class);
|
||||
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.registryImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_Registry, Registry.class);
|
||||
this.overnightSettingsImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OvernightSettings, OvernightSettings.class);
|
||||
}
|
||||
public Collection<Long> getCurrencyRegistry() {
|
||||
ImdgPredicateBuilder builder = registryImdg.predicateBuilder();
|
||||
ImdgPredicate registryPredicate = builder.and(
|
||||
builder.regex("registryCode", "^PM.*T"),
|
||||
builder.not(builder.equals("registryStatus", RegistryStatus.OK.getKey()))
|
||||
);
|
||||
|
||||
return registryImdg.getCollectionIdsByPredicate(registryPredicate);
|
||||
}
|
||||
|
||||
public Optional<OvernightSettings> findOvernightSettingsByCompany(Long companyId) {
|
||||
ImdgPredicateBuilder builder = overnightSettingsImdg.predicateBuilder();
|
||||
ImdgPredicate predicate = builder.and(
|
||||
builder.equals("market", ru.spcex.platform.enumeration.Market.curr),
|
||||
builder.equals("companyId", companyId)
|
||||
);
|
||||
OvernightSettings overnightSettings = overnightSettingsImdg.getFirstObjectByPredicate(predicate);
|
||||
return Optional.ofNullable(overnightSettings);
|
||||
}
|
||||
|
||||
public String resolveOrderCategory(Long companyId) {
|
||||
ImdgPredicateBuilder pb = categoryImdg.predicateBuilder();
|
||||
ClearingMemberCategory category = categoryImdg.getFirstObjectByPredicate(
|
||||
pb.equals("companyId", companyId)
|
||||
);
|
||||
return "P".equals(category.getClearingMemberCategory()) ? "PL" : "UK";
|
||||
}
|
||||
|
||||
public CounterpartyInfo getCompanyByRole(CompanyRole role) {
|
||||
ImdgPredicateBuilder pb = companyRoleSetImdg.predicateBuilder();
|
||||
CompanyRoleSet roleSet = companyRoleSetImdg.getSingleObjectByPredicate(
|
||||
pb.equals("companyRole", role)
|
||||
);
|
||||
|
||||
Company company = companyImdg.getSingleObjectByID(roleSet.getCompanyId());
|
||||
TradingClearingRegistry registry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
pb.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
return new CounterpartyInfo(
|
||||
company.getId(),
|
||||
company.getTradingCode(),
|
||||
registry != null ? registry.getId() : null,
|
||||
registry != null ? registry.getCode() : null
|
||||
);
|
||||
}
|
||||
|
||||
public CounterpartyInfo getCompanyByClearingCategory(String clearingCategory) {
|
||||
ImdgPredicateBuilder pb = categoryImdg.predicateBuilder();
|
||||
ClearingMemberCategory category = categoryImdg.getFirstObjectByPredicate(
|
||||
pb.equals("clearingMemberCategory", clearingCategory)
|
||||
);
|
||||
|
||||
Company company = companyImdg.getSingleObjectByID(category.getCompanyId());
|
||||
TradingClearingRegistry registry = tradingClearingRegistryImdg.getFirstObjectByPredicate(
|
||||
pb.equals("companyId", company.getId())
|
||||
);
|
||||
|
||||
return new CounterpartyInfo(
|
||||
company.getId(),
|
||||
company.getTradingCode(),
|
||||
registry != null ? registry.getId() : null,
|
||||
registry != null ? registry.getCode() : null
|
||||
);
|
||||
}
|
||||
|
||||
public Market getSwapMarket() {
|
||||
ImdgPredicateBuilder pb = marketImdg.predicateBuilder();
|
||||
return marketImdg.getSingleObjectByPredicate(pb.equals("marketType", MarketType.SCSW));
|
||||
}
|
||||
|
||||
public Listing findSwapListing(Registry registry, String marketCode) {
|
||||
return "RUB".equals(registry.getSecuritySymbol())
|
||||
? findListingForRub(registry, marketCode)
|
||||
: findListingForOtherCurrency(registry, marketCode);
|
||||
}
|
||||
|
||||
public RiskParameter findRiskParameter(Registry registry) {
|
||||
return "RUB".equals(registry.getSecuritySymbol())
|
||||
? findRiskParameterForRub()
|
||||
: findRiskParameterForOtherCurrency(registry);
|
||||
}
|
||||
|
||||
public Rates getRate(String currency, LocalDate valueDate) {
|
||||
ImdgPredicateBuilder pb = ratesImdg.predicateBuilder();
|
||||
return ratesImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.equals("currency", currency),
|
||||
pb.equals("valueDate", valueDate),
|
||||
pb.equals("workflowStatus", WorkflowStatus.Active.getKey())
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public BigDecimal defineTransferRate(Long currencyPairDictionaryId, String securitySymbol) {
|
||||
ImdgPredicateBuilder pb = riskParameterImdg.predicateBuilder();
|
||||
String baseCurrency = "RUB".equals(securitySymbol) ? "CNY" : securitySymbol;
|
||||
|
||||
RiskParameter riskParameter = riskParameterImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.equals("settlementType", "T0"),
|
||||
pb.equals("currencyPairId", currencyPairDictionaryId),
|
||||
pb.equals("baseCurrency", baseCurrency)
|
||||
)
|
||||
);
|
||||
return riskParameter.getQuoteValue();
|
||||
}
|
||||
|
||||
public CurrencyPairDictionary getCurrencyPairDictionaryByListing(Listing listing) {
|
||||
CurrencyPairSecurity security = currencyPairSecurityImdg.getSingleObjectByID(listing.getSecurityId());
|
||||
return currencyPairDictionaryImdg.getSingleObjectByID(security.getCurrencyPairId());
|
||||
}
|
||||
|
||||
private Listing findListingForRub(Registry registry, String marketCode) {
|
||||
ImdgPredicateBuilder pb = currencyPairDictionaryImdg.predicateBuilder();
|
||||
|
||||
CurrencyPairDictionary pair = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
pb.and(
|
||||
pb.equals("baseCurrency", "CNY"),
|
||||
pb.equals("quoteCurrency", registry.getSecuritySymbol())
|
||||
)
|
||||
);
|
||||
|
||||
Collection<Long> securityIds = currencyPairSecurityImdg.getCollectionIdsByPredicate(
|
||||
pb.equals("currencyPairId", pair.getId())
|
||||
);
|
||||
|
||||
return listingImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.in("securityId", securityIds.toArray(new Long[0])),
|
||||
pb.equals("market", marketCode)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private Listing findListingForOtherCurrency(Registry registry, String marketCode) {
|
||||
ImdgPredicateBuilder pb = currencyPairDictionaryImdg.predicateBuilder();
|
||||
|
||||
CurrencyPairDictionary pair = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
pb.and(
|
||||
pb.equals("baseCurrency", registry.getSecuritySymbol()),
|
||||
pb.equals("quoteCurrency", "RUB")
|
||||
)
|
||||
);
|
||||
|
||||
Collection<Long> securityIds = currencyPairSecurityImdg.getCollectionIdsByPredicate(
|
||||
pb.equals("currencyPairId", pair.getId())
|
||||
);
|
||||
|
||||
return listingImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.in("securityId", securityIds.toArray(new Long[0])),
|
||||
pb.equals("market", marketCode)
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private RiskParameter findRiskParameterForRub() {
|
||||
ImdgPredicateBuilder pb = currencyPairDictionaryImdg.predicateBuilder();
|
||||
CurrencyPairDictionary pair = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
pb.equals("baseCurrency", "CNY")
|
||||
);
|
||||
|
||||
return riskParameterImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.equals("currencyPairId", pair.getId()),
|
||||
pb.equals("settlementType", "T0")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private RiskParameter findRiskParameterForOtherCurrency(Registry registry) {
|
||||
ImdgPredicateBuilder pb = currencyPairDictionaryImdg.predicateBuilder();
|
||||
CurrencyPairDictionary pair = currencyPairDictionaryImdg.getFirstObjectByPredicate(
|
||||
pb.equals("baseCurrency", registry.getSecuritySymbol())
|
||||
);
|
||||
|
||||
return riskParameterImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.equals("currencyPairId", pair.getId()),
|
||||
pb.equals("settlementType", "T0")
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
public Registry getRegistryById(Long id) {
|
||||
return registryImdg.getSingleObjectByID(id);
|
||||
}
|
||||
|
||||
public Registry findAmtRegistry(Registry registry, String securitySymbol) {
|
||||
ImdgPredicateBuilder pb = registryImdg.predicateBuilder();
|
||||
return registryImdg.getSingleObjectByPredicate(
|
||||
pb.and(
|
||||
pb.regex("registryCode", "^PM.*T"),
|
||||
pb.equals("securitySymbol", securitySymbol),
|
||||
pb.equals("tradingClearingRegistryId", registry.getId()),
|
||||
pb.equals("companyId", registry.getCompanyId())
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package ru.spcex.clearing.dflt.management.service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
import ru.clearing.classes.statics.data.misc.OrderCurrency;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.security.RiskParameter;
|
||||
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
|
||||
import ru.spcex.clearing.dflt.management.model.SwapContext;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.CompanyRole;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
@Service
|
||||
public class SpotOvernightOrderService {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final ImdgQueryService imdgQueryService;
|
||||
private final Imdg<OrderCurrency> orderCurrencyImdg;
|
||||
private final SwapOrderTemplateBuilder templateBuilder;
|
||||
private final SwapCalculationService swapCalculationService;
|
||||
|
||||
public SpotOvernightOrderService(ImdgProvider imdgProvider,
|
||||
ImdgQueryService imdgQueryService,
|
||||
SwapOrderTemplateBuilder templateBuilder,
|
||||
SwapCalculationService swapCalculationService) {
|
||||
this.imdgQueryService = imdgQueryService;
|
||||
this.orderCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OrderCurrency, OrderCurrency.class);
|
||||
this.templateBuilder = templateBuilder;
|
||||
this.swapCalculationService = swapCalculationService;
|
||||
}
|
||||
|
||||
public void process(Registry registry) {
|
||||
String orderCategory = imdgQueryService.resolveOrderCategory(registry.getCompanyId());
|
||||
|
||||
Market market = imdgQueryService.getSwapMarket();
|
||||
Listing listing = imdgQueryService.findSwapListing(registry, market.getCode());
|
||||
RiskParameter riskParameter = imdgQueryService.findRiskParameter(registry);
|
||||
CounterpartyInfo categoryP = imdgQueryService.getCompanyByClearingCategory("P");
|
||||
CounterpartyInfo clcc = imdgQueryService.getCompanyByRole(CompanyRole.CLCC);
|
||||
CounterpartyInfo rgcm = imdgQueryService.getCompanyByRole(CompanyRole.RGCM);
|
||||
|
||||
SwapContext context = SwapContext.builder()
|
||||
.registry(registry)
|
||||
.orderCategory(orderCategory)
|
||||
.market(market)
|
||||
.listing(listing)
|
||||
.riskParameter(riskParameter)
|
||||
.categoryP(categoryP)
|
||||
.clcc(clcc)
|
||||
.rgcm(rgcm)
|
||||
.build();
|
||||
|
||||
// OrderCurrency primaryTransfer = templateBuilder.buildPrimaryTransfer(context);
|
||||
// OrderCurrency counterTransfer = templateBuilder.buildCounterTransfer(context);
|
||||
// OrderCurrency primaryBalancing = templateBuilder.buildPrimaryBalancing(context);
|
||||
// OrderCurrency counterBalancing = templateBuilder.buildCounterBalancing(context);
|
||||
//
|
||||
// swapCalculationService.calcAndEnrich(primaryTransfer, context);
|
||||
// swapCalculationService.calcAndEnrich(counterTransfer, context);
|
||||
// swapCalculationService.calcAndEnrich(primaryBalancing, context);
|
||||
// swapCalculationService.calcAndEnrich(counterBalancing, context);
|
||||
//
|
||||
// orderCurrencyImdg.insert(primaryTransfer);
|
||||
// orderCurrencyImdg.insert(counterTransfer);
|
||||
// orderCurrencyImdg.insert(primaryBalancing);
|
||||
// orderCurrencyImdg.insert(counterBalancing);
|
||||
|
||||
log.info("Spot orders created for registryId={}", registry.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,110 @@
|
|||
package ru.spcex.clearing.dflt.management.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.math.MathContext;
|
||||
import java.math.RoundingMode;
|
||||
import java.time.LocalDate;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.OrderCurrency;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.security.Rates;
|
||||
import ru.clearing.platform.dictionary.CurrencyPairDictionary;
|
||||
import ru.spcex.clearing.dflt.management.model.CalculationResult;
|
||||
import ru.spcex.clearing.dflt.management.model.SwapContext;
|
||||
|
||||
@Service
|
||||
public class SwapCalculationService {
|
||||
private static final MathContext MC = new MathContext(20, RoundingMode.HALF_UP);
|
||||
|
||||
private final ImdgQueryService imdgQueryService;
|
||||
private final TransferDateService transferDateService;
|
||||
|
||||
public SwapCalculationService(ImdgQueryService imdgQueryService,
|
||||
TransferDateService transferDateService) {
|
||||
this.imdgQueryService = imdgQueryService;
|
||||
this.transferDateService = transferDateService;
|
||||
}
|
||||
|
||||
public void calcAndEnrich(OrderCurrency order,
|
||||
SwapContext context) {
|
||||
Registry registry = context.getRegistry();
|
||||
Listing listing = context.getListing();
|
||||
|
||||
CurrencyPairDictionary pair = imdgQueryService.getCurrencyPairDictionaryByListing(listing);
|
||||
BigDecimal s = imdgQueryService.defineTransferRate(pair.getId(), registry.getSecuritySymbol());
|
||||
BigDecimal n = transferDateService.numberOfDaysOfTransfer();
|
||||
|
||||
CalculationResult result = isRub(registry)
|
||||
? calculationSwapRubSums(registry, listing.getLotSize().intValue(), s, n)
|
||||
: calculationSwapSums(registry, listing.getLotSize().intValue(), s, n);
|
||||
|
||||
BigDecimal quantityLot = result.sum3().abs();
|
||||
BigDecimal price = swapPriceCalc(pair.getBaseCurrency(), s, n);
|
||||
|
||||
order.setPrice(price);
|
||||
order.setQuantityLot(quantityLot);
|
||||
}
|
||||
|
||||
private CalculationResult calculationSwapSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) {
|
||||
BigDecimal planPosition = registry.getBalance();
|
||||
BigDecimal sum1 = planPosition.abs();
|
||||
|
||||
Registry rubRegistry = imdgQueryService.findAmtRegistry(registry, "RUB");
|
||||
BigDecimal planPositionRub = rubRegistry.getBalance();
|
||||
|
||||
Rates rates = imdgQueryService.getRate(registry.getSecuritySymbol(), LocalDate.now());
|
||||
BigDecimal rateValue = rates.getValue();
|
||||
|
||||
BigDecimal sum2 = planPositionRub.divide(rateValue, lotSize, RoundingMode.HALF_DOWN);
|
||||
BigDecimal sum3 = sum1.setScale(0, RoundingMode.CEILING).min(sum2);
|
||||
BigDecimal sum4 = sum3.multiply(rateValue, MC).negate();
|
||||
BigDecimal sum5 = sum3.negate();
|
||||
|
||||
BigDecimal multiplier = BigDecimal.ONE.add(
|
||||
s.divide(BigDecimal.valueOf(365), MC).multiply(n, MC),
|
||||
MC
|
||||
);
|
||||
|
||||
BigDecimal sum6 = sum3.multiply(rateValue, MC).multiply(multiplier, MC);
|
||||
|
||||
return new CalculationResult(sum1, sum2, sum3, sum4, sum5, sum6);
|
||||
}
|
||||
|
||||
private CalculationResult calculationSwapRubSums(Registry registry, Integer lotSize, BigDecimal s, BigDecimal n) {
|
||||
BigDecimal planPosition = registry.getBalance();
|
||||
Rates cnyRate = imdgQueryService.getRate(registry.getSecuritySymbol(), LocalDate.now());
|
||||
BigDecimal rateValue = cnyRate.getValue();
|
||||
|
||||
BigDecimal sum1 = planPosition.divide(rateValue, MC);
|
||||
|
||||
Registry cnyRegistry = imdgQueryService.findAmtRegistry(registry, "CNY");
|
||||
BigDecimal planPositionCny = cnyRegistry.getBalance();
|
||||
|
||||
BigDecimal sum2 = planPositionCny.divide(rateValue, lotSize, RoundingMode.HALF_DOWN);
|
||||
BigDecimal sum3 = sum1.setScale(0, RoundingMode.CEILING).min(sum2).negate();
|
||||
BigDecimal sum4 = sum3.multiply(rateValue, MC).negate();
|
||||
BigDecimal sum5 = sum3.negate();
|
||||
|
||||
BigDecimal multiplier = BigDecimal.ONE.add(
|
||||
s.divide(BigDecimal.valueOf(365), MC).multiply(n, MC),
|
||||
MC
|
||||
);
|
||||
|
||||
BigDecimal sum6 = sum3.multiply(rateValue, MC).multiply(multiplier, MC);
|
||||
|
||||
return new CalculationResult(sum1, sum2, sum3, sum4, sum5, sum6);
|
||||
}
|
||||
|
||||
private BigDecimal swapPriceCalc(String baseCurrency, BigDecimal s, BigDecimal n) {
|
||||
Rates rate = imdgQueryService.getRate(baseCurrency, LocalDate.now());
|
||||
return rate.getValue()
|
||||
.multiply(s, MC)
|
||||
.multiply(n, MC)
|
||||
.divide(BigDecimal.valueOf(365), MC);
|
||||
}
|
||||
|
||||
private boolean isRub(Registry registry) {
|
||||
return "RUB".equals(registry.getSecuritySymbol());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,231 @@
|
|||
package ru.spcex.clearing.dflt.management.service;
|
||||
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
import ru.clearing.classes.statics.data.misc.OrderCurrency;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.security.RiskParameter;
|
||||
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
|
||||
import ru.spcex.clearing.dflt.management.model.SwapContext;
|
||||
import ru.spcex.platform.enumeration.Side;
|
||||
|
||||
@Service
|
||||
public class SwapOrderTemplateBuilder {
|
||||
private final ImdgQueryService imdgQueryService;
|
||||
|
||||
public SwapOrderTemplateBuilder(ImdgQueryService imdgQueryService) {
|
||||
this.imdgQueryService = imdgQueryService;
|
||||
}
|
||||
|
||||
public OrderCurrency buildPrimaryTransfer(SwapContext context) {
|
||||
OrderCurrency orderCurrency;
|
||||
switch (context.getOrderCategory()) {
|
||||
case "PL" -> orderCurrency = buildPrimaryTransferPl(context);
|
||||
case "UK" -> orderCurrency = buildPrimaryTransferUk(context);
|
||||
default -> throw new IllegalArgumentException("Unsupported order category: " + context.getOrderCategory());
|
||||
}
|
||||
Side side = resolvePrimaryTransferSide(context.getRegistry());
|
||||
enrichOrder(orderCurrency, context, side, "overnight");
|
||||
return orderCurrency;
|
||||
}
|
||||
|
||||
public OrderCurrency buildCounterTransfer(SwapContext context) {
|
||||
OrderCurrency orderCurrency;
|
||||
switch (context.getOrderCategory()) {
|
||||
case "PL" -> orderCurrency = buildCounterTransferPl(context);
|
||||
case "UK" -> orderCurrency = buildCounterTransferUk(context);
|
||||
default -> throw new IllegalArgumentException("Unsupported order category: " + context.getOrderCategory());
|
||||
};
|
||||
Side side = resolveCounterTransferSide(context.getRegistry());
|
||||
enrichOrder(orderCurrency, context, side, "overnight");
|
||||
return orderCurrency;
|
||||
}
|
||||
|
||||
public OrderCurrency buildPrimaryBalancing(SwapContext context) {
|
||||
OrderCurrency orderCurrency;
|
||||
switch (context.getOrderCategory()) {
|
||||
case "PL" -> orderCurrency = buildPrimaryBalancingPl(context);
|
||||
case "UK" -> orderCurrency = buildPrimaryBalancingUk(context);
|
||||
default -> throw new IllegalArgumentException("Unsupported order category: " + context.getOrderCategory());
|
||||
};
|
||||
Side side = resolvePrimaryBalancingSide(context.getRegistry());
|
||||
enrichOrder(orderCurrency, context, side, "balance");
|
||||
return orderCurrency;
|
||||
}
|
||||
|
||||
public OrderCurrency buildCounterBalancing(SwapContext context) {
|
||||
OrderCurrency orderCurrency;
|
||||
switch (context.getOrderCategory()) {
|
||||
case "PL" -> orderCurrency = buildCounterBalancingPl(context);
|
||||
case "UK" -> orderCurrency = buildCounterBalancingUk(context);
|
||||
default -> throw new IllegalArgumentException("Unsupported order category: " + context.getOrderCategory());
|
||||
};
|
||||
Side side = resolveCounterBalancingSide(context.getRegistry());
|
||||
enrichOrder(orderCurrency, context, side, "balance");
|
||||
return orderCurrency;
|
||||
}
|
||||
|
||||
private OrderCurrency buildPrimaryTransferUk(SwapContext context) {
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
Registry registry = context.getRegistry();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(registry.getTradingClearingRegistry());
|
||||
order.setTradingClearingRegistryId(registry.getTradingClearingRegistryId());
|
||||
order.setCompanyId(registry.getCompanyId());
|
||||
order.setTradingCode(registry.getTradingCode());
|
||||
order.setCounterPartyId(clcc.companyId());
|
||||
order.setCounterTradingCode(clcc.tradingCode());
|
||||
order.setType("CMOV");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildCounterTransferUk(SwapContext context) {
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
Registry registry = context.getRegistry();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(clcc.registryCode());
|
||||
order.setTradingClearingRegistryId(clcc.registryId());
|
||||
order.setCompanyId(clcc.companyId());
|
||||
order.setTradingCode(clcc.tradingCode());
|
||||
order.setCounterPartyId(registry.getCompanyId());
|
||||
order.setCounterTradingCode(registry.getTradingCode());
|
||||
order.setType("CMOV");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildPrimaryBalancingUk(SwapContext context) {
|
||||
CounterpartyInfo categoryP = context.getCategoryP();
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(categoryP.registryCode());
|
||||
order.setTradingClearingRegistryId(categoryP.registryId());
|
||||
order.setCompanyId(categoryP.companyId());
|
||||
order.setTradingCode(categoryP.tradingCode());
|
||||
order.setCounterPartyId(clcc.companyId());
|
||||
order.setCounterTradingCode(clcc.tradingCode());
|
||||
order.setType("CMBL");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildCounterBalancingUk(SwapContext context) {
|
||||
CounterpartyInfo categoryP = context.getCategoryP();
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(clcc.registryCode());
|
||||
order.setTradingClearingRegistryId(clcc.registryId());
|
||||
order.setCompanyId(clcc.companyId());
|
||||
order.setTradingCode(clcc.tradingCode());
|
||||
order.setCounterPartyId(categoryP.companyId());
|
||||
order.setCounterTradingCode(categoryP.tradingCode());
|
||||
order.setType("CMBL");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildPrimaryTransferPl(SwapContext context) {
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
Registry registry = context.getRegistry();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(registry.getTradingClearingRegistry());
|
||||
order.setTradingClearingRegistryId(registry.getTradingClearingRegistryId());
|
||||
order.setCompanyId(registry.getCompanyId());
|
||||
order.setTradingCode(registry.getTradingCode());
|
||||
order.setCounterPartyId(clcc.companyId());
|
||||
order.setCounterTradingCode(clcc.tradingCode());
|
||||
order.setType("PLOV");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildCounterTransferPl(SwapContext context) {
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
Registry registry = context.getRegistry();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(clcc.registryCode());
|
||||
order.setTradingClearingRegistryId(clcc.registryId());
|
||||
order.setCompanyId(clcc.companyId());
|
||||
order.setTradingCode(clcc.tradingCode());
|
||||
order.setCounterPartyId(registry.getCompanyId());
|
||||
order.setCounterTradingCode(registry.getTradingCode());
|
||||
order.setType("PLOV");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildPrimaryBalancingPl(SwapContext context) {
|
||||
CounterpartyInfo rgcm = context.getRgcm();
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(rgcm.registryCode());
|
||||
order.setTradingClearingRegistryId(rgcm.registryId());
|
||||
order.setCompanyId(rgcm.companyId());
|
||||
order.setTradingCode(rgcm.tradingCode());
|
||||
order.setCounterPartyId(clcc.companyId());
|
||||
order.setCounterTradingCode(clcc.tradingCode());
|
||||
order.setType("PLBL");
|
||||
return order;
|
||||
}
|
||||
|
||||
private OrderCurrency buildCounterBalancingPl(SwapContext context) {
|
||||
CounterpartyInfo clcc = context.getClcc();
|
||||
CounterpartyInfo rgcm = context.getRgcm();
|
||||
|
||||
OrderCurrency order = new OrderCurrency();
|
||||
order.setAccount(clcc.registryCode());
|
||||
order.setTradingClearingRegistryId(clcc.registryId());
|
||||
order.setCompanyId(clcc.companyId());
|
||||
order.setTradingCode(clcc.tradingCode());
|
||||
order.setCounterPartyId(rgcm.companyId());
|
||||
order.setCounterTradingCode(rgcm.tradingCode());
|
||||
order.setType("PLBL");
|
||||
return order;
|
||||
}
|
||||
|
||||
public void enrichOrder(OrderCurrency order,
|
||||
SwapContext context,
|
||||
Side side,
|
||||
String comment) {
|
||||
Registry registry = context.getRegistry();
|
||||
Listing listing = context.getListing();
|
||||
Market market = context.getMarket();
|
||||
RiskParameter riskParameter = context.getRiskParameter();
|
||||
|
||||
order.setOvernightType("SWAP");
|
||||
order.setMarket(market.getCode());
|
||||
order.setListingId(listing.getId());
|
||||
order.setSecuritySymbol(listing.getSymbolCode());
|
||||
order.setSecurityId(listing.getSecurityId());
|
||||
order.setLotSize(listing.getLotSize());
|
||||
order.setRate(riskParameter.getQuoteValue());
|
||||
order.setSide(side.getKey());
|
||||
order.setSettleCode("T1");
|
||||
order.setStatus("CRET");
|
||||
order.setComment(comment);
|
||||
order.setRegistryId(registry.getId());
|
||||
}
|
||||
|
||||
private Side resolvePrimaryTransferSide(Registry registry) {
|
||||
return isRub(registry) ? Side.BUY : Side.SELL;
|
||||
}
|
||||
|
||||
private Side resolveCounterTransferSide(Registry registry) {
|
||||
return isRub(registry) ? Side.SELL : Side.BUY;
|
||||
}
|
||||
|
||||
private Side resolvePrimaryBalancingSide(Registry registry) {
|
||||
return isRub(registry) ? Side.SELL : Side.BUY;
|
||||
}
|
||||
|
||||
private Side resolveCounterBalancingSide(Registry registry) {
|
||||
return isRub(registry) ? Side.BUY : Side.SELL;
|
||||
}
|
||||
|
||||
private boolean isRub(Registry registry) {
|
||||
return "RUB".equals(registry.getSecuritySymbol());
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,76 @@
|
|||
package ru.spcex.clearing.dflt.management.service;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.misc.Listing;
|
||||
import ru.clearing.classes.statics.data.misc.Market;
|
||||
import ru.clearing.classes.statics.data.misc.OrderCurrency;
|
||||
import ru.clearing.classes.statics.data.registry.Registry;
|
||||
import ru.clearing.classes.statics.data.security.RiskParameter;
|
||||
import ru.spcex.clearing.dflt.management.model.CounterpartyInfo;
|
||||
import ru.spcex.clearing.dflt.management.model.SwapContext;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.CompanyRole;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
|
||||
@Service
|
||||
public class SwapOvernightOrderService {
|
||||
private final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
private final ImdgQueryService imdgQueryService;
|
||||
private final Imdg<OrderCurrency> orderCurrencyImdg;
|
||||
private final SwapOrderTemplateBuilder templateBuilder;
|
||||
private final SwapCalculationService swapCalculationService;
|
||||
|
||||
public SwapOvernightOrderService(ImdgProvider imdgProvider,
|
||||
ImdgQueryService imdgQueryService,
|
||||
SwapOrderTemplateBuilder templateBuilder,
|
||||
SwapCalculationService swapCalculationService) {
|
||||
this.imdgQueryService = imdgQueryService;
|
||||
this.orderCurrencyImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_OrderCurrency, OrderCurrency.class);
|
||||
this.templateBuilder = templateBuilder;
|
||||
this.swapCalculationService = swapCalculationService;
|
||||
}
|
||||
|
||||
public void process(Registry registry) {
|
||||
String orderCategory = imdgQueryService.resolveOrderCategory(registry.getCompanyId());
|
||||
|
||||
Market market = imdgQueryService.getSwapMarket();
|
||||
Listing listing = imdgQueryService.findSwapListing(registry, market.getCode());
|
||||
RiskParameter riskParameter = imdgQueryService.findRiskParameter(registry);
|
||||
CounterpartyInfo categoryP = imdgQueryService.getCompanyByClearingCategory("P");
|
||||
CounterpartyInfo clcc = imdgQueryService.getCompanyByRole(CompanyRole.CLCC);
|
||||
CounterpartyInfo rgcm = imdgQueryService.getCompanyByRole(CompanyRole.RGCM);
|
||||
|
||||
SwapContext context = SwapContext.builder()
|
||||
.registry(registry)
|
||||
.orderCategory(orderCategory)
|
||||
.market(market)
|
||||
.listing(listing)
|
||||
.riskParameter(riskParameter)
|
||||
.categoryP(categoryP)
|
||||
.clcc(clcc)
|
||||
.rgcm(rgcm)
|
||||
.build();
|
||||
|
||||
OrderCurrency primaryTransfer = templateBuilder.buildPrimaryTransfer(context);
|
||||
OrderCurrency counterTransfer = templateBuilder.buildCounterTransfer(context);
|
||||
OrderCurrency primaryBalancing = templateBuilder.buildPrimaryBalancing(context);
|
||||
OrderCurrency counterBalancing = templateBuilder.buildCounterBalancing(context);
|
||||
|
||||
swapCalculationService.calcAndEnrich(primaryTransfer, context);
|
||||
swapCalculationService.calcAndEnrich(counterTransfer, context);
|
||||
swapCalculationService.calcAndEnrich(primaryBalancing, context);
|
||||
swapCalculationService.calcAndEnrich(counterBalancing, context);
|
||||
|
||||
orderCurrencyImdg.insert(primaryTransfer);
|
||||
orderCurrencyImdg.insert(counterTransfer);
|
||||
orderCurrencyImdg.insert(primaryBalancing);
|
||||
orderCurrencyImdg.insert(counterBalancing);
|
||||
|
||||
log.info("Swap orders created for registryId={}", registry.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,56 @@
|
|||
package ru.spcex.clearing.dflt.management.service;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.time.DayOfWeek;
|
||||
import java.time.LocalDate;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import org.springframework.stereotype.Service;
|
||||
import ru.clearing.classes.statics.data.scheduler.ClearingCalendar;
|
||||
import ru.spcex.clearing.imdg.IMDGDistributedNames;
|
||||
import ru.spcex.platform.enumeration.DayStatus;
|
||||
import ru.spcex.platform.imdg.api.Imdg;
|
||||
import ru.spcex.platform.imdg.api.ImdgProvider;
|
||||
import ru.spcex.platform.imdg.api.predicate.ImdgPredicateBuilder;
|
||||
|
||||
@Service
|
||||
public class TransferDateService {
|
||||
private final Imdg<ClearingCalendar> clearingCalendarImdg;
|
||||
|
||||
public TransferDateService(ImdgProvider imdgProvider) {
|
||||
this.clearingCalendarImdg = imdgProvider.getImdg(IMDGDistributedNames.Map_ClearingCalendar, ClearingCalendar.class);
|
||||
}
|
||||
|
||||
public LocalDate findNextWorkingDate() {
|
||||
LocalDate checkingDate = LocalDate.now().plusDays(1);
|
||||
ImdgPredicateBuilder pb = clearingCalendarImdg.predicateBuilder();
|
||||
|
||||
while (true) {
|
||||
ClearingCalendar calendarDay = clearingCalendarImdg.getFirstObjectByPredicate(
|
||||
pb.equals("clearingDate", checkingDate)
|
||||
);
|
||||
|
||||
if (isWeekday(checkingDate.getDayOfWeek())) {
|
||||
// Будний день рабочий, если НЕТ явной записи DOFF
|
||||
if (calendarDay == null || !DayStatus.DayOff.equalsByKey(calendarDay.getDayStatus())) {
|
||||
return checkingDate;
|
||||
}
|
||||
} else {
|
||||
// Выходной рабочий, только если ЕСТЬ явная запись BDAY
|
||||
if (calendarDay != null && DayStatus.Workday.equalsByKey(calendarDay.getDayStatus())) {
|
||||
return checkingDate;
|
||||
}
|
||||
}
|
||||
|
||||
checkingDate = checkingDate.plusDays(1);
|
||||
}
|
||||
}
|
||||
|
||||
public BigDecimal numberOfDaysOfTransfer() {
|
||||
long days = ChronoUnit.DAYS.between(LocalDate.now(), findNextWorkingDate());
|
||||
return BigDecimal.valueOf(days);
|
||||
}
|
||||
|
||||
private boolean isWeekday(DayOfWeek dayOfWeek) {
|
||||
return dayOfWeek != DayOfWeek.SATURDAY && dayOfWeek != DayOfWeek.SUNDAY;
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Reference in a new issue