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
Collection<ExecutionDeposit> execDeposits = executionDepositImdg.getCollectionObjectsBySQL("sessionId = null");
//делаем группировку ExecutionDeposit по категории и компании, делаем сортировку
LinkedHashMap<ClearingCategory, List<List<ExecDepositWCategory>>> executionDeposits = sorter.sortExecutionDeposit(execDeposits);
LinkedHashMap<ClearingCategory, List<List<ExecutionDeposit>>> executionDeposits = sorter.sortExecutionDeposit(execDeposits);
executionDeposits.forEach((category, companies) -> {
for (List<ExecDepositWCategory> companyExecDeposits : companies) {
for (List<ExecutionDeposit> companyExecDeposits : companies) {
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());
boolean financialError = false;
for (ExecDepositWCategory execDepositWrapper : executionDeposits) {
ExecutionDeposit execDeposit = execDepositWrapper.getExecutionDeposit();
for (ExecutionDeposit execDeposit : executionDeposits) {
if (financialError) {
updateDenied(execDeposit);
continue;

View file

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