流水簿记修改为先进先出逻辑

This commit is contained in:
吴方海
2024-06-07 10:10:05 +08:00
parent 08eb622ca1
commit 2d3eacd296
2 changed files with 132 additions and 313 deletions
@@ -417,7 +417,7 @@ namespace YLErp.Modules.SwapModule
&& !ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus)).ToList();
var swapTradeIds = swaptrades.Select(s => s.id);
var tradeExtends = DbContext.trade_extend.Where(x => swapTradeIds.Contains(x.TradeId));
var clientMarginTemplates = DbContext.client_marginrate.Where(x => x.Type == "品种" && x.ValueDate <= valueDate).OrderByDescending(o => o.ValueDate).ToList();
var clientMarginTemplates = DbContext.client_marginrate.Where(x => x.ValueDate <= valueDate).OrderByDescending(o => o.ValueDate).ToList();
var restSwapTrades = new List<trade>();
foreach (var swaptrade in swaptrades)
{
@@ -442,9 +442,9 @@ namespace YLErp.Modules.SwapModule
/// </summary>
/// <param name="mergeList"></param>
/// <param name="valueDate"></param>
public void MergeAvgModeCompose(List<swap_flow> swapFlows, DateTime valueDate, Action<int>? action)
public void MergeAvgModeCompose(List<swap_flow_merge> mergeList, DateTime valueDate, Action<int>? action)
{
var flowquery = swapFlows.GroupBy(g => g.ClientId);
var flowquery = mergeList.GroupBy(g => g.ClientId);
var flowCount = flowquery.Count();
if (flowCount == 0)
{
@@ -456,13 +456,14 @@ namespace YLErp.Modules.SwapModule
&& !ConsTrade.TradeCompleteStatus.Contains(t.TradeStatus)).ToList();
var swapTradeIds = swaptrades.Select(s => s.id);
var swapPositions = DbContext.swap_position.Where(x => swapTradeIds.Contains(x.SwapTradeId) && x.PosiDirection > 0 && !x.IsInitial && x.PosiQuantity > 0 && !x.Invalid).ToList();
var clientMarginTemplates = DbContext.client_marginrate.Where(x => x.ValueDate <= valueDate).OrderByDescending(o => o.ValueDate).ToList();
var matuirityDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate.AddDays(14));
var floatRatePredicate = PredicateBuilder.Create<SwapFloatRate>(x => x.StartDate <= valueDate && x.EndDate >= matuirityDate);
var floatRateQuery = DbContext.swap_float_rate.Where(floatRatePredicate);
int dealCount = 0;
foreach (var groupItem in flowquery)
{
MergeAvgModelItem(groupItem, swaptrades, swapPositions, floatRateQuery, ref dealCount, action);
MergeAvgModelItem(groupItem, swaptrades, swapPositions, floatRateQuery, clientMarginTemplates, ref dealCount, action);
}
}
public void UpdateSwapFlowState(List<swap_flow> swapFlows)
@@ -583,10 +584,11 @@ namespace YLErp.Modules.SwapModule
/// <param name="direction"></param>
/// <param name="matuirityDate"></param>
/// <exception cref="ServiceException"></exception>
private void MergeAvgModelItem(IGrouping<int?, swap_flow> groupItem,
private void MergeAvgModelItem(IGrouping<int?, swap_flow_merge> groupItem,
List<trade> swaptrades,
List<swap_position> swapPositions,
IQueryable<SwapFloatRate> floatRateQuery, ref int dealCount, Action<int>? action)
IQueryable<SwapFloatRate> floatRateQuery,
List<client_marginrate> client_Marginrates, ref int dealCount, Action<int>? action)
{
var clientId = groupItem.Key;
var client = DataCacheProvider.GetClientDataSource().GetData(clientId ?? 0);
@@ -597,7 +599,11 @@ namespace YLErp.Modules.SwapModule
var clientSwapTrades = swaptrades.Where(x => x.ClientId == clientId).ToList();
var clientSwapTradeIds = clientSwapTrades.Select(s => s.id);
var clientSwapPositions = swapPositions.Where(x => clientSwapTradeIds.Contains(x.SwapTradeId));//现有客户持仓
var clientMarginTemplate = client_Marginrates.FirstOrDefault(x => x.ClientId == clientId);
if (clientMarginTemplate == null)
{
clientMarginTemplate = client_Marginrates.FirstOrDefault(x => x.ClientId == 0);
}
var underlyingCodes = underlyingGroup.Select(s => s.Key).ToList();
var underlyings = DataCacheProvider.GetUnderlyingDataSource().AsQueryable(x => underlyingCodes.Contains(x.UnderlyingCode));
foreach (var underlyingGroupItem in underlyingGroup)
@@ -617,11 +623,11 @@ namespace YLErp.Modules.SwapModule
if (!hasPayPosition)//没有持仓
{
var bsType = mergeList.OrderBy(o => o.OptTime).First().BsType;
AvgDealNoPosition(mergeList, client, asset, underlying, floatRate, clearingAgency, bsType);
AvgDealNoPosition(mergeList, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency, bsType);
}
else
{
AvgDealHasPosition(mergeList, client, asset, underlying, floatRate, clientSwapPositionList, clientSwapTrades, clearingAgency);
AvgDealHasPosition(mergeList, client, asset, underlying, floatRate, clientSwapPositionList, clientSwapTrades, clientMarginTemplate, clearingAgency);
}
}
@@ -697,178 +703,90 @@ namespace YLErp.Modules.SwapModule
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
private trade AvgDealNoPosition(List<swap_flow> swapFlows,
private trade AvgDealNoPosition(List<swap_flow_merge> swapFlows,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
client_marginrate clientMarginTemplate,
string clearingAgency,
int byType)
{
var negativeFlows = swapFlows.Where(x => x.BsType != byType).OrderBy(o => o.OptTime).ToList();
var sameFlows = swapFlows.Where(x => x.BsType == byType).OrderBy(o => o.OptTime).ToList();
if (negativeFlows.Count == 0)
var negativeFlow = swapFlows.Where(x => x.BsType != byType).FirstOrDefault();
var sameFlow = swapFlows.Where(x => x.BsType == byType).FirstOrDefault();
if (negativeFlow==null)
{
return DealOneDirectionFlows(sameFlows, client, asset, underlying, floatRate, clearingAgency);
return NewSwapTrade(sameFlow, client, asset, underlying, floatRate, clientMarginTemplate,clearingAgency);
}
return DealTwoDirectionFlows(sameFlows, negativeFlows, client, asset, underlying, floatRate, clearingAgency);
}
/// <summary>
/// 当前无持仓,且只有一个方向的流水合成簿记
/// </summary>
/// <param name="sameFlows"></param>
/// <param name="client"></param>
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
/// <param name="clearingAgency"></param>
private trade DealOneDirectionFlows(List<swap_flow> sameFlows,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
string clearingAgency)
{
List<SwapFlowDeal> swapFlowDeals = new List<SwapFlowDeal>();
foreach (var flow in sameFlows)
{
SwapFlowDeal swapFlowDeal = GetSwapFlowDeal(flow, flow.TradingQty, (int)OpenCloseEnum., flow.TradingFee, null);
swapFlowDeals.Add(swapFlowDeal);
}
return NewSwapTrade(swapFlowDeals, client, asset, underlying, floatRate, clearingAgency);
return DealTwoDirectionFlows(sameFlow, negativeFlow, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency);
}
/// <summary>
/// 当前无持仓,且有2个方向流水合成簿记
/// </summary>
/// <param name="sameFlows"></param>
/// <param name="negativeFlows"></param>
/// <param name="sameFlow"></param>
/// <param name="negativeFlow"></param>
/// <param name="client"></param>
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
/// <param name="clientMarginTemplate"></param>
/// <param name="clearingAgency"></param>
private trade DealTwoDirectionFlows(List<swap_flow> sameFlows,
List<swap_flow> negativeFlows,
/// <returns></returns>
private trade DealTwoDirectionFlows(swap_flow_merge sameFlow,
swap_flow_merge negativeFlow,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
client_marginrate clientMarginTemplate,
string clearingAgency)
{
var swapTradeService = new SwapTradeService(UserInfo);
var sameQty = sameFlows.Sum(s => s.TradingQty);
var negaQty = negativeFlows.Sum(s => s.TradingQty);
//第一次开仓流水拆分明细
List<SwapFlowDeal> openFirstFlows = new List<SwapFlowDeal>();
//第一次平仓流水拆分明细
List<SwapFlowDeal> unwindFirstFlows = new List<SwapFlowDeal>();
//第二次开仓流水拆分明细,最多可能存在第二次开仓
List<SwapFlowDeal> openLastFlows = new List<SwapFlowDeal>();
List<swap_flow> negaFlowClones = DataHelper.DeepCopyObject(negativeFlows);
List<swap_flow> sameFlowClones = DataHelper.DeepCopyObject(sameFlows);
unwindFirstFlows = GetRemainderFlows(negaFlowClones, sameQty, null);
var unwindQty = unwindFirstFlows.Sum(s => s.TradingQty);
//日内轧差全开全平
//同向总数量>=反向总数量,同向新开仓,反向流水全部平仓,同向剩余新开仓
if (sameQty >= negaQty)
var sameQty = sameFlow.TradingQty;
var negaQty = negativeFlow.TradingQty;
swap_flow_merge negaFlowClone = DataHelper.DeepCopyObject(negativeFlow);
swap_flow_merge sameFlowClone = DataHelper.DeepCopyObject(sameFlow);
//先开数量大的,再用小的平仓
if (sameQty < negaQty)
{
openFirstFlows = GetRemainderFlows(sameFlowClones, negaQty, null);
openFirstFlows.ForEach(x => { x.OpenFlag = (int)OpenCloseEnum.; });
var openQty = openFirstFlows.Sum(s => s.TradingQty);
if (openQty < negaQty)
{
var sameFlow = sameFlowClones.First();
var unwindFirstQty = negaQty - openQty;
var unwindFee = sameFlow.TradingFee * unwindFirstQty / sameFlow.TradingQty;
SwapFlowDeal firstOpenFlowDeal = GetSwapFlowDeal(sameFlow, unwindFirstQty, (int)OpenCloseEnum., unwindFee, null);
openFirstFlows.Add(firstOpenFlowDeal);
sameFlow.TradingQty = sameFlow.TradingQty - unwindFirstQty;
sameFlow.TradingFee = sameFlow.TradingFee - unwindFee;
sameFlow.TradingAmount = sameFlow.TradingQty;
}
//反向流水全部平仓
foreach (var negaFlow in negaFlowClones)
{
SwapFlowDeal swapFlowDeal = GetSwapFlowDeal(negaFlow, negaFlow.TradingQty, (int)OpenCloseEnum., negaFlow.TradingFee, null);
unwindFirstFlows.Add(swapFlowDeal);
}
foreach (var sameFlow in sameFlowClones)
{
SwapFlowDeal swapFlowDeal = GetSwapFlowDeal(sameFlow, sameFlow.TradingQty, (int)OpenCloseEnum., sameFlow.TradingFee, null);
openLastFlows.Add(swapFlowDeal);
}
sameFlowClone= DataHelper.DeepCopyObject(negativeFlow);
negaFlowClone = DataHelper.DeepCopyObject(sameFlow);
}
else //同向总数量 < 反向总数量,同向先开仓,反向流水部分平仓,反向剩余新开仓
{
if (unwindQty < sameQty)
{
var negaFlow = negaFlowClones.First();
var unwindFirstQty = sameQty - unwindQty;
var unwindFee = negaFlow.TradingFee * unwindFirstQty / negaFlow.TradingQty;
SwapFlowDeal swapFirstFlowDeal = GetSwapFlowDeal(negaFlow, unwindFirstQty, (int)OpenCloseEnum., unwindFee, null);
unwindFirstFlows.Add(swapFirstFlowDeal);
negaFlow.TradingQty = negaFlow.TradingQty - unwindFirstQty;
negaFlow.TradingFee = negaFlow.TradingFee - unwindFee;
negaFlow.TradingAmount = negaFlow.TradingQty;
}
foreach (var flow in sameFlowClones)
{
SwapFlowDeal swapFlowDeal = GetSwapFlowDeal(flow, flow.TradingQty, (int)OpenCloseEnum., flow.TradingFee, null);
openFirstFlows.Add(swapFlowDeal);
}
foreach (var minFlow in negaFlowClones)
{
SwapFlowDeal swapFlowDeal = GetSwapFlowDeal(minFlow, minFlow.TradingQty, (int)OpenCloseEnum., minFlow.TradingFee, null);
openLastFlows.Add(swapFlowDeal);
}
}
var trade = NewSwapTrade(openFirstFlows, client, asset, underlying, floatRate, clearingAgency);
unwindFirstFlows.ForEach(x => { x.SwapTradeId = trade.id; x.SwapTradeNo = trade.TradeNumber; });
DbContext.swap_flow_deal.AddRange(unwindFirstFlows);
var mergeUnwindFlows = SummaryFlow(unwindFirstFlows);
var unwindMergeFlow = mergeUnwindFlows.First();
var trade = NewSwapTrade(sameFlowClone, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency);
// 平仓
new SwapDealService(UserInfo).AuotoSwapUnwind(trade.id,
unwindMergeFlow.TradingAmountAvg,
unwindMergeFlow.TradingAmountFeeAvg,
unwindMergeFlow.TradingAmountNetFeeAvg ?? 0,
unwindMergeFlow.TradingAmountNetAvg ?? 0,
unwindMergeFlow.OccurTime,
unwindMergeFlow.TradingQty,
unwindMergeFlow.TradingQty,
unwindMergeFlow.TradingFeePending);
if (openLastFlows.Count > 0)
{
return NewSwapTrade(openLastFlows, client, asset, underlying, floatRate, clearingAgency);
}
negaFlowClone.TradingAmountAvg,
negaFlowClone.TradingAmountFeeAvg,
negaFlowClone.TradingAmountNetFeeAvg ?? 0,
negaFlowClone.TradingAmountNetAvg ?? 0,
negaFlowClone.OccurTime,
negaFlowClone.TradingQty,
negaFlowClone.TradingQty,
negaFlowClone.TradingFeePending);
return trade;
}
/// <summary>
/// 流水拆分后新开仓
/// 流水新开仓
/// </summary>
/// <param name="openFlows"></param>
/// <param name="flowMergeFirst"></param>
/// <param name="client"></param>
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
/// <param name="clientMarginTemplate"></param>
/// <param name="clearingAgency"></param>
/// <returns></returns>
private trade NewSwapTrade(List<SwapFlowDeal> openFlows,
private trade NewSwapTrade(swap_flow_merge flowMergeFirst,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
client_marginrate clientMarginTemplate,
string clearingAgency)
{
var swapTradeService = new SwapTradeService(UserInfo);
var mergeFlows = SummaryFlow(openFlows);
swap_flow_merge flowMergeFirst = mergeFlows.First();
var trade = swapTradeService.NewSwapTrade(flowMergeFirst, client, asset, underlying, floatRate, null, clearingAgency, LongShortStructType);
var trade = swapTradeService.NewSwapTrade(flowMergeFirst, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency, LongShortStructType);
flowMergeFirst.SwapTradeNo = trade.TradeNumber;
flowMergeFirst.SwapTradeId = trade.id;
openFlows.ForEach(x => { x.SwapTradeId = trade.id; x.SwapTradeNo = trade.TradeNumber; });
DbContext.swap_flow_deal.AddRange(openFlows);
DbContext.SaveChanges();
return trade;
}
@@ -976,24 +894,25 @@ namespace YLErp.Modules.SwapModule
/// <param name="floatRate"></param>
/// <param name="clientSwapPositionList"></param>
/// <param name="clientSwapTrades"></param>
private void AvgDealHasPosition(List<swap_flow> flowList,
private void AvgDealHasPosition(List<swap_flow_merge> flowList,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
List<swap_position> clientSwapPositionList,
List<trade> clientSwapTrades,
client_marginrate clientMarginTemplate,
string clearingAgency)
{
var firstFlow = flowList.First();
var negaFlowExist = flowList.Any(x => x.BsType != firstFlow.BsType);
if (!negaFlowExist)//只有同向流水情况
var negativeFlow = flowList.Where(x => x.BsType != firstFlow.BsType).FirstOrDefault();
if (negativeFlow==null)//只有同向流水情况
{
AvgDealSingleFlow(flowList, clientSwapPositionList, clientSwapTrades, client, asset, underlying, floatRate, clearingAgency);
NewSwapTrade(firstFlow, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency);
}
else
{
AvgDealDoubleFlow(flowList, clientSwapPositionList, clientSwapTrades, client, asset, underlying, floatRate, clearingAgency);
AvgDealDoubleFlow(flowList, clientSwapPositionList, clientSwapTrades, client, asset, underlying, floatRate, clientMarginTemplate,clearingAgency);
}
}
/// <summary>
@@ -1073,38 +992,6 @@ namespace YLErp.Modules.SwapModule
flowMergeClone.TradingAmountNetFeeAvg = flowMergeClone.TradingAmountNetAvg + ratio * flowMergeClone.TradingFeePending / flowMergeClone.TradingQty;
}
/// <summary>
/// 加权平均处理单条流水情况
/// </summary>
/// <param name="flowList"></param>
/// <param name="clientSwapPositionList"></param>
/// <param name="clientSwapTrades"></param>
/// <param name="matuirityDate"></param>
/// <param name="client"></param>
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
private void AvgDealSingleFlow(List<swap_flow> flowList,
List<swap_position> clientSwapPositionList,
List<trade> clientSwapTrades,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
string clearingAgency)
{
swap_flow flowMergeMax = flowList.First();
var negaSwapPositions = clientSwapPositionList.Where(x => x.PositionType != flowMergeMax.BsType).ToList();
List<swap_flow> flowClones = DataHelper.DeepCopyObject(flowList);
if (negaSwapPositions.Count > 0)//流水与持仓反向
{
AvgDealUnwind(flowClones, clientSwapTrades, negaSwapPositions, client, asset, underlying, floatRate, clearingAgency,true);
}
else //只存在同向交易,同向流水合并新开仓
{
DealOneDirectionFlows(flowClones, client, asset, underlying, floatRate, clearingAgency);
}
}
/// <summary>
/// 处理多条流水情况
/// </summary>
/// <param name="mergeList"></param>
@@ -1174,64 +1061,92 @@ namespace YLErp.Modules.SwapModule
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
public void AvgDealDoubleFlow(List<swap_flow> flowList,
public void AvgDealDoubleFlow(List<swap_flow_merge> flowList,
List<swap_position> clientSwapPositionList,
List<trade> clientSwapTrades,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
client_marginrate clientMarginTemplate,
string clearingAgency)
{
var swapTradeService = new SwapTradeService(UserInfo);
var firstPosi = clientSwapPositionList.First();
var swapPositions = clientSwapPositionList.Where(x => x.PositionType == firstPosi.PositionType).ToList();
var posiQty = swapPositions.Sum(s => s.PosiQuantity);
var flowSames = flowList.Where(x => x.BsType == firstPosi.PositionType).ToList();
var flowNegs = flowList.Where(x => x.BsType != firstPosi.PositionType).ToList();
var negaBsType= flowNegs.First().BsType;
var flowSame = flowList.Where(x => x.BsType == firstPosi.PositionType).First();
var flowNeg = flowList.Where(x => x.BsType != firstPosi.PositionType).First();
var negaBsType= flowNeg.BsType;
var sameQty = posiQty + flowSames.Sum(s => s.TradingQty);
var flowSameClones = DataHelper.DeepCopyObject(flowSames);
var flowNegClones = DataHelper.DeepCopyObject(flowNegs);
var sameQty = posiQty + flowSame.TradingQty;
var flowSameClone = DataHelper.DeepCopyObject(flowSame);
var flowNegClone = DataHelper.DeepCopyObject(flowNeg);
//先平反向
AvgDealUnwind(flowNegClones, clientSwapTrades, swapPositions, client, asset, underlying, floatRate, clearingAgency,false);
var trade= AvgDealUnwind(flowNegClone, clientSwapTrades, swapPositions, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency);
var newFlowList = new List<swap_flow>();
var openBystype = firstPosi.PositionType;
if (flowNegClones.Count > 0)
if (trade!=null)
{
newFlowList.AddRange(flowNegClones);
openBystype = negaBsType;
var flowQty = flowSameClone.TradingQty;
var currentPosiQty = flowNegClone.TradingQty;
var newOpenQty = currentPosiQty - flowQty;
var unwindQty = newOpenQty > 0 ? flowQty : currentPosiQty;
var unwindFee = flowSameClone.TradingFeePending * unwindQty / currentPosiQty;
flowQty = flowQty - unwindQty;
// 平仓
new SwapDealService(UserInfo).AuotoSwapUnwind(trade.id,
flowSameClone.TradingAmountAvg,
flowSameClone.TradingAmountFeeAvg,
flowSameClone.TradingAmountNetFeeAvg ?? 0,
flowSameClone.TradingAmountNetAvg ?? 0,
flowSameClone.OccurTime,
flowSameClone.TradingQty,
unwindQty,
unwindFee);
if (flowQty>0)
{
var unwindPercent = 1 - (flowQty / flowSameClone.TradingQty);
var fee = (1 - unwindPercent) * flowSameClone.TradingFeePending;
flowSameClone.TradingQty = flowQty;
flowSameClone.TradingAmount = flowSameClone.TradingQty;
flowSameClone.TradingFeePending = fee;
NewSwapTrade(flowSameClone, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency);
}
}
else
{
NewSwapTrade(flowSameClone, client, asset, underlying, floatRate, clientMarginTemplate, clearingAgency);
}
newFlowList.AddRange(flowSameClones);
//有历史持仓按反方向先开仓
AvgDealNoPosition(newFlowList, client, asset, underlying, floatRate, clearingAgency, openBystype);
}
/// <summary>
/// 有持仓流水
/// 有持仓流水反向平仓
/// </summary>
/// <param name="swapFlows"></param>
/// <param name="swapFlow"></param>
/// <param name="trades"></param>
/// <param name="swapPositions"></param>
/// <param name="client"></param>
/// <param name="asset"></param>
/// <param name="underlying"></param>
/// <param name="floatRate"></param>
/// <param name="clientMarginTemplate"></param>
/// <param name="clearingAgency"></param>
private void AvgDealUnwind(List<swap_flow> swapFlows,
/// <returns></returns>
private trade AvgDealUnwind(swap_flow_merge swapFlow,
List<trade> trades,
List<swap_position> swapPositions,
Client client,
AssetUnit asset,
underlying_manager underlying,
SwapFloatRate floatRate,
string clearingAgency,
bool needAdd)
client_marginrate clientMarginTemplate,
string clearingAgency)
{
var swapTradeService = new SwapTradeService(UserInfo);
var flowQty = swapFlow.TradingQty;
foreach (var posi in swapPositions)
{
if (swapFlows.Count == 0)
if (swapFlow==null|| flowQty == 0)
{
break;
}
@@ -1239,40 +1154,34 @@ namespace YLErp.Modules.SwapModule
if (td != null)
{
var posiQty = posi.PosiQuantity;
var flowQty = swapFlows.Sum(s => s.TradingQty);
var unwindSwapFlowDeals = GetRemainderFlows(swapFlows, posiQty, td);
var unwindQty = unwindSwapFlowDeals.Sum(x => x.TradingQty);
if (unwindQty < posiQty && swapFlows.Count > 0)
{
var unwindSwapFlow = swapFlows.First();
var flowUnindQty = posiQty - unwindQty;
var unwindFee = unwindSwapFlow.TradingQty == 0 ? 0 : unwindSwapFlow.TradingFee * flowUnindQty / unwindSwapFlow.TradingQty;
unwindSwapFlow.TradingQty = unwindSwapFlow.TradingQty - flowUnindQty;
unwindSwapFlow.TradingFee = unwindSwapFlow.TradingFee - unwindFee;
unwindSwapFlow.TradingAmount = unwindSwapFlow.TradingQty;
var unwindFlowDeal = GetSwapFlowDeal(unwindSwapFlow, flowUnindQty, (int)OpenCloseEnum., unwindFee, td);
unwindSwapFlowDeals.Add(unwindFlowDeal);
}
DbContext.swap_flow_deal.AddRange(unwindSwapFlowDeals);
var unwindMergeFlow = SummaryFlow(unwindSwapFlowDeals).First();
var newOpenQty = posiQty - flowQty;
var unwindQty = newOpenQty > 0 ? flowQty : posiQty;
var unwindFee = swapFlow.TradingFeePending* unwindQty / flowQty;
flowQty = flowQty - unwindQty;
// 平仓
new SwapDealService(UserInfo).AuotoSwapUnwind(td.id,
unwindMergeFlow.TradingAmountAvg,
unwindMergeFlow.TradingAmountFeeAvg,
swapFlow.TradingAmountAvg,
swapFlow.TradingAmountFeeAvg,
unwindMergeFlow.TradingAmountNetFeeAvg ?? 0,
unwindMergeFlow.TradingAmountNetAvg ?? 0,
unwindMergeFlow.OccurTime,
unwindMergeFlow.TradingQty,
posiQty,
unwindMergeFlow.TradingFeePending);
swapFlow.TradingAmountNetFeeAvg ?? 0,
swapFlow.TradingAmountNetAvg ?? 0,
swapFlow.OccurTime,
swapFlow.TradingQty,
unwindQty,
unwindFee);
}
}
if (swapFlows.Count > 0 && needAdd)
if (flowQty > 0) //平仓完有剩余流水,
{
var bsType = swapFlows.First().BsType;
AvgDealNoPosition(swapFlows, client, asset, underlying, floatRate, clearingAgency, bsType);
var unwindPercent =1- (flowQty / swapFlow.TradingQty);
var fee = (1 - unwindPercent) * swapFlow.TradingFeePending;
swapFlow.TradingQty = flowQty;
swapFlow.TradingAmount = swapFlow.TradingQty;
swapFlow.TradingFeePending = fee;
return NewSwapTrade(swapFlow, client, asset, underlying, floatRate, clientMarginTemplate,clearingAgency);
}
return null;
}
/// <summary>
/// 2条流水处理明细
@@ -1422,95 +1331,5 @@ namespace YLErp.Modules.SwapModule
}
return (0, 0, false, null);
}
/// <summary>
/// 定时任务合成持仓
/// </summary>
/// <param name="flowList"></param>
/// <param name="swapPositions"></param>
/// <param name="clientPosition"></param>
/// <param name="multiplier"></param>
/// <param name="positionType"></param>
public void MergeSwapPositionAvg(List<swap_flow> flowList, List<swap_position> swapPositions, ClientPosition clientPosition, decimal multiplier, int positionType)
{
var hasPayPosition = swapPositions != null && swapPositions.Count > 0;
var posiQty = swapPositions == null ? 0 : swapPositions.Sum(x => x.PosiQuantity);
var flowSames = flowList.Where(x => x.BsType == positionType).OrderBy(o => o.OptTime).ToList();
var flowNegatives = flowList.Where(x => x.BsType != positionType).OrderBy(o => o.OptTime).ToList();
var sameQty = flowSames.Sum(s => s.TradingQty);
var negaQty = flowNegatives.Sum(s => s.TradingQty);
if (sameQty + posiQty < negaQty)
{
var negaPosiType = flowNegatives.First().BsType;
clientPosition.side = negaPosiType - 1;
}
var posiType = clientPosition.id == 0 ? 0 : clientPosition.side;
List<swap_flow> maxFlowClones = new List<swap_flow>(flowSames);
var mergeFlow = new swap_flow_merge();
if (hasPayPosition)//有日终持仓
{
var posiFlows = ConvertToSwapFlow(swapPositions, (int)clientPosition.client_id);
maxFlowClones.AddRange(posiFlows);
maxFlowClones = maxFlowClones.OrderBy(o => o.id).ToList();
sameQty = maxFlowClones.Sum(s => s.TradingQty);
}
var maxQty = sameQty;
var minQty = negaQty;
if (clientPosition.side + 1 != positionType)
{
maxQty = negaQty;
minQty = sameQty;
maxFlowClones = new List<swap_flow>(flowNegatives);
}
maxFlowClones.ForEach(x => { x.OccurTime = DateTime.Now.Date; });
var unwindDeals = GetRemainderFlows(maxFlowClones, minQty, null);
var unwindQty = unwindDeals.Sum(s => s.TradingQty);
if (minQty != 0 && unwindQty < maxQty)
{
var firstFlow = maxFlowClones.First();
var unwindFlowQty = minQty - unwindQty;
var unwindFee = firstFlow.TradingFee * unwindFlowQty / firstFlow.TradingQty;
firstFlow.TradingQty = firstFlow.TradingQty - unwindFlowQty;
firstFlow.TradingFee = firstFlow.TradingFee - unwindFee;
firstFlow.TradingAmount = firstFlow.TradingQty;
}
var mergeList = SummaryFlow(maxFlowClones, false);
mergeFlow = mergeList.Count>0? mergeList.First():new swap_flow_merge();
clientPosition.commission = mergeFlow.TradingFee;
clientPosition.position_qty = mergeFlow.TradingQty / 10000;
clientPosition.position_notional_principal = mergeFlow.TradingQty;
clientPosition.deal_full_price_avg = mergeFlow.TradingAmountAvg * multiplier;
clientPosition.deal_price_avg = mergeFlow.TradingAmountNetAvg * multiplier;
}
/// <summary>
/// 将持仓转换为流水
/// </summary>
/// <param name="positions"></param>
/// <param name="clientId"></param>
/// <returns></returns>
private List<swap_flow> ConvertToSwapFlow(List<swap_position> positions, int clientId)
{
List<swap_flow> flows = new List<swap_flow>();
foreach (var item in positions)
{
swap_flow flow = new swap_flow();
flow.TradingAmount = item.PosiNotionalValue;
flow.TradingAmountAvg = item.PosiGrossPrice;
flow.TradingAmountFeeAvg = item.PosiNetPrice;
flow.TradingAmountNet = item.PosiNetNoFeePrice;
flow.TradingAmountNetFee = item.PosiNetFeePrice;
flow.TradingFee = item.PosiTradingFeePending;
flow.TradingQty = item.PosiQuantity;
flow.UnderlyingCode = item.UnderlyingCode;
flow.OccurTime = DateTime.Now.Date;
flow.ContractSize = item.ContractSize;
flow.ClientId = clientId;
flow.BsType = item.PositionType;
flow.SettleDate = item.PosiStartDate;
flows.Add(flow);
}
return flows;
}
}
}
+4 -4
View File
@@ -70,14 +70,14 @@ namespace YLErp.Web.Hubs
//var dmaFlows = swapFlows.Where(x => dmaClientIds.Contains(x.ClientId)).ToList();
#region DMA合成持仓
if (swapFlows.Count > 0)
if (mergeList.Count > 0)
{
currentStep = $"正在合成簿记:共{swapFlows.Count}条流水";
currentStep = $"正在合成簿记:共{mergeList.Count}条合成流水";
await client.SendAsync("ReceiveMessage", currentStep);
service.MergeAvgModeCompose(swapFlows, req.tradeDate, (dealCount) =>
service.MergeAvgModeCompose(mergeList, req.tradeDate, (dealCount) =>
{
currentStep = $"正在合成簿记:{dealCount}/{swapFlows.Count}";
currentStep = $"正在合成簿记:{dealCount}/{mergeList.Count}";
client.SendAsync("ReceiveMessage", currentStep);
});
currentStep = "簿记合成完毕";