名义本金算价格

This commit is contained in:
吴方海
2025-04-11 16:25:46 +08:00
parent ad0a8fa0d9
commit cbe8b2dc91
10 changed files with 214 additions and 388 deletions
+10 -83
View File
@@ -837,7 +837,7 @@ namespace YLErp.Modules.SwapModule
unwindData.AnnualDays = tradeExtend == null ? 365 : tradeExtend.ExtendObj.AnnualDays;
unwindData.CloseMethod = unwindQty == unwindData.PositionQty ? (int)CloseMethodEnum. : (int)CloseMethodEnum.;
unwindData.ClosePercent = unwindData.PositionQty == 0 ? 0 : unwindPercent;
unwindData.CloseNotionalValue = unwindData.PosiNotionalValue* unwindPercent;
unwindData.CloseNotionalValue = position == null ? 0 : unwindQty * position.PosiGrossPrice * position.ContractSize;
unwindData.CloseQty = unwindQty;
if (position != null)
{
@@ -867,9 +867,9 @@ namespace YLErp.Modules.SwapModule
floatEvent.TradingFeePending = position.PosiTradingFeePending * unwindData.ClosePercent;
var mergeClosePercent = mergeQty == 0 ? 0 : unwindQty / mergeQty;
floatEvent.TradingFee = penddingFee * mergeClosePercent;
floatEvent.MarkClosePnl = (unwindPriceFee - position.PosiNetPrice) * unwindQty * floatRatio * longRatio;
floatEvent.MarkClosePnl = decimal.Parse(floatEvent.MarkClosePnl.ToString("0.00"));
floatEvent.TradingAmount = floatEvent.Quantity * floatEvent.ContractSize;
floatEvent.MarkClosePnl = (unwindPrice - position.PosiGrossPrice) * unwindQty * floatRatio * longRatio;
floatEvent.MarkClosePnl = Math.Round(floatEvent.MarkClosePnl + (floatEvent.TradingFee * floatRatio * -1), ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
floatEvent.TradingAmount = unwindPrice * floatEvent.Quantity * floatEvent.ContractSize;
floatEvent.OptLog = "流水自动";
floatEvent.ClientId = td.ClientId;
floatEvent.SetOpt(UserInfo);
@@ -1038,10 +1038,10 @@ namespace YLErp.Modules.SwapModule
{
AddClientCashInCashOut(td, Convert.ToDouble(unwindData.SwapMarginAmount), ClientCashInCashOut._应付预付金, unwindData.ValueDate);
}
if (unwindData.SwapMarginRebatePnl != 0)
{
AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut._预付金返息, unwindData.ValueDate);
}
//if (unwindData.SwapMarginRebatePnl != 0)
//{
// AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapMarginRebatePnl), ClientCashInCashOut.系统操作_预付金返息, unwindData.ValueDate);
//}
var flowList = new List<swap_flow_event>(unwindData.FlowEvents);
var eventId = SaveSwapDeal(unwindData, (int)SwapEventTypeEnum., clientCashId, actionMsg);
if (unwindData.CloseMethod == (int)CloseMethodEnum.)
@@ -1376,15 +1376,9 @@ namespace YLErp.Modules.SwapModule
{
if (!string.IsNullOrEmpty(position.UnderlyingCode))
{
var dealFloat = flowList.FirstOrDefault(x => !string.IsNullOrEmpty(x.UnderlyingCode));
if (dealFloat != null)
{
decimal ratio = dealFloat.EventType == (int)SwapFlowEventTypeEnum. ? -1m : 1m;
position.PosiTradingFeePending += dealFloat.TradingFeePending * ratio;
position.PosiDividendIncome += dealFloat.DividendPending;
}
position.PosiQuantity -= unwindData.CloseQty;
position.PosiNotionalValue = position.PosiQuantity * position.ContractSize;
position.PosiNotionalValue = position.PosiGrossPrice * position.PosiQuantity * position.ContractSize;
position.PosiTradingFee -= position.PosiTradingFee * unwindData.ClosePercent;
}
else
{
@@ -1401,73 +1395,6 @@ namespace YLErp.Modules.SwapModule
}
}
}
/// <summary>
/// 单标的互换更新实时持仓信息
/// </summary>
/// <param name="deal_Floats"></param>
/// <param name="deal_Interests"></param>
/// <param name="positions"></param>
public void UpdateInitalPosition(DateTime valueDate, trade td, List<swap_position> positions, List<swap_flow_event> swpFlowEvents)
{
var preSettleDate = GetPreValueDate(valueDate);//上一交易日期
var realPositions = positions.Where(x => !x.IsInitial);
var originalPositions = positions.Where(x => x.IsInitial);
var unwindFlowEvents = swpFlowEvents.Where(x => x.EventType == (int)SwapFlowEventTypeEnum. || x.EventType == (int)SwapFlowEventTypeEnum.).ToList();
List<eod_swap_position> preEodSwapPositions = DbContext.eod_swap_position.Where(x => !x.Invalid && x.SwapTradeId == td.id && valueDate == preSettleDate).ToList();
foreach (var position in realPositions)
{
var currEod = new eod_swap_position() { ContractSize = position.ContractSize };
var eod = preEodSwapPositions.FirstOrDefault(x => x.PositionId == position.PositionId);
if (eod == null)
{
eod = new eod_swap_position()
{
ContractSize = position.ContractSize,
PositionType = position.PositionType,
PosiDirection = position.PosiDirection,
PosiFeePending = 0,
PosiNetPrice = position.PosiNetPrice,
PosiGrossPrice = position.PosiGrossPrice,
PosiNetFeePrice = position.PosiNetFeePrice,
PosiNetNoFeePrice = position.PosiNetNoFeePrice,
};
}
new SwapEodPositionService(UserInfo).SetPriceInfoByFlowEvent(eod, currEod, unwindFlowEvents, position);
var oriPosition = originalPositions.FirstOrDefault(x => x.id == position.PositionId);
position.InterestAmount = currEod.RealizedInterest;
position.InterestFeePending = currEod.InterestFeePending;
position.PosiTradingFeePending = currEod.PosiFeePending;
position.PosiDividendIncome = currEod.PosiDividendSum;
position.PosiQuantity = currEod.PosiQuantity;
position.PosiNetPrice = currEod.PosiNetPrice;
position.PosiGrossPrice = currEod.PosiGrossPrice;
position.PosiNetFeePrice = currEod.PosiNetFeePrice;
position.PosiNetNoFeePrice = currEod.PosiNetNoFeePrice;
position.PosiNotionalValue = currEod.PosiNotionalValue;
td.StockEqvNotional = Convert.ToDouble(position.PosiNotionalValue);
td.TradeAmount = Convert.ToDouble(position.PosiQuantity);
}
}
/// <summary>
/// 获取标的平仓比例
/// </summary>
/// <param name="tradeId"></param>
/// <returns></returns>
private decimal GetUnwindPercent(int tradeId)
{
var swapEvents = DbContext.swap_event.Where(x => x.SwapTradeId == tradeId && !x.Invalid && x.EventType == (int)SwapEventTypeEnum.).ToList();
decimal unwindPercent = 0;
foreach (var swapEvent in swapEvents)
{
if (!string.IsNullOrEmpty(swapEvent.EventData))
{
swapEvent.unwindData = JsonConvert.DeserializeObject<UnwindData>(swapEvent.EventData);
unwindPercent += swapEvent.unwindData.ClosePercent;
}
}
return unwindPercent;
}
}
}
@@ -156,11 +156,7 @@ namespace YLErp.Modules.SwapModule
var curEodPosis = DealFloatPositions(posiList, realPosiList, eodPositions, todyEodPositions, settleDate, td, preSettleDate, flowEvents);
var posiLongNotional = curEodPosis.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue);
var posiShortNotional = curEodPosis.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue);
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize);
if (longShort)
{
closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiNetPrice);
}
var closePosiNotional = curEodPosis.Where(s => s.TdCloseQty > 0).Sum(s => s.TdCloseQty * s.ContractSize * s.PosiNetPrice);
var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0;
//处理利息腿
DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv);
@@ -314,20 +310,9 @@ namespace YLErp.Modules.SwapModule
var unwindEvents = flowEvents.Where(x => x.PositionId == posi.id).ToList();//当前日平仓信息
var realPosition = realPosiList.FirstOrDefault(s => s.PositionId == posi.id);
eod_swap_position eodPosi = new eod_swap_position();
if (eodPosition == null || td.StartDate == settleDate)
if (eodPosition == null || td.TradeDate == settleDate)
{
if (tdEodPosition == null)//第一次生成归档信息
{
eodPosi = SaveCurrentEodInitalPosi(posi, td, settleDate, preSettleDate, unwindEvents);
}
else
{
tdEodPosition.PosiFeePending = posi.PosiTradingFeePending;
tdEodPosition.PosiNotionalValue = tdEodPosition.PosiQuantity * tdEodPosition.ContractSize;
tdEodPosition.PosiNetFeePrice = posi.PosiNetFeePrice;
tdEodPosition.PosiNetNoFeePrice = posi.PosiNetNoFeePrice;
}
eodPosi = SaveCurrentEodInitalPosi(posi, td, settleDate, preSettleDate, unwindEvents);
}
else if (unwindEvents.Count() == 0)
{
@@ -1276,12 +1261,12 @@ namespace YLErp.Modules.SwapModule
curretEod.PosiNetFeePrice = position.PosiNetFeePrice;
curretEod.PosiNetNoFeePrice = position.PosiNetNoFeePrice;
curretEod.PosiQuantity = position.PosiQuantity;
curretEod.PosiTradingFee = position.PosiTradingFee;
curretEod.PosiTradingFee = -position.PosiTradingFee * directionRatio;
}
else
{
var eventTradingFee = unwindEvents.Where(x => x.EventType == (int)SwapFlowEventTypeEnum. || x.EventType == (int)SwapFlowEventTypeEnum.).Sum(s => s.TradingFeePending * (s.EventType == (int)SwapFlowEventTypeEnum. ? 1 : -1));
curretEod.PosiFeePending = eod.PosiFeePending + eventTradingFee;
var eventTradingFee = openFlowEvents.Sum(s => s.TradingFee);
curretEod.PosiTradingFee = eod.PosiTradingFee - eventTradingFee * directionRatio;
if (openFlowEvents.Count() == 0)
{
curretEod.PosiNetPrice = eod.PosiNetPrice;
@@ -1297,12 +1282,16 @@ namespace YLErp.Modules.SwapModule
{
posiQty = 0;
}
curretEod.PosiGrossPrice = (eod.PosiGrossPrice * posiQty + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountAvg)) / (eod.PosiQuantity + openQty);
curretEod.PosiNetNoFeePrice = (eod.PosiNetNoFeePrice * posiQty + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountNetAvg)) / (eod.PosiQuantity + openQty);
curretEod.PosiNetFeePrice = curretEod.PosiQuantity == 0 ? eod.PosiNetFeePrice : curretEod.PosiNetNoFeePrice + curretEod.PosiFeePending / curretEod.PosiQuantity * shortRatio;
curretEod.PosiNetPrice = curretEod.PosiQuantity == 0 ? eod.PosiNetPrice : curretEod.PosiGrossPrice + curretEod.PosiFeePending / curretEod.PosiQuantity * shortRatio;
curretEod.PosiGrossPrice = (eod.PosiGrossPrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountAvg)) / (eod.PosiQuantity + openQty);
curretEod.PosiGrossPrice = Math.Round(curretEod.PosiGrossPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
curretEod.PosiNetPrice = (eod.PosiNetPrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountFeeAvg)) / (eod.PosiQuantity + openQty);
curretEod.PosiNetPrice = Math.Round(curretEod.PosiNetPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
curretEod.PosiNetNoFeePrice = (eod.PosiNetNoFeePrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountNetAvg)) / (eod.PosiQuantity + openQty);
curretEod.PosiNetNoFeePrice = Math.Round(curretEod.PosiNetNoFeePrice ?? 0, 10, MidpointRounding.AwayFromZero);
curretEod.PosiNetFeePrice = (eod.PosiNetFeePrice * eod.PosiQuantity + openFlowEvents.Sum(a => a.Quantity * a.TradingAmountNetFeeAvg)) / (eod.PosiQuantity + openQty);
curretEod.PosiNetFeePrice = Math.Round(curretEod.PosiNetFeePrice ?? 0, 10, MidpointRounding.AwayFromZero);
}
curretEod.PosiNotionalValue = curretEod.PosiQuantity * curretEod.ContractSize;
curretEod.PosiNotionalValue = curretEod.PosiGrossPrice * curretEod.PosiQuantity * curretEod.ContractSize;
curretEod.TdPosiDividend = unwindEvents.Sum(x => x.DividendIn) * directionRatio;
//curretEod.TdCloseFee = unwindEvents.Sum(x => x.TradingFee);
curretEod.TdCloseQty = unwindQty;
@@ -341,15 +341,19 @@ namespace YLErp.Modules.SwapModule
DataState = (int)SwapFlowDateStateEnum.,
ContractSize = swapflow.ContractSize,
ClientId = swapflow.ClientId,
TradingAmount = gourpItem.Sum(s => s.TradingAmount),
};
int tradeSide = swap_flow_summary.BsType == (int)EnumDirection.Long ? 1 : -1;
swap_flow_summary.FirstFlowTime = swapflow.OptTime;
swap_flow_summary.SettleDate = gourpItem.Max(s => s.SettleDate);
swap_flow_summary.TradingAmount = swap_flow_summary.TradingQty * swap_flow_summary.ContractSize;
swap_flow_summary.TradingAmountAvg = swap_flow_summary.TradingQty == 0 ? 0 : gourpItem.Sum(s => s.TradingAmountAvg * s.TradingQty) / swap_flow_summary.TradingQty;
swap_flow_summary.TradingAmountFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountAvg : swap_flow_summary.TradingAmountAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty;
swap_flow_summary.TradingAmountAvg = Math.Round(swap_flow_summary.TradingAmountAvg, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
swap_flow_summary.TradingAmountFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountAvg : swap_flow_summary.TradingAmountAvg + swap_flow_summary.TradingFee * tradeSide / swap_flow_summary.TradingQty;
swap_flow_summary.TradingAmountFeeAvg = Math.Round(swap_flow_summary.TradingAmountFeeAvg, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
swap_flow_summary.TradingAmountNetAvg = swap_flow_summary.TradingQty == 0 ? 0 : gourpItem.Sum(s => s.TradingAmountNet * s.TradingQty) / swap_flow_summary.TradingQty;
swap_flow_summary.TradingAmountNetFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountNetAvg : swap_flow_summary.TradingAmountNetAvg + swap_flow_summary.TradingFeePending * tradeSide / swap_flow_summary.TradingQty;
swap_flow_summary.TradingAmountNetAvg = Math.Round(swap_flow_summary.TradingAmountNetAvg ?? 0, 10);
swap_flow_summary.TradingAmountNetFeeAvg = swap_flow_summary.TradingQty == 0 ? swap_flow_summary.TradingAmountNetAvg : swap_flow_summary.TradingAmountNetAvg + swap_flow_summary.TradingFee * tradeSide / swap_flow_summary.TradingQty;
swap_flow_summary.TradingAmountNetFeeAvg = Math.Round(swap_flow_summary.TradingAmountNetFeeAvg ?? 0, 10);
swap_flow_summary.SetOpt(UserInfo);
if (save)
{
@@ -114,32 +114,6 @@ namespace YLErp.Modules.SwapModule
return dbTrade;
}
/// <summary>
/// 生成推送记录给衡泰
/// </summary>
/// <param name="add"></param>
/// <param name="td"></param>
public void AddPushLog(trade td)
{
bool longShort = td.StructureType == "多空组合";
if (!longShort)
{
AddSinglePushLog(td);
}
}
/// <summary>
/// 生成非多空组合记录
/// </summary>
/// <param name="add"></param>
/// <param name="td"></param>
/// <param name="posiPositions"></param>
public void AddSinglePushLog(trade td)
{
var marginModes = new int[] { (int)InterestModeEnum., (int)InterestModeEnum. };
var positions = DbContext.swap_position.Where(x => x.SwapTradeId == td.id && x.IsInitial && !x.Invalid).ToList();
td.swap_positions = positions.Where(x => marginModes.Contains(x.InterestMode)).ToList();
var posiPositions = positions.Where(x => x.PosiDirection > 0).ToList();
}
/// <summary>
/// 单标的生成开仓事件
/// </summary>
/// <param name="td"></param>
@@ -254,20 +228,6 @@ namespace YLErp.Modules.SwapModule
{
var dbTrade = req.Clone();
DbContext.trade.Add(dbTrade);
//申万交易编号特殊处理(如果交易编号是用户手动输入时)
if (!tradeNumberGenerated && PS.Config.Is申万)
{
var client = DataCacheProvider.GetClientDataSource().GetData(dbTrade.ClientId);
if (client?.Code != null && dbTrade.TradeNumber.StartsWith(client.Code))
{
var canParseInt = int.TryParse(dbTrade.TradeNumber.Substring(client.Code.Length), out var contractNo);
if (canParseInt && contractNo > (client.CurrentContractNo ?? 0))
{
client.CurrentContractNo = contractNo;
}
}
}
InnerSaveTrade(true, dbTrade, "");
return dbTrade;
@@ -413,10 +373,8 @@ namespace YLErp.Modules.SwapModule
PosiNetFeePrice = flowMerge.TradingAmountNetFeeAvg ?? 0,
PosiNetNoFeePrice = flowMerge.TradingAmountNetAvg ?? 0,
PosiQuantity = flowMerge.TradingQtyAbs,
PosiNotionalValue = flowMerge.TradingQtyAbs * flowMerge.ContractSize,
PosiNotionalValue = flowMerge.TradingAmountAvg * flowMerge.TradingQtyAbs * flowMerge.ContractSize,
PosiTradingFeePending = flowMerge.TradingFeePending,
//PosiTradingFee = flowMerge.TradingFee,
//PosiTradingFeeUnit = flowMerge.TradingQtyAbs == 0 ? 0 : flowMerge.TradingFee * flowMerge.ContractSize / flowMerge.TradingQtyAbs,
PosiTradingFee = 0,
PosiTradingFeeUnit = 0,
SwapTradeId = td.id,
@@ -700,10 +658,6 @@ namespace YLErp.Modules.SwapModule
new TradeDocumentDataService(this).DeleteBooksAfterEditTrade(dbTrade);
}
int eventType = isAddNew ? (int)SwapEventTypeEnum. : (int)SwapEventTypeEnum.;
if (!string.IsNullOrEmpty(changsStr))
{
changsStr = new DatatraceQueryService(UserInfo).ReplaceDataChanges(new trade(), changsStr);
}
new SwapEventService(UserInfo).AddSwapEventDate(dbTrade.TradeDate.Value, dbTrade.id, eventType, "", 0, true, "", true);
DbContext.SaveChanges();
}
@@ -1435,10 +1389,9 @@ namespace YLErp.Modules.SwapModule
position.UnderlyingInstrumentType = swap.UnderlyingInstrumentType;
position.PosiDirection = swap.PosiDirection;
position.PosiGrossPrice = swap.PosiGrossPrice;
position.PosiNetPrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiGrossPrice + (position.PosiTradingFeePending / swap.PosiQuantity) * ratio);
position.PosiNetNoFeePrice = swap.PosiNetNoFeePrice;
position.PosiNetFeePrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiNetNoFeePrice + (position.PosiTradingFeePending / swap.PosiQuantity) * ratio);
position.PosiNotionalValue = swap.PosiQuantity * swap.ContractSize;
position.PosiNetPrice = swap.PosiQuantity == 0 ? 0 : (swap.PosiGrossPrice + (position.PosiTradingFee / swap.PosiQuantity) * ratio);
position.PosiNetPrice = Math.Round(position.PosiNetPrice, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero);
position.PosiNotionalValue = position.PosiGrossPrice * swap.PosiQuantity * swap.ContractSize;
position.PosiQuantity = swap.PosiQuantity;
position.InterestDirection = swap.InterestDirection;
position.InterestMode = swap.InterestMode;
@@ -1570,7 +1523,6 @@ namespace YLErp.Modules.SwapModule
InvalidTradeOptionDatasByDate(tradeId, valueDate, backToBegin);
swapEventService.AddSwapEventDate(valueDate, tradeId, (int)SwapEventTypeEnum.退, string.Empty, 0, false, $"交易回退至{valueDate:yyyy年MM月dd日}");
DbContext.SaveChanges();
AddPushLog(td);
if (del)
{
new TradeRiskCheckLogService(UserInfo).DeleteLog(td.TradeNumber, valueDate);//重置风控记录
@@ -1708,6 +1660,7 @@ namespace YLErp.Modules.SwapModule
{
posi.InterestAmount = eodPosi.RealizedInterest;
posi.InterestFeePending = eodPosi.InterestFeePending;
posi.InterestPrincipalFix= eodPosi.InterestPrincipalFix;
posi.PosiTradingFeePending = eodPosi.PosiFeePending;
posi.PosiDividendIncome = eodPosi.PosiDividendSum;
posi.PosiQuantity = eodPosi.PosiQuantity;
@@ -1731,8 +1684,6 @@ namespace YLErp.Modules.SwapModule
var clientCashs = DbContext.ClientCashInCashOut.Where(x => x.TradeId == td.id && x.HappenDate >= valueDate).ToList();
DbContext.ClientCashInCashOut.RemoveRange(clientCashs);
DbContext.SaveChanges();
var marginPosis = swapPositions.Where(x => x.HappenDate <= valueDate || x.InterestMode == (int)InterestModeEnum.).ToList();
ResetMarginAmount(td, valueDate, marginPosis);
}
/// <summary>
/// 多空组合回到初始