using Qdp.Pricing.Library.Options.Products.Asian; using YLErp.DBModels.Helpers; using YLErp.Enums; using YLErp.Modules.CalculationModule; using YLErp.Modules.DataProviderModule; using YLErp.Modules.SalesModule; using YLErp.Modules.TagModule; using YLErp.Modules.TradeDalModule; using YLErp.Modules.TradeModule; namespace YLErp.Web.Controllers { public abstract class OtcTradeControllerBase : BaseController { public virtual ActionResult TradeView(string enid, bool isFromPositionReport = false, bool isOnlyCloseButton = false, string operationStatus = "") { ViewBag.BinaryCalculation = valuedateBLL.BinaryCalculation; var intid = DecryptInt(enid); var tradeObj = yldb.trade.Find(intid); if (tradeObj == null) { return ShowError("没有找到交易数据"); } tradeBLL.SetFieldsByTradeType(tradeObj); TradeViewModel model; //如果是结构化主交易则转成第一个子交易显示 if (tradeObj.TradeType == "结构化交易" && tradeObj.IsGroup == 0) { tradeObj = yldb.trade.FirstOrDefault(c => c.ParentTradeId == tradeObj.id); } var hasTradeProcess = HasTradeProcess(); tradeObj.MetaDic = new TradeMetaService(CurUser).GetTradeMeta(tradeObj.id); if (tradeObj.MetaDic.ContainsKey("ActualExerciseDate") && DateTime.TryParse(tradeObj.MetaDic["ActualExerciseDate"],out DateTime newActualExerciseDate)) { tradeObj.ActualExerciseDate = newActualExerciseDate; } model = new TradeViewModel(tradeObj) { IsFromPositionReport = isFromPositionReport, BinaryCalculation = valuedateBLL.BinaryCalculation, IsOnlyCloseButton = isOnlyCloseButton, OperationStatus = operationStatus }; if (model.Trade.trade_autocall != null && model.Trade.TradeType == "凤凰期权") { var koInfo = TradeObservationHelper.GetAutocallKOObservationAndCoupon(model.Trade.trade_autocall.KOObservationDates, model.Trade.trade_autocall.CouponBarrier); model.Trade.trade_autocall.CouponObservation = koInfo.Item1; model.Trade.trade_autocall.KOObservationDates = string.IsNullOrWhiteSpace(koInfo.Item2) ? null : koInfo.Item2; } //获取结构化交易伙伴交易 if (tradeObj.ParentTradeId > 0 && tradeObj.IsGroup == 0) { model.SubTrades = yldb.trade.AsNoTracking().Where(n => n.ParentTradeId == tradeObj.ParentTradeId) .Select(t => new OtcTradeDto { id = t.id, BuySell = t.BuySell }).ToArray(); } //获取交易现金数据 var tradeWithSettlement = new TradeDalService(CurUser).GetTradeWithSettlementTradeCash(tradeObj); //获取交易销售提成数据 model.SalesCommission = new SalesCommissionDataService(CurUser).GetSalesCommissionInfoDtos(intid); if (PS.Config.ErpElement.SalesCommissionCalculation == "公式1") { foreach (var item in model.SalesCommission) {//为了迁就前端逻辑,前端展示时只取第一个; item.Commission = item.Commission * model.SalesCommission.Count(); } } model.ClientCashInCashOutList = yldb.ClientCashInCashOut.Where(c => c.TradeId == intid && c.ValidState != ConsGlobal.InValid).ToList(); model.unWindTradeCashList = tradeWithSettlement.UnwindTradeCashList; model.unwindChildrenTradeCashList = tradeWithSettlement.UnwindChildrenTradeCashList; model.maturityTradeCash = tradeWithSettlement.MaturityTradeCash; model.swapTradeCashList = tradeWithSettlement.SwapTradeCashList; model.couponTradeCashList = tradeWithSettlement.CouponTradeCashList; model.tradeMarginTemplates = new TradeQueryService(CurUser).SearchTradeMarginTemplateList(intid); model.canEditMaturityDate = tradeObj.CanEditMaturityDate() && model.maturityTradeCash != null && CurUser.交易管理_到期修改; //需要审批或者复核的交易都会显示行权审核提交按钮 model.IsShowReCheckClose = ((valuedateBLL.SystemDate.CloseReCheck == 1) || (valuedateBLL.SystemDate.CloseReApprove == 1 && hasTradeProcess)) && tradeObj.TradeStatus != ConsTrade.平仓待复核; model.CanEdit = tradeObj.CanEdit() && !isFromPositionReport && CurUser.交易管理_交易编辑; using (var tagService = new TagService(CurUser)) { model.Tags = tagService.GetTagByTradeId(intid); } using (var tagService = new TagService(CurUser)) { ViewBag.TagList = tagService.GetTagListByType(TagTypeEnum.Trade); } if (tradeObj.TradeType == "远期") { if (!string.IsNullOrWhiteSpace(tradeObj.OptionType)) { tradeObj.OptionType = (tradeObj.OptionType == "看涨") ? "多头" : "空头"; } if (!string.IsNullOrWhiteSpace(tradeObj.BasisUnderlyingCode)) { ViewBag.Underlying2Name = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeObj.BasisUnderlyingCode)?.UnderlyingName; } if (model.Trade.Comments!=null && model.Trade.Comments.Contains("累计期权")) { model.Trade.AccumulatorOptionId = yldb.trade.FirstOrDefault(l => l.TradeNumber == model.Trade.Comments.Replace("累计期权:", ""))?.EncryptId; } return View("~/Views/ForwardTrade/TradeView.cshtml", model); } if (model.maturityTradeCash != null) { //对于历史过期交易到期的数据做一下处理; //最新的到期交易,ValueDate不会大于ExerciseDate; //敲出的交易,ValueDate会小于ExerciseDate。 model.maturityTradeCash.ValueDate = model.maturityTradeCash.ValueDate > tradeObj.ExerciseDate.Value ? tradeObj.ExerciseDate.Value : model.maturityTradeCash.ValueDate; } var um = DataCacheProvider.GetUnderlyingDataSource().GetData(tradeObj.UnderlyingCode); if (um != null) { model.Trade.UnderlyingInstrumentType = um?.UnderlyingInstrumentType; model.Trade.QuoteUnitSingle = ConsGlobal.InstrumentType.Stock.Equals(um?.UnderlyingInstrumentType) ? "元/股" : ("元/" + um.QuoteUnitString); model.Trade.QuoteUnit = um.QuoteUnit; //方顿 JD TradeUnit 录的是 千克 数量是用 吨 计算的 model.Trade.TradeUnit = um.QuoteUnit == "500千克" ? "吨" : um.TradeUnit; model.Trade.CountRatio = um.CountRatio; model.Trade.TradeAmount = model.Trade.Notional / um.CountRatio; var v = DataCacheProvider.GetVarietyDataSource().GetData(um.UnderlyingTypeId); model.Trade.QuoteCurrency = v != null ? v.QuoteCurrency : ""; } SetTradeExtendForView(model); if (model.CanEdit && tradeObj.ParentTradeId > 0) { var subTrades = yldb.trade.AsNoTracking().Where(n => n.ParentTradeId == tradeObj.ParentTradeId && n.id != tradeObj.id).ToArray(); model.CanEdit &= subTrades.All(t => t.CanEdit()); } double exchangeRate = 0; if (PS.Config.Company == Configuration.CompanyEnum.中粮 && !string.IsNullOrEmpty(model.Trade.QuoteCurrency) && !"CNY".Equals(model.Trade.QuoteCurrency) && model.Trade.OriginalStockEqvNotionalV2 != null && model.Trade.MetaDic.ContainsKey("ExchangeRate") && double.TryParse(model.Trade.MetaDic["ExchangeRate"], out exchangeRate)) { model.OriginalStockEqvNotionalV2MultipleExchangeRate = ((double)model.Trade.OriginalStockEqvNotionalV2 * exchangeRate).OtcFormat(OtcFormatFlag.StockEqvNotional); } if (model.Trade.trade_accumulator_option != null && model.Trade.TradeType == "累计期权" && model.autoCallObsercationList.Where(l => !string.IsNullOrWhiteSpace(l.ConvTradeNumber)).Any()) { model.autoCallObsercationList.Where(l => !string.IsNullOrWhiteSpace(l.ConvTradeNumber)).ToList().ForEach(o => o.ConvForwardTradeId = yldb.trade.FirstOrDefault(l => l.TradeNumber == o.ConvTradeNumber)?.EncryptId); } return View("~/Views/Trade/TradeView.cshtml", model); } //交易数据扩展 private void SetTradeExtendForView(TradeViewModel model) { var tradeObj = model.Trade; switch (tradeObj.TradeType) { case "凤凰期权": case "累计期权": case "区间累积期权": { model.autoCallObsercationList = yldb.autocall_observation.Where(x => x.TradeId == tradeObj.id) .OrderBy(n => n.EndDate).ToList(); break; } case "雪球期权": { try { model.autoCallObsercationList = new TradeSnowballService(CurUser).GetObservations(tradeObj.id, valuedateBLL.ValueDate); if (model.autoCallObsercationList != null) { var tc = yldb.trade_cash.Where(c => c.TradeId == tradeObj.id && c.Action == ClientCashInCashOut.系统操作_票息 && !c.IsDeleted).FirstOrDefault(); model.autoCallObsercationList.ForEach(x => { if (tc != null) { //tc的Amount包含了年化权利金,PaymentAmount代表的是票息,从detail获取 var detail = yldb.trade_cash_detail.Where(y => y.TradeCashId == tc.id && y.Action == ClientCashInCashOut.系统操作_票息).FirstOrDefault(); if (detail != null) { x.PaymentAmount = detail.Amount.Value; } else { x.PaymentAmount = TradeHelper.GetAmountByPaymentAmount(x.PaymentAmount, tradeObj.PrincipalSum(), tradeObj.BuySell); } } else { x.PaymentAmount = TradeHelper.GetAmountByPaymentAmount(x.PaymentAmount, tradeObj.PrincipalSum(), tradeObj.BuySell); } }); } } catch (Exception ex) { ViewBag.Error = ex.Message; } break; } } //Final Price赋值 if (tradeObj.TradeStatus != ConsTrade.确认成交 || tradeObj.ExerciseDate == null) { return; } if (tradeObj.TradeType != "现金流交易") { model.ClosePrice = EodPriceQueryService.GetClosePrice(tradeObj.ExerciseDate.Value, tradeObj.UnderlyingCode); tradeObj.FinalPrice = model.ClosePrice; } if (tradeObj.TradeType == "亚式期权" && tradeObj.trade_asian_option != null && tradeObj.trade_asian_option.StrikeType != "Floating" && tradeObj.trade_asian_option.AveragingPeriodStartDate < valuedateBLL.ValueDate) { var QdpTrade = TradeCalcHelper.GetQdpTrade(tradeObj); if (QdpTrade.Instrument is AsianOption asianOpt && asianOpt.Fixings?.Count > 0) { tradeObj.FinalPrice = asianOpt.FinalPrice(); } } } protected bool HasTradeProcess() { return yldb.approvalprocess.Where(t => t.processType == "TradeProcess").Any(); } } }