Merge remote-tracking branch 'origin/glms/feature/1.4.2' into glms/feature/1.4.2
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
namespace YLErp.Modules.DataProviderModule
|
||||
{
|
||||
/// <summary>
|
||||
/// TryGetSettlementEodPrice(债券感知统一取价)的白盒测试。
|
||||
/// 覆盖期权/交易到期结算场景:债券标的应走中债估值表取到价(修复"结算价未找到"),
|
||||
/// 非债券标的行为应与原 TryGetEodPrice 完全一致(不影响期货/股票)。
|
||||
/// 注:DB 驱动,需连测试库;无数据时 Assert.Inconclusive 跳过。
|
||||
/// </summary>
|
||||
[TestClass]
|
||||
public class EodPriceQueryServiceSettlementTest : YLUnitTestBase
|
||||
{
|
||||
[TestMethod]
|
||||
public void BondUnderlying_RoutesToChinaBondValuation()
|
||||
{
|
||||
using var db = DbContextFactory.GetYLDbContext();
|
||||
var bond = (from b in db.china_bond_valuation
|
||||
join u in db.underlying_manager on b.bond_id equals u.UnderlyingCode
|
||||
where b.dirty_price_close > 0
|
||||
orderby b.valuation_date descending
|
||||
select new { b.bond_id, vd = b.valuation_date }).FirstOrDefault();
|
||||
if (bond == null) Assert.Inconclusive("测试库无债券估值数据,跳过");
|
||||
|
||||
var ok = EodPriceQueryService.TryGetSettlementEodPrice(bond.vd, bond.bond_id, out var ep);
|
||||
Assert.IsTrue(ok, "债券标的应走中债估值表取到价(修复点)");
|
||||
Assert.IsNotNull(ep);
|
||||
// 债券 ClosePrice=全价(dirty_price_close),应与 GetBondPrice().ClosePrice 一致
|
||||
var bondPrice = EodPriceQueryService.GetBondPrice(bond.vd, bond.bond_id);
|
||||
Assert.IsNotNull(bondPrice);
|
||||
Assert.AreEqual(bondPrice.ClosePrice, ep.ClosePrice, 1e-6);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void NonBondUnderlying_RoutesToStockOrFuturePath()
|
||||
{
|
||||
using var db = DbContextFactory.GetYLDbContext();
|
||||
var stock = (from s in db.eod_stock_price
|
||||
join u in db.underlying_manager on s.UnderlyingCode equals u.UnderlyingCode
|
||||
where s.ClosePrice > 0 && u.UnderlyingInstrumentType == "Stock"
|
||||
select new { s.UnderlyingCode, s.ValueDate }).FirstOrDefault();
|
||||
if (stock == null) Assert.Inconclusive("测试库无(股票类型)价格数据,跳过");
|
||||
|
||||
var ok = EodPriceQueryService.TryGetSettlementEodPrice(stock.ValueDate, stock.UnderlyingCode, out var ep);
|
||||
var okOld = EodPriceQueryService.TryGetEodPrice(stock.ValueDate, stock.UnderlyingCode, out var epOld);
|
||||
Assert.AreEqual(okOld, ok, "非债券标的行为应与原 TryGetEodPrice 一致");
|
||||
if (ok)
|
||||
{
|
||||
Assert.IsNotNull(ep);
|
||||
Assert.AreEqual(epOld.ClosePrice, ep.ClosePrice, 1e-6, "非债券标的取到的收盘价应与原路径相同");
|
||||
}
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void BondOptionExpiry_Regression_OldPathFailsNewPathSucceeds()
|
||||
{
|
||||
using var db = DbContextFactory.GetYLDbContext();
|
||||
var bond = (from b in db.china_bond_valuation
|
||||
join u in db.underlying_manager on b.bond_id equals u.UnderlyingCode
|
||||
where b.dirty_price_close > 0
|
||||
orderby b.valuation_date descending
|
||||
select new { b.bond_id, vd = b.valuation_date }).FirstOrDefault();
|
||||
if (bond == null) Assert.Inconclusive("测试库无债券估值数据,跳过");
|
||||
|
||||
// 旧路径:TryGetEodPrice 只 join 期货/股票两表,债券取不到价
|
||||
var oldOk = EodPriceQueryService.TryGetEodPrice(bond.vd, bond.bond_id, out _);
|
||||
// 新路径:债券感知统一取价,应能取到
|
||||
var newOk = EodPriceQueryService.TryGetSettlementEodPrice(bond.vd, bond.bond_id, out var ep);
|
||||
Assert.IsFalse(oldOk, "回归基线:旧路径对债券标的应取不到价(这正是期权到期报'结算价未找到'的根因)");
|
||||
Assert.IsTrue(newOk && ep != null && ep.ClosePrice > 0,
|
||||
"修复验证:统一取价应能为债券标的取到结算价,期权到期不再报'结算价未找到'");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -187,5 +187,55 @@ namespace YLErp.Modules.SwapModule
|
||||
"SwapRealizedPnL 应=SwapCloseAmount(6000)");
|
||||
Console.WriteLine($"UW_006: CloseReCheck={service.CloseReCheckCallCount}次, SwapRealizedPnL={service.SaveSwapDealCalls[0].data.SwapRealizedPnL} ✅");
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景7:前端传"占期初(A)"语义,后端入口转"占剩余(B)" —— 全平判定
|
||||
// 原始名义本金 100M / 剩余 60M,前端传 A=0.6(平掉原始 60M = 剩余全部)
|
||||
// B = A × Notional/Posi = 0.6 × 100/60 = 1.0 → 触发全平
|
||||
// ================================================================
|
||||
[TestMethod]
|
||||
public void UW_007_SwapUnwind_占期初A转占剩余B_全平判定正确()
|
||||
{
|
||||
var td = SwapDealTestFactory.CreateTrade();
|
||||
var service = new TestableSwapDealService(td);
|
||||
var unwindData = SwapDealTestFactory.CreateUnwindData(
|
||||
swapRealizedPnL: 0m, closeMethod: (int)CloseMethodEnum.全部平仓, closePercent: 0.6m,
|
||||
closeQty: 600000m, closeNotionalValue: 600000m, positionQty: 600000m);
|
||||
unwindData.NotionalValue = 1000000m; // 期初名义本金
|
||||
unwindData.PosiNotionalValue = 600000m; // 剩余名义本金
|
||||
|
||||
service.SwapUnwind(unwindData);
|
||||
|
||||
// 桩 SaveSwapDeal 收集的是转换后的 B(落库 A 还原在生产 SaveSwapDealInternal 中,桩跳过)
|
||||
Assert.AreEqual(1.0m, service.SaveSwapDealCalls[0].data.ClosePercent, 0.0001m,
|
||||
"入口 A=0.6 应转为 B=1.0(占剩余全平)");
|
||||
Assert.AreEqual("已平仓", td.TradeStatus, "B==1 触发全平 TradeStatus=已平仓");
|
||||
Console.WriteLine($"UW_007: A=0.6→B={service.SaveSwapDealCalls[0].data.ClosePercent}, TradeStatus={td.TradeStatus} ✅");
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// 场景8:占期初(A)转占剩余(B) —— 部分平仓
|
||||
// 原始 100M / 剩余 60M,前端传 A=0.3(平掉原始 30M = 剩余的 50%)
|
||||
// B = A × Notional/Posi = 0.3 × 100/60 = 0.5 → 部分平仓
|
||||
// ================================================================
|
||||
[TestMethod]
|
||||
public void UW_008_SwapUnwind_占期初A转占剩余B_部分平仓正确()
|
||||
{
|
||||
var td = SwapDealTestFactory.CreateTrade();
|
||||
var service = new TestableSwapDealService(td);
|
||||
var unwindData = SwapDealTestFactory.CreateUnwindData(
|
||||
swapRealizedPnL: 0m, closeMethod: (int)CloseMethodEnum.部分平仓, closePercent: 0.3m,
|
||||
closeQty: 300000m, closeNotionalValue: 300000m, positionQty: 600000m);
|
||||
unwindData.NotionalValue = 1000000m; // 期初名义本金
|
||||
unwindData.PosiNotionalValue = 600000m; // 剩余名义本金
|
||||
|
||||
service.SwapUnwind(unwindData);
|
||||
|
||||
Assert.AreEqual(0.5m, service.SaveSwapDealCalls[0].data.ClosePercent, 0.0001m,
|
||||
"入口 A=0.3 应转为 B=0.5(占剩余 50%)");
|
||||
Assert.AreEqual(1, td.HasPartialUnWind, "B≠1 应为部分平仓,设 HasPartialUnWind=1");
|
||||
Assert.AreEqual("确认成交", td.TradeStatus, "部分平仓 TradeStatus 保持不变");
|
||||
Console.WriteLine($"UW_008: A=0.3→B={service.SaveSwapDealCalls[0].data.ClosePercent}, HasPartialUnWind={td.HasPartialUnWind} ✅");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,6 +140,9 @@ namespace YLErp.Modules.DataProviderModule
|
||||
{
|
||||
if (item.UnderlyingInstrumentType == "Bonds")
|
||||
{
|
||||
// [Layer2-待统一] 债券映射口径:SettlePrice=全价(dirty_price_close),ClosePrice=净价(net_price)。
|
||||
// 注意:这与 EodPriceQueryService.GetBondPrice 的映射【完全相反】(GetBondPrice: ClosePrice=全价,SettlePrice=净价)。
|
||||
// 两处对"债券收盘价/结算价"的净全价定义不一致属历史遗留,请勿随意改动单侧,需业务先定调后统一(见 TryGetSettlementEodPrice 注释)。
|
||||
item.SettlePrice = Convert.ToDouble(BondPriceConverter.ToStorage(item.DeciSettlePrice));
|
||||
item.ClosePrice = Convert.ToDouble(BondPriceConverter.ToStorage(item.DeciClosePrice));
|
||||
item.ReferencePrice = Convert.ToDouble(BondPriceConverter.ToStorage(item.DeciReferencePrice));
|
||||
|
||||
@@ -114,6 +114,23 @@ namespace YLErp.Modules.DataProviderModule
|
||||
return (eodPrice = GetBondPrice(valueDate, underlyingCode)) != null;
|
||||
}
|
||||
/// <summary>
|
||||
/// 统一日终结算取价(债券感知)。
|
||||
/// 用于交易/期权到期结算:债券标的走中债估值表(TryGetBondEodPrice),期货/股票走原 InnerGetEodPrice。
|
||||
/// 解决到期路径(tradeExpireInner / MultipleTradeExpireConfirm)漏查债券表导致"结算价未找到"的问题。
|
||||
/// 注:债券 ClosePrice/SettlePrice 映射沿用 GetBondPrice 口径(ClosePrice=全价 dirty_price_close,SettlePrice=净价 net_price),
|
||||
/// 与 EodPriceProvider 的映射(ClosePrice=净价,SettlePrice=全价)相反——属历史不一致(见 EodPriceProvider.Initialize 与 GetBondPrice 的注释),
|
||||
/// 本方法保持与系统既有"债券现价"约定(UnderlyingCodePrice)一致,不引入新口径。
|
||||
/// </summary>
|
||||
public static bool TryGetSettlementEodPrice(DateTime valueDate, string underlyingCode, out EodPrice eodPrice)
|
||||
{
|
||||
var um = DataCacheProvider.GetUnderlyingDataSource().GetData(underlyingCode);
|
||||
if (um != null && ConsGlobal.InstrumentType.IsBond(um.UnderlyingInstrumentType))
|
||||
{
|
||||
return TryGetBondEodPrice(valueDate, underlyingCode, out eodPrice);
|
||||
}
|
||||
return TryGetEodPrice(valueDate, underlyingCode, out eodPrice);
|
||||
}
|
||||
/// <summary>
|
||||
/// 尝试获取标的某日的日终价
|
||||
/// </summary>
|
||||
public static bool TryGetEodPrice(DateTime valueDate, int underlyingId, out EodPrice eodPrice)
|
||||
@@ -231,6 +248,9 @@ namespace YLErp.Modules.DataProviderModule
|
||||
Vobp = bondPrice.vobp,
|
||||
ValueDate = valueDate,
|
||||
UnderlyingCode = underlyingCode,
|
||||
// [Layer2-待统一] 债券映射口径:ClosePrice=全价(dirty_price_close),SettlePrice=净价(net_price)。
|
||||
// 注意:这与 EodPriceProvider.Initialize 的映射【完全相反】(EodPriceProvider: ClosePrice=净价,SettlePrice=全价)。
|
||||
// 两处对"债券收盘价/结算价"的净全价定义不一致属历史遗留,请勿随意改动单侧,需业务先定调后统一(见 TryGetSettlementEodPrice 注释)。
|
||||
ClosePrice = Convert.ToDouble(BondPriceConverter.ToStorage(bondPrice.dirty_price_close)),
|
||||
SettlePrice = Convert.ToDouble(BondPriceConverter.ToStorage(bondPrice.net_price)),
|
||||
ReferencePrice = Convert.ToDouble(BondPriceConverter.ToStorage(bondPrice.yield))
|
||||
|
||||
@@ -726,6 +726,30 @@ namespace YLErp.Modules.SwapModule
|
||||
return (closePrincipal, posiPrincipal, newClosePercent);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 平仓比例口径转换(解决"显示占期初 / 计算占剩余"双语义问题)。
|
||||
/// 前端与事件列表展示用"占期初(original)"语义(A);后端 CalcNotionalByMode / 费用递减 /
|
||||
/// 全平判定均按"占剩余(remaining)"语义(B)消费。
|
||||
/// A → B:B = A × 期初名义本金(NotionalValue) / 剩余名义本金(PosiNotionalValue),并 cap 到 1。
|
||||
/// B → A:A = B × 剩余名义本金 / 期初名义本金。
|
||||
/// 分母为 0(无持仓等异常场景)时原样返回,避免除零。
|
||||
/// </summary>
|
||||
public static decimal ToRemainingClosePercent(decimal originalClosePercent, decimal notionalValue, decimal posiNotionalValue)
|
||||
{
|
||||
if (posiNotionalValue <= 0) return originalClosePercent;
|
||||
var remaining = originalClosePercent * notionalValue / posiNotionalValue;
|
||||
return remaining > 1 ? 1 : remaining;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// B(占剩余) → A(占期初),用于落库 / 事件列表展示还原。见 ToRemainingClosePercent。
|
||||
/// </summary>
|
||||
public static decimal ToOriginalClosePercent(decimal remainingClosePercent, decimal notionalValue, decimal posiNotionalValue)
|
||||
{
|
||||
if (notionalValue <= 0) return remainingClosePercent;
|
||||
return remainingClosePercent * posiNotionalValue / notionalValue;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取固定利率
|
||||
/// </summary>
|
||||
@@ -1226,6 +1250,9 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
//CheckLastEod(unwindData.ValueDate, td.StartDate.Value, unwindData.SwapTradeId); //去掉平仓收盘限制
|
||||
ValidateFrontendPnL(unwindData, isIncome: false); // 只读校验告警,不阻断交易
|
||||
// 前端按"占期初(original)"语义传 ClosePercent(A);后端全链路按"占剩余(remaining)"语义(B)消费。
|
||||
// 入口统一转换为 B,落库展示用的 A 由 SaveSwapDealInternal 还原。
|
||||
unwindData.ClosePercent = ToRemainingClosePercent(unwindData.ClosePercent, unwindData.NotionalValue, unwindData.PosiNotionalValue);
|
||||
bool cofirm = false;
|
||||
ExecuteInTransaction(() =>
|
||||
{
|
||||
@@ -1843,7 +1870,13 @@ namespace YLErp.Modules.SwapModule
|
||||
}
|
||||
var flowList = new List<swap_flow_event>(unwindData.FlowEvents);
|
||||
unwindData.FlowEvents.Clear();
|
||||
// 落库展示用"占期初(original)"语义(A);计算链(费用递减/全平判定)用"占剩余(remaining)"语义(B)。
|
||||
// 序列化前把 ClosePercent 还原为 A,序列化后立即还原回 B 供后续使用。
|
||||
var storedClosePercent = ToOriginalClosePercent(unwindData.ClosePercent, unwindData.NotionalValue, unwindData.PosiNotionalValue);
|
||||
var incomingClosePercent = unwindData.ClosePercent;
|
||||
unwindData.ClosePercent = storedClosePercent;
|
||||
string data = JsonConvert.SerializeObject(unwindData);
|
||||
unwindData.ClosePercent = incomingClosePercent;
|
||||
var swapEvent = new SwapEventService(this).AddSwapEventDate(unwindData.ValueDate, unwindData.SwapTradeId, eventType, data, clientCashId, true, eventResason);//将平仓、互换总额存入事件
|
||||
foreach (var item in flowList)
|
||||
{
|
||||
|
||||
@@ -140,7 +140,9 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
|
||||
#region 设置期末价格和执行价格
|
||||
|
||||
var finalPrice = EodPriceQueryService.TryGetEodPrice(exerciseDate, td.UnderlyingCode, out var eodPrice)
|
||||
// 债券标的需走中债估值表取价,原 TryGetEodPrice 只查期货/股票两表会漏掉债券,导致"结算价未找到"。
|
||||
// 统一改用债券感知的 TryGetSettlementEodPrice(见 EodPriceQueryService)。
|
||||
var finalPrice = EodPriceQueryService.TryGetSettlementEodPrice(exerciseDate, td.UnderlyingCode, out var eodPrice)
|
||||
? eodPrice.GetPrice(td.SettlementType) : 0;
|
||||
|
||||
if (finalPrice <= 0)
|
||||
@@ -280,8 +282,6 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
trade_cash tradeCash = null;
|
||||
|
||||
//日终价格
|
||||
var underlyingIds = tradeUnwindTrades.Select(t => t.UnderlyingId).ToList();
|
||||
var EodPriceProvider = new EodPriceProvider(valueDate);
|
||||
//批量结算的全是现金流交易就不用结算价
|
||||
if (!EodPriceQueryService.CheckDbExists(valueDate) && tradeQuery.Any(t => t.TradeType != "现金流交易"))
|
||||
{
|
||||
@@ -308,8 +308,8 @@ namespace YLErp.Modules.TradeModule.DealModule
|
||||
var CountRatio = 1;
|
||||
if (t.TradeType != "现金流交易")
|
||||
{
|
||||
//结算价
|
||||
if (EodPriceProvider.TryGetEodPrice(t.UnderlyingCode, out var eodPrice))
|
||||
//结算价(债券感知统一取价:债券走中债估值,期货/股票走原路径,见 EodPriceQueryService.TryGetSettlementEodPrice)
|
||||
if (EodPriceQueryService.TryGetSettlementEodPrice(valueDate, t.UnderlyingCode, out var eodPrice))
|
||||
{
|
||||
settlePrice = eodPrice.GetPrice(t.SettlementType);
|
||||
}
|
||||
|
||||
@@ -283,9 +283,12 @@ namespace YLErp.Web.Controllers
|
||||
/// <param name="tradeId"></param>
|
||||
/// <param name="closePercent"></param>
|
||||
/// <returns></returns>
|
||||
public JsonResult GetUnwindInterestList(DateTime valueDate,DateTime unwindDate, int tradeId, decimal closePercent, int eventType)
|
||||
public JsonResult GetUnwindInterestList(DateTime valueDate,DateTime unwindDate, int tradeId, decimal closePercent, int eventType, decimal notionalValue = 0, decimal posiNotionalValue = 0)
|
||||
{
|
||||
var interests = new SwapDealService(CurUser).GetUnwindInterests(valueDate, unwindDate, tradeId, closePercent, eventType);
|
||||
// 前端按"占期初(original)"语义传 closePercent(A);后端 GetUnwindInterests 按"占剩余(remaining)"语义(B)计算。
|
||||
// 多空互换前端不传 notionalValue/posiNotionalValue(默认 0),则跳过转换保持原行为。
|
||||
var convertedClosePercent = SwapDealService.ToRemainingClosePercent(closePercent, notionalValue, posiNotionalValue);
|
||||
var interests = new SwapDealService(CurUser).GetUnwindInterests(valueDate, unwindDate, tradeId, convertedClosePercent, eventType);
|
||||
foreach (var interest in interests)
|
||||
{
|
||||
interest.TdInterestAmount=Math.Round(interest.TdInterestAmount, ConsGlobal.MoneyRound,MidpointRounding.AwayFromZero);
|
||||
|
||||
@@ -148,7 +148,7 @@ namespace YLErp.Web.Controllers
|
||||
{
|
||||
valueDate = QdpCalendarHelper.GetNonHolidayDefore(valueDate);
|
||||
}
|
||||
if (!EodPriceQueryService.TryGetEodPrice(valueDate, td.UnderlyingCode, out _))
|
||||
if (!EodPriceQueryService.TryGetSettlementEodPrice(valueDate, td.UnderlyingCode, out _))
|
||||
{
|
||||
return JsonError($"交易日{valueDate:yyyy-MM-dd}的结算价或收盘价未找到!");
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ const vue = new Vue({
|
||||
marginList: [],
|
||||
initPosiNetPrice: 0,
|
||||
multiplier: 1,
|
||||
// 多次部分平仓后,ClosePercent 语义为“占剩余持仓的比例”(后端 GetUnwindInterests 用 remainingBase×closePercent 计算预付金返还),
|
||||
// 故最多可平 100% 剩余,oriClosePercent 恒为 1;不能用 model.ClosePercent(=剩余/原始,Definition A 旧口径),否则全部平仓/按比例会少返预付金
|
||||
// 平仓比例展示/输入均为"占期初(original)"语义(A):默认与每次重开都基于原始名义本金。
|
||||
// oriClosePercent = 剩余名义本金/期初名义本金 = 最多可平比例(不能平超过剩余持仓)。
|
||||
oriClosePercent: 1,
|
||||
ratio: 1,
|
||||
shortRatio: 1,
|
||||
@@ -55,12 +55,9 @@ const vue = new Vue({
|
||||
this.ratio = this.floatPosition.PayDirection == 1 ? -1 : 1;
|
||||
this.shortRatio = this.floatPosition.PositionType == 1 ? 1 : -1;
|
||||
this.TradeStartDate = model.TradeStartDate;
|
||||
// 多次部分平仓后 ClosePercent 语义为"占剩余持仓比例"。
|
||||
// 仅当"全部平仓"(CloseMethod==1) 时修正旧口径(model.ClosePercent 可能=剩余/原始<1)为 1;
|
||||
// "部分平仓"(CloseMethod==2) 时保留已提交比例(平仓待复核场景),避免覆盖用户已提交的 closePercent
|
||||
if (this.deal.CloseMethod === 1) {
|
||||
this.deal.ClosePercent = 1;
|
||||
}
|
||||
// 最多可平比例(占期初口径) = 剩余名义本金 / 期初名义本金;分母为 0 时兜底为 1
|
||||
this.oriClosePercent = (this.deal.NotionalValue && this.deal.PosiNotionalValue)
|
||||
? this.deal.PosiNotionalValue / this.deal.NotionalValue : 1;
|
||||
// 转换期末标的价格为百分比形式
|
||||
if (this.floatPosition.TradingAmountAvg) {
|
||||
this.floatPosition.TradingAmountAvg = this.floatPosition.TradingAmountAvg * this.multiplier;
|
||||
@@ -154,8 +151,8 @@ const vue = new Vue({
|
||||
} else {
|
||||
this.deal.CloseMethod = 2;
|
||||
}
|
||||
// 多次部分平仓后 PosiNotionalValue 才是剩余本金,不能用原始 NotionalValue,否则平仓名义本金偏大
|
||||
this.deal.CloseNotionalValue = otcformat.trading.StockEqvNotional(parseFloat(this.deal.ClosePercent) * parseFloat(this.deal.PosiNotionalValue));
|
||||
// 占期初口径:平仓名义本金 = 平仓比例 × 期初名义本金(NotionalValue)
|
||||
this.deal.CloseNotionalValue = otcformat.trading.StockEqvNotional(parseFloat(this.deal.ClosePercent) * parseFloat(this.deal.NotionalValue));
|
||||
this.calcTradingFeePending();
|
||||
this.getInterestList();
|
||||
this.calcFloatClosePnl();
|
||||
@@ -167,8 +164,8 @@ const vue = new Vue({
|
||||
return;
|
||||
}
|
||||
this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.PositionQty) * parseFloat(this.deal.ClosePercent));
|
||||
// 多次部分平仓后 PosiNotionalValue 才是剩余本金,不能用原始 NotionalValue,否则平仓名义本金偏大
|
||||
this.deal.CloseNotionalValue = otcformat.trading.StockEqvNotional(parseFloat(this.deal.ClosePercent) * parseFloat(this.deal.PosiNotionalValue));
|
||||
// 占期初口径:平仓名义本金 = 平仓比例 × 期初名义本金(NotionalValue)
|
||||
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;
|
||||
} else {
|
||||
@@ -184,8 +181,8 @@ const vue = new Vue({
|
||||
this.deal.CloseNotionalValue = this.deal.PosiNotionalValue;
|
||||
return;
|
||||
}
|
||||
// 多次部分平仓后应以 PosiNotionalValue(剩余) 为分母,否则 ClosePercent 偏小,导致后端预付金返还本金计算错误
|
||||
this.deal.ClosePercent = otcformat.fixed6(parseFloat(this.deal.CloseNotionalValue) / parseFloat(this.deal.PosiNotionalValue));
|
||||
// 占期初口径:平仓比例 = 平仓名义本金 / 期初名义本金(NotionalValue)
|
||||
this.deal.ClosePercent = otcformat.fixed6(parseFloat(this.deal.CloseNotionalValue) / parseFloat(this.deal.NotionalValue));
|
||||
this.deal.CloseQty = otcformat.trading.notional(parseFloat(this.deal.PositionQty) * parseFloat(this.deal.ClosePercent));
|
||||
this.calcTradingFeePending();
|
||||
this.getInterestList();
|
||||
@@ -272,7 +269,8 @@ const vue = new Vue({
|
||||
},
|
||||
getInterestList() {//根据平仓日期获取利息腿信息
|
||||
var thisObj = this;
|
||||
var postData = { valueDate: thisObj.deal.ValueDate, unwindDate: thisObj.deal.UnwindDate, tradeId: thisObj.deal.SwapTradeId, closePercent: thisObj.deal.ClosePercent, eventType: 2 }
|
||||
// closePercent 按"占期初(original)"语义(A)传给后端,由 GetUnwindInterestList 转为"占剩余(B)"计算
|
||||
var postData = { valueDate: thisObj.deal.ValueDate, unwindDate: thisObj.deal.UnwindDate, tradeId: thisObj.deal.SwapTradeId, closePercent: thisObj.deal.ClosePercent, eventType: 2, notionalValue: thisObj.deal.NotionalValue, posiNotionalValue: thisObj.deal.PosiNotionalValue }
|
||||
main.post("/swaptrade2/GetUnwindInterestList", postData, { async: true }).done(function (resp) {
|
||||
thisObj.interestList = resp.obj.filter((item) => {
|
||||
return item.InterestMode == 1 || item.InterestMode == 2 || item.InterestMode == 7 || item.InterestMode == 8 || item.InterestMode == 9;
|
||||
|
||||
@@ -669,7 +669,7 @@ var app = new Vue({
|
||||
return;
|
||||
}
|
||||
if (thisObj.tradeItems != null && thisObj.tradeItems.length > 0) {
|
||||
main.confirm("确认修改交易审批流程?", function () {
|
||||
main.confirm("审批页面存在未审批完的交易,修改审批流程后这些交易需要重新审批,确认修改?", function () {
|
||||
main.post("/AccountOpeningProcess/AddProcess",
|
||||
{ type: thisObj.tradeItems[0].Type, data: thisObj.tradeItems },
|
||||
{ async: false }).done(
|
||||
@@ -1391,7 +1391,7 @@ var app = new Vue({
|
||||
}
|
||||
thisObj.stringifyAllTrigger(thisObj.closeItems); // 需求①:序列化触发条件
|
||||
if (thisObj.closeItems != null && thisObj.closeItems.length > 0) {
|
||||
main.confirm("确认修改交易了结审批流程?", function () {
|
||||
main.confirm("审批页面存在未审批完的交易,修改审批流程后这些交易需要重新审批,确认修改?", function () {
|
||||
main.post("/AccountOpeningProcess/AddProcess",
|
||||
{ type: "CloseProcess", data: thisObj.closeItems },
|
||||
{ async: false }).done(
|
||||
|
||||
Reference in New Issue
Block a user