ialbert 2023-02-01 12:12:26 +03:00
parent 196ec996df
commit 76bde6941a
3 changed files with 54 additions and 28 deletions

View file

@ -45,20 +45,19 @@ public class Clearing {
//выгружаем ExecutionDeposit с пустым sessionId //выгружаем ExecutionDeposit с пустым sessionId
Collection<ExecutionDeposit> execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null"); Collection<ExecutionDeposit> execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null");
//делаем группировку ExecutionDeposit по категории и компании, делаем сортировку //делаем группировку ExecutionDeposit по категории и компании, делаем сортировку
LinkedHashMap<ClearingCategory, List<List<ExecDepositWCategory>>> executionDeposits = sorter.sortExecutionDeposit(execDeposits); LinkedHashMap<ClearingCategory, List<List<ExecutionDeposit>>> executionDeposits = sorter.sortExecutionDeposit(execDeposits);
executionDeposits.forEach((category, companies) -> { executionDeposits.forEach((category, companies) -> {
for (List<ExecDepositWCategory> companyExecDeposits : companies) { for (List<ExecutionDeposit> companyExecDeposits : companies) {
processSingleCompany(category, companyExecDeposits); processSingleCompany(category, companyExecDeposits);
} }
}); });
} }
private void processSingleCompany(ClearingCategory category, List<ExecDepositWCategory> executionDeposits) { private void processSingleCompany(ClearingCategory category, List<ExecutionDeposit> executionDeposits) {
log.info("Start clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId()); log.info("Start clearing for category: {}, company: {}", category, executionDeposits.get(0).getCompanyId());
boolean financialError = false; boolean financialError = false;
for (ExecDepositWCategory execDepositWrapper : executionDeposits) { for (ExecutionDeposit execDeposit : executionDeposits) {
ExecutionDeposit execDeposit = execDepositWrapper.getExecutionDeposit();
if (financialError) { if (financialError) {
updateDenied(execDeposit); updateDenied(execDeposit);
continue; continue;

View file

@ -3,9 +3,9 @@ package ru.spcex.clearing.service.order;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;
import ru.clearing.classes.statics.data.execution.ExecutionDeposit; import ru.clearing.classes.statics.data.execution.ExecutionDeposit;
import ru.spcex.clearing.service.ExecDepositWCategory;
import ru.spcex.platform.enumeration.ClearingCategory; import ru.spcex.platform.enumeration.ClearingCategory;
import ru.spcex.platform.enumeration.MoneyFlowSide; import ru.spcex.platform.enumeration.MoneyFlowSide;
import ru.spcex.platform.utils.collection.Pair;
import ru.spcex.platform.utils.enumeration.IEnumKey; import ru.spcex.platform.utils.enumeration.IEnumKey;
import java.util.*; import java.util.*;
@ -23,7 +23,7 @@ public class ExecutionDepositSorter {
this.clearingMemberCategoryProvider = clearingMemberCategoryProvider; this.clearingMemberCategoryProvider = clearingMemberCategoryProvider;
} }
public LinkedHashMap<ClearingCategory, List<List<ExecDepositWCategory>>> sortExecutionDeposit(Collection<ExecutionDeposit>execDeposits) { public LinkedHashMap<ClearingCategory, List<List<ExecutionDeposit>>> sortExecutionDeposit(Collection<ExecutionDeposit>execDeposits) {
//отсортировали все записи по категориям //отсортировали все записи по категориям
// внутри каждой подгруппы по категориям сортируем по компаниям // внутри каждой подгруппы по категориям сортируем по компаниям
// обрабатываем почередно все записи первой компании // обрабатываем почередно все записи первой компании
@ -32,18 +32,18 @@ public class ExecutionDepositSorter {
// начинаем аналогично обработавать все записи второй категории и так далее). // начинаем аналогично обработавать все записи второй категории и так далее).
//сортируем по категориям //сортируем по категориям
Map<ClearingCategory, List<ExecDepositWCategory>> categoryGrouping = execDeposits.stream().map(executionDeposit -> { Map<ClearingCategory, List<ExecutionDeposit>> categoryGrouping = execDeposits.stream().map(executionDeposit -> {
ClearingCategory category = clearingMemberCategoryProvider.apply(executionDeposit.getCompanyId()); ClearingCategory category = clearingMemberCategoryProvider.apply(executionDeposit.getCompanyId());
return new ExecDepositWCategory(executionDeposit, category); return new Pair<>(category, executionDeposit);
}).collect(Collectors.groupingBy(ExecDepositWCategory::getClearingMemberCategory)); }).collect(Collectors.groupingBy(Pair::getFirst, Collectors.mapping(Pair::getSecond, Collectors.toList())));
//внутри категорий сортируем по компаниям //внутри категорий сортируем по компаниям
LinkedHashMap<ClearingCategory, List<List<ExecDepositWCategory>>> byCategoryByCompany = new LinkedHashMap<>(); LinkedHashMap<ClearingCategory, List<List<ExecutionDeposit>>> byCategoryByCompany = new LinkedHashMap<>();
Consumer<ClearingCategory> takeByClearingCategoryAnSortByCompaniId = clearingCategory -> { Consumer<ClearingCategory> takeByClearingCategoryAndSortByCompanyId = clearingCategory -> {
List<ExecDepositWCategory> wrappers = categoryGrouping.remove(clearingCategory); List<ExecutionDeposit> wrappers = categoryGrouping.remove(clearingCategory);
if (wrappers != null) { if (wrappers != null) {
List<List<ExecDepositWCategory>> batches = wrappers.stream() List<List<ExecutionDeposit>> batches = wrappers.stream()
.collect(Collectors.groupingBy(ExecDepositWCategory::getCompanyId)) .collect(Collectors.groupingBy(ExecutionDeposit::getCompanyId))
.entrySet() .entrySet()
.stream() .stream()
.sorted(Map.Entry.comparingByKey()) .sorted(Map.Entry.comparingByKey())
@ -53,29 +53,29 @@ public class ExecutionDepositSorter {
} }
}; };
//кладем в порядке I, V, B //кладем в порядке I, V, B
takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.I); takeByClearingCategoryAndSortByCompanyId.accept(ClearingCategory.I);
takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.V); takeByClearingCategoryAndSortByCompanyId.accept(ClearingCategory.V);
takeByClearingCategoryAnSortByCompaniId.accept(ClearingCategory.B); takeByClearingCategoryAndSortByCompanyId.accept(ClearingCategory.B);
//для всех остальных порядок не важен, будут последними //для всех остальных порядок не важен, будут последними
categoryGrouping.keySet().forEach(takeByClearingCategoryAnSortByCompaniId); categoryGrouping.keySet().forEach(takeByClearingCategoryAndSortByCompanyId);
//метод для дополнительной сортировки внутри групп по категории и компании //метод для дополнительной сортировки внутри групп по категории и компании
BiConsumer<ClearingCategory, Comparator<ExecDepositWCategory>> additionalSorting = BiConsumer<ClearingCategory, Comparator<ExecutionDeposit>> additionalSorting =
(clearingCategory, comparator) -> byCategoryByCompany (clearingCategory, comparator) -> byCategoryByCompany
.get(clearingCategory) .get(clearingCategory)
.forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator)); .forEach(singleCompanyBatch -> singleCompanyBatch.sort(comparator));
//применяем дополнительные сортировки //применяем дополнительные сортировки
//для V сначала Sell, потом Buy, в первую очередь должны обрабатываться новые сделки с наименьшими объемами //для V сначала Sell, потом Buy, в первую очередь должны обрабатываться новые сделки с наименьшими объемами
additionalSorting.accept(ClearingCategory.V, firstSellThenBuy additionalSorting.accept(ClearingCategory.V,
.thenComparing(wrapper -> wrapper.getExecutionDeposit().getFirstLegAmount())); firstSellThenBuy.thenComparing(ExecutionDeposit::getFirstLegAmount));
//для V сначала Buy, потом Sell, exchangeExecutionId - возрастающий //для V сначала Buy, потом Sell, exchangeExecutionId - возрастающий
additionalSorting.accept(ClearingCategory.B, firstBuyThenSell additionalSorting.accept(ClearingCategory.B,
.thenComparing(wrapper -> wrapper.getExecutionDeposit().getExchangeExecutionId())); firstBuyThenSell.thenComparing(ExecutionDeposit::getExchangeExecutionId));
return byCategoryByCompany; return byCategoryByCompany;
} }
public static Comparator<ExecDepositWCategory> firstSellThenBuy = Comparator.comparing(wrapper -> { public static Comparator<ExecutionDeposit> firstSellThenBuy = Comparator.comparing(wrapper -> {
MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getExecutionDeposit().getSide()); MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getSide());
if (side == null) return Integer.MAX_VALUE; if (side == null) return Integer.MAX_VALUE;
switch (side) { switch (side) {
case BUY -> { case BUY -> {
@ -90,8 +90,8 @@ public class ExecutionDepositSorter {
} }
}); });
public static Comparator<ExecDepositWCategory> firstBuyThenSell = Comparator.comparing(wrapper -> { public static Comparator<ExecutionDeposit> firstBuyThenSell = Comparator.comparing(wrapper -> {
MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getExecutionDeposit().getSide()); MoneyFlowSide side = IEnumKey.getEnumByKey(MoneyFlowSide.class, wrapper.getSide());
if (side == null) return Integer.MAX_VALUE; if (side == null) return Integer.MAX_VALUE;
switch (side) { switch (side) {
case BUY -> { case BUY -> {

View file

@ -0,0 +1,27 @@
package ru.spcex.platform.utils.collection;
public class Pair<T1, T2> {
private T1 first;
private T2 second;
public Pair(T1 first, T2 second) {
this.first = first;
this.second = second;
}
public T1 getFirst() {
return first;
}
public void setFirst(T1 first) {
this.first = first;
}
public T2 getSecond() {
return second;
}
public void setSecond(T2 second) {
this.second = second;
}
}