using System.Linq.Expressions; using YLErp.Helpers; using YLErp.Model; using YLErp.Modules.DataProviderModule; using YLErp.Modules.SwapModule; using YLErp.Modules.TradeModule; using YLErp.Modules.TradeModule.DealModule; using YLErp.Modules.TradeModule.ExoticOptionModule; using YLErp.QdpModule; namespace YLErp.Modules.EodModule.SettlementModule { /// /// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息 /// class EodCheckMonitoredTrade : EodSettleServiceBaseV2 { public const string Step = "检查期权观察状态"; private static IYcLogger logger = LogFactory.GetLogger(); readonly IEnumerable _trades; public EodCheckMonitoredTrade(EodSettlementContextV2 context) : base(context) { if (_context is EodSettlementContextV2 contextV2) { _trades = contextV2.OtcTrades; } } private Action getAfterKnowInOut(Expression> propExp) { if (_trades == null) return null; var valueParam = Expression.Parameter(typeof(T)); var assign = Expression.Lambda>( Expression.Assign(propExp.Body, valueParam), propExp.Parameters.Single(), valueParam).Compile(); return new Action((td, tdex) => { if (td != null && tdex != null) { var otd = _trades.FirstOrDefault(t => t.id == td.id); if (otd != null) { assign(otd, tdex); otd.MetaDic.Remove("from_eod_trade"); } } }); } /// /// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息 /// public void ExecuteTask1(Action setTaskStep) { var blReset = false; var settleDate = _context.SettleDate; var clienIds = _context.Request.ClientIds; var eodPriceProvider = _context.GetEodPriceProvider(); //设置障碍期权敲入敲出 setTaskStep?.Invoke("设置障碍期权敲入敲出"); new BarrierOptionKnockioService(OptUser).SetKnockInOut(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_barrier_option),clienIds); //检查美式二元期权状态 setTaskStep?.Invoke("检查美式二元期权状态"); new BinaryOptionDealService(OptUser).CheckTouchStatus(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_binary_option), clienIds); //检查双鲨期权 setTaskStep?.Invoke("检查双鲨期权"); new DoubleSharkOptionKnockoutService(OptUser).CheckKnockoutStatus(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_double_sharkfin_option), clienIds); //检查区间累积期权 setTaskStep?.Invoke("检查区间累积期权"); new TradeRangeAccrualService(OptUser).CheckStatus(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_rangeaccrual), clienIds); //检查气囊结构 setTaskStep?.Invoke("检查气囊结构"); new TradeAirbagService(OptUser).SetKnockIn(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_airbag), clienIds); //检查互换结算日资金处理 setTaskStep?.Invoke("检查互换结算日处理"); new TradeSwapService(OptUser).HandleSwapTradeCashPre(settleDate, clienIds); //检查累计期权 setTaskStep?.Invoke("检查累计期权"); new TradeModule.AccumulatorOptionModule.TradeAccumulatorService(OptUser).CheckSettleStatus(settleDate, eodPriceProvider, out var tdForwadList, _context.StartDate, (td, tdAcc) => { blReset = ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus); }, clienIds); if (blReset) { _context.InitOtcTrades(); } else if (tdForwadList != null && tdForwadList.Any()) { _context.OtcTrades.AddRange(tdForwadList); } } /// /// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息 /// public void ExecuteTask2(Action setTaskStep) { var settleDate = _context.SettleDate; var eodPriceProvider = _context.GetEodPriceProvider(); var clienIds = _context.Request.ClientIds; //检查凤凰期权 setTaskStep?.Invoke("检查凤凰期权"); new TradeAutocallBLL(OptUser).CheckStatus(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_autocall), clienIds); //检查雪球期权 setTaskStep?.Invoke("检查雪球期权"); new TradeSnowballBLL(OptUser).CheckStatus(settleDate, eodPriceProvider, _context.StartDate , getAfterKnowInOut(t => t.trade_snowball), clienIds); } /// /// 自动定期计算互换收益 /// /// public void ExecuteBalanceSwapProfit(Action setTaskStep) { setTaskStep?.Invoke("定期结算互换收益"); var settleDate = _context.SettleDate; var clientIds=_context.Request.ClientIds; new EodSwapSettleService(OptUser).BalanceSwapTrade(settleDate, clientIds); } /// /// 自动归档收益互换 /// /// public void ExecuteEodSwapPosition(Action setTaskStep) { setTaskStep?.Invoke("定期归档收益互换"); var settleDate = _context.SettleDate; var clientIds = _context.Request.ClientIds; var nextSettleDate = QdpCalendarHelper.GetNonHoliday(settleDate.AddDays(1)); var days = (nextSettleDate - settleDate).Days; logger.Info("settleDate:" + settleDate.ToString("yyyy-MM-dd") + " nextSettleDate:" + nextSettleDate + " days:" + days); for (var i = 0; i < days; i++) { var yesterday = settleDate.AddDays(i - 1); var today = settleDate.AddDays(i); new SwapEodPositionService(OptUser).SwapPositionCompose(today, yesterday, clientIds); CalculateMargin(today, yesterday, clientIds); new SwapEodPositionService(OptUser).SwapEodCompose(today, yesterday, clientIds); } } /// /// 计算互换预付金(保证金模板V2 引擎,本端闭环)。 /// 2026-08-26 收口:原实现 HTTP 调 bond-oms /marginAlgorithm/triggerMarginCalc——Java 按 marginrate /// (旧预付金率维护数据)对在市互换算盯市并清写当天 trade_span/client_span;现改为直接跑本端预付金引擎 /// EodWorstClientPayableCalc(模板V2 三级层解析:无预付金=0、区间追保结构 x/y 或方案B收盘落档, /// 产出 trade_span.Spv 并聚合 client_span),保证金计算→追加预付金生成闭环全部在 .NET。 /// 交易范围与原 Java selectPreCloseTradeList 同口径:在市收益互换(确认成交未到期 + 平仓日落在区间), /// 剔除多空组合子交易(引擎本身跳过);"日终持仓结算"步骤随后会对确认成交全集幂等重算覆盖。 /// Java 侧自此仅保留资金通知书邮件与 DMA 实时预付金(RealtimePnlCalc.CalcDMAMargin,迁移方案阶段三待切项)。 /// preSettleDate 参数保留以维持调用签名,引擎取数按 settleDate 自行解析。 /// /// public bool CalculateMargin(DateTime settleDate, DateTime preSettleDate, IEnumerable ClientIds) { var clientIds = ClientIds?.Where(x => x > 0).Distinct().ToList(); List tradeList; using (var db = new YLErp.BLL.YLContext()) { var query = db.trade.Where(t => t.TradeType == "收益互换" && t.ValidState != YLErp.ConsGlobal.InValid && t.ParentTradeId == 0 && ((t.TradeStatus == YLErp.DBModels.ConsTrade.确认成交 && t.TradeDate <= settleDate && t.ExerciseDate >= settleDate) || (t.TradeStatus == YLErp.DBModels.ConsTrade.已平仓 && t.TradeDate <= settleDate && t.UnWindDate > settleDate && t.UnWindDate > t.StartDate))); if (clientIds != null && clientIds.Count > 0) { var idScope = clientIds; query = query.Where(t => idScope.Contains(t.ClientId)); } tradeList = query.ToList(); } new EodWorstClientPayableCalc(_context).WorstClientPayableCalc(tradeList); return true; } } /// /// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息 /// public class EodCheckMonitoredTradeSingle { public const string Step = "检查期权观察状态"; OptUserInfo user; public EodCheckMonitoredTradeSingle(OptUserInfo opt) { user = opt; } /// /// 检查障碍期权、美式二元等待观察的期权交易状态 并同步日终快照信息 /// public void ExecuteTask(DateTime StartDate, List ClientIds) { var blReset = false; var settleDate = StartDate; var clienIds = ClientIds; var eodPriceProvider = new EodPriceProvider(settleDate); //设置障碍期权敲入敲出 new BarrierOptionKnockioService(user).SetKnockInOut(settleDate, eodPriceProvider, null , null, clienIds); //检查美式二元期权状态 new BinaryOptionDealService(user).CheckTouchStatus(settleDate, eodPriceProvider, null , null, clienIds); //检查双鲨期权 new DoubleSharkOptionKnockoutService(user).CheckKnockoutStatus(settleDate, eodPriceProvider, null , null, clienIds); //检查区间累积期权 new TradeRangeAccrualService(user).CheckStatus(settleDate, eodPriceProvider, null , null, clienIds); //检查气囊结构 new TradeAirbagService(user).SetKnockIn(settleDate, eodPriceProvider, null , null, clienIds); //检查互换结算日资金处理 new TradeSwapService(user).HandleSwapTradeCashPre(settleDate, clienIds); //检查累计期权 new TradeModule.AccumulatorOptionModule.TradeAccumulatorService(user).CheckSettleStatus(settleDate, eodPriceProvider, out var tdForwadList, null, (td, tdAcc) => { blReset = ConsTrade.TradeCompleteStatus.Contains(td.TradeStatus); }, clienIds); //检查凤凰期权 new TradeAutocallBLL(user).CheckStatus(settleDate, eodPriceProvider, null , null, clienIds); //检查雪球期权 new TradeSnowballBLL(user).CheckStatus(settleDate, eodPriceProvider, null , null, clienIds); } } }