using YLErp.BLL; using YLErp.Commons; using YLErp.DBModels.Helpers; using YLErp.QdpModule; using static iTextSharp.text.pdf.AcroFields; namespace YLErp.Modules.TradeModule { /// /// 交易扩展通用服务 /// public class TradeExtendService : YLBaseService { public TradeExtendService(OptUserInfo optUser, YLContext dbContext) : base(optUser, dbContext) { } public TradeExtendService(YLBaseService baseService) : base(baseService) { } public TradeExtendService(OptUserInfo userInfo) : base(userInfo) { } /// /// 设置奇异要素 /// public void SetTradeExtendWithCnKey(IEnumerable otcTrades, bool setMetaData = false, DateTime? dateTime = null) { if (otcTrades is null || !otcTrades.Any()) { return; } Dictionary getTradeEx(IEnumerable tids) where T : TradeExtendBase { return DbContext.Set().AsNoTracking().Where(n => tids.Contains(n.TradeId)).ToDictionary(n => n.TradeId); } var extGroups = otcTrades.GroupBy(n => n.IsGroup == 1 && n.StructureType == "气囊结构" ? "气囊结构" : n.TradeType).ToArray(); foreach (var g in extGroups) { var tids = g.Select(n => n.id).ToHashSet(); switch (g.Key) { case "亚式期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; if (dic.TryGetValue(td.id, out var ext)) { extDic["亚式_均价起算日"] = ext.AveragingPeriodStartDate.OtcFormatDate(); extDic["亚式_均价计算"] = TradeHelper.GetAsianPayoffTypeCn(ext.PayoffType); if (ext.PayoffTypeCn.Contains("增强")) { extDic["亚式_结算类型"] = ext.SettleMode == "AtEnd" ? "递延" : "立即"; } else { extDic["亚式_结算类型"] = ""; } extDic["亚式_行权价类型"] = TradeHelper.GetAsianStrikeTypeCn(ext.StrikeType); extDic["亚式_杠杆率"] = ext.StrikeGearingFactor.OtcFormatPercent(); if (td.TradeType == "亚式期权" && ext.PayoffType == "EnhancedArithmeticAverage" && ext.StrikeType != "Floating") { if (td.IsMoneynessOptionData) { extDic["增强价格"] = ext.EnhancedPrice.OtcFormatPercent(); } else { extDic["增强价格"] = ext.EnhancedPrice.OtcFormatUmPrice(); } } else { extDic["增强价格"] = ""; } } } } break; case "障碍期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["障碍_障碍类型"] = ext.BarrierType; extDic["障碍_障碍价格"] = ext.BarrierPrice.OtcFormatUmPrice(isMoneyness); extDic["障碍_高障碍价格"] = ext.UpperBarrierPrice.OtcFormatUmPrice(isMoneyness); extDic["障碍_补偿支付"] = TradeHelper.GetRebateTypeCn(ext.RebateType); extDic["障碍_补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateRate, ext.Rebate); extDic["障碍_高障碍补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateHighRate, ext.RebateHigh); extDic["障碍_障碍偏移"] = NumberHelper.Format(ext.BarrierShift, "F2"); extDic["障碍_观察方式"] = ext.Discrete; extDic["障碍_敲入敲出状态"] = ext.KnockInOutStatusCn; extDic["障碍_敲入敲出日期"] = ext.KnockInOutDate.OtcFormatDate(); extDic["障碍_补偿按敲出日年化"] = ext.RebateAnnualizedAtKO ? "是" : "否"; extDic["障碍_补偿计息规则"] = ext.RebateDayCount; } } } break; case "双鲨期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["双鲨_低障碍价格"] = ext.BarrierLow.OtcFormatUmPrice(isMoneyness); extDic["双鲨_高障碍价格"] = ext.BarrierHigh.OtcFormatUmPrice(isMoneyness); extDic["双鲨_低行权价"] = td.Strike.OtcFormatUmPrice(isMoneyness); extDic["双鲨_高行权价"] = ext.StrikeHigh.OtcFormatUmPrice(isMoneyness); extDic["双鲨_补偿支付"] = TradeHelper.GetRebateTypeCn(ext.RebateType); extDic["双鲨_补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateRate, ext.Rebate); extDic["双鲨_高障碍补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.RebateHighRate, ext.RebateHigh); extDic["双鲨_观察方式"] = ext.Discrete; extDic["双鲨_高参与率"] = ext.CallParticipationRate.OtcFormatPercent(); extDic["双鲨_低参与率"] = ext.PutParticipationRate.OtcFormatPercent(); extDic["双鲨_敲入敲出日期"] = ext.KnockInOutDate.OtcFormatDate(); extDic["双鲨_敲入敲出状态"] = ext.KnockInOutStatusCn; } } } break; case "二元期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["二元_二元类型"] = ext.PayoffType; extDic["二元_高障碍价格"] = ext.UpperBarrier.OtcFormatUmPrice(isMoneyness); extDic["二元_补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.CashOrNothingAmountRate, ext.CashOrNothingAmount); extDic["二元_高障碍补偿金额"] = OtcFormatHelper.FormatPremium(td.IsUsePremiumRate, ext.CashOrNothingAmountHighRate, ext.CashOrNothingAmountHigh); extDic["二元_观察方式"] = ext.MonitorType; extDic["二元_补偿支付"] = TradeHelper.GetRebateTypeCn(ext.RebateType); extDic["二元_一级收益率"] = (td.IsUsePremiumRate == true ? (td.PremiumRate > 0 ? (ext.CashOrNothingAmountRate ?? 0) / td.PremiumRate.Value : 0) : (td.TradeSinglePrice > 0 ? (ext.CashOrNothingAmount ?? 0) / td.TradeSinglePrice.Value : 0)).OtcFormat(OtcFormatFlag.percent); extDic["二元_保底收益率"] = (td.PrincipalRate ?? 0).OtcFormat(OtcFormatFlag.percent); extDic["二元_补偿按敲出日年化"] = ext.RebateAnnualizedAtKO ? "是" : "否"; extDic["二元_补偿计息规则"] = ext.RebateDayCount; } } } break; case "区间累积期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["区间累积_区间下限"] = ext.LowerRange.OtcFormatUmPrice(isMoneyness); extDic["区间累积_区间上限"] = ext.UpperRange.OtcFormatUmPrice(isMoneyness); extDic["区间累积_观察日期"] = string.IsNullOrEmpty(ext.ObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : ext.ObservationDates; extDic["区间累积_区间收益"] = ext.BonusRate.OtcFormatPercent(4); } } } break; case "气囊结构": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["气囊_障碍价格"] = ext.Barrier.OtcFormatUmPrice(isMoneyness); extDic["气囊_是否离散观察"] = ext.IsDiscreteMonitored ? "是" : "否"; extDic["气囊_未敲入参与率"] = ext.NotKIParticipationRate.OtcFormatPercent(); extDic["气囊_敲入参与率"] = ext.KIParticipationRate.OtcFormatPercent(); extDic["气囊_收益封顶"] = ext.HasPayoffLimit ? "是" : "否"; extDic["气囊_收益封顶价格"] = ext.HasPayoffLimit ? ext.HighStrike.OtcFormatUmPrice(isMoneyness) : ""; extDic["气囊_敲入敲出状态"] = ext.KnockInOutStatusCn; extDic["气囊_敲入敲出日期"] = ext.KnockInOutDate.OtcFormatDate(); } } } break; case "收益增强结构": { var dic = getTradeEx(tids); foreach (var td in g) { if (dic.TryGetValue(td.id, out var ext)) { td.MetaDic["收益增强_年化增强收益"] = ext.AnnualizedEnhanceRate.OtcFormatPercent(4); } } } break; case "凤凰期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["凤凰_票息年化"] = ext.IsFixedCoupon ? "否" : "是"; extDic["凤凰_票息率"] = GetCoupon(ext.IsFixedCoupon, ext.CouponDayCount, ext.Coupon).OtcFormat(OtcFormatFlag.premiumRateP); extDic["凤凰_票息日历规则"] = ext.CouponDayCount; extDic["凤凰_票息包含首日"] = ext.CouponIncludeStartDate == true ? "是" : "否"; extDic["凤凰_使用支付日计息"] = ext.CouponUsePaymentDate == true ? "是" : "否"; extDic["凤凰_票息障碍价格"] = ext.CouponBarrier.OtcFormatUmPrice(isMoneyness); extDic["凤凰_票息结算方式"] = ext.CouponPayTypeDesc(); extDic["凤凰_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness); extDic["凤凰_敲入障碍价格"] = ext.KIBarrier.OtcFormatUmPrice(isMoneyness); extDic["凤凰_敲入到期是否支付票息"] = ext.IncludeCouponAfterKI ? "是" : "否"; extDic["凤凰_敲入到期支付类别"] = ext.KIPayoffTypeDesc(); extDic["凤凰_敲入行权价1"] = ext.SpreadStrike1.OtcFormatUmPrice(isMoneyness); extDic["凤凰_敲入行权价2"] = ext.SpreadStrike.OtcFormatUmPrice(isMoneyness); var KOObservationDates = ext.KOObservationDates ?? string.Empty; var CouponObservation = string.Empty; if (!string.IsNullOrWhiteSpace(KOObservationDates) && KOObservationDates.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries).Any()) { var koInfo = TradeObservationHelper.GetAutocallKOObservationAndCoupon(ext.KOObservationDates, ext.CouponBarrier); var koObInfo = koInfo.Item2; var customizedResults = koObInfo.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); if (customizedResults != null && customizedResults.Any()) { var koObservationDates = customizedResults[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var customizedKOBarriers = customizedResults[1].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); //|| customizedCoupons != null && customizedCoupons.Distinct().Count() >= 2 if (customizedKOBarriers != null && customizedKOBarriers.Distinct().Count() >= 2) { KOObservationDates = string.Empty; var index = 0; foreach (var date in koObservationDates) { KOObservationDates += date.ToString() + "," + Convert.ToDouble(customizedKOBarriers[index]).OtcFormatUmPrice(isMoneyness) + ";"; index++; } } else if (koObservationDates != null) { KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString())); } } else { KOObservationDates = ""; } var coInfo = koInfo.Item1; if (coInfo != null) { var coResults = coInfo.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries); var coObservationDates = coResults[0].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var coBarriers = coResults[1].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); var coCoupons = coResults[2].Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); if (coCoupons != null && coCoupons.Distinct().Count() >= 2) { var index = 0; foreach (var date in coObservationDates) { CouponObservation += date.ToString() + "," + Convert.ToDouble(coBarriers[index]).OtcFormatUmPrice(isMoneyness) + "," + Convert.ToDouble(coCoupons[index]).OtcFormatUmPrice(isMoneyness) + ";"; index++; } } else if (coObservationDates != null) { CouponObservation = string.Join(";", coObservationDates.Select(O => O.ToString())); } } } extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : KOObservationDates; extDic["票息观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : CouponObservation; extDic["敲入观察频率"] = string.IsNullOrEmpty(ext.ObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : ext.ObservationDates; extDic["期权年化"] = ext.IsAnnualized2 ? "是" : "否"; extDic["凤凰_敲入敲出状态"] = ext.KnockInOutStatusCn; } } } break; case "收益互换": //{ // var dic = getTradeEx(tids); // foreach (var td in g) // { // var extDic = td.MetaDic; // var isMoneyness = td.IsMoneynessOption == "是"; // if (dic.TryGetValue(td.id, out var ext)) // { // var PaySwapTimeAndRate = ext.PaySwapTimeAndRate == null ? "" : ext.PaySwapTimeAndRate.Split(';')[1]; // var GetSwapTimeAndRate = ext.GetSwapTimeAndRate == null ? "" : ext.GetSwapTimeAndRate.Split(';')[1]; // var GetSwapTime = ext.GetSwapTimeAndRate == null ? "" : ext.GetSwapTimeAndRate.Substring(0, ext.GetSwapTimeAndRate.IndexOf(";")); // var PaySwapTime = ext.PaySwapTimeAndRate == null ? "" : ext.PaySwapTimeAndRate.Substring(0, ext.PaySwapTimeAndRate.IndexOf(";")); // var GetUnderlyingAssetName = DataCacheProvider.GetUnderlyingDataSource().GetData(ext.GetUnderlyingCode)?.UnderlyingName; // var PayUnderlyingAssetName = DataCacheProvider.GetUnderlyingDataSource().GetData(ext.PayUnderlyingCode)?.UnderlyingName; // var PaySingleFeeToString = ""; // var GetSingleFeeToString = ""; // #region 单位交易费用导出逻辑 // if (ext.IsGetFloatingProfit == false && ext.GetUnAnnualRate < 1 && ext.GetUnAnnualRate > 0) // { // GetSingleFeeToString = ext.GetUnAnnualRate.OtcFormatPercent(4); // } // else // { // GetSingleFeeToString = ext.GetSingleFee.OtcFormatUmPrice(); // } // if (ext.IsPayFloatingProfit == false && ext.PayUnAnnualRate < 1 && ext.PayUnAnnualRate > 0) // { // PaySingleFeeToString = ext.PayUnAnnualRate.OtcFormatPercent(4); // } // else // { // PaySingleFeeToString = ext.PaySingleFee.OtcFormatUmPrice(); // } // #endregion // extDic["互换_支付方互换利率"] = PaySwapTimeAndRate; // extDic["互换_支付方标的代码"] = ext.PayUnderlyingCode; // extDic["互换_支付方标的名称"] = PayUnderlyingAssetName; // extDic["互换_支付方期初标的价格"] = ext.PaySpotPrice.OtcFormatUmPrice(); // extDic["互换_支付方交易数量"] = ext.PayTradeAmount.OtcFormatNotional(); // extDic["互换_支付方到期标的价格"] = ext.PayFinalPrice.OtcFormatUmPrice(); // extDic["互换_支付方固定收益"] = ext.PayFixedProfit.OtcFormat(OtcFormatFlag.tradePrice); // extDic["互换_支付方单位交易费用"] = PaySingleFeeToString; // extDic["互换_支付方初始预付金"] = ext.PayMarginRate.OtcFormatPercent(); // extDic["互换_支付方交易费用"] = ext.PayTradePrice.OtcFormat(OtcFormatFlag.tradePrice); // extDic["互换_支付方多空方向"] = ext.PayLongShort; // extDic["互换_收取方单位交易费用"] = GetSingleFeeToString; // extDic["互换_收取方互换利率"] = GetSwapTimeAndRate; // extDic["互换_收取方固定收益"] = ext.GetFixedProfit.OtcFormat(OtcFormatFlag.tradePrice); // extDic["互换_收取方初始预付金"] = ext.GetMarginRate.OtcFormatPercent(); // extDic["互换_收取方交易费用"] = ext.GetTradePrice.OtcFormat(OtcFormatFlag.tradePrice); // extDic["互换_收取方标的代码"] = ext.GetUnderlyingCode; // extDic["互换_收取方标的名称"] = GetUnderlyingAssetName; // extDic["互换_收取方多空方向"] = ext.GetLongShort; // extDic["互换_收取方期初标的价格"] = ext.GetSpotPrice.OtcFormatUmPrice(); // extDic["互换_收取方交易数量"] = ext.GetTradeAmount.OtcFormatNotional(); // extDic["互换_收取方到期标的价格"] = ext.GetFinalPrice.OtcFormatUmPrice(); // extDic["互换_互换日期"] = GetSwapTime ?? PaySwapTime; // extDic["年化天数"] = ext.AnnualDays.ToString(); // } // } //} break; case "掉期": case "远期": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; if (dic.TryGetValue(td.id, out var ext)) { extDic["手数"] = td.Lots.OtcFormatMoney(); extDic["挂钩标的"] = td.BasisUnderlyingCode; extDic["基差"] = td.BasisGap.OtcFormatNotional(); extDic["远期价值"] = ext.ForwardValue.OtcFormatMoney(); extDic["开仓费用"] = (ext.OpenCommission * -1).OtcFormatMoney(); extDic["开仓总费用"] = (td.TradePrice * -1).OtcFormatMoney(); extDic["年化预付金成本"] = ext.AnnualMarginRate.OtcFormatPercent(); extDic["年化仓储成本"] = ext.AnnualStoragePrice.OtcFormatMoney(); extDic["均价计算日期"] = ext.ObservationDates; } } } break; case "雪球期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { var KOObservationDates = ext.KOObservationDates ?? string.Empty; if (!string.IsNullOrWhiteSpace(KOObservationDates)) { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ext.KOObservationDates); var koObservationDates = customizedResults.Item1; var customizedKOBarriers = customizedResults.Item2; var customizedCoupons = customizedResults.Item3; if (customizedKOBarriers != null && customizedKOBarriers.Distinct().Count() >= 2 || customizedCoupons != null && customizedCoupons.Distinct().Count() >= 2) { KOObservationDates = string.Empty; var index = 0; foreach (var date in koObservationDates) { KOObservationDates += date.ToString() + "," + customizedKOBarriers[index].OtcFormatUmPrice(isMoneyness) + "," + customizedCoupons[index].OtcFormat(OtcFormatFlag.premiumRateP) + ";"; index++; } } else { KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString())); } } extDic["雪球_红利票息"] = ext.Coupon./*OtcFormatPercent()*/OtcFormatFlex(2, percent: true); extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : KOObservationDates; extDic["敲入观察频率"] = ext.IsInitialKnockedIn ? "" : (string.IsNullOrEmpty(ext.ObservationDates) ? "起始日(含)至到期日(含)间每一交易日" : ext.ObservationDates); extDic["期权年化"] = ext.IsAnnualized2 ? "是" : "否"; extDic["雪球_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness); extDic["雪球_敲入敲出状态"] = ext.KnockInOutStatusCn; switch (ext.KOPayoffType) { case KOPayoffTypeEnum.Rebate: extDic["雪球_敲出赔付类别"] = "票息补偿"; extDic["雪球_票息年化"] = ext.IsFixedCoupon ? "否" : "是"; extDic["雪球_票息率"] = ext.KORebate.OtcFormat(OtcFormatFlag.premiumRateP); extDic["雪球_票息日历规则"] = ext.CouponDayCount; extDic["雪球_票息包含首日"] = ext.CouponIncludeStartDate == true ? "是" : "否"; extDic["雪球_使用支付日计息"] = ext.CouponUsePaymentDate == true ? "是" : "否"; extDic["雪球_年化期权费率"] = ext.AnnualizedPremiumRate.OtcFormat(OtcFormatFlag.premiumRateP); if (!string.IsNullOrWhiteSpace(ext.KOObservationSettleDates)) { extDic["雪球_票息支付日期"] = ext.KOObservationSettleDates; } else { extDic["雪球_票息支付日期"] = extDic["敲出观察频率"]; } break; case KOPayoffTypeEnum.ToOption: extDic["雪球_敲出赔付类别"] = KOPayoffTypeEnumHelper.GetDesc(KOPayoffTypeEnum.ToOption, td.CallPut); extDic["雪球_敲出行权价1"] = ext.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; case KOPayoffTypeEnum.ToSpreadOption: extDic["雪球_敲出赔付类别"] = KOPayoffTypeEnumHelper.GetDesc(KOPayoffTypeEnum.ToSpreadOption, td.CallPut); extDic["雪球_敲出行权价2"] = ext.SpreadStrikeAtKO.OtcFormatUmPrice(isMoneyness); extDic["雪球_敲出行权价1"] = ext.SpreadStrikeAtKO1.OtcFormatUmPrice(isMoneyness); break; default: extDic["雪球_敲出赔付类别"] = ext.KOPayoffType.ToString(); break; } extDic["雪球_敲出支付方式"] = RebateTypeEnumHelper.GetDesc(ext.KORebateType); extDic["雪球_初始敲入"] = ext.IsInitialKnockedIn ? "是" : "否"; extDic["雪球_敲入障碍价格"] = ext.IsInitialKnockedIn ? "" : ext.KIBarrier.OtcFormatUmPrice(isMoneyness); switch (ext.KIPayoffType) { case KIPayoffTypeEnum.None: extDic["雪球_敲入到期支付类别"] = "无"; break; case KIPayoffTypeEnum.ToPutOption: extDic["雪球_敲入到期支付类别"] = "敲入转看跌"; extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToPutSpreadOption: extDic["雪球_敲入到期支付类别"] = "敲入转熊市价差"; extDic["雪球_封顶/封底"] = extDic["雪球_敲入行权价2"] = ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness); extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToCallOption: extDic["雪球_敲入到期支付类别"] = "敲入转看涨"; extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; case KIPayoffTypeEnum.ToCallSpreadOption: extDic["雪球_敲入到期支付类别"] = "敲入转牛市价差"; extDic["雪球_封顶/封底"] = extDic["雪球_敲入行权价2"] = ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness); extDic["雪球_敲入行权价"] = extDic["雪球_敲入行权价1"] = ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness); break; default: extDic["雪球_敲入到期支付类别"] = ext.KIPayoffType.ToString(); break; } if (PS.Config.IsGuoJun) { var instrumentTypeArr = ConsGlobal.InstrumentType.EquityTypes(); if (!instrumentTypeArr.Contains(DataCacheProvider.GetUnderlyingDataSource().GetData(td.UnderlyingCode).UnderlyingInstrumentType)) { if (td.OptionType == "看涨") { extDic["雪球_敲入行权价1"] = (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || ext.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption ? ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness) : ""); extDic["雪球_敲入行权价2"] = (ext.KIPayoffType != KIPayoffTypeEnum.None ? ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness) : ""); } else { extDic["雪球_敲入行权价1"] = (ext.KIPayoffType != KIPayoffTypeEnum.None ? ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness) : ""); extDic["雪球_敲入行权价2"] = (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || ext.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption ? ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness) : ""); } } else { extDic["雪球_敲入行权价1"] = (ext.KIPayoffType == KIPayoffTypeEnum.ToPutSpreadOption || ext.KIPayoffType == KIPayoffTypeEnum.ToCallSpreadOption ? ext.SpreadStrikeAtMaturity.OtcFormatUmPrice(isMoneyness) : ""); extDic["雪球_敲入行权价2"] = (ext.KIPayoffType != KIPayoffTypeEnum.None ? ext.SpreadStrikeAtMaturity1.OtcFormatUmPrice(isMoneyness) : ""); } } } } } break; case "现金流交易": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; if (dic.TryGetValue(td.id, out var ext)) { extDic["利率"] = ext.ProfitRate.OtcFormatPercent(); extDic["利率类型"] = ext.RateType.ToString(); extDic["计息日历规则"] = ext.ProfitDayCount; extDic["预付返还比例"] = ext.PrepayRatio.OtcFormatPercent(); } } } break; case "累计期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["累计期权_结构类型"] = ext.AccumulatorStructureType.ToString(); if (ext.AccumulatorStructureType == AccumulatorStructureTypeEnum.Segmented) { //获取 trade ,valuedate extDic["累计三段式_行权价2"] = ext.Strike2.OtcFormatUmPrice(isMoneyness); extDic["累计三段式_行权价3"] = ext.Strike3.OtcFormatUmPrice(isMoneyness); extDic["累计三段式_乘数1"] = ext.Multiplier.OtcFormatUmPrice(); extDic["累计三段式_乘数2"] = ext.Multiplier2.OtcFormatUmPrice(); extDic["累计三段式_乘数3"] = ext.Multiplier3.OtcFormatUmPrice(); if (dateTime != null) { var td_db = DbContext.trade.FirstOrDefault(l => l.id == td.id); bool Isexist = new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(td_db, Convert.ToDateTime(dateTime)); if (Isexist) extDic["累计三段式_敲出障碍价格"] = td_db.trade_accumulator_option.KOBarrier.OtcFormatUmPrice(isMoneyness); else extDic["累计三段式_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness); } else { extDic["累计三段式_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness); } extDic["累计三段式_上端收益类型"] = ext.PayoffType; extDic["累计三段式_累计类型"] = ext.AccumuType; if (ext.PayoffType == "固定") { extDic["累计三段式_票息1"] = ext.Coupon.OtcFormat(ext.CouponPercent ? OtcFormatFlag.premiumRateP : OtcFormatFlag.umprice); extDic["累计三段式_票息2"] = ext.Coupon2.OtcFormat(ext.CouponPercent ? OtcFormatFlag.premiumRateP : OtcFormatFlag.umprice); extDic["累计三段式_票息日历规则"] = ext.CouponDayCount; extDic["累计三段式_票息年化"] = ext.IsFixedCoupon ? "否" : "是"; } extDic["累计三段式_敲出是否终止"] = ext.EarlyTerminate ? "是" : "否"; if (string.IsNullOrEmpty(ext.KOObservationDates)) { extDic["累计三段式_观察日期"] = "起始日至到期日(含)间每一交易日"; } else { extDic["累计三段式_观察日期"] = ext.KOObservationDates; } extDic["累计三段式_结算方式1"] = ext.SettlementMode == "现金结算" ? "现金结算(当日)" : ext.SettlementMode; //判断结算方式是否为实物交割 if (ext.SettlementMode != "实物交割"&& ext.SettlementMode!= "现金实物合并结算") { extDic["累计三段式_远期期初价类型1"] = null; extDic["累计三段式_远期到期日类型1"] = null; } else { extDic["累计三段式_远期期初价类型1"] = ext.ForwardPriceType; extDic["累计三段式_远期到期日类型1"] = ext.ForwardDateType; } extDic["累计三段式_结算方式2"] = ext.SettlementMode2 == "现金结算" ? "现金结算(当日)" : ext.SettlementMode2; //判断结算方式是否为实物交割 if (ext.SettlementMode2 != "实物交割"&& ext.SettlementMode2 != "现金实物合并结算") { extDic["累计三段式_远期期初价类型2"] = null; extDic["累计三段式_远期到期日类型2"] = null; } else { extDic["累计三段式_远期期初价类型2"] = ext.ForwardPriceType2; extDic["累计三段式_远期到期日类型2"] = ext.ForwardDateType2; } extDic["累计三段式_结算方式3"] = ext.SettlementMode3 == "现金结算" ? "现金结算(当日)" : ext.SettlementMode3; //判断结算方式是否为实物交割 if (ext.SettlementMode3 != "实物交割" && ext.SettlementMode3 != "现金实物合并结算") { extDic["累计三段式_远期期初价类型3"] = null; extDic["累计三段式_远期到期日类型3"] = null; } else { extDic["累计三段式_远期期初价类型3"] = ext.ForwardPriceType3; extDic["累计三段式_远期到期日类型3"] = ext.ForwardDateType3; } extDic["累计三段式_沽购数量"] = ext.OriginalAccumuTradeAmount.OtcFormatUmPrice(); var KOObservationDates = ext.KOObservationDates ?? string.Empty; if (!string.IsNullOrWhiteSpace(KOObservationDates)) { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ext.KOObservationDates); var koObservationDates = customizedResults.Item1; KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString())); } extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日至到期日(含)间每一交易日" : KOObservationDates; } else { //获取 trade ,valuedate if (dateTime != null) { var td_db = DbContext.trade.FirstOrDefault(l => l.id == td.id); bool Isexist = new OptionTradeActionRestoreService(this).RestoreTradeDataToSpecialDay(td_db, Convert.ToDateTime(dateTime)); if (Isexist) extDic["累计_敲出障碍价格"] = td_db.trade_accumulator_option.KOBarrier.OtcFormatUmPrice(isMoneyness); else extDic["累计_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness); } else { extDic["累计_敲出障碍价格"] = ext.KOBarrier.OtcFormatUmPrice(isMoneyness); } extDic["累计_上端收益类型"] = ext.PayoffType; extDic["累计_累计类型"] = ext.AccumuType; if (ext.PayoffType == "固定") { extDic["累计_票息"] = ext.Coupon.OtcFormat(ext.CouponPercent ? OtcFormatFlag.premiumRateP : OtcFormatFlag.umprice); extDic["累计_票息日历规则"] = ext.CouponDayCount; extDic["累计_票息年化"] = ext.IsFixedCoupon ? "否" : "是"; } extDic["累计_看涨乘数"] = ext.CallMultiplier.OtcFormatUmPrice(); extDic["累计_看跌乘数"] = ext.PutMultiplier.OtcFormatUmPrice(); extDic["累计_杠杆倍数"] = ConsGlobal.CallPut.IsCall(td.CallPut) ? extDic["累计_看跌乘数"] : extDic["累计_看涨乘数"]; extDic["累计_敲出是否终止"] = ext.EarlyTerminate ? "是" : "否"; extDic["累计_结算方式"] = ext.GetSettlementModeDesc(); if (string.IsNullOrEmpty(ext.KOObservationDates)) { extDic["累计_观察日期"] = "起始日至到期日(含)间每一交易日"; } else { extDic["累计_观察日期"] = ext.KOObservationDates; } //判断结算方式是否为实物交割 if (ext.GetSettlementModeDesc() != "实物交割"&& ext.GetSettlementModeDesc() != "现金实物合并结算") { extDic["累计_远期期初价类型"] = null; extDic["累计_远期到期日类型"] = null; } else { extDic["累计_远期期初价类型"] = ext.ForwardPriceType; extDic["累计_远期到期日类型"] = ext.ForwardDateType; } extDic["累计_沽购数量"] = ext.OriginalAccumuTradeAmount.OtcFormatUmPrice(); var KOObservationDates = ext.KOObservationDates ?? string.Empty; if (!string.IsNullOrWhiteSpace(KOObservationDates)) { var customizedResults = QdpHelper.ParseAutocallCustomizedInfo(ext.KOObservationDates); var koObservationDates = customizedResults.Item1; KOObservationDates = string.Join(";", koObservationDates.Select(O => O.ToString())); } extDic["敲出观察频率"] = string.IsNullOrEmpty(ext.KOObservationDates) ? "起始日至到期日(含)间每一交易日" : KOObservationDates; } } } } break; case "自定义交易": { var otherTrades = otcTrades.Where(x => x.ExtendInfo != null).ToList(); otherTrades.ForEach(x => { if (x.Propertys != null) { foreach (var item in x.Propertys) { var extDic = x.MetaDic; extDic["自定义_" + item.name] = item.value; } } }); } break; case "Risky期权": { var dic = getTradeEx(tids); foreach (var td in g) { var extDic = td.MetaDic; var isMoneyness = td.IsMoneynessOption == "是"; if (dic.TryGetValue(td.id, out var ext)) { extDic["Risky_执行价格1"] = ext.Strike1.OtcFormatUmPrice(isMoneyness); extDic["Risky_执行价格2"] = ext.Strike2.OtcFormatUmPrice(isMoneyness); extDic["Risky_执行价格3"] = ext.Strike3.OtcFormatUmPrice(isMoneyness); extDic["Risky_参与率1"] = ext.ParticipationRate1.OtcFormat(OtcFormatFlag.premiumRateP); extDic["Risky_参与率2"] = ext.ParticipationRate2.OtcFormat(OtcFormatFlag.premiumRateP); extDic["Risky_参与率3"] = ext.ParticipationRate3.OtcFormat(OtcFormatFlag.premiumRateP); } }; } break; } } if (setMetaData) { SetTradeMeta(otcTrades); } } /// /// 转化票息率 /// /// 是否年化 false 是 true 否 /// 票息日历规则 /// 票息率 /// private double GetCoupon(bool isFixedCoupon, string couponDayCount, double coupon) { //if (PS.Config.Company == Configuration.CompanyEnum.国泰君安) //{ // if (isFixedCoupon) // { // switch (couponDayCount) // { // case "Monthly": // return coupon * 12; // default: // return coupon; // } // } //} return coupon; } /// /// 设置奇异要素 /// public void SetTradeExtend(IEnumerable otcTrades, bool setMetaData = false) { if (otcTrades is null || !otcTrades.Any()) { return; } void setTradeEx(IEnumerable tds) where T : TradeExtendBase { var tids = tds.Select(n => n.id).ToHashSet(); var dic = DbContext.Set().Where(n => tids.Contains(n.TradeId)).ToDictionary(n => n.TradeId); foreach (var td in tds) { if (dic.TryGetValue(td.id, out var ext)) { YLAutoMapper.Map(ext, td); } } } var extGroups = otcTrades.GroupBy(n => n.IsGroup == 1 && n.StructureType == "气囊结构" ? "气囊结构" : n.TradeType).ToArray(); foreach (var g in extGroups) { switch (g.Key) { case "亚式期权": setTradeEx(g); break; case "障碍期权": setTradeEx(g); break; case "双鲨期权": setTradeEx(g); break; case "二元期权": setTradeEx(g); break; case "区间累积期权": setTradeEx(g); break; case "气囊结构": setTradeEx(g); break; case "收益增强结构": setTradeEx(g); break; case "凤凰期权": setTradeEx(g); break; case "雪球期权": setTradeEx(g); break; case "累计期权": setTradeEx(g); break; case "现金流交易": setTradeEx(g); break; case "自定义交易": setTradeEx(g); break; case "Risky期权": setTradeEx(g); break; } } if (setMetaData) { SetTradeMeta(otcTrades); } } public void SetTradeExtend(OtcOptionTradeFull otcTrade, trade input) { if (otcTrade == null || input == null) { return; } switch (otcTrade.TradeType) { case "亚式期权": setTradeEx(input.trade_asian_option); break; case "障碍期权": setTradeEx(input.trade_barrier_option); break; case "双鲨期权": setTradeEx(input.trade_double_sharkfin_option); break; case "二元期权": setTradeEx(input.trade_binary_option); break; case "区间累积期权": setTradeEx(input.trade_rangeaccrual); break; case "气囊结构": setTradeEx(input.trade_airbag); break; case "收益增强结构": setTradeEx(input.trade_underlying_enhance); break; case "凤凰期权": setTradeEx(input.trade_autocall); break; case "雪球期权": setTradeEx(input.trade_snowball); break; case "累计期权": setTradeEx(input.trade_accumulator_option); otcTrade.StrikeGearingFactor = ConsGlobal.CallPut.IsCall(input.OptionType) ? otcTrade.PutMultiplier : otcTrade.CallMultiplier; break; case "现金流交易": setTradeEx(input.trade_cashflow); break; case "自定义交易": setTradeEx(input.trade_custom); break; } void setTradeEx(T extend) where T : TradeExtendBase { YLAutoMapper.Map(extend, otcTrade); } } /// /// 设置奇异要素 /// public void SetTradeExtend(IEnumerable tradeList, bool setMetaData = false, bool tracking = false) { if (tradeList is null || !tradeList.Any()) { return; } void InnerSetExt(IEnumerable tds, Func getter, Action setter) where T : TradeExtendBase { var tids = tds.Where(n => { var obj = getter(n); return obj == null || obj.TradeId != n.id; }).Select(n => n.id).ToHashSet(); var dic = (tracking ? DbContext.Set() : DbContext.Set().AsNoTracking()).Where(n => tids.Contains(n.TradeId)).ToDictionary(n => n.TradeId); foreach (var td in tds) { if (dic.TryGetValue(td.id, out var ext)) { setter(td, ext); } } } void InnerSetExt2(IEnumerable tds, Func> getter, Action> setter) where T : TradeExtendBase { var tids = tds.Where(n => { var obj = getter(n); return obj == null || obj.Count == 0 || obj.FirstOrDefault()?.TradeId != n.id; }).Select(n => n.id).ToHashSet(); var dic = (tracking ? DbContext.Set() : DbContext.Set().AsNoTracking()).Where(n => tids.Contains(n.TradeId)) .AsEnumerable().GroupBy(O => O.TradeId).ToDictionary(K => K.Key, V => V.ToList()); foreach (var td in tds) { if (dic.TryGetValue(td.id, out var ext)) { setter(td, ext); } } } var extGroups = tradeList.Where(n => n.id > 0).GroupBy(n => n.IsGroup == 1 && n.StructureType == "气囊结构" ? "气囊结构" : n.TradeType).ToArray(); foreach (var g in extGroups) { var tids = g.Select(n => n.id).ToHashSet(); switch (g.Key) { case "亚式期权": InnerSetExt(g, t => t.trade_asian_option, (t, ext) => t.trade_asian_option = ext); break; case "障碍期权": InnerSetExt(g, t => t.trade_barrier_option, (t, ext) => t.trade_barrier_option = ext); break; case "Risky期权": InnerSetExt(g, t => t.trade_risky_option, (t, ext) => t.trade_risky_option = ext); break; case "双鲨期权": InnerSetExt(g, t => t.trade_double_sharkfin_option, (t, ext) => t.trade_double_sharkfin_option = ext); break; case "二元期权": InnerSetExt(g, t => t.trade_binary_option, (t, ext) => t.trade_binary_option = ext); break; case "区间累积期权": InnerSetExt(g, t => t.trade_rangeaccrual, (t, ext) => t.trade_rangeaccrual = ext); break; case "气囊结构": InnerSetExt(g, t => t.trade_airbag, (t, ext) => t.trade_airbag = ext); break; case "收益增强结构": InnerSetExt(g, t => t.trade_underlying_enhance, (t, ext) => t.trade_underlying_enhance = ext); break; case "凤凰期权": InnerSetExt(g, t => t.trade_autocall, (t, ext) => t.trade_autocall = ext); break; case "雪球期权": InnerSetExt(g, t => t.trade_snowball, (t, ext) => t.trade_snowball = ext); break; case "彩虹期权": InnerSetExt(g, t => t.trade_rainbow_option, (t, ext) => t.trade_rainbow_option = ext); break; case "价差期权": InnerSetExt(g, t => t.trade_spread_option, (t, ext) => t.trade_spread_option = ext); break; case "收益互换": //InnerSetExt(g, t => t.trade_swap, (t, ext) => t.trade_swap = ext); //InnerSetExt2(g, t => t.get_trade_swap_details, (t, ext) => t.get_trade_swap_details = ext.Where(O => O.IsForGet && O.ValidState != "InValid").ToList()); //InnerSetExt2(g, t => t.pay_trade_swap_details, (t, ext) => t.pay_trade_swap_details = ext.Where(O => !O.IsForGet && O.ValidState != "InValid").ToList()); break; case "合成价差期权": //香草期权和合成价差期权都没有奇异要素扩展字段 break; case "远期": InnerSetExt(g, t => t.trade_forward, (t, ext) => t.trade_forward = ext); break; case "现金流交易": InnerSetExt(g, t => t.trade_cashflow, (t, ext) => t.trade_cashflow = ext); break; case "自定义交易": InnerSetExt(g, t => t.trade_custom, (t, ext) => t.trade_custom = ext); break; case "累计期权": InnerSetExt(g, t => t.trade_accumulator_option, (t, ext) => t.trade_accumulator_option = ext); break; } } if (setMetaData) { SetTradeMeta(tradeList); } } /// /// 设置元数据 /// public void SetTradeMeta(IEnumerable otcTrades) { if (otcTrades is null || !otcTrades.Any()) { return; } var set = new HashSet();//应该没有重复的数据但也防止下意外情况的发生 var tradDic = otcTrades.Where(n => set.Add(n.id)).ToDictionary(n => n.id); //为前端下载所有数据优化 for (var i = 0; i < set.Count; i += 1000) { var ids = set.Skip(i).Take(1000).ToArray(); var metaDatas = DbContext.TradeMeta.Where(n => ids.Contains(n.TradeId)) .Select(n => new { n.TradeId, n.MetaKey, n.MetaValue }).ToArray(); foreach (var meta in metaDatas) { if (tradDic.TryGetValue(meta.TradeId, out var td)) { td.MetaDic[meta.MetaKey] = meta.MetaValue; } } } } } }