fix(swap): 修复股票基金类互换合约平仓时公司行为处理逻辑
- 优化 FindFundCorporateActions 方法,明确查询范围为严格大于 eodDate 的开区间,并添加日志记录 - 重命名 TryRestoreEffectiveFundPosition 为 TryRestorePositionFromEod 和 TryRestoreAndValidateUnwindData - 完善 EOD 数据完整性验证,检查持仓数量和价格的有效性 - 添加详细的公司行为查询和应用过程日志记录 - 优化异常信息,包含更多上下文信息如生效日和记录ID - 更新方法调用引用以使用新的方法名称
This commit is contained in:
@@ -497,6 +497,48 @@ namespace YLErp.Modules.SwapModule
|
||||
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// 根据指定日期刷新浮动腿基线(处理公司行为除权)
|
||||
/// 用于前端修改平仓日期后重新获取除权后的持仓数量和价格
|
||||
/// </summary>
|
||||
/// <param name="tradeId">交易ID</param>
|
||||
/// <param name="valueDate">平仓日期</param>
|
||||
/// <returns>返回浮动腿的最新基线数据</returns>
|
||||
public virtual (decimal PositionQty, decimal PosiNotionalValue, decimal PosiGrossPrice, decimal PosiNetPrice, bool IsRestored) RefreshFloatLegBaseline(int tradeId, DateTime valueDate)
|
||||
{
|
||||
var td = DbContext.trade.Find(tradeId);
|
||||
if (td == null)
|
||||
{
|
||||
throw new ServiceException("未找到交易信息");
|
||||
}
|
||||
|
||||
var positions = DbContext.swap_position.ActiveByTrade(tradeId);
|
||||
var position = positions.Where(x => !string.IsNullOrEmpty(x.UnderlyingCode) && !x.IsInitial).FirstOrDefault();
|
||||
|
||||
if (position == null)
|
||||
{
|
||||
// 无浮动腿,返回trade表的原始值
|
||||
return (
|
||||
Convert.ToDecimal(td.TradeAmount),
|
||||
Convert.ToDecimal(td.StockEqvNotional),
|
||||
0m,
|
||||
0m,
|
||||
false
|
||||
);
|
||||
}
|
||||
|
||||
// 尝试恢复除权后的 EOD 基线
|
||||
var restoredCorporateActionBaseline = TryRestorePositionFromEod(position, valueDate);
|
||||
|
||||
return (
|
||||
position.PosiQuantity,
|
||||
position.PosiNotionalValue,
|
||||
position.PosiGrossPrice,
|
||||
position.PosiNetPrice,
|
||||
restoredCorporateActionBaseline
|
||||
);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 平仓初始化
|
||||
/// </summary>
|
||||
|
||||
@@ -393,6 +393,32 @@ namespace YLErp.Web.Controllers
|
||||
new SwapTradeService(CurUser).TradeBack(model.TradeId, model.TradeDate);
|
||||
return JsonSuccess("回退成功");
|
||||
}
|
||||
/// <summary>
|
||||
/// 根据平仓日期刷新持仓基线(处理公司行为除权)
|
||||
/// </summary>
|
||||
/// <param name="tradeId">交易ID</param>
|
||||
/// <param name="valueDate">事件日期/平仓日期</param>
|
||||
/// <returns>返回最新的持仓数量、价格等基线数据</returns>
|
||||
public JsonResult RefreshUnwindBaseline(int tradeId, DateTime valueDate)
|
||||
{
|
||||
var (positionQty, posiNotionalValue, posiGrossPrice, posiNetPrice, isRestored) =
|
||||
new SwapDealService(CurUser).RefreshFloatLegBaseline(tradeId, valueDate);
|
||||
|
||||
var result = new
|
||||
{
|
||||
PositionQty = positionQty,
|
||||
PosiNotionalValue = posiNotionalValue,
|
||||
PosiGrossPrice = posiGrossPrice,
|
||||
PosiNetPrice = posiNetPrice,
|
||||
IsRestored = isRestored,
|
||||
// 全平时,平仓数量等于持仓数量
|
||||
CloseQty = positionQty,
|
||||
CloseNotionalValue = posiNotionalValue
|
||||
};
|
||||
|
||||
return JsonSuccess("", result);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 平仓利息腿信息
|
||||
/// </summary>
|
||||
|
||||
@@ -175,6 +175,8 @@ const vue = new Vue({
|
||||
this.floatPosition.UnwindDate = e;
|
||||
}
|
||||
if (!isUseApproval) {
|
||||
// 新增:刷新持仓基线(处理公司行为除权)
|
||||
this.refreshUnwindBaseline();
|
||||
this.getInterestList();
|
||||
//this.refreshUnderlyingPrice();
|
||||
} else {
|
||||
@@ -365,6 +367,57 @@ const vue = new Vue({
|
||||
thisObj.deal.SwapMarginRebatePnl = formatSwapAmount(thisObj.deal.SwapMarginRebatePnl);
|
||||
thisObj.deal.SwapMarginAmount = formatSwapAmount(thisObj.deal.SwapMarginAmount);
|
||||
},
|
||||
refreshUnwindBaseline() {//刷新持仓基线(处理公司行为除权)
|
||||
var thisObj = this;
|
||||
var postData = {
|
||||
tradeId: thisObj.deal.SwapTradeId,
|
||||
valueDate: thisObj.deal.ValueDate
|
||||
};
|
||||
main.post("/swaptrade2/RefreshUnwindBaseline", postData, { async: true }).done(function (resp) {
|
||||
if (resp.success) {
|
||||
var data = resp.obj;
|
||||
// 更新持仓数量和名义本金
|
||||
thisObj.deal.PositionQty = data.PositionQty;
|
||||
thisObj.deal.PositionQty2 = data.PositionQty; // 新增:同时更新 PositionQty2(界面显示用)
|
||||
thisObj.deal.PosiNotionalValue = data.PosiNotionalValue;
|
||||
|
||||
// 如果是全平,更新平仓数量和名义本金
|
||||
if (thisObj.deal.CloseMethod == 1) { // 全部平仓
|
||||
thisObj.deal.CloseQty = data.CloseQty;
|
||||
thisObj.deal.CloseNotionalValue = data.CloseNotionalValue;
|
||||
}
|
||||
|
||||
// 更新浮动腿的期初价格和数量
|
||||
if (thisObj.floatPosition) {
|
||||
thisObj.floatPosition.PosiGrossPrice = data.PosiGrossPrice;
|
||||
thisObj.floatPosition.PosiNetPrice = data.PosiNetPrice;
|
||||
thisObj.initPosiNetPrice = data.PosiGrossPrice;
|
||||
// 更新浮动腿的持仓数量(底部表格显示用)
|
||||
thisObj.floatPosition.PositionQty = data.PositionQty;
|
||||
}
|
||||
|
||||
// 重新计算最多可平比例
|
||||
thisObj.oriClosePercent = (thisObj.deal.NotionalValue && thisObj.deal.PosiNotionalValue)
|
||||
? thisObj.deal.PosiNotionalValue / thisObj.deal.NotionalValue : 1;
|
||||
|
||||
// 如果是全平,更新平仓比例
|
||||
if (thisObj.deal.CloseMethod == 1) {
|
||||
thisObj.deal.ClosePercent = thisObj.oriClosePercent;
|
||||
}
|
||||
|
||||
// 强制 Vue 更新界面
|
||||
thisObj.$forceUpdate();
|
||||
|
||||
// 可选:显示提示信息
|
||||
if (data.IsRestored && window.otcDebug) {
|
||||
console.log('[公司行为] 已根据除权后的EOD基线刷新持仓数据', {
|
||||
PositionQty: data.PositionQty,
|
||||
PosiGrossPrice: data.PosiGrossPrice
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
getInterestList() {//根据平仓日期获取利息腿信息
|
||||
var thisObj = this;
|
||||
// closePercent 按"占期初(original)"语义(A)传给后端,由 GetUnwindInterestList 转为"占剩余(B)"计算
|
||||
|
||||
Reference in New Issue
Block a user