From ad0a8fa0d9d75febc9fb64b3b58f4989bc3d3ed6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=90=B4=E6=96=B9=E6=B5=B7?= Date: Fri, 11 Apr 2025 14:09:47 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=A9=E6=81=AF=E8=AE=A1=E7=AE=97=E5=8F=82?= =?UTF-8?q?=E8=80=83=E7=94=B3=E4=B8=87poc?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Framework/YLErp.Core/ConsGlobal.cs | 10 ++ YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs | 7 +- .../Modules/SwapModule/SwapDealService.cs | 84 +++++---- .../SwapModule/SwapEodPositionService.cs | 164 +++--------------- .../Scripts/app/swaptrade/unwindSwapTrade.js | 10 +- 5 files changed, 97 insertions(+), 178 deletions(-) diff --git a/Framework/YLErp.Core/ConsGlobal.cs b/Framework/YLErp.Core/ConsGlobal.cs index 22ca70d5..f1bbb324 100644 --- a/Framework/YLErp.Core/ConsGlobal.cs +++ b/Framework/YLErp.Core/ConsGlobal.cs @@ -58,6 +58,16 @@ namespace YLErp /// 互换计算岗邮件配置key /// public const string SwapSettlementConfigEmail = "SettlementEmail"; + /// + /// 价格四舍五入保留位数 + /// + + public const int PriceRound = 4; + /// + /// 金额四舍五入保留位数 + /// + + public const int MoneyRound = 4; #region----有效Valid/无效InValid---- diff --git a/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs b/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs index df7b4f86..a6b18619 100644 --- a/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs +++ b/YLErpDAL/BLL/EodSettlement/RealtimePnlCalc.cs @@ -587,11 +587,11 @@ namespace YLErp.BLL.Eod bondDb.SaveChanges(); SetClientPositionPrice(clientPosition); clientPosition.today_profit_loss = clientPosition.swap_market_value - lastPv; - bondDb.SaveChanges(); if (clientPosition.deal_full_price_avg > 0 && enableCalcBongd)//发kafka 获取成交收益率 { - CalcBandPrice(clientPosition); + BondCalcApi(clientPosition); } + bondDb.SaveChanges(); } var sql = $"{nameof(ClientPosition.create_time)}<'{datenow.AddSeconds(-1):yyyy-MM-dd HH:mm:ss}' or {nameof(ClientPosition.position_qty)}=0"; bondDb.BulkDelete(sql); @@ -630,7 +630,7 @@ namespace YLErp.BLL.Eod bondDb.SaveChanges(); SetClientPositionPrice(clientPosition); clientPosition.today_profit_loss = clientPosition.swap_market_value; - bondDb.SaveChanges(); + //发kafka 获取成交收益率 if (clientPosition.deal_full_price_avg > 0 && enableCalcBongd) { @@ -640,6 +640,7 @@ namespace YLErp.BLL.Eod { clientPosition.update_time = DateTime.Now; } + bondDb.SaveChanges(); } } #endregion diff --git a/YLErpDAL/Modules/SwapModule/SwapDealService.cs b/YLErpDAL/Modules/SwapModule/SwapDealService.cs index 9e30f482..bb640927 100644 --- a/YLErpDAL/Modules/SwapModule/SwapDealService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapDealService.cs @@ -93,8 +93,7 @@ namespace YLErp.Modules.SwapModule unwindData.PositionQty = position != null ? position.PosiQuantity : Convert.ToDecimal(td.TradeAmount); unwindData.AnnualDays = tradeExtend == null ? 365 : tradeExtend.ExtendObj.AnnualDays; unwindData.CloseMethod = (int)CloseMethodEnum.全部平仓; - var closePercent = GetUnwindPercent(tradeId); - unwindData.ClosePercent = 1 - closePercent; + unwindData.ClosePercent = 1; unwindData.CloseNotionalValue = unwindData.PosiNotionalValue; unwindData.CloseQty = unwindData.PositionQty; if (position != null) @@ -311,6 +310,7 @@ namespace YLErp.Modules.SwapModule var tradeExtend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == tradeId); List eventTypes = new List() { (int)SwapEventTypeEnum.平仓, (int)SwapEventTypeEnum.互换, (int)SwapEventTypeEnum.自动互换 }; var lastEod = DbContext.eod_swap.Where(x => x.ValueDate < unwindDate && x.SwapTradeId == tradeId).OrderByDescending(o => o.ValueDate).FirstOrDefault(); + var orginPv = lastEod != null ? lastEod.NotionalValue : 0; var _preSetteDate = lastEod == null ? unwindDate.AddDays(-1) : lastEod.ValueDate; List lastEodPositions = new SwapEodPositionService(this).GetPreEodPositions(tradeId, _preSetteDate);//上一交易数据 var posiLongNotionalValue = longPositions.Sum(s => s.PosiNotionalValue);// 剩余名义本金 @@ -319,7 +319,7 @@ namespace YLErp.Modules.SwapModule var posiNotionalValue = stockEqvNotional * closePercent;//剩余名义本金 var grossPrice = realPostitions.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice; bool tdClose = DbContext.swap_flow_event.Any(x => x.SwapTradeId == tradeId && x.UnwindDate == unwindDate && eventTypes.Contains(x.EventType) && x.DataState == (int)SwapFlowDateStateEnum.完成); - interests = GetInterests(td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions, stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue, closePercent, eventType, tdClose, false, grossPrice ?? 0, true, false, false); + interests = GetInterests(td, tradeExtend, valueDate, unwindDate, lastEodPositions, positions, stockEqvNotional, posiLongNotionalValue, posiShortNotionalValue, posiNotionalValue, closePercent, eventType, tdClose, false, grossPrice ?? 0, orginPv, true, false, false); return interests; } /// @@ -355,6 +355,7 @@ namespace YLErp.Modules.SwapModule bool tdClose, bool needPrice, decimal grossPrice, + decimal orginPv, bool add = false, bool calcLast = true, bool settment = true) @@ -377,8 +378,8 @@ namespace YLErp.Modules.SwapModule if (!preDealDate.HasValue) { preEodPosition = new eod_swap_position(); - preEodPosition.PosiStartDate = startDate; - preEodPosition.ValueDate = startDate; + preEodPosition.PosiStartDate = position.PosiStartDate; + preEodPosition.ValueDate = position.PosiStartDate; } var swapIntervalToday = position.SwapIntervalList.Where(x => x.Date <= startDate).OrderByDescending(o => o.Date).FirstOrDefault(); if (position.InterestMode == (int)InterestModeEnum.固定值) @@ -440,7 +441,13 @@ namespace YLErp.Modules.SwapModule { rate = swapIntervalToday.Rate; } - swap_flow_event interest = InitSwapDealInterest(td, valueDate, endDate, rate, positionClone, add, swap, _posiNotionalValue, _closePosiNotionalValue, newClosePercent, annualDays, eventType, preEodPosition, needPrice, settment); + if (preEodPosition.id == 0) + { + preEodPosition.FloatRate = positionClone.FloatRate; + preEodPosition.TdInterestPrincipal = _posiNotionalValue; + preEodPosition.PosiNotionalValue = _posiNotionalValue; + } + swap_flow_event interest = InitSwapDealInterest(td, valueDate, endDate, rate, positionClone, add, swap, _posiNotionalValue, _closePosiNotionalValue, newClosePercent, annualDays, eventType, preEodPosition, needPrice, settment, orginPv); interests.Add(interest); } return interests; @@ -474,7 +481,8 @@ namespace YLErp.Modules.SwapModule int eventType, eod_swap_position preEodPosition, bool needPrice, - bool settment + bool settment, + decimal orginPv ) { DateTime lastSwapDate = preEodPosition.ValueDate; @@ -514,11 +522,11 @@ namespace YLErp.Modules.SwapModule var floateRate = preEodPosition.FloatRate; if (settment)//收盘利息计算 { - CalcDailyCompoundInterestByEod(preEodPosition, endDate, td.StartDate.Value, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, ref InterestAmount, ref TdInterestAmount); + CalcDailyCompoundInterestByEod(preEodPosition, endDate, td.StartDate.Value, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, ref InterestAmount, ref TdInterestAmount); } else { - CalcDailyCompoundInterest(preEodPosition, endDate, td.StartDate.Value, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, ref InterestAmount, ref TdInterestAmount); + CalcDailyCompoundInterest(preEodPosition, endDate, td.StartDate.Value, position, closePosiNotionalValue, posiNotionalValue, interest, annualDays, needPrice, floateRate, closePrecent, orginPv, ref InterestAmount, ref TdInterestAmount); } } else @@ -554,8 +562,8 @@ namespace YLErp.Modules.SwapModule } - interest.InterestAmount = decimal.Parse(InterestAmount.ToString("0.0000")); - interest.TdInterestAmount = decimal.Parse(TdInterestAmount.ToString("0.0000")); + interest.InterestAmount = Math.Round(InterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + interest.TdInterestAmount = Math.Round(TdInterestAmount, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); interest.InterestClosePnL = interest.InterestAmount * interestRatio; } if (add) @@ -576,7 +584,7 @@ namespace YLErp.Modules.SwapModule /// 是否年化 /// 年化天数 /// - public void CalcDailyCompoundInterest(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, ref decimal InterestAmount, ref decimal TdInterestAmount) + public void CalcDailyCompoundInterest(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, ref decimal InterestAmount, ref decimal TdInterestAmount) { DateTime lastSwapDate = preEodPosition.ValueDate; decimal interestProfitSum = preEodPosition.InterestProfitSum; @@ -618,35 +626,36 @@ namespace YLErp.Modules.SwapModule } } - flowEvent.InterestPrincipal = tdDynomicPrincipal; + flowEvent.InterestPrincipal = tdDynomicPrincipal * closePercent; TdInterestPrincipal = tdDynomicPrincipal; } else { - flowEvent.InterestPrincipal = TdInterestPrincipal * closePercent; + flowEvent.InterestPrincipal = (preEodPosition.TdInterestPrincipal + posiPrincipal - orginPv) * closePercent; tdDynomicPrincipal = flowEvent.InterestPrincipal; + TdInterestPrincipal = (preEodPosition.TdInterestPrincipal + posiPrincipal - orginPv); } flowEvent.FloatRate = Convert.ToDecimal(floatRate); var interest1 = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); - var tdinterest1 = tdDynomicPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + var tdinterest1 = TdInterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); if (position.IsAnnualized) { interest1 /= annualDays; tdinterest1 /= annualDays; } - interest += decimal.Parse(interest1.ToString("0.0000")); - tdinterest += decimal.Parse(tdinterest1.ToString("0.0000")); + interest += interest1; + tdinterest += tdinterest1; } - else + else if (lastSwapDate >= rateDate) { interest = interestProfitSum * closePercent; tdinterest = interestProfitSum * closePercent; } } - InterestAmount = interest; - TdInterestAmount = tdinterest; + InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); } /// @@ -661,7 +670,7 @@ namespace YLErp.Modules.SwapModule /// 是否年化 /// 年化天数 /// - public void CalcDailyCompoundInterestByEod(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, ref decimal InterestAmount, ref decimal TdInterestAmount) + public void CalcDailyCompoundInterestByEod(eod_swap_position preEodPosition, DateTime endDate, DateTime tradeDate, swap_position position, decimal principal, decimal posiPrincipal, swap_flow_event flowEvent, int annualDays, bool needPrice, decimal floateRate, decimal closePercent, decimal orginPv, ref decimal InterestAmount, ref decimal TdInterestAmount) { decimal interestProfitSum = preEodPosition.InterestProfitSum; decimal interest = preEodPosition.TdInterestIncome; @@ -687,19 +696,27 @@ namespace YLErp.Modules.SwapModule { throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{fr007RateDate:yyyy年MM月dd日}的价格"); } - flowEvent.InterestPrincipal = tdDynomicPrincipal; + flowEvent.InterestPrincipal = tdDynomicPrincipal * closePercent; + interest = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + tdinterest = tdDynomicPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + if (position.IsAnnualized) + { + interest /= annualDays; + tdinterest /= annualDays; + } } else { - flowEvent.InterestPrincipal = preEodPosition.TdInterestPrincipal * closePercent; - tdDynomicPrincipal = flowEvent.InterestPrincipal; - } - interest = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); - tdinterest = tdDynomicPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); - if (position.IsAnnualized) - { - interest /= annualDays; - tdinterest /= annualDays; + flowEvent.InterestPrincipal = (preEodPosition.TdInterestPrincipal + tdDynomicPrincipal - orginPv) * closePercent; + var interest1 = flowEvent.InterestPrincipal * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + var tdinterest1 = (preEodPosition.TdInterestPrincipal + tdDynomicPrincipal - orginPv) * (flowEvent.InterestRate + Convert.ToDecimal(floatRate)); + if (position.IsAnnualized) + { + interest1 /= annualDays; + tdinterest1 /= annualDays; + } + interest = interest1; + tdinterest = tdinterest1; } } else @@ -707,8 +724,8 @@ namespace YLErp.Modules.SwapModule flowEvent.InterestPrincipal = preEodPosition.TdInterestPrincipal * closePercent; } flowEvent.FloatRate = Convert.ToDecimal(floatRate); - InterestAmount = interest; - TdInterestAmount = tdinterest; + InterestAmount = Math.Round(interest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); + TdInterestAmount = Math.Round(tdinterest, ConsGlobal.PriceRound, MidpointRounding.AwayFromZero); } /// @@ -1320,6 +1337,7 @@ namespace YLErp.Modules.SwapModule } item.PayDate = unwindData.PayDate; item.UnwindDate = unwindData.UnwindDate; + item.EventDate = unwindData.ValueDate; item.EventId = swapEvent.id; DbContext.swap_flow_event.Add(item); } diff --git a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs index ff92f889..460aa950 100644 --- a/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs +++ b/YLErpDAL/Modules/SwapModule/SwapEodPositionService.cs @@ -131,6 +131,7 @@ namespace YLErp.Modules.SwapModule td.trade_extend = tradeExtend; var todyEodPositions = allEodPositions.Where(x => x.ValueDate == settleDate).ToList(); var allPositionQty = realPositions.Sum(x => x.PosiQuantity);//总剩余持仓数量 + var orginPv = eodPositions.Sum(s => s.PosiNotionalValue); if (longShort && td.ExerciseDate.Value == settleDate && allPositionQty != 0)//多空组合判断是否已到到期日且无持仓信息 { throw new Exception($"交易【{td.TradeNumber}】到期扔有持仓信息"); @@ -162,7 +163,7 @@ namespace YLErp.Modules.SwapModule } var grossPrice = curEodPosis.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0; //处理利息腿 - DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice); + DealInterests(interestList, eodPositions, todyEodPositions, settleDate, td, flowEvents, autoInterests, lastEodSwap, posiLongNotional, posiShortNotional, closePosiNotional, grossPrice, orginPv); DealAutoInterests(autoInterests, td, settleDate, preDealDate, posiLongNotional + posiShortNotional); //多空组合判断是否已到到期日且无持仓信息 if (longShort && td.ExerciseDate.Value == settleDate && allPositionQty == 0) @@ -211,50 +212,6 @@ namespace YLErp.Modules.SwapModule DbContext.SaveChanges(); } /// - /// 追加预付金腿归档 - /// - /// - /// - public void SwapEodMarginCompose(DateTime settleDate, IEnumerable ClientIds) - { - var tradePredicate = PredicateBuilder.Create(n => n.ValidState != ConsGlobal.InValid - && n.TradeType == "收益互换" - && n.TradeDate <= settleDate - && n.ExerciseDate >= settleDate - && (n.TradeStatus == ConsTrade.确认成交 || n.UnWindDate >= settleDate) - ); - if (ClientIds != null && ClientIds.Any()) - { - tradePredicate = tradePredicate.And(x => ClientIds.Contains(x.ClientId)); - } - var marginPredicate = PredicateBuilder.Create(n => n.IsInitial && n.HappenDate == settleDate && n.InterestMode == (int)InterestModeEnum.追加预付金 && !n.Invalid); - var query = from p in DbContext.swap_position.Where(marginPredicate) - join t in DbContext.trade.Where(tradePredicate) on p.SwapTradeId equals t.id - select new - { - t, - p - }; - var result = query.ToList(); - var posiIds = result.Select(x => x.p.id).ToList(); - var eodSwapPositions = DbContext.eod_swap_position.Where(x => posiIds.Contains(x.SwapTradeId) && x.ValueDate == settleDate).ToList(); - foreach (var item in result) - { - List interestList = new List() { item.p }; - var td = item.t; - var eodPosi = eodSwapPositions.FirstOrDefault(x => x.PositionId == item.p.id); - var posiLongNotional = eodSwapPositions.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue); - var posiShortNotional = eodSwapPositions.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue); - var grossPrice = eodSwapPositions.Where(x => x.PosiDirection > 0).FirstOrDefault()?.PosiGrossPrice ?? 0; - //处理利息腿 - DealInterest(item.p, eodPosi, settleDate, td, posiLongNotional, posiShortNotional, grossPrice); - } - if (result.Count > 0) - { - DbContext.SaveChanges(); - } - } - /// /// 处理利息腿归档 /// /// 利息腿持仓信息 @@ -277,7 +234,8 @@ namespace YLErp.Modules.SwapModule decimal posiLongNational, decimal posiShortNational, decimal closeNational, - decimal grossPrice) + decimal grossPrice, + decimal orginPv) { var hasClose = flowEvents.Any(x => x.EventType == (int)SwapEventTypeEnum.平仓); var hasSwap = flowEvents.Any(x => x.EventType == (int)SwapEventTypeEnum.互换); @@ -299,7 +257,7 @@ namespace YLErp.Modules.SwapModule { if (!hasClose)//当日无平仓 { - var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiLongNational, posiShortNational, grossPrice); + var _autoInterests = SaveAutoEodInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, lastEodSwap, posiLongNational, posiShortNational, grossPrice, orginPv); if (_autoInterests.Count > 0) { autoInterests.AddRange(_autoInterests); @@ -307,7 +265,7 @@ namespace YLErp.Modules.SwapModule } else { - var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, true, grossPrice); + var _autoInterests = SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, true, grossPrice, orginPv); if (_autoInterests.Count > 0) { autoInterests.AddRange(_autoInterests); @@ -320,38 +278,14 @@ namespace YLErp.Modules.SwapModule } else if (hasClose) { - SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, false, grossPrice); + SaveAutoEodWithCloseInterestPosition(eodPosition, tdEodPosition, interest, td, settleDate, insterval, posiLongNational, posiShortNational, swapEvents, closeNational, false, grossPrice, orginPv); } else//无自动互换、互换/平仓,复制上一日终信息,并计算当日新增利息 { - SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiLongNational, posiShortNational, grossPrice); + SaveEodInterestPositionCopy(eodPosition, tdEodPosition, settleDate, td, interest, lastEodSwap, true, posiLongNational, posiShortNational, grossPrice, orginPv); } } } - - /// - /// 处理利息腿归档 - /// - /// 利息腿持仓信息 - /// 上一日终归档持仓信息 - /// 当日归档持仓信息 - /// 当前结算日期 - /// 互换交易主信息 - /// 当日平仓/互换信息 - /// 自动互换集合 - /// 多空组合平仓利息腿信息 - /// 上一日终框架合约 - private void DealInterest(swap_position interest, - eod_swap_position tdEodPosition, - DateTime settleDate, - trade td, - decimal posiLongNational, - decimal posiShortNational, - decimal grossPrice) - { - var insterval = interest.SwapIntervalList.FirstOrDefault(x => x.Date == settleDate && x.Settlement == 1);//自动互换观察日信息 - SaveAutoEodInterestPosition(null, tdEodPosition, interest, td, settleDate, insterval, null, posiLongNational, posiShortNational, grossPrice); - } /// /// 处理浮动腿归档 /// @@ -758,7 +692,7 @@ namespace YLErp.Modules.SwapModule /// 上一平仓/互换日期 /// 当日平仓金额 /// 上一日终框架合约估值 - private List SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiLongNotional, decimal posiShortNational, decimal grossPrice) + private List SaveAutoEodInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, eod_swap lastEodSwap, decimal posiLongNotional, decimal posiShortNational, decimal grossPrice, decimal orginPv) { var tradeExtend = td.trade_extend.ExtendObj; @@ -792,7 +726,11 @@ namespace YLErp.Modules.SwapModule positions.Add(position); List preEodPositions = new List(); preEodPositions.Add(eodPayPosition); - var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, posiNotionalValue, closePercent, (int)SwapEventTypeEnum.自动互换, false, true, grossPrice, true); + if (position.InterestMode == (int)InterestModeEnum.固定值) + { + orginPv = eodPayPosition.InterestPrincipalFix; + } + var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, posiNotionalValue, closePercent, (int)SwapEventTypeEnum.自动互换, false, true, grossPrice, orginPv, true); decimal InterestAmount = interests.Sum(x => x.InterestAmount); decimal TdInterestAmount = interests.Sum(x => x.TdInterestAmount); @@ -855,7 +793,7 @@ namespace YLErp.Modules.SwapModule /// 当日平仓金额 /// 上一日终框架合约估值 /// 平仓主信息 - private List SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiLongNotional, decimal posiShortNational, List flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice) + private List SaveAutoEodWithCloseInterestPosition(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, swap_position position, trade td, DateTime valueDate, IntervalModel interval, decimal posiLongNotional, decimal posiShortNational, List flowEvents, decimal closeNational, bool autoSwap, decimal grossPrice, decimal orginPv) { var tradeExtend = td.trade_extend.ExtendObj; @@ -879,6 +817,10 @@ namespace YLErp.Modules.SwapModule newEodPayPosition = eodPayPosition.Clone(); newEodPayPosition.id = 0; } + if (position.InterestMode == (int)InterestModeEnum.固定值) + { + orginPv = eodPayPosition.InterestPrincipalFix; + } decimal closePercent = oriPosiNotionalValue == 0 ? 0 : closeNational / oriPosiNotionalValue; var eventType = autoSwap ? (int)SwapEventTypeEnum.自动互换 : (int)SwapEventTypeEnum.平仓; bool longShort = td.StructureType == ClientMarginTypeEnum.多空组合.ToString(); @@ -894,7 +836,7 @@ namespace YLErp.Modules.SwapModule positions.Add(position); List preEodPositions = new List(); preEodPositions.Add(eodPayPosition); - var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, closeNational, 1, eventType, false, true, grossPrice, true); + var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNotional, posiShortNational, closeNational, 1, eventType, false, true, grossPrice, orginPv, true); decimal TdInterestAmount = interests.Sum(x => x.TdInterestAmount); newEodPayPosition.ValueDate = valueDate; @@ -968,7 +910,7 @@ namespace YLErp.Modules.SwapModule /// 上一交易日 /// 当前结算日 /// 互换交易主干 - private void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiLongNational, decimal posiShortNational, decimal grossPrice) + private void SaveEodInterestPositionCopy(eod_swap_position eodPayPosition, eod_swap_position newEodPayPosition, DateTime valueDate, trade td, swap_position position, eod_swap lastEodSwap, bool needPrice, decimal posiLongNational, decimal posiShortNational, decimal grossPrice, decimal orginPv) { List intervals = position.SwapIntervalList; var tradeExtend = td.trade_extend.ExtendObj; @@ -1003,7 +945,10 @@ namespace YLErp.Modules.SwapModule newEodPayPosition.id = 0; newEodPayPosition.PositionId = position.id; } - + if (position.InterestMode == (int)InterestModeEnum.固定值) + { + orginPv = eodPayPosition.InterestPrincipalFix; + } bool longShort = td.StructureType == ClientMarginTypeEnum.多空组合.ToString(); decimal oriPosiNotionalValue = posiLongNational + posiShortNational; decimal posiNotionalValue = oriPosiNotionalValue; @@ -1034,7 +979,7 @@ namespace YLErp.Modules.SwapModule { preEodPositions.Add(eodPayPosition); } - var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNational, posiShortNational, posiNotionalValue, closePercent, 0, false, needPrice, grossPrice); + var interests = new SwapDealService(this).GetInterests(td, td.trade_extend, valueDate, valueDate, preEodPositions, positions, posiNotionalValue, posiLongNational, posiShortNational, posiNotionalValue, closePercent, 0, false, needPrice, grossPrice, orginPv); UpdateDbOption(newEodPayPosition); newEodPayPosition.PosiStatus = 0; @@ -2039,43 +1984,7 @@ namespace YLErp.Modules.SwapModule return; } } - /// - /// 确认交易后,生成eod数据 - /// - /// - public void InitSaveEodSwapPosition(trade td) - { - //if (td.StartDate > td.TradeDate) - //{ - // return; - //} - var positions = DbContext.swap_position.Where(x => x.SwapTradeId == td.id && x.IsInitial && !x.Invalid).ToList(); - var posiList = positions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode)).ToList(); - var interestList = positions.Where(x => string.IsNullOrEmpty(x.UnderlyingCode)).ToList(); - var eodSwapPostions = DbContext.eod_swap_position.Where(x => x.SwapTradeId == td.id); - var eodSwaps = DbContext.eod_swap.Where(x => x.SwapTradeId == td.id); - td.trade_extend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == td.id); - List eventTypes = new List() { (int)SwapFlowEventTypeEnum.平仓, (int)SwapFlowEventTypeEnum.互换, (int)SwapFlowEventTypeEnum.自动互换, (int)SwapFlowEventTypeEnum.开仓 }; - var flowEvents = GetSwapFlowEvents(td.id, td.StartDate.Value, eventTypes);//当日平仓/互换/自动互换信息 - DbContext.eod_swap_position.RemoveRange(eodSwapPostions); - DbContext.eod_swap.RemoveRange(eodSwaps); - var preday = QdpCalendarHelper.GetNonHolidayDefore(td.StartDate.Value.AddDays(-1)); - var preSettleDate= QdpCalendarHelper.GetNonHolidayDefore(td.TradeDate.Value.AddDays(-1)); - var posiLongNotional = positions.Where(s => s.PositionType == (int)PositionTypeFlag.Long).Sum(s => s.PosiNotionalValue); - var posiShortNotional = positions.Where(s => s.PositionType == (int)PositionTypeFlag.Short).Sum(s => s.PosiNotionalValue); - var grossPrice = posiList.FirstOrDefault()?.PosiGrossPrice ?? 0; - foreach (var item in interestList) - { - SaveEodInterestPositionCopy(null, null, td.StartDate.Value, td, item, null, false, posiLongNotional, posiShortNotional, grossPrice); - } - foreach (var item in posiList) - { - SaveCurrentEodInitalPosi(item, td, td.StartDate.Value, preday, flowEvents); - } - DbContext.SaveChanges(); - SaveEodSwap(td, td.StartDate.Value, preSettleDate); - DbContext.SaveChanges(); - } + /// /// 获取客户互换持仓信息 /// @@ -2093,25 +2002,6 @@ namespace YLErp.Modules.SwapModule var tradeExtends = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList(); return ConvertEodPnl(eodSwaps, trades, tradeExtends); } - /// - /// 获取客户互换历史持仓信息 - /// - /// - /// - /// - public List GetSwapHistoryPositions(int clientId, DateTime valueDate) - { - var trades = DbContext.trade.Where(x => x.TradeType == "收益互换" - && x.ClientId == clientId - && x.ExerciseDate <= valueDate - && ConsTrade.TradeCompleteStatus.Contains(x.TradeStatus) - && x.ValidState != "InValid").ToList(); - var tradeIds = trades.Select(s => s.id).ToList(); - var eodSwaps = DbContext.eod_swap_position.Where(x => tradeIds.Contains(x.SwapTradeId) && x.ValueDate == valueDate).ToList(); - var tradeExtends = DbContext.trade_extend.Where(x => tradeIds.Contains(x.TradeId)).ToList(); - return ConvertEodPnl(eodSwaps, trades, tradeExtends); - - } private List ConvertEodPnl(List eodSwaps, List trades, List tradeExtends) { diff --git a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js index fc4c4f82..9d5f79d8 100644 --- a/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js +++ b/YLErpWeb/wwwroot/Scripts/app/swaptrade/unwindSwapTrade.js @@ -119,7 +119,7 @@ const vue = new Vue({ this.deal.CloseNotionalValue = otcformat.trading.StockEqvNotional(parseFloat(this.deal.PosiNotionalValue)); this.deal.CloseQty = this.deal.PositionQty; } else { - this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.NotionalQty) * parseFloat(this.deal.ClosePercent)); + this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.PositionQty) * parseFloat(this.deal.ClosePercent)); } this.calcTradingFeePending(); this.getInterestList(); @@ -133,7 +133,7 @@ const vue = new Vue({ main.message("平仓数量不能超过持仓数量"); return; } - this.deal.ClosePercent = otcformat.fixed6(parseFloat(this.deal.CloseQty) / parseFloat(this.deal.NotionalQty)); + this.deal.ClosePercent = otcformat.fixed6(parseFloat(this.deal.CloseQty) / parseFloat(this.deal.PositionQty)); if (parseFloat(this.deal.CloseQty) == parseFloat(this.deal.PositionQty)) { this.deal.CloseMethod = 1; } else { @@ -150,7 +150,7 @@ const vue = new Vue({ this.deal.ClosePercent = this.oriClosePercent; return; } - this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.NotionalQty) * parseFloat(this.deal.ClosePercent)); + this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.PositionQty) * parseFloat(this.deal.ClosePercent)); this.deal.CloseNotionalValue = otcformat.trading.StockEqvNotional(parseFloat(this.deal.ClosePercent) * parseFloat(this.deal.NotionalValue)); if (parseFloat(this.deal.CloseNotionalValue) == parseFloat(this.deal.PosiNotionalValue)) { this.floatPosition.CloseMethod = 1; @@ -168,7 +168,7 @@ const vue = new Vue({ return; } this.deal.ClosePercent = otcformat.fixed6(parseFloat(this.deal.CloseNotionalValue) / parseFloat(this.deal.NotionalValue)); - this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.NotionalQty) * parseFloat(this.deal.ClosePercent)); + this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.PositionQty) * parseFloat(this.deal.ClosePercent)); this.calcTradingFeePending(); this.getInterestList(); this.calcFloatClosePnl(); @@ -194,7 +194,7 @@ const vue = new Vue({ let longRatio = thisObj.floatPosition.PositionType == 1 ? 1 : -1; let TradingFee = thisObj.floatPosition.TradingFee == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFee); let TradingFeePending = thisObj.floatPosition.TradingFeePending == "" ? 0 : parseFloat(thisObj.floatPosition.TradingFeePending); - thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseNotionalValue * (thisObj.floatPosition.TradingAmountAvg - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000; + thisObj.floatPosition.MarkClosePnl = Math.round(thisObj.deal.CloseQty * (thisObj.floatPosition.TradingAmountAvg - thisObj.initPosiNetPrice) * floatRatio * longRatio * 10000) / 10000; thisObj.floatPosition.MarkClosePnl = Number(thisObj.floatPosition.MarkClosePnl.toFixed(2)); thisObj.floatPosition.MarkClosePnl = thisObj.floatPosition.MarkClosePnl + (TradingFee + TradingFeePending) * floatRatio * -1 + parseFloat(thisObj.floatPosition.DividendIn); thisObj.floatPosition.MarkClosePnl = otcformat.trading.StockEqvNotional(thisObj.floatPosition.MarkClosePnl);