fix: 流水的分红计算

This commit is contained in:
gongpei
2025-10-23 17:10:05 +08:00
parent 866f13d85e
commit f5463e4a57
2 changed files with 25 additions and 23 deletions
@@ -102,6 +102,7 @@ namespace YLErp.DBModels
/// <summary>
/// 更新时间
/// </summary>
[DisplayName("更新时间")]
[Column("update_time")]
public DateTime update_time { get; set; }
}
+24 -23
View File
@@ -9,6 +9,7 @@ using OfficeOpenXml.Drawing.Controls;
using Org.BouncyCastle.Asn1.Ocsp;
using Qdp.Pricing.Base.Implementations;
using Qdp.Pricing.Core.Modules;
using Qdp.Pricing.Library.Base.Utilities;
using System.Linq.Expressions;
using YLErp.BLL;
using YLErp.BLL.Eod;
@@ -320,7 +321,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, orginPv, 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;
}
/// <summary>
@@ -401,7 +402,7 @@ namespace YLErp.Modules.SwapModule
}
else if (position.InterestMode == (int)InterestModeEnum.)
{
_closePosiNotionalValue = _posiNotionalValue * closePrecent;
_closePosiNotionalValue = _posiNotionalValue * closePrecent;
_posiNotionalValue = _posiNotionalValue;
}
else if (position.InterestMode == (int)InterestModeEnum. || position.InterestMode == (int)InterestModeEnum.)
@@ -434,7 +435,7 @@ namespace YLErp.Modules.SwapModule
position.FloatRate = Convert.ToDecimal(floatRate);
positionClone.FloatRate = position.FloatRate;
}
else if(!swap)
else if (!swap)
{
throw new Exception($"获取不到{position.FloatRateUnderlyingCode}在{rateDate:yyyy年MM月dd日}的价格");
}
@@ -770,7 +771,7 @@ namespace YLErp.Modules.SwapModule
DealFloatPosition(unwindData);
var flowList = new List<swap_flow_event>(unwindData.FlowEvents);
var eventId = SaveSwapDeal(unwindData, (int)SwapEventTypeEnum., clientCashId, "系统操作_平仓");
if (unwindData.CloseMethod == (int)CloseMethodEnum.|| unwindData.ClosePercent==1)
if (unwindData.CloseMethod == (int)CloseMethodEnum. || unwindData.ClosePercent == 1)
{
td.TradeStatus = "已平仓";
td.trade_extend = DbContext.trade_extend.FirstOrDefault(x => x.TradeId == td.id);
@@ -813,7 +814,7 @@ namespace YLErp.Modules.SwapModule
/// <param name="td"></param>
/// <param name="unwindPrice"></param>
/// <param name="unwindPriceFee"></param>
public void AuotoSwapUnwind(int tradeid, decimal unwindPrice, decimal unwindPriceFee, decimal unwindNetFee, decimal unwindNet, DateTime valueDate, decimal unwindQty,decimal closeFee)
public void AuotoSwapUnwind(int tradeid, decimal unwindPrice, decimal unwindPriceFee, decimal unwindNetFee, decimal unwindNet, DateTime valueDate, decimal unwindQty, decimal closeFee)
{
unwindPriceFee = decimal.Parse(unwindPriceFee.ToString("F10"));
var td = DbContext.trade.Find(tradeid);
@@ -851,7 +852,7 @@ namespace YLErp.Modules.SwapModule
unwindData.CloseMethod = unwindQty == unwindData.PositionQty ? (int)CloseMethodEnum. : (int)CloseMethodEnum.;
unwindData.ClosePercent = unwindData.PositionQty == 0 ? 0 : unwindPercent;
unwindData.CloseNotionalValue = position == null ? 0 : unwindQty * position.PosiGrossPrice * position.ContractSize;
unwindData.CloseNotionalValue = unwindPercent >= 1? unwindData.PosiNotionalValue: Math.Round(unwindData.CloseNotionalValue, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
unwindData.CloseNotionalValue = unwindPercent >= 1 ? unwindData.PosiNotionalValue : Math.Round(unwindData.CloseNotionalValue, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
unwindData.CloseQty = unwindQty;
if (position != null)
{
@@ -881,23 +882,14 @@ namespace YLErp.Modules.SwapModule
floatEvent.TradingFeePending = position.PosiTradingFeePending * unwindData.ClosePercent;
floatEvent.TradingFeePending = Math.Round(floatEvent.TradingFeePending, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
floatEvent.TradingFee = closeFee;
BondPaymentService bondPaymentService = new BondPaymentService(UserInfo);
var tax = GetUnderlyingTax(floatEvent.UnderlyingCode);
// 只计算事件日期当天的分红收益
var payments = bondPaymentService.GetTargetDatePayments(floatEvent.UnderlyingCode, floatEvent.EventDate);
floatEvent.DividendIn = bondPaymentService.CalcPayment(payments, unwindQty, longRatio, floatRatio) / (1 + tax) * (1 - tax);
floatEvent.DividendIn = Math.Round(floatEvent.DividendIn, 2, MidpointRounding.AwayFromZero);
floatEvent.DividendPending = bondPaymentService.CalcPayment(payments, floatEvent.PositionQty ?? 0, longRatio, floatRatio) / (1 + tax) * (1 - tax);
floatEvent.MarkClosePnl = (unwindPrice - position.PosiGrossPrice) * unwindQty * floatRatio * longRatio;
floatEvent.MarkClosePnl = Math.Round(floatEvent.MarkClosePnl + ((floatEvent.TradingFeePending+ closeFee) * floatRatio * -1) + floatEvent.DividendIn, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
floatEvent.MarkClosePnl = Math.Round(floatEvent.MarkClosePnl + ((floatEvent.TradingFeePending + closeFee) * floatRatio * -1) + floatEvent.DividendIn, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
floatEvent.TradingAmount = unwindPrice * floatEvent.Quantity * floatEvent.ContractSize;
floatEvent.TradingAmount = Math.Round(floatEvent.TradingAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
floatEvent.OptLog = "流水自动";
floatEvent.ClientId = td.ClientId;
floatEvent.SetOpt(UserInfo);
EnrichDividendIn(floatEvent, unwindQty);
}
unwindData.FlowEvents.Add(floatEvent);
var interestPositions = GetUnwindInterests(unwindData.ValueDate, unwindData.UnwindDate.Value, td.id, unwindPercent, (int)SwapEventTypeEnum.);
@@ -907,8 +899,8 @@ namespace YLErp.Modules.SwapModule
});
foreach (var item in interestPositions)
{
item.TdInterestAmount=Math.Round(item.TdInterestAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
item.InterestAmount=Math.Round(item.InterestAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
item.TdInterestAmount = Math.Round(item.TdInterestAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
item.InterestAmount = Math.Round(item.InterestAmount, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
item.InterestClosePnL = Math.Round(item.InterestClosePnL, ConsGlobal.MoneyRound, MidpointRounding.AwayFromZero);
}
unwindData.FlowEvents.AddRange(interestPositions);
@@ -916,6 +908,15 @@ namespace YLErp.Modules.SwapModule
DealUnwind(unwindData, td);
}
private void EnrichDividendIn(swap_flow_event flowEvent, decimal unwindQty)
{
// 平仓数量/平仓前的数量*平仓对象的待实现分红收益,保留2位小数
var yest = QdpCalendarHelper.GetNonHolidayDefore(flowEvent.EventDate.AddDays(-1));
var eod = DbContext.eod_swap_position.Where(e => e.SwapTradeId == flowEvent.SwapTradeId && !e.Invalid && e.PosiQuantity > 0 && e.ValueDate == yest).FirstOrDefault();
var dividendIn = eod.PosiProfitSum * unwindQty / eod.PosiQuantity;
flowEvent.DividendIn = Math.Round(dividendIn, 2, MidpointRounding.AwayFromZero);
}
public decimal GetUnderlyingTax(string code)
{
var data = DataCacheProvider.GetUnderlyingDataSource().GetData(code);
@@ -1073,7 +1074,7 @@ namespace YLErp.Modules.SwapModule
return interests;
}
private void DealUnwind(UnwindData unwindData, trade td, string actionMsg = "系统操作_自动平仓")
private void DealUnwind(UnwindData unwindData, trade td, string actionMsg = "系统操作_自动平仓")
{
int clientCashId = AddClientCashInCashOut(td, Convert.ToDouble(-unwindData.SwapRealizedPnL), ClientCashInCashOut._平仓费, unwindData.ValueDate);
if (unwindData.SwapMarginAmount != 0)
@@ -1104,7 +1105,7 @@ namespace YLErp.Modules.SwapModule
td.TradeAmount -= Convert.ToDouble(unwindData.CloseQty);
td.Notional = td.TradeAmount;
td.OptDate = DateTime.Now;
td.OptId= UserId;
td.OptId = UserId;
td.OptName = UserName;
DbContext.SaveChanges();
}
@@ -1384,7 +1385,7 @@ namespace YLErp.Modules.SwapModule
decimal shortRatio = item.PositionType == (int)PositionTypeFlag.Long ? -1m : 1m;
item.TradingAmountFeeAvg = item.TradingAmountAvg + item.TradingFeePending / unwindData.CloseQty * shortRatio;
item.TradingAmountNetFeeAvg = item.TradingAmountNetAvg + item.TradingFeePending / unwindData.CloseQty * shortRatio;
item.TradingAmount= item.TradingAmountAvg * unwindData.CloseQty;
item.TradingAmount = item.TradingAmountAvg * unwindData.CloseQty;
}
}
}
@@ -1400,7 +1401,7 @@ namespace YLErp.Modules.SwapModule
if (!string.IsNullOrEmpty(position.UnderlyingCode))
{
position.PosiQuantity -= unwindData.CloseQty;
position.PosiNotionalValue = unwindData.PosiNotionalValue- unwindData.CloseNotionalValue;
position.PosiNotionalValue = unwindData.PosiNotionalValue - unwindData.CloseNotionalValue;
position.PosiTradingFee -= position.PosiTradingFee * unwindData.ClosePercent;
position.PosiTradingFeePending -= position.PosiTradingFeePending * unwindData.ClosePercent;
}