using YLErp.BLL; using YLErp.Model; using YLErp.Model.Enum; using YLErp.Modules.TradeDalModule; namespace YLErp.Modules.TradeModule.DealModule { /// /// 交易平仓操作 /// public class TradeCloseService : TradeCashService { public TradeCloseService(YLBaseService baseService) : base(baseService) { } public TradeCloseService(OptUserInfo userInfo) : base(userInfo) { } /// /// 平仓待复核提交 /// public TradeCashResult CloseReCheck(TradeCashReq req, bool isFromExercise = false) { var tradeDalService = new TradeDalService(OptUser); //这个对象只提供收盘前数据,用于创建TradeCash记录 var td = tradeDalService.GetTradeOrEodTrade(new[] { req.TradeId }, req.ValueDate ?? SystemValueDate).FirstOrDefault(); if (td == null) { if (isFromExercise) { throw new ServiceException("行权失败,该交易不存在,不能提交行权审核"); } else { throw new ServiceException("平仓失败,该交易不存在,不能提交平仓审核"); } } if (td.TradeType == "结构化交易") { throw new ServiceException("操作失败,结构化交易主交易不支持此操作"); } if (td.TradeStatus != ConsTrade.确认成交 && td.TradeStatus != ConsTrade.提前终止拒绝) { if (isFromExercise) { throw new ServiceException("行权失败,该交易处于待" + td.TradeStatus + "状态,不能提交行权审核!"); } else { throw new ServiceException("平仓失败,该交易处于待" + td.TradeStatus + "状态,不能提交平仓审核!"); } } if (PS.Config.TradeElement.ExecuteAfterGeneratedConfirmDoc && td.TradeType != "远期" && td.TradeType != "自定义交易" && td.TradeType != "现金流交易" && !DbContext.trade_contract_r.Any(n => n.TradeId == td.id && n.Type == "交易确认书" && n.IsValid)) { throw new ServiceException("请先去生成交易确认书"); } bool isPartialClose = false; if (req != null) { unwindPreHandle(req, td, isFromExercise, out isPartialClose); } //保存tradecash //增加现金交割交易记录 req.ValidState = ConsGlobal.InValid; var tc = CloseTrade_TradeCashSave(td, req, false, !isFromExercise, !isPartialClose); var hasTradeProcess = HasTradeProcess(); CloseReCheck_SetTrade(td.id, isFromExercise, hasTradeProcess); //配对 平仓待复合提交 if (req.IsUnwindPairTrade && !string.IsNullOrEmpty(td.PairTrade)) { int pairTradeId = Convert.ToInt32(td.PairTrade); //这个对象只提供收盘前数据,用于创建TradeCash记录 var pairTrade = tradeDalService.GetTradeOrEodTrade(new[] { pairTradeId }, req.ValueDate.Value).FirstOrDefault(); //配对交易平仓总份额取各自剩余的总份额 req.Notional = pairTrade.Notional; //UnwindNotional >= Notional代表全部品仓,配对交易的平仓份额为自己剩余的总份额 //UnwindNotional < td.Notional部分平仓,配对的两笔交易部分平仓份额相等,即req.UnwindNotional不变 if (req.UnwindNotional >= Math.Floor(pairTrade.Notional * Math.Pow(10, 8)) / Math.Pow(10, 8)) { req.UnwindNotional = pairTrade.Notional; } if (isFromExercise) { req.UnwindFee = -req.UnwindFee; } CloseTrade_TradeCashSave(pairTrade, req, !isFromExercise, !isPartialClose); CloseReCheck_SetTrade(pairTrade.id, isFromExercise, hasTradeProcess); } DbContext.SaveChanges(); return new TradeCashResult(td, tc); } //平仓待复核提交 public void CloseReCheck_SetTrade(int tradeId, bool isFromExercise, bool hasTradeProcess) { var td = DbContext.trade.Find(tradeId); td.OptId = UserId; td.OptName = UserName; td.OptDate = OptDate; if (isFromExercise) { td.TradeStatus = ConsTrade.行权待复核; } else { td.TradeStatus = ConsTrade.平仓待复核; } td.CheckStatus = Convert.ToInt32(TradeCheckEnum.StatusOfOld); //检查是否有交易审批流程 if (valuedateBLL.SystemDate.CloseReApprove == 1 && hasTradeProcess) { // 如果有审批组 InitTradeProcessOrder(td, UserId); } AddTradeOperationHistoryAndSetParentTradeInfo(false, td, isFromExercise ? "部分行权审核提交" : "平仓审核提交"); } } /// /// /// public class TradeCashResult { public TradeCashResult(trade td, trade_cash tc) { Trade = td ?? throw new ArgumentNullException(nameof(td)); TradeCash = tc ?? throw new ArgumentNullException(nameof(tc)); } public trade Trade { get; } public trade_cash TradeCash { get; } } }