This commit is contained in:
parent
196ec996df
commit
76bde6941a
3 changed files with 54 additions and 28 deletions
|
|
@ -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;
|
||||||
|
|
|
||||||
|
|
@ -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 -> {
|
||||||
|
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
Add table
Reference in a new issue